如何在替换文本时使用python docx恢复原始字体属性及其相关属性(如粗体、斜体)

如何在替换文本时使用python docx恢复原始字体属性及其相关属性(如粗体、斜体),python,python-2.7,python-3.x,Python,Python 2.7,Python 3.x,我使用PythonDocx作为自动化工具。我有一次遇到这样的问题,在我运行代码以替换一个列表中的某些单词和另一个列表中的相应单词后,它删除了所有属性,如字体大小、字体名称、粗体或斜体文本的一部分,段落或表格中的书签,以及段落和表格中的文本及其附带的Calibri纯文本,字体大小为“12” 我使用的代码是: wrongWord = "xyz" correctWord = "abcd" def iter_block_items(parent): if isinstance(parent, _

我使用PythonDocx作为自动化工具。我有一次遇到这样的问题,在我运行代码以替换一个列表中的某些单词和另一个列表中的相应单词后,它删除了所有属性,如字体大小、字体名称、粗体或斜体文本的一部分,段落或表格中的书签,以及段落和表格中的文本及其附带的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")

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

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

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

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

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

这是一个很难解决的问题,因为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)

基本上,这将替换第一次运行的文本,并删除所有剩余的运行。由于第一次运行通常包含所需的格式,因此这通常是可行的。如果第一个单词的格式不同,比如说粗体,那么所有替换文本也将是粗体的。您必须了解这种方法在您的具体案例中是如何起作用的。

非常感谢scanny。但是我得到一个错误,如下AttributeError:“\u Cell”对象没有属性“text\u frame”,我在下面的链接中搜索到:哦,对不起,我给了你python pptx的代码,而不是python docx:我在答案中更新了代码。基本上,您只需删除.text_frame元素,并直接从cell对象访问段落。上面的代码在处理以下示例段落中的某些文本时不起作用:此段落以粗体文本开头。在那句话之后是斜体字。后来它变成了普通文本**在同一段中,它再次变成粗体文本。**在上面的示例段落中,在一些文本替换之后,整个文本显示为粗体,并使用run[0]在文本开头给出的字体,但我的要求是恢复后面几行给出的原始格式。@vikashvishnu这正是我描述的难题。您必须映射每次跑步的开始和长度,找出搜索词在跑步中开始和结束的跑步和偏移量,然后操纵这些跑步来替换文本。