Python-docx 如何在同样式的段落后设置space
Python-docx How to set space after paragraphs of the same style
我在使用 python-docx 时注意到,如果我按顺序将样式应用于每个段落,但样式为 space_after = Pt(12)
,Word 不接受 space_after 环境。我注意到在段落选项中选中了 "Don't add space between paragraphs of the same style"。有什么办法可以解决这个问题,以便应用 space_after
设置?
我在文本末尾使用了换行符,但我并不总是需要换行符。有时,我可能想要部分线条或特定尺寸。
我建立了一个文档,其中包含几个相同样式的段落 ("Normal") 和各种 space_after
:
Select 所有段落并将 "Dont' add space between paragraphs of the same style" 切换为选中。
现在看起来是这样:
从 Word 中保存并关闭文档,然后通过 docx 检查它:
>>> from docx import Document
>>> document = Document(r'c:\debug\doc1.docx')
>>> for p in document.paragraphs:
... print(p.paragraph_format.space_after)
...
635000
None
None
所以,很明显 space_after
被保留了,但是在文档中没有观察到它,因为它被复选框选项覆盖了。这是由 <w:pPr>
的 <w:contextualSpacing/>
元素给出的(我通过检查 Docx 的 \word\document.xml
部分注意到了这一点)。
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" w:rsidR="00E00961" w:rsidRDefault="00174F18">
<w:pPr>
<w:spacing w:after="1000"/>
<w:contextualSpacing/>
</w:pPr>
<w:bookmarkStart w:id="0" w:name="_GoBack"/>
<w:r>
<w:t>hello, world!
</w:t>
</w:r>
</w:p>
您可以像这样从底层 XML 中删除它们:
for p in document.paragraphs:
p_element = p._element
cspacing = p_element.xpath(r'w:pPr/w:contextualSpacing')[0]
cspacing.getparent().remove(cspacing)
删除这些元素后,再次打开文档,观察切换已关闭,段落观察 space_after
:
我尝试使用 David Zemens 的答案,使用样式为“List Number”的有序列表,但在我的 docx 文件中仍然检查了“不要在相同样式的段落之间添加 space”。
检查基础 xml 文件时,我在 word/styles.xml.
的“列表编号”部分中发现了一个“w:contextualSpacing”条目
我的解决方法是在没有上下文间距条目的情况下重写 docx 文件(存档):
from io import BytesIO
import re
from zipfile import ZipFile
def remove_contextual_spacing_from_style(docx_path, style_name):
mod_docx = BytesIO()
style_byte = style_name.encode('utf-8')
# load docx file as zip archive
with ZipFile(docx_path, 'r') as old_docx, ZipFile(mod_docx, 'w') as new_docx:
# iterate through underlying xml files
for xml_item in old_docx.infolist():
with old_docx.open(xml_item) as old_xml:
content = old_xml.read()
# search style_name section in word/styles.xml
if xml_item.filename == 'word/styles.xml':
cspace = re.search(b'"%s".*?<\/w:pPr>'%(style_byte), content)
# remove contextualSpacing entry
if cspace:
cspace = cspace.group(0)
wo_cspace = cspace.replace(b'<w:contextualSpacing/>', b'')
content = re.sub(cspace, wo_cspace, content)
# store xml file in modified docx archive
new_docx.writestr(xml_item, content)
# overwrite old docx file with modified docx
with open(docx_path, 'wb') as new_docx:
new_docx.write(mod_docx.getbuffer())
# example usage with style "List Number"
remove_contextual_spacing_from_style('path_to.docx', 'List Number')
使用的来源:
在“用例 #3,尝试 #3”下
https://medium.com/dev-bits/ultimate-guide-for-working-with-i-o-streams-and-zip-archives-in-python-3-6f3cf96dca50
https://techoverflow.net/2020/11/11/how-to-modify-file-inside-a-zip-file-using-python/
我在使用 python-docx 时注意到,如果我按顺序将样式应用于每个段落,但样式为 space_after = Pt(12)
,Word 不接受 space_after 环境。我注意到在段落选项中选中了 "Don't add space between paragraphs of the same style"。有什么办法可以解决这个问题,以便应用 space_after
设置?
我在文本末尾使用了换行符,但我并不总是需要换行符。有时,我可能想要部分线条或特定尺寸。
我建立了一个文档,其中包含几个相同样式的段落 ("Normal") 和各种 space_after
:
Select 所有段落并将 "Dont' add space between paragraphs of the same style" 切换为选中。
现在看起来是这样:
从 Word 中保存并关闭文档,然后通过 docx 检查它:
>>> from docx import Document
>>> document = Document(r'c:\debug\doc1.docx')
>>> for p in document.paragraphs:
... print(p.paragraph_format.space_after)
...
635000
None
None
所以,很明显 space_after
被保留了,但是在文档中没有观察到它,因为它被复选框选项覆盖了。这是由 <w:pPr>
的 <w:contextualSpacing/>
元素给出的(我通过检查 Docx 的 \word\document.xml
部分注意到了这一点)。
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" w:rsidR="00E00961" w:rsidRDefault="00174F18">
<w:pPr>
<w:spacing w:after="1000"/>
<w:contextualSpacing/>
</w:pPr>
<w:bookmarkStart w:id="0" w:name="_GoBack"/>
<w:r>
<w:t>hello, world!
</w:t>
</w:r>
</w:p>
您可以像这样从底层 XML 中删除它们:
for p in document.paragraphs:
p_element = p._element
cspacing = p_element.xpath(r'w:pPr/w:contextualSpacing')[0]
cspacing.getparent().remove(cspacing)
删除这些元素后,再次打开文档,观察切换已关闭,段落观察 space_after
:
我尝试使用 David Zemens 的答案,使用样式为“List Number”的有序列表,但在我的 docx 文件中仍然检查了“不要在相同样式的段落之间添加 space”。
检查基础 xml 文件时,我在 word/styles.xml.
的“列表编号”部分中发现了一个“w:contextualSpacing”条目我的解决方法是在没有上下文间距条目的情况下重写 docx 文件(存档):
from io import BytesIO
import re
from zipfile import ZipFile
def remove_contextual_spacing_from_style(docx_path, style_name):
mod_docx = BytesIO()
style_byte = style_name.encode('utf-8')
# load docx file as zip archive
with ZipFile(docx_path, 'r') as old_docx, ZipFile(mod_docx, 'w') as new_docx:
# iterate through underlying xml files
for xml_item in old_docx.infolist():
with old_docx.open(xml_item) as old_xml:
content = old_xml.read()
# search style_name section in word/styles.xml
if xml_item.filename == 'word/styles.xml':
cspace = re.search(b'"%s".*?<\/w:pPr>'%(style_byte), content)
# remove contextualSpacing entry
if cspace:
cspace = cspace.group(0)
wo_cspace = cspace.replace(b'<w:contextualSpacing/>', b'')
content = re.sub(cspace, wo_cspace, content)
# store xml file in modified docx archive
new_docx.writestr(xml_item, content)
# overwrite old docx file with modified docx
with open(docx_path, 'wb') as new_docx:
new_docx.write(mod_docx.getbuffer())
# example usage with style "List Number"
remove_contextual_spacing_from_style('path_to.docx', 'List Number')
使用的来源:
在“用例 #3,尝试 #3”下 https://medium.com/dev-bits/ultimate-guide-for-working-with-i-o-streams-and-zip-archives-in-python-3-6f3cf96dca50
https://techoverflow.net/2020/11/11/how-to-modify-file-inside-a-zip-file-using-python/