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/