用 Excel 表格中的数据批量替换 docx 模板中的标记(原创)

# 修改模板文件后,DOC中段落受格式影响,可能导致占位标记被分割成两个段落,出现这种情况可以将模板中
# 全部内容以“无格式文本”粘贴到新文档中,重新设置格式,可纠正错误的段落分割

import docx
import xlwings as xw
import sys
import time
import re

if (len(sys.argv) != 2):
    print("Error: Cannot found the argument!")
    exit()

path = sys.path[0]
app = xw.App(visible=False, add_book=False)
try:
    doc = docx.Document('template.dx')
except:
    print('Error: Cannot found template file!')
    exit()

try:
    print(path + '\\' + sys.argv[1])
    wb = app.books.open(path + '\\' + sys.argv[1])

    sh = wb.sheets['计算表']

    now = time.localtime(time.time())
    strDate = "{}年{}月{}日".format(now.tm_year, now.tm_mon, now.tm_mday)
    dtMon = sh.range('B2').value
    strMon = "{}年{}月".format(dtMon.year, dtMon.month)
    
    for p in doc.paragraphs:
        for r in p.runs:
            # 取得当前格式段中的替换标记,形如 <AB2>
            matched = re.findall("<.*?>", r.text)
            for item in matched:
                if item == '<DATE>':
                    r.text = r.text.replace(item, strDate)
                elif item == '<MON>':
                    r.text = r.text.replace(item , strMon)
                else:                      
                    value = str(sh.range(item[1:-1]).value)
                    if value == "None":
                        value = '0'  

                    # 删除末尾的小数点和0                 
                    cleaned_num = value.rstrip('0').rstrip('.') if '.' in value else value
                    r.text = r.text.replace(item , cleaned_num)
    try:
        strFileName = "方案{}年{:02d}月.docx".format(dtMon.year, dtMon.month)
        doc.save(strFileName)
    except Exception as r:
        #print('Error: Cannot write to a used file!')
        print(r)
        exit()                        
except Exception as r:
    #print('Error: Cannot open the file!')
    print(r)
finally:
    wb.close()
    app.quit()    

使用 docxtpl 库可以进一步简化代码:

# docx 模板中使用 {{AC3}} 形式保存单元格标记
from docxtpl import DocxTemplate
import xlwings as xw
import sys
import datetime
 
if (len(sys.argv) != 2):
    print("Error: Cannot found the argument!")
    exit()
 
path = sys.path[0]
app = xw.App(visible=False, add_book=False)
 
try:
    print(path + '\\' + sys.argv[1])
    wb = app.books.open(path + '\\' + sys.argv[1])
    sh = wb.sheets['计算表']
 
    context = {}
    for cell in sh.used_range:
        if type(cell.value) == float:
            # 数值类型的单元格都会被读入为 float 类型,在此去除末尾不必要的 0
            value = str(cell.value)
            #context[cell.get_address(False, False)] = f"{value:g}" 
            context[cell.get_address(False, False)] = value.rstrip('0').rstrip('.') if '.' in value else value
        else:
            context[cell.get_address(False, False)] = cell.value
            
    context['D6_S'] = int(context['D6']) - 1
    context['SPE'] = float(context['M2']) - float(context['AC8'])
  
    now = datetime.datetime.now()
    context['DATE'] = f"{now.year}年{now.month}月{now.day}日"

    Mon = sh.range('B2').value
    context['MON'] = f"{Mon.year}年{Mon.month}月"
except:
    print('Error: Cannot open the file!')
    exit()
finally:
    wb.close()
    app.quit()

doc = DocxTemplate("template.dx")
doc.render(context)
strFileName = f"分配计划{Mon.year}年{Mon.month:02d}月.docx"
doc.save(strFileName)
posted @ 2025-04-11 10:54  汉学  阅读(49)  评论(0)    收藏  举报