0
点赞
收藏
分享

微信扫一扫

python应用之Word生成


1. 介绍

最近一个做文职的朋友提出了一个想法, 希望实现自动修改他的一个Word内容. 因为正常情况下一个工程其实只需要修改Word里面的日期, 名称, 和一些参数, 所以希望我能为他写个脚本, 完成Word的自动填充并生成新的Word.

1.1 需求

  • 指定位置关键词填充: 比如XXXXX村饮水安全巩固提升工程
  • 时间填充: 已知A时间, B时间=A时间+days

1.2 对应解决方案

  1. 编写Word模板, 里面标记需要填充的关键字
  2. 指定Excel表格填写关键字和对应的值
  3. 读取Word模板待填充关键字, 匹配Excel表格中的关键字对应的值
  4. 根据关键字格式如
  1. date_1-4 在date_1的基础上+4天
  2. random_1_4(1,5) 生成4个范围是1,5的随机数
  1. 写入到新的Word

2. 实现

2.1 环境

python3.8
pip install docx-mailmerge==0.5.0 # 用于对Word里面设置的域(关键字)进行解析和填充
pip install python-docx==0.8.11 # 用于读取Word的段落, 表格进行解析和增删改查
pip install pandas==1.4.2 # 用于读取Excel表格数据

2.2 创建Word模板, 增加域定位关键字

python应用之Word生成_word

2.3 编写对应的Excel

python应用之Word生成_随机数_02

2.4 文件存储路径

.
├── main.py # 主函数
├── readme.md
├── req.txt # 环境包request
├── result
│ └── t.docx # 生成的文件
├── sources
│ ├── doc1.docx # Word模板
│ └── input.csv # 定义的key-value
$ python main.py # 运行

2.5 main.py代码

python应用之Word生成_数据_03

'''
1. 初始化对象
2. 获取模本对象 <- template_file_path
3. 读取输入csv文件<- input_csv_path
4. 写数据到对象
1. 模板对象中key, 直接填csv中对应的key数据
2. 模板对象中的date, 根据csv中的数据填充, 并依次生成date_n_long的数据进行填充
3. 模板对象中的random, 根据key中的(a,b), 生成对应的随机数, 进行填充
5. 对象保存 <- save_path
'''

import pandas as pd # pandas==1.4.2
from mailmerge import MailMerge # docx-mailmerge==0.5.0
import random
import re
from datetime import datetime
from dateutil.relativedelta import relativedelta


class WriteDocx():
def __init__(self,format_date='%Y.%m.%d'):
super().__init__()
self.doc = None
self.doc_key = None
self.dict_csv = {}
self.format_date = format_date

def createTemplateDoc(self, template_file_path = "sources/doc1.docx"):
self.doc = MailMerge(template_file_path)
self.doc_key = self.doc.get_merge_fields()
print("模板里面的关键字包含如下: ", self.doc_key)
print("模板对象创建完毕, 开始向对象填充数据...")

def getInputData(self, input_csv_path = "sources/input.csv"):
csv = pd.read_csv("sources/input.csv")
print(csv.head(2))
for i in range(len(csv["key"].values)):
self.dict_csv[csv.loc[i]["key"]] = csv.loc[i]["value"]
print(self.dict_csv)

# 解析生成随机数的方案
def getRandom(self, data = "random_2_6(1,3)")->list:
random_order = [eval(_) for _ in list(re.findall(r"(.*)\((.*),(.*)\)", data.split("_")[-1])[0])]
res_list = ["%0.2f"%random.uniform(random_order[1], random_order[2]) for i in range(random_order[0])]
return "[%s]"%",".join(res_list)

def getDate(self, date="2017.10.23", data = 'date_2-6'):
add_day = int(data.split("-")[-1]) # 增加的天数
time_1 = datetime.strptime(date, "%Y.%m.%d") + relativedelta(days=add_day)
return datetime.strftime(time_1, '%Y.%m.%d') # 这里是最终的格式

# 格式化日期格式
def format_date_(self, date):
time_1 = datetime.strptime(date, "%Y.%m.%d")
return datetime.strftime(time_1, self.format_date) # 这里是最终的格式

def writeDoc(self, ):
# 生成doc_key中random和date的数据
# 对于random生成对应的数据, 对于date生成对应的延时
for _ in self.doc_key:
if "random" in _:
self.dict_csv[_] = self.getRandom(_) # random_2_2(0,3) --> [1.2, 0.5]
if "date" in _ and len(_.split("-"))==2: # '2017.10.23', 'date_2-6' --> 2017.10.29
self.dict_csv[_] = self.getDate(self.dict_csv[_.split("-")[0]], _)
if "date" in _: # 统一格式化日期格式 2017.10.23->
self.dict_csv[_] = self.format_date_(self.dict_csv[_])

print("要填充的数据是: ", self.dict_csv)
print(type(self.dict_csv))
self.doc.merge(** self.dict_csv) #生成一份Word文档


def save(self, save_path = "result/t.docx"):
self.doc.write(save_path)
print("新文件已经成功保存到: ", save_path)


# 只需要修改这里的位置即可
def main():
object = WriteDocx(format_date='%Y年%m月%d日')
object.createTemplateDoc("sources/doc1.docx")
object.getInputData("sources/input.csv")
object.writeDoc()
object.save("result/t.docx")

if __name__=='__main__':
main()

3. 思考

通过这次练习, 让我发现文职人员能够改进很多工作流程. 就拿我们每次转团关系的介绍信, 都是发下来自己手写里面的内容, 比如姓名等个人信息, 团关系从哪个位置转到哪个位置, 在交上去盖章. 如果根据本文的工作流程, 只需要统计每个人的上述信息保存到Excel的每一列, 做一个Word模板, 就可以一次性按列生成所有人对应的转团关系介绍信, 打印盖章即可, 完全不必要自己手写, 流水线操作总是比分开单干更加便捷顺利. 最后2202年了, 希望文职工作的同志都能拥有编程思想, 也许无法实现, 但是咱可以找编程朋友改善工作流程, 提高工作效率, 提高幸福指数!!!

未完待续

  1. 利用python-docx处理段落和表格 (其实这块跟前端HTML很像, 一块一块拼凑, 也跟爬虫很像, 一个关键字关键字的解析)


举报

相关推荐

0 条评论