使用python的进行word批量生成

330 阅读2分钟

使用python的zipfile模块进行word批量生成

  1. 平台:windows10
  2. 解释器:python3.7
  3. 需求:一包含目标数据的excel文档,需要将其中的每一行数据的对应内容替换到指定word中,并逐一保存

使用zipfile模块

from shutil import rmtree
import zipfile
from copy import deepcopy
from pathlib import Path
from win32com import client as wc  # pip install pypiwin32
import pandas as pd

# doc文档不包含所需xml文件,使用win32com转存为docx文档
def doctransform2docx(doc_path):
    docx_path = doc_path + 'x'
    suffix = doc_path.split('.')[1]
    assert 'doc' in suffix, '传入的不是word文档,请重新输入!'
    if suffix == 'docx':
        return Path(doc_path)
    word = wc.Dispatch('Word.Application')
    doc = word.Documents.Open(doc_path)
    doc.SaveAs2(docx_path, 16)  # docx为16
    doc.Close()
    word.Quit()
    return Path(docx_path)

# docx文档解压
def docx_unzip(docx_path):
    docx_path = Path(docx_path) if isinstance(docx_path, strelse docx_path
    upzip_path = docx_path.with_name(docx_path.stem)
    with zipfile.ZipFile(docx_path, 'r'as f:
        for file in f.namelist():
            f.extract(file, path=upzip_path)
    xml_path = upzip_path.joinpath('word/document.xml')
    with xml_path.open(encoding='utf-8'as f:
        xml_file = f.read()
    return upzip_path, xml_path, xml_file

# 讲文件夹中的所有文件压缩成docx文档
def docx_zipped(docx_path, zipped_path):
    docx_path = Path(docx_path) if isinstance(docx_path, strelse docx_path
    with zipfile.ZipFile(zipped_path, 'w', zipfile.zlib.DEFLATED) as f:
        for file in docx_path.glob('**/*.*'):
            f.write(file, file.as_posix().replace(docx_path.as_posix() + '/'''))

# 删除生成的解压文件夹
def remove_folder(path):
    path = Path(path) if isinstance(path, strelse path
    if path.exists():
        rmtree(path)
    else:
        raise "系统找不到指定的文件"
            
# 替换docx中的特定字符,重新保存document.xml至需要压缩的目录下
def replace_docx(name, values, xml_file, xml_path, unzip_path, path_name='Company'):
    xml_path = Path(xml_path) if isinstance(xml_path, strelse xml_path
    xml_file_copy = deepcopy(xml_file)  # 深复制xml内容
    for col_name, value in zip(name, values):
        if col_name == 'Company':
            path_name = str(value)
        xml_file_copy = xml_file_copy.replace(col_name, str(value))
    with xml_path

使用python-docx.Document读取word文档(备注:解决不了特殊字符的问题)

from copy import deepcopy
from pathlib import Path
from win32com import client as wc  # pip install pypiwin32
from docx import Document  # pip install python-docx
import pandas as pd


# python-docx不能处理doc文档,使用win32com转存为docx文档
def doctransform2docx(doc_path):
    docx_path = doc_path + 'x'
    suffix = doc_path.split('.')[1]
    assert 'doc' in suffix, '传入的不是word文档,请重新输入!'
    if suffix == 'docx':
        return Document(doc_path)
    word = wc.Dispatch('Word.Application')
    doc = word.Documents.Open(doc_path)
    doc.SaveAs2(docx_path, 16)  # docx为16
    doc.Close()
    word.Quit()
    return Document(docx_path)

# 替换docx中的特定字符,由于run方法在有格式的docx文件中展示效果很差,故将docx中的文本的需要填充出英文字符占位
def replace_docx(name, values, wordfile, path_name='Company'):
    wordfile_copy = deepcopy(wordfile)  # 防止原文件被篡改,deepcopy为副本
    for col_name, value in zip(name, values):
        if col_name == 'Company':
            path_name = str(value)
        for paragraphs in wordfile_copy.paragraphs:
            for run in paragraphs.runs:
                run.text = run.text.replace(col_name, str(value))
    # docx文档替换完毕,另存为,一定要用绝对路径
    wordfile_copy.save(f'{save_folder}/{path_name}.docx')

if __name__ == '__main__':
    # 定义需处理的文件路径
    doc_path = r"D:\solve_path\单位.doc"
    excel_path = r"D:\solve_path\信息.xls"
    save_folder = Path('D:/docx_save')
    save_folder.mkdir(parents=True, exist_ok=True)  # 文件夹没有时自动创建
    # 获取excel数据
    data = pd.read_excel(excel_path)
    wordfile = doctransform2docx(doc_path)
    data_save = data.apply(lambda x: replace_docx(x.index, x.values, wordfile), axis=1)