我将为您介绍如何使用Python的openpyxl和python-docx模块结合Excel和Word模板进行数据写入。以下是几个具体案例:
案例1:从Excel读取数据并填充到Word模板
1.1 准备工作
首先安装所需模块:
bash
pip install openpyxl python-docx
1.2 Excel数据文件 (data.xlsx)
| 姓名 | 年龄 | 职位 | 部门 | 入职日期 |
|---|---|---|---|---|
| 张三 | 28 | 工程师 | 技术部 | 2020-01-15 |
| 李四 | 32 | 经理 | 市场部 | 2018-05-20 |
1.3 Word模板文件 (template.docx)
在Word中创建包含占位符的模板:
员工信息报告
姓名:{姓名}
年龄:{年龄}
职位:{职位}
部门:{部门}
入职日期:{入职日期}
报告生成时间:{报告时间}
1.4 Python代码实现
python
from openpyxl import load_workbook
from docx import Document
from datetime import datetime
def fill_word_from_excel(excel_file, word_template, output_dir):
# 加载Excel文件
wb = load_workbook(excel_file)
ws = wb.active
# 获取表头
headers = [cell.value for cell in ws[1]]
# 遍历每一行数据(从第二行开始)
for row in range(2, ws.max_row + 1):
# 读取行数据
row_data = {}
for col, header in enumerate(headers, 1):
row_data[header] = ws.cell(row=row, column=col).value
# 加载Word模板
doc = Document(word_template)
# 替换模板中的占位符
for paragraph in doc.paragraphs:
for key, value in row_data.items():
if value is None:
value = ""
elif isinstance(value, datetime):
value = value.strftime('%Y-%m-%d')
else:
value = str(value)
if f'{{{key}}}' in paragraph.text:
paragraph.text = paragraph.text.replace(f'{{{key}}}', value)
# 替换报告时间
if '{报告时间}' in paragraph.text:
report_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
paragraph.text = paragraph.text.replace('{报告时间}', report_time)
# 保存生成的Word文档
output_file = f"{output_dir}/员工信息_{row_data['姓名']}.docx"
doc.save(output_file)
print(f"已生成: {output_file}")
# 使用示例
if __name__ == "__main__":
fill_word_from_excel('data.xlsx', 'template.docx', 'output')
案例2:批量生成合同文档
2.1 Excel数据文件 (contract_data.xlsx)
| 合同编号 | 客户名称 | 产品名称 | 金额 | 签订日期 | 有效期 |
|---|---|---|---|---|---|
| CT001 | 甲公司 | 软件服务 | 50000 | 2024-01-10 | 1年 |
| CT002 | 乙公司 | 技术支持 | 30000 | 2024-01-12 | 2年 |
2.2 Word模板 (contract_template.docx)
合同编号:{合同编号}
甲方:{客户名称}
乙方:XX科技有限公司
产品/服务:{产品名称}
合同金额:人民币{金额}元
签订日期:{签订日期}
合同有效期:{有效期}
特此证明
生成时间:{生成时间}
2.3 Python代码实现
python
from openpyxl import load_workbook
from docx import Document
from datetime import datetime
import os
def generate_contracts(excel_file, template_file, output_dir):
# 创建输出目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 加载Excel数据
wb = load_workbook(excel_file)
ws = wb.active
# 获取表头映射
headers = {}
for idx, cell in enumerate(ws[1], 1):
headers[cell.value] = idx
# 处理每一行数据
for row in range(2, ws.max_row + 1):
# 构建数据字典
data = {}
for header, col in headers.items():
data[header] = ws.cell(row=row, column=col).value
# 加载并处理Word模板
doc = Document(template_file)
# 替换所有段落中的占位符
replace_placeholders_in_paragraphs(doc, data)
# 替换表格中的占位符
replace_placeholders_in_tables(doc, data)
# 保存文档
filename = f"合同_{data['合同编号']}_{data['客户名称']}.docx"
output_path = os.path.join(output_dir, filename)
doc.save(output_path)
print(f"合同已生成: {filename}")
def replace_placeholders_in_paragraphs(doc, data):
"""替换段落中的占位符"""
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
for paragraph in doc.paragraphs:
for key, value in data.items():
placeholder = f'{{{key}}}'
if value is None:
value = ""
elif isinstance(value, datetime):
value = value.strftime('%Y-%m-%d')
else:
value = str(value)
if placeholder in paragraph.text:
paragraph.text = paragraph.text.replace(placeholder, value)
# 替换生成时间
if '{生成时间}' in paragraph.text:
paragraph.text = paragraph.text.replace('{生成时间}', current_time)
def replace_placeholders_in_tables(doc, data):
"""替换表格中的占位符"""
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for paragraph in cell.paragraphs:
for key, value in data.items():
placeholder = f'{{{key}}}'
if value is None:
value = ""
elif isinstance(value, datetime):
value = value.strftime('%Y-%m-%d')
else:
value = str(value)
if placeholder in paragraph.text:
paragraph.text = paragraph.text.replace(placeholder, value)
# 替换生成时间
if '{生成时间}' in paragraph.text:
paragraph.text = paragraph.text.replace('{生成时间}', current_time)
# 使用示例
if __name__ == "__main__":
generate_contracts('contract_data.xlsx', 'contract_template.docx', 'contracts_output')
案例3:生成复杂格式的报告
3.1 Excel数据 (report_data.xlsx)
| 项目名称 | 负责人 | 开始日期 | 结束日期 | 进度 | 状态 | 备注 |
|---|---|---|---|---|---|---|
| 项目A | 王五 | 2024-01-01 | 2024-06-30 | 75% | 进行中 | 按计划进行 |
| 项目B | 赵六 | 2024-02-01 | 2024-08-31 | 30% | 进行中 | 资源紧张 |
3.2 Python代码实现
python
from openpyxl import load_workbook
from docx import Document
from docx.shared import Inches
from datetime import datetime
def generate_project_report(excel_file, template_file, output_file):
# 加载Excel数据
wb = load_workbook(excel_file)
ws = wb.active
# 准备数据
projects = []
headers = [cell.value for cell in ws[1]]
for row in range(2, ws.max_row + 1):
project = {}
for col, header in enumerate(headers, 1):
value = ws.cell(row=row, column=col).value
if isinstance(value, datetime):
value = value.strftime('%Y-%m-%d')
project[header] = value
projects.append(project)
# 加载Word模板
doc = Document(template_file)
# 替换基本信息
replace_basic_info(doc)
# 添加项目表格
add_project_table(doc, projects)
# 添加总结
add_summary(doc, projects)
# 保存文档
doc.save(output_file)
print(f"项目报告已生成: {output_file}")
def replace_basic_info(doc):
"""替换基本信息"""
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
for paragraph in doc.paragraphs:
if '{报告标题}' in paragraph.text:
paragraph.text = paragraph.text.replace('{报告标题}', '项目进度报告')
if '{生成日期}' in paragraph.text:
paragraph.text = paragraph.text.replace('{生成日期}', current_time)
if '{报告人}' in paragraph.text:
paragraph.text = paragraph.text.replace('{报告人}', '系统自动生成')
def add_project_table(doc, projects):
"""添加项目表格"""
# 在文档末尾添加表格
table = doc.add_table(rows=1, cols=6)
table.style = 'Light Grid Accent 1'
# 添加表头
headers = ['项目名称', '负责人', '开始日期', '结束日期', '进度', '状态']
hdr_cells = table.rows[0].cells
for i, header in enumerate(headers):
hdr_cells[i].text = header
# 添加数据行
for project in projects:
row_cells = table.add_row().cells
row_cells[0].text = str(project.get('项目名称', ''))
row_cells[1].text = str(project.get('负责人', ''))
row_cells[2].text = str(project.get('开始日期', ''))
row_cells[3].text = str(project.get('结束日期', ''))
row_cells[4].text = str(project.get('进度', ''))
row_cells[5].text = str(project.get('状态', ''))
def add_summary(doc, projects):
"""添加总结部分"""
doc.add_paragraph("\n项目总结:")
total_projects = len(projects)
in_progress = sum(1 for p in projects if p.get('状态') == '进行中')
completed = total_projects - in_progress
summary_text = f"""
总项目数: {total_projects}
进行中项目: {in_progress}
已完成项目: {completed}
"""
doc.add_paragraph(summary_text)
# 使用示例
if __name__ == "__main__":
generate_project_report('report_data.xlsx', 'report_template.docx', '项目报告.docx')
案例4:高级功能 - 带格式的替换
python
from openpyxl import load_workbook
from docx import Document
from docx.shared import RGBColor
from datetime import datetime
def advanced_template_filling(excel_file, template_file, output_file):
# 加载Excel数据
wb = load_workbook(excel_file)
ws = wb.active
# 读取数据
data = {}
for row in range(1, ws.max_row + 1):
key = ws.cell(row=row, column=1).value
value = ws.cell(row=row, column=2).value
if key:
data[key] = value
# 加载Word模板
doc = Document(template_file)
# 高级替换(保留格式)
replace_placeholders_preserve_formatting(doc, data)
doc.save(output_file)
print(f"文档已生成: {output_file}")
def replace_placeholders_preserve_formatting(doc, data):
"""保留格式的占位符替换"""
for paragraph in doc.paragraphs:
for key, value in data.items():
placeholder = f'{{{key}}}'
if value is None:
value = ""
elif isinstance(value, datetime):
value = value.strftime('%Y-%m-%d')
else:
value = str(value)
if placeholder in paragraph.text:
# 保留原始格式进行替换
for run in paragraph.runs:
if placeholder in run.text:
run.text = run.text.replace(placeholder, value)
# 根据值设置颜色
if '警告' in value or '紧急' in value:
run.font.color.rgb = RGBColor(255, 0, 0) # 红色
elif '完成' in value or '正常' in value:
run.font.color.rgb = RGBColor(0, 128, 0) # 绿色
# 使用示例
if __name__ == "__main__":
advanced_template_filling('config_data.xlsx', 'advanced_template.docx', '高级报告.docx')
使用说明
- Excel文件准备:确保第一行是列标题,这些标题将作为Word模板中的占位符名称
- Word模板准备 :在Word中使用
{列标题}格式创建占位符 - 运行脚本:根据需要修改文件路径和参数
- 输出:生成的Word文档将保存在指定目录
这些案例涵盖了从简单到复杂的各种场景,您可以根据实际需求进行修改和扩展。