1,需求
- 客户要求每周出项目运行报告,统计某些重要用户操作情况。给定了一个word模板,现在需要通过查询数据库把相关数据填充替换,实现自动化任务处理。
- 数据标识字段说明:文档统计时间范围,YEAR、MONTH、DAY1、DAY2;
- 数据标识字段说明2:SQL查询统计后的用户数量{{USER_COUNT}}、所有用户操作总数量{{USER_LOG_COUNT}}、各模块操作次数统计{{USER_LOG_DETAIL_TABLE}}

2,代码实现
from docx import Document
from docx.shared import Inches, Pt
from datetime import datetime, timedelta, time
import pandas as pd
df = pd.DataFrame({
'Col1': range(1, 6),
'Col2': ['A', 'B', 'C', 'D', 'E'],
'Col3': [10, 20, 30, 40, 50],
**{f'Col{i}': [i] * 5 for i in range(4, 16)}
})
doc = Document("1.docx")
today = datetime.now().date()
seven_days_ago_date = today - timedelta(days=7)
one_day_ago_date = today - timedelta(days=1)
seven_days_ago_start = datetime.combine(seven_days_ago_date, time.min)
one_day_ago_end = datetime.combine(one_day_ago_date, time.max)
replacements = {
"YEAR": seven_days_ago_start.year,
"MONTH": seven_days_ago_start.month,
"DAY1": seven_days_ago_start.day,
"DAY2": one_day_ago_end.day ,
"{{USER_COUNT}}": "27",
"{{USER_LOG_COUNT}}": "6789",
}
TABLE_FLAG="{{USER_LOG_DETAIL_TABLE}}"
for paragraph in doc.paragraphs:
for key, value in replacements.items():
if key in paragraph.text:
inline = paragraph.runs
for run in inline:
run.text = run.text.replace(key, str(value))
def insert_table_after( doc, TABLE_FLAG , df_final):
"""
将表格插入到指定段落之后。
"""
for paragraph in doc.paragraphs:
if paragraph.text.strip() == TABLE_FLAG:
df_final = df_final.reset_index()
df_final.insert(0, '序号', df_final['index'] + 1)
df_final = df_final.drop(columns=['index'])
rows = len(df_final) + 1
cols = len(df_final.columns)
table = doc.add_table(rows=rows, cols=cols)
table.style = 'Table Grid'
header_cells = table.rows[0].cells
for i, col_name in enumerate(df_final.columns):
header_cells[i].text = str(col_name)
for i, row in df_final.iterrows():
row_cells = table.rows[i + 1 ].cells
for j, val in enumerate(row):
row_cells[j].text = str(val)
tbl, p = table._tbl, paragraph._element
p.addnext(tbl)
p = paragraph._element
p.getparent().remove(p)
table.autofit = True
default_style = doc.styles['Normal']
for row in table.rows:
for cell in row.cells:
for paragraph in cell.paragraphs:
paragraph.style = default_style
paragraph.style.font.size = Pt(11)
paragraph.alignment = 1
paragraph.paragraph_format.word_wrap = True
break
insert_table_after( doc, TABLE_FLAG, df )
doc.save("11.docx")
3,验证结果
