1. 根据模板批量生成文档
想要运用python来编辑word是有些难度的,主要是因为文档涉及到的因素比较多,仅仅是字体就有颜色、大小、加粗等等属性,这也就造成了使用python“无中生有”一个文档的困难性。
这里推荐一个使用模板批量生成文档的包:mailmerge。
1.1 制定模板文件docx
我个人使用的是WPS,office的Word操作大同小异。
首先点击插入,
之后点击文档部件,并选择域,之后在弹出的对话框中选择邮件合并:
在域代码那一栏后面写上变量名,
点击确定后得到:
重复操作得到如下所示结果:
上面的操作可以简单地理解为创建了几个“变量”,“变量”的格式就是之后生成的真实文档的格式,这样也就简化了多属性操作,之后我们就可以在python中通过docx-mailmerge库用实际的值来替换模板中的“变量”而得到真实文档。
(注:文件的扩展名必须是经由WPS/Office生成的.docx)。
1.2 安装包
安装则比较简单:
pip3 install docx-mailmerge
1.3 生成单文档
from mailmerge import MailMerge
def write2docx(datum, template_name, output):
doc = MailMerge(template_name)
doc.merge(**datum)
doc.write(output)
if __name__ == '__main__':
datum = {'teacher_name': '路人甲', 'day': '365', 'name': '路人乙', 'date': '2019-01-01'}
write2docx(datum, 'template.docx', '请假单.docx')
代码比较简单,需要注意的是变量的值必须是字符串,如果是其他的类型的话则可能会报错。上面的代码是根据模板生成的单文档, 如果要生成多个文档的话可以重复调用上面的函数。
1.4 生成一个多文档
mailmerge还可以根据模板生成一个多文档,这里所说的多文档就相当于若干个相同模板生成的单文档的合并,代码也比较简洁:
def write2one_docx(data, template, output, separator='page_break'):
"""
根据data数组生成一个len(data)个的一个总文档
:param data: 数组,键值对用来替换模板
:param template: 模板完整名称
:param output: 输出文件名称
:param separator: 分隔符 默认为换页符
:return:
"""
doc = MailMerge(template)
doc.merge_templates(data, separator=separator)
doc.write(output)
if __name__ == '__main__':
data = [
{'teacher_name': 'sky', 'day': '3', 'name': 'moon', 'date': '2019/11/26'},
{'teacher_name': '周志华', 'day': '3', 'name': 'moon', 'date': '2019/11/26'},
]
write2one_docx(data, 'template.docx', 'two.docx', separator='textWrapping_break')
'page_break'是换页符,'textWrapping_break'是换行符。
导出的文档内容结果如下:
2. 合并多个文档
把多个文件合并成为一个文件的解决办法是:打开一个文件,读取该文件的内容并添加到新文件的末尾。文档的合并也与此类似。
2.1 安装
pip install python-docx
2.2 代码的编写
def combine_word_documents(files, output):
from docx import Document
"""
合并多个文档为一个文档 目前会造成部分格式问题 需要保证输出文件所在的路径存在
:param files: 数组,保存着要合并的文件路径
:param output: 合并文件名称
:return:
"""
merged_document = Document()
for index, file in enumerate(files):
sub_doc = Document(file)
# 在文档和文档之间添加一个换页
if index < len(files) - 1:
sub_doc.add_page_break()
# 添加到总文件里
for element in sub_doc.element.body:
merged_document.element.body.append(element)
merged_document.save(output)
实现起来并不算困难,不过我在合并文档的时候发现某些文字的格式会发生改变。
3. 读取一个xlsx文件
openpyxl可以对xlsx文件进行操作。
3.1 安装
pip install openpyxl
3.2 读取xlsx并生成字典数组
def read_xlsx2dict(filename, sheet=None, callback=None):
"""
读取excel文件,并得到[{}] 以第一行为键,其他行为指
:param filename: 扩展名为xlsx的文件
:param sheet: 要读取的sheet名称
:param callback: callback(key, value)返回值用以代替原来的value
:return: 数组
"""
workbook = load_workbook(filename=filename)
# 获取sheet
sheet_names = workbook.sheetnames
sheet = sheet_names[0] if not sheet else sheet
table = workbook[sheet]
# 把第一行作为键
keys, index = None, 0
# 按照行进行遍历
for row in table.rows:
line = []
is_none = True
# 获取每一个列
for col in row:
line.append(col.value)
is_none = is_none and col.value is None
# 第一列作为键
if index == 0:
keys = [key for key in line if key is not None]
elif not is_none:
datum = {}
for i in range(len(keys)):
if not callback:
datum[keys[i]] = callback(keys[i], line[i])
else:
datum[keys[i]] = line[i]
yield datum
index += 1
默认读取第一个sheet。因为要生成键值对,所以该函数把第一行当作键,其他行则作为值,据此生成一个字典数组。
相关代码:https://github.com/sky94520/tools
word.py和src/template.docx