序言
各位好!,又到Python办公系统系列产品。
今日大家再次共享一个真正的办公系统需求:如何使Python Excel Word大批量转化成特定文件格式內容的合同书。
关键涉及到的知识要点有:openpyxl控制模块的综合性应用与Word文本文档的二种解析xml逻辑性。
需求叙述
你是承包方建筑工程公司,手里有一份空缺合同书模板的Word文档,如下图:
此外也有一份Excel合同书信息表,在其中是全部招标方(发包方)在合同书中必须填好的內容
由此可见一个人行为一个企业的所有信息,如今必须把Excel中每一个企业的信息填写空缺Word合同书模板中,转化成各企业的合同书,最后結果以下
流程剖析
本来大家必须将Excel明细表中每一行的信息填入word模板中,转化成相对应的合同书。
如今大家必须交到Python来完成,就引出来了一个难题:程序流程如何知道要将某一信息填到哪一个下横线?为了更好地处理这个问题,大家必须对模板开展改动。
将要下横线改成某类标志,让程序流程能够见到标志就搞清楚这里应当放什么信息,这儿采用的对策是:将必须填好的下横线改成明细表中的列名,即下面的图所显示
那样程序流程就可以鉴别必须填好哪些內容了。说白了的鉴别在这儿能够换一个尤其简易的词,即文本替换。只需查找到#xxxx#(excel中的列名),把这个换成实际的信息就可以了。
出自于这类对策,列名就必须用#xxxx#的文件格式,不然一切正常的不相干文字中的信息也会被更换,就毁坏了原来的需求,最终模板被修改成以下:
根据Excel表我们可以见到,一个人行为一个企业的信息,而每一列的列名就存有于模板中,用每个企业的具体信息更换到模板中的列名(程序流程鉴别和文本替换的根据)
用那样的方式 就可以进行这一需求。全部大需求的完成能够依照下边的流程:
剖析后的流程:将 空缺合同书 调节成 合同书模板,必须填好的下横线改成专享的列名开启Excel表,按行循环系统,随后按表格中逐一循环系统每个信息,每一个信息都寻找模板中存有的相匹配列名并将其更换(假如不理解下面也有表述)每一次循环系统完一行的所有表格中后储存合同书,存活每个企业独立的合同书
剖析清晰后逻辑性就比较简单了,但有一个暗含的知识要点沒有提及,使我们边敲代码边说!
编码完成
最先导进控制模块,设定途径,创建文件夹名称,本例中涉及到Excel表的开启和Word的建立,因而必须从openpyxl导进load_workbook,而Word不管开启或是建立,用docx控制模块的Document均可
from docx import Documentfrom openpyxl import load_workbook# 运用os模块创建文件夹名称,用以储放转化成的合同书import os # 给出合同书模板和明细表所属的文件夹名称途径,便捷多路复用path = r'C:\Users\chenx\Desktop\合同书' # 融合途径分辨转化成文件夹名称,避开程序流程出错而停止的风险性if not os.path.exists(path '/' '所有合同书'):os.mkdir(path '/' '所有合同书')
然后开启Excel文档
workbook = load_workbook(path '/' '合同书信息表.xlsx')sheet = workbook.active
如今解析xmlExcel,转化成合同书。前边也不断提及,Excel的每一行是一份特殊合同书的信息,因而docx对于Word文档的实例化和储存一定是在循环体里的,而并不像Excel的实例化是在循环体外边
# 合理信息行是以第二行逐渐的,第二行是表头,包括列名,也是文本替换的根据for table_row in range(2, sheet.max_row 1):# 每循环系统一行实例化一个新的word文档wordfile = Document(path '/' '合同书模板.docx')# 表格中必须逐一解析xml,每一个都包括着有效的信息for table_col in range(1, sheet.max_column 1):# 旧的文字也就是列名,早已在模板里填完了,用以文本替换,将row限制在第一行后便是列名old_text = str(sheet.cell(row=1, column=table_col).value)# 新的文字便是具体的信息,table_col循环系统到某一标值时,具体的表格中和列名就明确了new_text = str(sheet.cell(row=table_row, column=table_col).value)# 再加上这一分辨是由于日期信息读进程序流程是“日期 時间”文件格式的,假如要保存日期信息可以用字符串数组方式 或是用time/datetime控制模块解决if ' ' in new_text:new_text = new_text.split[0]
根据下面的图进一步了解这一更换:
比如程序流程早已进到第三个循环系统(循环系统到第三个企业),对于表格中的循环系统进到第4个循环系统,那麼这时获得的具体值是基本建设C生态公园,相匹配的列名是#工程项目內容#。
这时就确立了必须被更换的內容了,只需在模板中寻找#工程项目內容#把它更换为基本建设C生态公园就可以!了解了这一更换后,下一步便是解析xmlWord模板,寻找相匹配列名更换!
以前大家说过docx控制模块,Word文字存有文本文档Document-文章段落Paragraph-文本块Run的三级构造,必须解析xml文字可以用下列编码:
all_paragraphs = wordfile.paragraphsfor paragraph in all_paragraphs:print(paragraph.text)for run in paragraph.runs:print(run.text)
对于文章段落和文本块均可以用.text获得到文本信息。本需求暗含的圈套就在这里,留意一下合同书最终必须填好的內容:
这一部分內容假如用以上编码是解析xml不上的。为何?由于它是Word文本文档中的报表!
解析xml报表必须有专业的解析xml逻辑性:文本文档Document-报表Table-行Row/列Column-表格中Cell,解析xml报表中文字的编码以下:
all_tables = wordfile.tablesfor table in all_tables:# 也可按列解析xmlfor row in table.rows:for cell in row.cells:print(cell.text)
拥有这种填补的专业知识以后,本实例中最关键的编码就可以那么写
for table_row in range(2, sheet.max_row 1):wordfile = Document(path '/' '合同书模板.docx')for table_col in range(1, sheet.max_column 1):old_text = str(sheet.cell(row=1, column=table_col).value)new_text = str(sheet.cell(row=table_row, column=table_col).value)if ' ' in new_text:new_text = new_text.split[0] # 文本文档Document - 文章段落Paragraph - 文本块Runall_paragraphs = wordfile.paragraphsfor paragraph in all_paragraphs:for run in paragraph.runs:run.text = run.text.replace(old_text, new_text) # 文本文档Document - 报表Table - 行Row/列Column - 表格中Cellall_tables = wordfile.tablesfor table in all_tables:for row in table.rows:for cell in row.cells:cell.text = cell.text.replace(old_text, new_text) # 获得企业名字用于转化成合同书的名字company = str(sheet.cell(row=table_row, column=1).value)wordfile.save(path '/' f'所有合同书/{company}合同书.docx') 写在最终
此次的实例具备极强的应用性,而且需求能够拓宽变成:将一份信息明细表Excel中的每一个独立信息(每一行或是每一列入本人、企业或是别的的信息)填好到特定的模板Eord中,转化成独立的文本文档,但是在写自动化技术脚本制作以前还要先分拆每日任务,确立构思再开展!
文章转载自网络,如有侵权,请联系api@1dq.com删除