I am trying to adjust the text on a per column basis in a docx table. I have tried
for row in doc.tables[2].column_cells(4):
font = run.font
font.size = Pt(8)
I don't get an error with the above code, but I also am not seeing any changes to the cell texts in that column
Make sure you are accessing the correct table: The code you provided is accessing the third table in the document (index 2) and the fourth column (index 3) of that table. Make sure that this is the table you want to make changes to, and that you are referencing the correct column.
Check the scope of the loop: Ensure that the loop is looping through the cells of the column correctly.
Use the .text attribute: the font attribute only affects the font of the text, not the text itself. You can use the .text attribute to change the text.
Apply the changes to the runs within the cells: Instead of changing the font of the whole cell, you should change the font of the runs within the cell. Each cell has a .paragraphs attribute that contains a list of the paragraphs in that cell, and each paragraph has a .runs attribute that contains a list of the runs of text within that paragraph.
for row in doc.tables[2].column_cells(3):
for paragraph in row.paragraphs:
for run in paragraph.runs:
run.font.size = Pt(8)
Save the changes: Remember to save the changes to the docx file after you have made the changes.
doc.save("updated_table.docx")
Related
I have been using python docx library and oxml to automate some changes to my tables in my word document. Unfortunately, no matter what I do, I cannot wrap the text in the table cells.
I managed to successfully manipulate 'autofit' and 'fit-text' properties of my table, but non of them contribute to the wrapping of the text in the cells. I can see that there is a "w:noWrap" in the xml version of my word document and no matter what I do I cannot manipulate and remove it. I believe it is responsible for the word wrapping in my table.
for example in this case I am adding a table. I can fit text in cell and set autofit to 'true' but cannot for life of me wrap the text:
from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
doc = Document()
table = doc.add_table(5,5)
table.autofit = True # Does Autofit but not wrapping
tc = table.cell(0,0)._tc # As a test, fit text to cell 0,0
tcPr = tc.get_or_add_tcPr()
tcFitText = OxmlElement('w:tcFitText')
tcFitText.set(qn('w:val'),"true")
tcPr.append(tcFitText) #Does fitting but no wrapping
doc.save('demo.docx')
I would appreciate any help or hints.
The <w:noWrap> element appears to be a child of <w:tcPr>, the element that controls table cell properties.
You should be able to access it from the table cell element using XPath:
tc = table.cell(0, 0)._tc
noWraps = tc.xpath(".//w:noWrap")
The noWraps variable here will then be a list containing zero or more <w:noWrap> elements, in your case probably one.
Deleting it is probably the simplest approach, which you can accomplish like this:
if noWraps: # ---skip following code if list is empty---
noWrap = noWraps[0]
noWrap.getparent().remove(noWrap)
You can also take the approach of setting the value of the w:val attribute of the w:noWrap element, but then you have to get into specifying the Clark name of the attribute namespace, which adds some extra fuss and doesn't really produce a different outcome unless for some reason you want to keep that element around.
I want to put my picture and table(only 1 cell) like below:
Click here to see picture
I have to use such table because python-docx can't handle text-box yet. Basically I need to put my table beside my picture, not below or upper. I find that paragraph.run has add_picture() method to add picture at the end of paragraph, but not add_table() method to add one more table. Anyone know how to achieve this
i have tried so many ways to put a picture into a table ,that is what i do deal with my problem, you may find something you can use
from docx import Document
document = Document
table = document.add_table(rows=2, cols=3)
# set the whole table in the center position
table.alignment = WD_TABLE_ALIGNMENT.CENTER
row_cell = table.add_row().cells
# choice one row
**row_pic = row_cell[0]**
# clear blank area
**row_pic._tc.clear_content()**
# use paragraph function
**pic_run = row_pic.add_paragraph().add_run()**
# insert a picture path as a str into a cell from a table
**pic_run.add_picture('./picture/{}'.format("picture_name.jpg"), width=Inches(5))**
I am trying to parse through all of the values in the column of this website (with different stock tickers). I am working in Python and am using XPath to scrape HTML data.
Lets say I want to extract the value of the "Change" which is currently 0.62% (and green). I would first get the tree to the website and then say.
stockInfo_1 = tree.xpath('//*[#class="table-dark-row"]/td[12]/b/span/text()')
I would then get an array of values and last element happens to be change value.
However, I noticed that if a value in this column has a color, it is in the /b/SPAN, while if it does not have a color, there is no span and its just in the /b.
So to explain:
stockInfo_1 = tree.xpath('//*[#class="table-dark-row"]/td[12]/b/span/text()')
^this array would have every value in this column that is Colored
while stockInfo_1 = tree.xpath('//*[#class="table-dark-row"]/td[12]/b/text()')
^would have every value in the column that does not have a color.
The colors are not consistent for each stock. Some stocks have random values that have colors and some do not. So that messes up the /b/span and /b array consistency.
How can I get an array of variables of ALL of the values (in order) in each column regardless of if they are in a span or not? I do not care about the colors, i just care about the values.
I can explain more if needed. Thanks!!
You can directly skip intermediate tags in xpath and get all the values in a list by using // inbetween.
So the snippet should be
tree.xpath('//*[#class="table-dark-row"]/td[12]/b//text()')
This skips all the intermediate tags between and text.
I've tried using lxml. Here is the code
import requests
from lxml import html
url="https://finviz.com/quote.ashx?t=acco&ty=c&ta=1&p=d"
resp=requests.get(url)
tree = html.fromstring(resp.content)
values = tree.xpath('//*[#class="table-dark-row"]/td[12]/b//text()')
print values
Which gives output as follows
['0.00%', '-2.43%', '-8.71%', '-8.71%', '7.59%', '-1.23%', '1.21', '0.30', '2.34% 2.38%', '12.05', '12.18', '1.04%']
Note: If you don't want to hardcode 12 in the above Xpath you can aslo use last() as tree.xpath('//*[#class="table-dark-row"]/td[last()]/b//text()')
Xpath cheat sheet for your kind reference.
Using "//" And ".//" Expressions In XPath XML Search Directives In ColdFusion
Using Openpyxl, is there a way to create a link within a cell?
I tried:
worksheet['A1'].hyperlink = 'http://mypage.com'
However, this sets the entire cell of 'A1' to be a link. I would like it to set the text within the cell to a link so that it looks like: My page in cell A1.
You can try something like this:
wb = load_workbook("my_book.xlsx")
worksheet1 = wb.active()
cell_value = '=HYPERLINK("http://mypage.com", "My Page")'
worksheet1.cell(row=1, column=1, value=cell_value)
The important part of my example is that you can just set the value of the cell to excel's hyperlink function as a string. The first parameter is the link and the second parameter is the text to display in the cell.
What I couldn't figure out is how to dynamically tag ranges of text with the Tkinter text widget.
The idea is that when the user selects a range of text, it dynamically creates a tag to modify the style.
Here's my code:
#...code...
tag = text_field.tag_ranges(SEL)
text_field.tag_add('sizesel',tag[0],tag[1])
text_field.tag_config('sizesel',font = appFont)
This code is part of a callback function that is bound to a Combobox, so that the size of the text changes every time the value changes.
This code works great, but if I try to stylize a second line of text, it takes the style of the 1st line.
If you want a unique style for each range you'll need to use a unique tag, because style information belongs to the tag rather than the range of text. The easiest method is to keep a global (or instance attribute) counter that you increment each time you add a tag, and use that as part of the tag name.
Here's how I did it:
tag = text_field.tag_ranges(SEL)
i = 0
for i in tag:
text_field.tag_add(i,tag[0],tag[1])
text_field.tag_config(i,font = appFont)
as you can see I added a simple for statement that goes on tag which is the variable that contains the indexes for the SEL tag.