Reputation: 11
How to set font spacing in python-docx or how to add element to w:rPr? //<w:rPr> <w:spacing w:val="200"/> </w:rPr>
Upvotes: 1
Views: 936
Reputation: 26
This is how I've set the spacing in a new document for 'Normal' text. of course this answer takes advantage of old replies
# create a new Document
doc = Document()
style = doc.styles['Normal']
spacing = OxmlElement("w:spacing")
spacing.set(qn('w:val'), str("-12"))
style.font._element.rPr.insert_element_before(
spacing,
*("w:w", "w:kern", "w:position", "w:sz", "w:szCs", "w:highlight", "w:u", "w:effect", "w:bdr", "w:shd",
"w:fitText", "w:vertAlign", "w:rtl", "w:cs", "w:em", "w:lang", "w:eastAsianLayout", "w:specVanish", "w:oMath",
),
)
Upvotes: 0
Reputation: 11
I tried the answer by scanny, It did not work. But the output document XML <w:spacing val="200"> is close to the right format. The right format is <w:spacing w:val="200">
Try this
from docx.oxml.ns import qn
spacing.set(qn('w:val'), str(value))
Upvotes: 0
Reputation: 28863
There is no API support for this setting in python-docx
.
Adding a <w:spacing>
element will work if that's what Word does, however the sequence in which child elements appear is, in general, significant in WordprocessingML (the XML schema .docx files adhere to). If you don't get the w:spacing
element in the right order among the w:rPr
child elements or you add one when one is already there, you'll trigger a repair error.
So you need something like this:
def run_set_spacing(run, value: int):
"""Set the font spacing for `run` to `value` in twips.
A twip is a "twentieth of an imperial point", so 1/1440 in.
"""
def get_or_add_spacing(rPr):
# --- check if `w:spacing` child already exists ---
spacings = rPr.xpath("./w:spacing")
# --- return that if so ---
if spacings:
return spacings[0]
# --- otherwise create one ---
spacing = OxmlElement("w:spacing")
rPr.insert_element_before(
spacing,
*(
"w:w",
"w:kern",
"w:position",
"w:sz",
"w:szCs",
"w:highlight",
"w:u",
"w:effect",
"w:bdr",
"w:shd",
"w:fitText",
"w:vertAlign",
"w:rtl",
"w:cs",
"w:em",
"w:lang",
"w:eastAsianLayout",
"w:specVanish",
"w:oMath",
),
)
return spacing
rPr = run._r.get_or_add_rPr()
spacing = get_or_add_spacing(rPr)
spacing.set("val", str(value))
Then you would call this for each run that needs that setting like so:
run_set_spacing(run, 200)
Upvotes: 1