You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySimpleGUI结合python-docx实现Word模板替换失效求助

Word模板占位符替换失败问题修复

问题概述

使用PySimpleGUI开发的GUI程序可正常运行、输入数据并按指定名称保存文档,但Word模板中形如{{-NAME_}}的占位符无法被输入内容替换,数据未正确作用于模板替换逻辑。

核心问题分析

从提供的代码来看,导致替换失败的主要原因有三点:

  • 占位符格式不匹配:代码中生成的占位符是{{name}}(基于data字典的键名拼接),但实际模板中使用的是{{-NAME_}},键名和占位符的格式完全不对应,导致匹配失败。
  • 重复的主程序入口:代码中存在两个if __name__ == "__main__"块,会导致程序逻辑重复执行,可能干扰数据存储和模板处理流程。
  • 段落替换的潜在格式丢失问题:直接修改paragraph.text会清除段落中的格式(如字体、颜色等),如果模板有格式要求,需要更精细的替换逻辑。

修复后的完整代码

import PySimpleGUI as sg
from docx import Document

input_data = {}

def window1():
    layout = [
        [sg.Text("Enter name:"), sg.InputText(key ="-NAME-")],
        [sg.Text("Enter email:"), sg.InputText(key="-EMAIL-")],
        [sg.Button("Next")]
    ]
    window = sg.Window("Window 1", layout)

    while True:
        event, values = window.read()
        if event == sg.WINDOW_CLOSED:
            break
        elif event == "Next":
            input_data["window1"] = {"name": values["-NAME-"], "email": values["-EMAIL-"]}
            window.close()

def window2():
    layout = [
        [sg.Text("Enter age:"), sg.InputText(key="-AGE-")],
        [sg.Button("Submit")]
    ]
    window = sg.Window("Window 2", layout)

    while True:
        event, values = window.read()
        if event == sg.WINDOW_CLOSED:
            break
        elif event == "Submit":
            input_data["window2"] = {"age": values["-AGE-"]}
            window.close()

def update_word_template(template_path, data_map):
    try:
        document = Document(template_path)
        # 遍历段落处理占位符,保留格式的方式替换run文本
        for paragraph in document.paragraphs:
            # 先处理段落中的所有run,避免直接替换text丢失格式
            for run in paragraph.runs:
                for placeholder, value in data_map.items():
                    if placeholder in run.text:
                        run.text = run.text.replace(placeholder, value)
            # 处理段落整体文本(防止占位符跨run的情况)
            for placeholder, value in data_map.items():
                if placeholder in paragraph.text:
                    paragraph.text = paragraph.text.replace(placeholder, value)
        return document
    except Exception as e:
        return str(e)

if __name__ == "__main__":
    window1()
    window2()

    template_path = "C:/Users/steve/OneDrive/Documents/Python practice/Scrollable/Template.docx" 
    # 构建数据与模板占位符的映射关系
    window1_data = input_data.get("window1", {})
    window2_data = input_data.get("window2", {})
    # 对应模板中的占位符格式:{{-NAME_}}, {{-EMAIL_}}, {{-AGE_}}
    template_data_map = {
        "{{-NAME_}}": window1_data.get("name", ""),
        "{{-EMAIL_}}": window1_data.get("email", ""),
        "{{-AGE_}}": window2_data.get("age", "")
    }

    name = window1_data.get("name", "Unnamed")
    output_path = f"C:/Users/steve/OneDrive/Documents/Python practice/Scrollable/{name}_modified.docx"

    try:
        modified_document = update_word_template(template_path, template_data_map)
        # 检查返回值是否为Document对象,避免异常时的字符串返回导致报错
        if isinstance(modified_document, Document):
            modified_document.save(output_path)
            print("Text inserted and document saved:", output_path)
        else:
            print("Template update failed:", modified_document)
    except Exception as e:
        print("An error occurred:", e)

关键修改说明

  1. 占位符映射修正:直接构建模板占位符到输入数据的映射字典,确保{{-NAME_}}等模板中的占位符能准确匹配到对应的输入值。
  2. 删除重复主程序入口:移除重复的if __name__ == "__main__"块,确保程序逻辑只执行一次。
  3. 保留格式的替换逻辑:先遍历段落中的run进行替换,再处理段落整体文本,避免直接替换paragraph.text导致格式丢失,同时覆盖占位符跨run的场景。
  4. 增加返回值校验:检查update_word_template的返回值是否为Document对象,避免异常时返回的字符串调用save()方法导致报错。

内容的提问来源于stack exchange,提问作者Gemsgolf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 01:12:09