如何在Linux上使用python更新docx文件中的目录?

Yur*_*piv 5 python docx openxml python-docx

我在更新由 Linux 上的python-docx生成的 docx 文件中的目录时遇到问题。一般来说,创建TOC并不难(感谢这个答案/sf/answers/3403559211/和这个线程https://github.com/python-openxml/python-docx/issues/36

from docx.oxml.ns import qn
from docx.oxml import OxmlElement

paragraph = self.document.add_paragraph()
run = paragraph.add_run()
fldChar = OxmlElement('w:fldChar')  # creates a new element
fldChar.set(qn('w:fldCharType'), 'begin')  # sets attribute on element
instrText = OxmlElement('w:instrText')
instrText.set(qn('xml:space'), 'preserve')  # sets attribute on element
instrText.text = 'TOC \o "1-3" \h \z \u'   # change 1-3 depending on heading levels you need

fldChar2 = OxmlElement('w:fldChar')
fldChar2.set(qn('w:fldCharType'), 'separate')
fldChar3 = OxmlElement('w:t')
fldChar3.text = "Right-click to update field."
fldChar2.append(fldChar3)

fldChar4 = OxmlElement('w:fldChar')
fldChar4.set(qn('w:fldCharType'), 'end')

r_element = run._r
r_element.append(fldChar)
r_element.append(instrText)
r_element.append(fldChar2)
r_element.append(fldChar4)
p_element = paragraph._p
Run Code Online (Sandbox Code Playgroud)

但稍后要使目录可见,需要更新字段。下面提到的解决方案涉及手动更新(右键单击目录提示并选择“更新字段”)。对于自动更新,我找到了以下带有Word应用程序模拟的解决方案(感谢这个答案/sf/answers/2437323661/

import win32com.client
import inspect, os

def update_toc(docx_file):
    word = win32com.client.DispatchEx("Word.Application")
    doc = word.Documents.Open(docx_file)
    doc.TablesOfContents(1).Update()
    doc.Close(SaveChanges=True)
    word.Quit()

def main():
    script_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
    file_name = 'doc_with_toc.docx'
    file_path = os.path.join(script_dir, file_name)
    update_toc(file_path)

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

它在 Windows 上运行得很好,但在 Linux 上显然不行。有人对如何在 Linux 上提供相同的功能有任何想法吗?我唯一的建议是对每个标题使用本地 URL(锚点),但我不确定python-docx是否可行,而且我对这些openxml功能也不是很了解。我将非常感谢任何帮助。

Fai*_*min 3

我从这个Github Issue中找到了解决方案。它可以在 ubuntu 上运行。

def set_updatefields_true(docx_path):
    namespace = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
    doc = Document(docx_path)
    # add child to doc.settings element
    element_updatefields = lxml.etree.SubElement(
        doc.settings.element, f"{namespace}updateFields"
    )
    element_updatefields.set(f"{namespace}val", "true")
    doc.save(docx_path)## Heading ##

Run Code Online (Sandbox Code Playgroud)

  • 对我来说,这本身并不更新表,而是在打开文件时弹出一个提示,询问您是否要更新。 (2认同)