首页 > 解决方案 > Python - 用 docx 中的图像替换字符串

问题描述

我一直在尝试用文件夹中的相关图像替换位于 docx 文件的表格中的单元格中的某些图像字符串。让所有图像的编译列表=图像。

到目前为止,我的“最佳”尝试是遍历文档中的所有表格单元格并尝试此任务,如下面的代码所示。

for Image in Images:                            
    for table in document.tables:
        for row in table.rows:
            for cell in row.cells:
                for paragraph in cell.paragraphs:
                    if Image in paragraph.text:
                        
                        for p in enumerate(cell.paragraphs):
                             img_paragraph = p[1]
                                               
                        runner = paragraph.add_run(img_paragraph)
                        runner.add_picture(f'{Image}.gif', width=Cm(1))
                        
                        paragraph.text = paragraph.text.replace(Image, "")

不幸的是,我收到错误代码“TypeError:'Paragraph' object is not iterable”,但每次我解决一个错误代码时,我都会发现自己盯着另一个错误代码。

我非常感谢您花时间阅读这个问题。

标签: pythonpython-docx

解决方案


开始是排除一些迭代:

def iter_target_paragraphs(document):
    """Generate each paragraph inside all tables of `document`."""
    for table in document.tables:
        for row in table.rows:
            for cell in row.cells:
                for paragraph in cell.paragraphs:
                    yield paragraph

我不认为你会从中得到任何错误,它使核心代码更简单。

然后我会为看起来像图像文件名的东西使用更具描述性的名称。此外,迭代段落会比迭代文件名慢很多,所以我会颠倒顺序/嵌套:

for paragraph in iter_target_paragraphs():
    for image_filename in image_filenames:
        if image_filename in paragraph.text:
            substitute_image_placeholder(paragraph, image_filename)

我也不希望这会(直接)引发错误,这样我们就可以使用该substitute_image_placeholder()功能了。我认为这将完成基本工作:

def substitute_image_placeholder(paragraph, image_filename):
    # --- start with removing the placeholder text ---
    paragraph.text = paragraph.text.replace(image_filename, "")
    # --- then append a run containing the image ---
    run = paragraph.add_run()
    run.add_picture(f'{image_filename}.gif', width=Cm(1))

这不是“完美”的,因为图像的位置将始终位于段落的末尾,而不是占位符所在的位置,但这似乎是您的原始代码试图做的事情,也许这就是您正在寻找的为了。

如果您需要图像“替换”段落中间某处的占位符,那么您需要将占位符文本隔离到自己的运行中。这里还有另一个答案显示了要完成的工作:
https ://stackoverflow.com/a/68507579/1902513


推荐阅读