基于python代码自动生成关于建筑安全检测的报告
一. 所需要的库
Pywin32com 一个拥有微软365办公软件接口的自动生成报告的库,这里不再赘述,直接上完整代码。
二. 代码
前提:配置好虚拟环境并按照好相关的第三方库。
以下代码仅需修改第533行,填入合适的图片地址即可直接运行。
PS:保存生成报告的地址目前是D盘自动新建名为report的文件夹,可修改。
import os
import datetime
import logging# 导入 win32com 相关模块,用于通过 COM 接口操作 Microsoft Word
from win32com.client.gencache import EnsureDispatch
from win32com.client import constants"""
脚本功能:自动生成一份「建筑健康报告」的 Word 文档,包括表格填写、用户输入交互、自动页码、表格样式控制等。主要使用 win32com 操作 Word COM 接口,生成 .docx 文件。
"""# ======================
# 一、基础配置部分
# ======================# 1. 设置报告保存的目标文件夹路径
save_folder = r"D:\report"# 2. 配置日志记录(用于调试和过程追踪)
logging.basicConfig(level=logging.INFO)# 3. 检查保存目录是否存在,不存在则创建
if not os.path.exists(save_folder):os.makedirs(save_folder)logging.debug("创建了保存文件夹")# 4. 获取当前日期,用于报告命名和内容
now = datetime.datetime.now()
current_date = now.strftime("%Y_%m_%d") # 格式如:2024_06_01# ======================
# 二、报告文件命名与序号生成
# ======================# 5. 定义函数:获取下一个可用的报告序号(用于文件名唯一性)
def get_next_sequence_number(folder_path):"""遍历指定文件夹,查找符合命名模式的报告文件,提取其中的序号部分,找出最大序号并返回下一个序号(5位数字,如 00001)。"""max_number = 0# 文件名前缀模式(用于筛选目标报告文件)pattern = f"建筑健康检测报告_"# 遍历文件夹中的所有文件for filename in os.listdir(folder_path):if filename.startswith(pattern) and filename.endswith(".docx"):try:# 提取文件名中序号部分(假设序号位于倒数第5位之前,如 xxxxx.docx -> xxxxx)number_part = filename[-10:-5] # 取倒数第10到第5个字符,如 '00001'current_number = int(number_part)if current_number > max_number:max_number = current_numberexcept ValueError:continue # 若转换失败(非数字),跳过该文件# 下一个序号 = 当前最大序号 + 1,并格式化为 5 位数字字符串(如 00002)next_number = max_number + 1return f"{next_number:05d}"# 调用函数,获取下一个序号
sequence_number = get_next_sequence_number(save_folder)
logging.info(f"检测到最大序号,新文件序号为:{sequence_number}")# 6. 拼接生成最终的报告文件名(含日期与序号)
report_name = f"建筑健康检测报告_{current_date}_{sequence_number}.docx"
full_path = os.path.join(save_folder, report_name) # 完整保存路径# 7. 生成一个报告编号,用于文档内部内容标识
report_id = f"{current_date}_{sequence_number}"# ======================
# 三、启动 Word 应用程序 & 创建文档
# ======================# 8. 启动 Word 应用程序(通过 COM 接口)
word_app = EnsureDispatch("Word.Application")
word_app.Visible = False # 设置为后台运行(不显示 Word 界面)# 9. 创建一个新的 Word 文档
doc = word_app.Documents.Add()# 10. 添加页码到页脚(居中显示)
section = doc.Sections(1)
footer = section.Footers(1) # 主要页脚(通常是第一页)
footer.Range.Fields.Add(footer.Range, 33, "") # 33 = wdFieldPage,插入页码
footer.Range.ParagraphFormat.Alignment = constants.wdAlignParagraphCenter # 居中# ======================
# 四、添加报告标题与报告编号
# ======================# 11. 在文档最开始添加主标题
title_range = doc.Range(0, 0) # 文档起始位置
title_range.Text = "建筑健康检测报告\n"
title_range.Font.Name = "黑体"
title_range.Font.Size = 14
title_range.ParagraphFormat.Alignment = constants.wdAlignParagraphCenter
title_range.Font.Bold = True# 12. 在标题后插入报告编号
id_range = doc.Range()
id_range.InsertAfter(f"报告编号:{report_id}\n")# 13. 设置报告编号的字体格式(中英文字体分别设置)
title_length = len("建筑健康检测报告\n")
id_text_cn_length = len(f"报告编号:")
id_text_en_length = len(f"{report_id}\n")id_cn_start = title_length
id_en_start = title_length + id_text_cn_length
id_en_end = title_length + id_text_cn_length + id_text_en_lengthid_text_cn_range = doc.Range(id_cn_start, id_en_start)
id_text_en_range = doc.Range(id_en_start, id_en_end)id_text_cn_range.Font.Name = "宋体"
id_text_cn_range.Font.Size = 12
id_text_cn_range.Font.Bold = Falseid_text_en_range.Font.Name = "Times New Roman"
id_text_en_range.Font.Size = 12# ======================
# 五、创建并设置主信息表格(12行4列)
# ======================# 14. 定位到文档末尾,准备插入表格
table_range = doc.Range()
table_range.Collapse(constants.wdCollapseEnd)
logging.debug(f"段落目前框选范围起点为{table_range.Start},终点为{table_range.End}")# 创建一个 12 行 4 列的表格
info_table = doc.Tables.Add(table_range, 12, 4)# 设置表格样式为“网格型”
info_table.ApplyStyleDirectFormatting("网格型")# 15. 设置所有行高为固定 34 pt,行高规则为“精确高度”
for row in info_table.Rows:row.Height = 34row.HeightRule = constants.wdRowHeightExactly# 16. 设置第1列和第3列的宽度为 70 pt(约2.5 cm)
first_column = info_table.Columns(1)
first_column.Width = 70
third_column = info_table.Columns(3)
third_column.Width = 70# 17. 设置整个表格宽度撑满页面(100% 宽度)
info_table.PreferredWidthType = constants.wdPreferredWidthPercent
info_table.PreferredWidth = 100# 18. 单独设置第9行高度为 198 pt(约7 cm)
if info_table.Rows.Count >= 9:nine_row = info_table.Rows(9)nine_row.Height = 198nine_row.HeightRule = constants.wdRowHeightExactly# 19. 设置表格所有边框为单实线,线宽 1.0 pt
for border_index in [constants.wdBorderTop,constants.wdBorderBottom,constants.wdBorderLeft,constants.wdBorderRight,constants.wdBorderHorizontal,constants.wdBorderVertical,
]:border = info_table.Borders(border_index)border.LineStyle = constants.wdLineStyleSingleborder.LineWidth = constants.wdLineWidth100pt# ======================
# 六、填充表格内容 & 用户输入交互
# ======================# 20.输入表格文字
# 第一格
cell_range = info_table.Cell(1, 1).Range
cell_range.Text = str("委托单位")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 合并单元格(1,2)到(1,4),通过左上角那个小格子(Cell)去操作这个大格子
start_cell = info_table.Cell(1, 2)
end_cell = info_table.Cell(1, 4)
start_cell.Merge(end_cell) # 合并这两个单元格(实际是合并一个矩形区域:2,2 到 2,4)
# 第二格
# 提示用户输入“委托单位”名称,并等待用户输入
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【委托单位】名称:")
cell_range = info_table.Cell(1, 2).Range
cell_range.Text = str(user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第三格
cell_range = info_table.Cell(2, 1).Range
cell_range.Text = str("地址")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第四格
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【委托单位所在地址】:" )
cell_range = info_table.Cell(2, 2).Range
cell_range.Text = str(user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第五格
cell_range = info_table.Cell(2, 3).Range
cell_range.Text = str("联系方式")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第六格
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【委托单位联系方式】:")
cell_range = info_table.Cell(2, 4).Range
cell_range.Text = str(user_input)
cell_range.Font.Name = "Times New Roman"
cell_range.Font.Size = 12# 第七格
cell_range = info_table.Cell(3, 1).Range
cell_range.Text = str("工程名称")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第八格
start_cell = info_table.Cell(3, 2)
end_cell = info_table.Cell(3, 4)
start_cell.Merge(end_cell)
arch_name_input = input("(!!! 务必输入检测建筑名称,用于后续内容描述)\n""其输入检测建筑名称:")
eight_input = f"{arch_name_input}建筑健康检测工程"
cell_range = info_table.Cell(3, 2).Range
cell_range.Text = str(eight_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第九格
cell_range = info_table.Cell(4, 1).Range
cell_range.Text = str("工程地点")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第十格
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【工程检测地点位置】:")
cell_range = info_table.Cell(4, 2).Range
cell_range.Text = str(user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第十一格
cell_range = info_table.Cell(4, 3).Range
cell_range.Text = str("工程编号")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第十二格
current_year = now.strftime("%Y")
cell_range = info_table.Cell(4, 4).Range
cell_range.Text = str(f"ARCH_{current_year}_{sequence_number}")
cell_range.Font.Name = "Times New Roman"
cell_range.Font.Size = 10
cell_range.Font.Bold = True# 第十三格
cell_range = info_table.Cell(5, 1).Range
cell_range.Text = str("检测项目")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12
cell_range.Font.Bold = False# 第十四格
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【检测项目】:")
cell_range = info_table.Cell(5, 2).Range
cell_range.Text = str(user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第十五格
cell_range = info_table.Cell(5, 3).Range
cell_range.Text = str("检测日期")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第十六格
cell_range = info_table.Cell(5, 4).Range
user_input = input("其输入检测日期,如不输入直接回车,则默认使用今天当天日期\n""请输入:")
if len(user_input) > 3:cell_range.Text = str(user_input)
else:cell_range.Text = str(f"{current_date}")
cell_range.Font.Name = "Times New Roman"
cell_range.Font.Size = 12# 第十七格
cell_range = info_table.Cell(6, 1).Range
cell_range.Text = str("检测仪器")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第十八格
start_cell = info_table.Cell(6, 2)
end_cell = info_table.Cell(6, 4)
start_cell.Merge(end_cell)
cell_range = info_table.Cell(6, 2).Range
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【检测仪器】:")
cell_range.Text = str(user_input)
cell_range.Font.Name = "Times New Roman"
cell_range.Font.Size = 12# 第十九格
cell_range = info_table.Cell(7, 1).Range
cell_range.Text = str("检测依据")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十格
start_cell = info_table.Cell(7, 2)
end_cell = info_table.Cell(7, 4)
start_cell.Merge(end_cell)
cell_range = info_table.Cell(7, 2).Range
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【检测依据】:")
cell_range.Text = str(user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十一格
start_cell = info_table.Cell(8, 1)
end_cell = info_table.Cell(8, 4)
start_cell.Merge(end_cell)
cell_range = info_table.Cell(8, 1).Range
cell_range.Text = str("检测结论")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十二格
start_cell = info_table.Cell(9, 1)
end_cell = info_table.Cell(9, 4)
start_cell.Merge(end_cell)
cell_range = info_table.Cell(9, 1).Range
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【检测结论】:")
cell_range.Text = str(user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十三格
cell_range = info_table.Cell(10, 1).Range
cell_range.Text = str("检测单位")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十四格
cell_range = info_table.Cell(10, 2).Range
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【检测单位】:")
cell_range.Text = str(user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十五格
cell_range = info_table.Cell(10, 3).Range
cell_range.Text = str("审核")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十七格
cell_range = info_table.Cell(11, 1).Range
cell_range.Text = str("检测员")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第二十九格
cell_range = info_table.Cell(11, 3).Range
cell_range.Text = str("批准")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第三十一格
cell_range = info_table.Cell(12, 1).Range
# 攥写报告的人:编制
cell_range.Text = str("编制")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第三十三格
cell_range = info_table.Cell(12, 3).Range
cell_range.Text = str(f"报告日期")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12# 第三十四格
cell_range = info_table.Cell(12, 4).Range
cell_range.Text = str(f"{current_date}")
cell_range.Font.Name = "Times New Roman"
cell_range.Font.Size = 12# ======================
# 七、生成第二张表格(六行一列,用于检测概况总结)
# ======================# 21. 换页:在当前文档末尾插入分页符
selection = word_app.Selection
selection.EndKey(Unit=6) # Unit=6 代表文档结尾(wdStory)
selection.TypeParagraph()
current_para = selection.Paragraphs(1)
current_para.Range.ParagraphFormat.PageBreakBefore = True# 22. 创建第二张表格(6行1列),用于检测概况描述
table_range_2 = doc.Range()
table_range_2.Collapse(constants.wdCollapseEnd)
logging.debug(f"换页之后,段落目前框选范围起点为{table_range_2.Start},终点为{table_range_2.End}")info_table_2 = doc.Tables.Add(table_range_2, 6, 1)# 23. 设置第二张表格样式与边框
info_table_2.ApplyStyleDirectFormatting("网格型")
for border_index in [constants.wdBorderTop,constants.wdBorderBottom,constants.wdBorderLeft,constants.wdBorderRight,constants.wdBorderHorizontal,constants.wdBorderVertical,
]:border = info_table_2.Borders(border_index)border.LineStyle = constants.wdLineStyleSingleborder.LineWidth = constants.wdLineWidth100pt# 24. 设置每行高度 & 取消“段前分页”
for row_idx in range(1, info_table_2.Rows.Count + 1):row = info_table_2.Rows(row_idx)row.Height = 109cell = row.Cells(1)para = cell.Range.Paragraphs(1)para.Range.ParagraphFormat.PageBreakBefore = False# 25. 设置文档末尾不分页
selection.EndKey(Unit=6)
current_para = selection.Paragraphs(1)
current_para.Range.ParagraphFormat.PageBreakBefore = False# 26. 填充第二张表格内容
# 第一格
cell_range = info_table_2.Cell(1, 1).Range
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【工程概况】:")
cell_range.Text = str("一、工程概况\n" + user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12
row = info_table_2.Rows(1)
row.Height = 109
cell_range.ParagraphFormat.Alignment = constants.wdAlignParagraphJustifyLow # 两端对齐# 第二格:
cell_range = info_table_2.Cell(2, 1).Range
temperature_input = input("(请输入检测环境相关信息)(单位 °)请输入气温,无需输入单位:")
humidity_input = input("(请输入检测环境相关信息)(单位 %)请输入相对湿度,无需输入单位:")
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【其它检测环境】:")
cell_range.Text = str(f"二、检测环境\n气温 {temperature_input}℃、相对湿度 {humidity_input}%" + user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12
row = info_table_2.Rows(2)
row.Height = 59
cell_range.ParagraphFormat.Alignment = constants.wdAlignParagraphJustifyLow # 两端对齐# 第三格
cell_range = info_table_2.Cell(3, 1).Range
user_input = input("(若直接回车默认无辅助措施) 请描述检测辅助措施:")
if user_input:cell_range.Text = str(f"三、检测辅助措施\n{user_input}")
else:cell_range.Text = str(f"三、检测辅助措施\n无")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12
row = info_table_2.Rows(3)
row.Height = 59
cell_range.ParagraphFormat.Alignment = constants.wdAlignParagraphJustifyLow # 两端对齐# 第四格
cell_range = info_table_2.Cell(4, 1).Range
user_input = input("(若直接回车默认为建筑东南西北四个外立面) 请描述检测具体部位 (例如某某建筑屋顶):")
if user_input:cell_range.Text = str(f"四、检测具体部位\n{user_input}")
else:cell_range.Text = str(f"四、检测具体部位\n{arch_name_input}东西南北四个立面墙壁 ")
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12
row = info_table_2.Rows(4)
row.Height = 59
cell_range.ParagraphFormat.Alignment = constants.wdAlignParagraphJustifyLow # 两端对齐# 第五格
cell_range = info_table_2.Cell(5, 1).Range
# 先清除单元格原有内容
# PS:这里是实现在表格单元先插入文字,再插入图片的重要步骤,没有会插入到错误位置
cell_range.Delete()
# 设置文字内容
cell_range.Text = "五、检测部分示例"
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12
# 设置行高和对齐
row = info_table_2.Rows(5)
row.Height = 259
cell_range.ParagraphFormat.Alignment = constants.wdAlignParagraphJustifyLow
# 在文字后插入段落标记(换行)
cell_range.Collapse(constants.wdCollapseEnd) # 折叠到文字末尾
cell_range.InsertParagraphAfter() # 插入段落标记
# 移动到新段落开始位置
cell_range.Collapse(constants.wdCollapseEnd) # 折叠到新段落开头
# 在新段落中插入图片
img = cell_range.InlineShapes.AddPicture(r"注意:这里需要修改为合适的图片地址")
# 设置图片大小
if img:# 方法1:直接设置高宽(推荐)img.Height = 200 # 根据实际需要调整img.Width = 200# 方法2:或者使用缩放比例# img.ScaleHeight = 50# img.ScaleWidth = 50# 第六格
cell_range = info_table_2.Cell(6, 1).Range
user_input = input("(注:可直接回车得到空白表格,打印后可手写)\n""请输入【结论】:")
cell_range.Text = str("六、结论\n" + user_input)
cell_range.Font.Name = "宋体"
cell_range.Font.Size = 12
row = info_table_2.Rows(6)
row.Height = 109
cell_range.ParagraphFormat.Alignment = constants.wdAlignParagraphJustifyLow # 两端对齐# ======================
# 八、保存 & 关闭文档
# ======================# 27. 保存文档到指定路径
doc.SaveAs(full_path)# 28. 关闭文档和 Word 应用程序
doc.Close()
word_app.Quit()# 29. 输出保存成功日志
logging.info(f"报告已保存至:{full_path}")
logging.info("检测报告已创建完成")