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.
Related
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")
I have a list that looks like this in my UI:
UI image
The XPATH for the first row's "..." button is //tbody/tr[1]/td[2]/a[1]/i[1], and each subsequent row's XPATH has the tr[] portion updated depending on the index of the row.
Is it possible to store the xpath of the button as:
button = //tbody/tr[i]/td[2]/a[1]/i[1] ?
And if so, if I create a new rule, is there a way I can update tr[i] to reflect the index of the newly added rule so I can call button.click()?
looks like, you wanna make indexing bit dynamic :
so, for this xpath :-
//tbody/tr[1]/td[2]/a[1]/i[1]
you can do following:
i = 1
button = f"//tbody/tr[{i}]/td[2]/a[1]/i[1]"
and can use it in Selenium.
you can use it for loop as well with the indices.
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 am making a simple text editor, and now I'm trying to make a replace function. The text the user wants to replace is highlighted green by using
.tag_add('select', index, end_index)
and then
.tag_config('select', background='green')
Now, I want to replace it by getting the index of text that has this specific tag and then replacing it by what the user has typed. So, my question is: How do I get the start and end index of text with a specific tag? The widget the text is in is the tkinter scrolledtext widget.
# Assuming you have only one tag matching 'select'...
start, stop = text.tag_ranges('select')
text.delete(start, stop)
text.insert(start, <new_text>)
I have to retrieve text inside an HTML table, in the cells the text sometimes is inside a <div> and sometimes is not.
How can I make a div in a XPath optional?
My actual code:
stuff = tree.xpath("/html/body/table/tbody/tr/td[5]/div/text()")
Wanted pseudocode:
stuff = tree.xpath("/html/body/table/tbody/tr/td[5]/div or nothing/text()")
You want the string value of the td[5] element. Use string():
stuff = tree.xpath("string(/html/body/table/tbody/tr/td[5])")
This will return text without markup beneath td[5].
You can also indirectly obtain the string value of an element via normalize-space() as suggested by splash58 in the comments, if you also want whitespace to be trimmed on the ends and reduced interiorly.