用python将word文档合并实例代码
作者:task138 发布时间:2021-08-13 06:17:01
背景:
由于工作需要,现在有这么一个需求,要合并大量的word文档,而且要在不同的目录下找到同一个人的word文档,进行合并,最终输出一个合并后的word文档。一般来说几个或者十几个量不多的话,就手工合并一下好了,但现在这个量是真的大。目录有十多个,每个目录又有50多个不同人的word文档,而且同一个人在不同目录下又不一定都有word文档,因此,整个合并工作就出现了人工操作的困难:
工作量多;容易疏漏犯错。
为此,利用python进行高效准确的执行这类工作,尤为凸显现代自动化办公的能力。因此,我写了这个python脚本,作为一个小工具来辅助我的工作需求。
设计思路:
首先,整个脚本实现两个功能:
查看各目录下未提交word文档的名单合并各目录下的word文档查看各目录未提交名单:
对于这个需求,首先是读一个写有所有人姓名等信息的Excel文件,有格式要求。然后通过遍历Excel的信息,获取到所有人的姓名。遍历各目录下,是否有对应姓名的文件存在,如果没有,则输出没有提交文件的姓名。
合并word文件:
合并word文件和上一个需求有类似的地方。首先我们都需要读Excel文件,得到姓名信息,然后在各目录下获取到这个人所提交的所有word文件的文件路径,然后通过合并word的操作实现文件合并,合并后最终输出到指定的目录下。
脚本环境说明:
脚本对第三方包有依赖,执行前必须先安装对应的第三方包
pip install python-docx pywin32 xlrd
首先,目录结构必须是如下图所示,所有需要遍历的目录名称都必须是【实训+数字】,因为脚本中涉及多处正则匹配。
其次,Excel文件必须遵循下图所示的格式,首行是标题行,遍历的时候会自动跳过,遍历时会遍历C列和D列,其中C列是人员编号,D列是人员姓名
接着,python脚本必须要根目录下
最后,执行脚本的时候,必须带有传参,传递的参数就是那个Excel表
Microsoft Windows [版本 10.0.19043.1415]
(c) Microsoft Corporation。保留所有权利。
C:\Windows\system32>python tools.py 花名册.xlsx
完整代码:
#! /usr/bin env python
# -*- coding:utf-8 -*-
"""
============================
======Power By Python3======
====== Author Task138 ======
============================
"""
import sys
import xlrd, os, re
from docx import Document
from docxcompose.composer import Composer
from win32com import client as wc
# 读Excel表获取学生的学号和姓名
def read_excel(excel_file):
workbook = xlrd.open_workbook(excel_file)
sheet = workbook.sheet_by_index(0)
name_list = []
name_dict = []
Sno_list = sheet.col_values(2)[1::]
Sname_list = sheet.col_values(3)[1::]
for i in range(len(Sno_list)):
try:
Sno = str(int(Sno_list[i]))
except:
Sno = Sno_list[i]
dict = {}
dict['Sno'] = Sno
dict['Sname'] = Sname_list[i]
name_list.append(Sname_list[i])
name_dict.append(dict)
return name_list, name_dict
# 合并文档
def merge_doc(source_file_path_list,target_file_path):
#填充分页符号文档
page_break_doc = Document()
page_break_doc.add_page_break()
#定义新文档
target_doc = Document(source_file_path_list[0])
target_composer = Composer(target_doc)
for i in range(len(source_file_path_list)):
#跳过第一个作为模板的文件
if i==0:
continue
#填充分页符文档
target_composer.append(page_break_doc)
#拼接文档内容
f = source_file_path_list[i]
target_composer.append(Document(f))
#保存目标文档
target_composer.save(target_file_path)
print('[ %s ]保存成功' % target_file_path)
if __name__ == '__main__':
if len(sys.argv) < 2:
print('缺乏必要的参数,请输入学生Excel表作为参数')
print('程序终止')
exit()
excel_file = sys.argv[1]
print('请选择需要执行的功能:')
print('[ 0 ] 查看各实训目录下未提交的学生名单')
print('[ 1 ] 合并实训文件')
cmd = input('请选择: ')
while cmd not in ['0','1']:
print('输入有误,请重新输入,按 Ctrl+C 可退出程序')
print('请选择需要执行的功能:')
print('[ 0 ] 查看各实训目录下未提交的学生名单')
print('[ 1 ] 合并实训文件')
cmd = input('请选择: ')
try:
name_list, name_dict = read_excel(excel_file)
except Exception as e:
print('Excel读取失败,程序终止,错误如下:')
print(e)
print()
exit()
else:
if cmd == '0':
# 实训目录的数列
file_list = []
for i in os.listdir():
if os.path.isdir(i):
if re.match(r'实训\d', i):
file_list.append(i)
for i in range(1, len(file_list) + 1):
dir_name = '实训%s' % i
# 进入该实训目录
os.chdir(dir_name)
file_list = os.listdir()
submit_list = []
for x in file_list:
for j in name_list:
if j in x and j not in submit_list:
submit_list.append(j)
result = list(set(submit_list) ^ set(name_list))
if result:
print(dir_name, result)
os.chdir('../')
if cmd == '1':
if not os.path.exists('实训汇总'):
os.mkdir('实训汇总')
print('目录[ 实训汇总 ]创建成功')
# 实训目录的数列
file_list = []
for i in os.listdir():
if os.path.isdir(i):
if re.match(r'实训\d',i):
file_list.append(i)
for i in name_dict:
doc_list = []
for j in range(1,len(file_list)+1):
dir_name = '实训%s' % j
# 进入该实训目录
os.chdir(dir_name)
tmp = []
for x in os.listdir():
# 判断文件尾缀
fname,fext = os.path.splitext(x)
# 如果是.doc,则转换为.docx
if fext == '.doc' and not x.startswith('~$'):
w = wc.Dispatch('Word.Application')
doc = w.Documents.Open(os.path.abspath(x))
doc.SaveAs(os.path.join(os.getcwd(),'%s.docx' % fname), 16)
doc.Close()
os.remove(x)
print('转换文件[ %s ]类型为.docx' % x)
elif fext == '.docx':
if (i['Sname'] in x) and (len(tmp) == 0):
# 只有一个文件
tmp.append(x)
elif (i['Sname'] in x) and (len(tmp) != 0):
# 有多个文件,按照最新的修改时间进行替换
tmp_file = tmp.pop()
old_file_mtime = os.path.getmtime(tmp_file)
new_file_mtime = os.path.getmtime(x)
if new_file_mtime > old_file_mtime:
# 新文件比较新,以新的为准
tmp.append(x)
else:
# 老文件比较新,以老文件为准
tmp.append(tmp_file)
else:
# 其它文件类型,直接跳过
# print('当前文件[ %s ]类型不是.doc或者.docx,跳过此文件的合并' % os.path.abspath(x))
continue
if tmp:
# 如果这次实训有这位同学的文件
doc_list.append(os.path.join(dir_name,tmp.pop()))
# 返回父目录
os.chdir('../')
if doc_list:
# 有内容,进行文档合并
try:
merge_file_name = i['Sno'] + '-' + i['Sname'] + '-' + '实训汇总' + '.docx'
merge_doc(doc_list, './实训汇总/' + merge_file_name)
except Exception as e:
print()
print('[ %s ]学生信息有误,程序中断' % i['Sname'])
print(e)
print()
功能执行效果图:
总结:
通过python,我们可以很便捷的满足我们的需求,鉴于这个需求似乎是长期性的,所以还是有必要写个小工具来优化一下自己的办公方式,提高自己的业务能力。
来源:https://blog.csdn.net/cbcrzcbc/article/details/122052694
猜你喜欢
- django静态文件配置原理静态文件配置就是为了让用户请求时django服务器能找到静态文件返回。首先要理解几个概念:媒体文件:用户上传的文
- 本文实例为大家分享了python将两张图片生成全景图片的具体代码,供大家参考,具体内容如下1、全景图片的介绍全景图通过广角的表现手段以及绘画
- 当代码已经写得差不多,发现某个变量名需要修改,但代码中很多地方都有该变量,一一修改太麻烦了,在不同的情景下,可以采取更加简便的方法,如下介绍
- 1. 数据处理中很恶心,出现 RuntimeWarning: divide by zero encountered in divide发现自
- 2009年2月24日,Safari 4.0 beta版正式发布,Safari从它的3.2版本开始就已经支持所有的CSS选择器(包括最新的CS
- 1、灵活运用样式 熟悉网页设计的网友就知道,调用Style的方法很多,我们可以单击鼠标右键选择Custon Style来调用Style标准,
- 這兩天﹐對xml作為數據庫產生了興趣﹐找了一些資料﹐也搞出了一點眉目﹐在這里記錄一下。算是對自己學習x
- 出自: 编程中国 http://www.bc-cn.net作者: 天涯听雨 &nbs
- 介绍psutil能够轻松实现获取系统运行的进程和系统利用率。导入模块import psutils获取系统性能信息CPU信息使用cpu_tim
- 在pycharm使用过程中,对于每次新建的python文件的时候,关于代码编写者的一些个人信息快捷填写,使用模板的方式比较方便。方法如下:1
- '****'函数名称: strReplace(Str)'函数功能: 过滤单引号'参数说明: Str 
- 本文主要是介绍Go,从语言对比分析的角度切入。之所以选择与Python、Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性,
- 本文实例为大家分享了Python求多幅图像栅格值的平均值,供大家参考,具体内容如下本程序所采用的方法并不是最优方法,ARCGIS已经提供了相
- 阅读上一篇:打造设计你自己的字体 Ⅱ永远都在寻觅字体设计的灵感。夏天过后,我买了一套便宜的书法钢笔,说服自己,它会让我的鸡爬字产生脱胎换骨的
- 译序:本文译自Smashingmagazine,但是原文讲述的内容有些浅,也不是很完整,前端观察在翻译的前提下,增加了更多的更系统的内容。如
- 什么是LSTM1、LSTM的结构我们可以看出,在n时刻,LSTM的输入有三个:当前时刻网络的输入值Xt;上一时刻LSTM的输出值ht-1;上
- 试一试这个办法:struserlist = struserlist & "<
- 不论是企业网站、个人博客,或者购物网站、游戏网站,我们都希望能吸引访问者并且给他们留下愉快的访问体验。可用性是用户体验的一种度量,它可以用访
- 缓存是基于Application实现的CacheState类,建议实例化时用名Cache程序代码<% Class Cache
- 1.使用 for key in dict遍历字典可以使用for key in dict遍历字典中所有的键x = {'a':