【问题标题】:how to regain the original font properties and its associated properties like bold, italics using python-docx while text replacement如何在文本替换时使用 python-docx 恢复原始字体属性及其相关属性,如粗体、斜体
【发布时间】:2017-07-13 05:00:21
【问题描述】:

我正在使用 python-docx 作为自动化工具。在我运行代码以将一个列表中的某些单词替换为另一个列表中的对应单词后,我遇到了一个问题,它正在删除所有属性(如字体大小、字体名称、粗体或斜体文本的一部分、书签中的段落和表格中的文本),并带有“Calibri”中的纯文本,字体大小为“12”。

我使用的代码是:

wrongWord = "xyz"
correctWord = "abcd"
def iter_block_items(parent):
    if isinstance(parent, _Document):
        parent_elm = parent.element.body
    elif isinstance(parent, _Cell):
        parent_elm = parent._tc
    else:
        raise ValueError("something's not right")

    for child in parent_elm.iterchildren():
        if isinstance(child, CT_P):
            yield Paragraph(child, parent)
        elif isinstance(child, CT_Tbl):
            yield Table(child, parent)



document = Document(r"F:\python\documentSample.docx")
for block in iter_block_items(document):
    if isinstance(block, Paragraph):
        if wrongWord in block.text:
            block.text = block.text.replace(wrongWord, correctWord)
    else:
        for row in block.rows:
            for cell in row.cells:
                if wrongWord in cell.text:
                    cell.text = cell.text.replace(wrongWord, correctWord)

document.save(r"F:\python\documentSampleAfterChanges.docx")

您能否帮我在文本替换后从原始文件中复制相同的字体大小、字体名称和其他相关属性。

【问题讨论】:

    标签: python python-2.7 python-3.x


    【解决方案1】:

    搜索和替换在一般情况下是一个难题,这是尚未添加功能的主要原因。

    这里发生的情况是,分配给单元格上的 .text 属性会删除所有现有运行,并且与这些运行相关的字体相关属性也将被删除。

    字体信息(例如粗体、斜体、字体、大小)存储在 run 级别(一个段落由零个或多个运行组成)。分配给.text 属性会删除所有运行并将它们替换为包含指定文本的单个 new 运行。

    因此,挑战在于在某处的多次运行中找到文本,并尽可能多地保留字体格式设置。

    这是一个难题,因为 Word 出于多种原因将段落文本分成单独的运行,并且运行往往会激增。根本无法保证您的搜索词将完全包含在单次运行中或从运行边界开始。因此,也许您开始看到通用案例解决方案的挑战。

    您可以做的一件事可能适用于您的情况:

    # ---replace text of first run with new cell value---
    runs = table_cell.paragraphs[0].runs
    runs[0].text = replacement_text
    # ---delete all remaining runs---
    for run in runs[1:]:
        r = run._element
        r.getparent().remove(r)
    

    基本上这会替换第一次运行的文本并删除任何剩余的运行。由于第一次运行通常包含您想要的格式,这通常可以工作。如果第一个单词的格式不同,比如粗体,那么所有替换文本也将是粗体。您必须看看这种方法在您的特定情况下如何工作。

    【讨论】:

    • 非常感谢您。但我收到如下错误 AttributeError: '_Cell' object has no attribute 'text_frame' 以及我在下面的链接中搜索:python-docx.readthedocs.io/en/latest/api/…
    • 糟糕,抱歉,我给了你python-pptx 的代码,而不是python-docx :) 我已经更新了答案中的代码。基本上,您只需删除 .text_frame 元素并直接从单元格对象中访问段落。
    • 上面的代码在涉及以下一些文本时不起作用示例段落:此段落以粗体文本开头那句话之后是斜体。后来它变成了普通文本。 **在同一段落中,它再次变为粗体文本。 ** 在上面的示例段落中,经过一些文本替换后,整个文本变为粗体,并且使用“run [0]”在文本开头给出的字体,但我的要求是恢复原始格式在接下来的几行中给出。
    • @vikashvishnu 这正是我所描述的难题。您必须映射每次运行的开始和长度,确定搜索词开始和结束的运行中的运行和偏移量,然后操作这些运行以替换您的文本。
    猜你喜欢
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-08
    • 2011-11-01
    • 1970-01-01
    • 2012-07-02
    相关资源
    最近更新 更多