在日常工作中,批量生成Word文档和Excel报表是高频需求。本文基于Ubuntu 24.04 + Python 3.12.3环境,通过24个可复现实验,系统讲解python-docx 1.1.2和openpyxl 3.1.5的核心用法,包括文档创建、表格操作、样式设置、页面布局、公式计算、性能坑点等。所有代码已上机通过,可直接用于生产脚本。
一、环境搭建与依赖安装
使用阿里云PyPI镜像安装三个核心库:
- pip3 install python-docx openpyxl Pillow --break-system-packages \
- -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
复制代码
注意:Ubuntu 24.04默认启用PEP 668,需加--break-system-packages跳过限制。若使用华为云香港PyPI源可能超时,建议切换国内镜像。验证安装:
- >>> from docx import Document
- >>> import openpyxl
- >>> openpyxl.__version__
- '3.1.5'
复制代码
二、python-docx:Word文档编程
2.1 核心架构
Document是顶层对象,内含paragraphs(段落)、tables(表格)、sections(节)。段落由Run(最小格式单元)组成。docx本质是ZIP包,word/document.xml为核心XML文件。
2.2 基础操作:创建文档、段落、标题
- from docx import Document
- doc = Document()
- doc.add_heading("一级标题", level=1)
- p = doc.add_paragraph("普通段落。")
- p.add_run(" 同一行内的Run文字。") # Run作为段落内独立格式单元
- p2 = doc.add_paragraph("第一行。")
- p2.add_run("\n第二行(软换行)。") # \n对应Word的Shift+Enter,不是新段落
- doc.add_page_break()
- doc.add_paragraph("新页面。")
- doc.save("output.docx")
复制代码
2.3 表格操作:创建、合并、增删行
- table = doc.add_table(rows=5, cols=4)
- table.style = 'Light Grid Accent 1'
- headers = ['类型','英文名','可变性','示例']
- for i,h in enumerate(headers):
- table.rows[0].cells[i].text = h
- data = [['整数','int','不可变','42'],['字符串','str','不可变','"hello"'],['列表','list','可变','[1,2,3]'],['字典','dict','可变','{"a":1}']]
- for ri,row in enumerate(data,1):
- for ci,val in enumerate(row):
- table.rows[ri].cells[ci].text = val
- # 合并与新增行
- t2 = doc.add_table(rows=3, cols=3)
- t2.cell(0,0).merge(t2.cell(0,2))
- t2.cell(0,0).text = "合并区域"
- row_new = t2.add_row()
- for j in range(3):
- row_new.cells[j].text = f"新列{j}"
- doc.save("table_demo.docx")
复制代码
内置63种表格样式,按类别分为:浅色网格(Light Grid Accent 1~6)、中等底纹(Medium Shading 1 Accent 1~6)、列表样式(Light List Accent 1~6)、彩色系列(Colorful Grid/List/Shading)等,可直接设置style属性。
2.4 Run属性详解
Run支持bold、italic、underline、font.strike(删除线)、font.size(Pt对象)、font.color.rgb(RGBColor)、font.name等。注意中文字体设置必须同时指定西文字体和东亚字体:
- from docx.shared import Pt, RGBColor
- from docx.oxml.ns import qn
- run = p.add_run("宋体中文")
- run.font.name = '宋体'
- run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体') # 关键:设置eastAsia属性,否则中文不生效
复制代码
2.5 样式系统
使用内置段落样式(共36种,如Normal、Heading1~9、Title、Subtitle、Quote、List Bullet等):
- doc.add_paragraph("引用样式", style='Quote')
- # 修改默认样式
- style = doc.styles['Normal']
- style.font.size = Pt(11)
- style.font.name = 'Times New Roman'
复制代码
2.6 文档属性与批量生成
通过core_properties设置标题、作者、创建时间等元数据,循环生成多份文档(例如4份入职通知书,每份约36KB):
- doc.core_properties.title = "批量文档"
- users = ["张三","李四"]
- for user in users:
- doc = Document()
- doc.add_heading(f"{user}入职通知", level=1)
- doc.add_paragraph(f"尊敬的{user}:恭喜入职。")
- doc.save(f"{user}_通知.docx")
复制代码
2.7 计量单位换算
python-docx使用EMU(English Metric Unit)作为基础单位:1 pt = 12700 EMU,1 cm = 360000 EMU,1 inch = 914400 EMU。可通过Pt、Cm、Inches等辅助类传入。
2.8 字体颜色RGB真彩色
- colors = [("红",0xFF,0,0),("绿",0,0x80,0)]
- for name,r,g,b in colors:
- run = p.add_run(f"[{name}]")
- run.font.color.rgb = RGBColor(r,g,b)
复制代码
2.9 段落间距与行距
- p.paragraph_format.space_before = Pt(6)
- p.paragraph_format.space_after = Pt(6)
- p.paragraph_format.line_spacing = 1.5 # 倍数
- p.paragraph_format.line_spacing = Pt(24) # 固定值
复制代码
2.10 页面设置与分节符混排
通过sections[0]设置A4页面,add_section()创建新节,可单独设置横向:
- from docx.shared import Cm
- from docx.enum.section import WD_ORIENT
- section = doc.sections[0]
- section.page_width = Cm(21)
- section.page_height = Cm(29.7)
- section.top_margin = Cm(2.54)
- doc.add_section()
- sec2 = doc.sections[1]
- sec2.orientation = WD_ORIENT.LANDSCAPE
- sec2.page_width = Cm(29.7)
- sec2.page_height = Cm(21)
复制代码
常用纸张尺寸:A4 21×29.7cm,A3 29.7×42.0cm,Letter 21.59×27.94cm,B5 17.6×25.0cm。
2.11 页脚与域:自动页码
通过OxmlElement构造w:fldChar和w:instrText实现PAGE、NUMPAGES域:
- footer = doc.sections[0].footer
- p = footer.paragraphs[0]
- p.text = "第 "
- # 插入PAGE域(需要begin、instrText、end三段)
- run = p.add_run()
- fldChar = OxmlElement('w:fldChar')
- fldChar.set(qn('w:fldCharType'), 'begin')
- run._r.append(fldChar)
- run2 = p.add_run()
- instrText = OxmlElement('w:instrText')
- instrText.set(qn('xml:space'), 'preserve')
- instrText.text = ' PAGE '
- run2._r.append(instrText)
- # … 类似插入NUMPAGES域 …
- p.add_run(" 页 / 共 ")
- p.add_run(" 页")
- p.alignment = 1 # 居中
复制代码
常用域代码:PAGE、NUMPAGES、DATE、TOC(需Word打开后更新域)、HYPERLINK。
2.12 页眉与目录
- header = doc.sections[0].header
- header.paragraphs[0].text = "手册标题"
- # TOC域只能写入代码,目录内容需Word打开后右键→更新域才能渲染
复制代码
2.13 综合Demo:列表、图片、表格
支持无序列表(List Bullet)、有序列表(List Number),插入图片(add_picture),也可用zipfile解压docx提取media目录中的图片。
三、openpyxl:Excel电子表格编程
3.1 核心架构
Workbook(工作簿)包含多个Worksheet(工作表),每个工作表由Cells(单元格)组成,支持行/列操作、样式、保护、属性等。
3.2 基础工作流
- from openpyxl import Workbook
- wb = Workbook()
- ws = wb.active
- ws.title = "数据表"
- ws['A1'] = '姓名'
- ws['B1'] = '年龄'
- data = [['张三',28,'深圳',15000],['李四',32,'北京',22000]]
- for i,row in enumerate(data,2):
- for j,val in enumerate(row):
- ws.cell(row=i, column=j+1, value=val)
- # 公式
- ws['D7'] = '=AVERAGE(D2:D6)'
- wb.save("basic.xlsx")
- # 回读
- wb2 = openpyxl.load_workbook("basic.xlsx")
- ws2 = wb2.active
- for row in ws2.iter_rows(min_row=1, max_row=7, values_only=True):
- print(row)
复制代码
注意:openpyxl的行列索引从1开始(与Excel一致),公式以字符串形式写入,Excel打开后自动计算。
3.3 工作表操作:CRUD、移动、复制
- wb = Workbook()
- for name in ['Q1','Q2','Q3','Q4']:
- wb.create_sheet(name)
- del wb['Sheet'] # 删除默认Sheet,如果只剩一个会报错:ValueError
- print(wb.sheetnames) # ['Q1','Q2','Q3','Q4']
- # 复制
- wb.copy_worksheet(wb['Q1'])
- wb['Q1 Copy'].title = 'Q1备份'
- # 移动
- wb.move_sheet('Q4', offset=-2)
- # 创建时指定位置
- wb.create_sheet("新表", 0)
复制代码
关键方法速查:create_sheet(name, index)、copy_worksheet(ws)、del wb[sheetname]、move_sheet(sheet, offset)、wb.active、wb.worksheets[0]。
3.4 工作表属性:标签颜色、显示比例、冻结窗格、自动筛选
- ws.sheet_properties.tabColor = "FF6B35" # 十六进制颜色
- ws.sheet_view.zoomScale = 120 # 120%缩放
- ws.sheet_view.showGridLines = False # 隐藏网格线
- ws.freeze_panes = 'A2' # 冻结首行
- ws.auto_filter.ref = "A1:F6"
复制代码
3.5 样式综合演示
openpyxl样式组件包括Font、PatternFill、Border、Side、Alignment等。构建企业级表格时,可设置表头样式、数据边框、隔行变色、条件着色:
- from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
- header_font = Font(name='微软雅黑', size=11, bold=True, color='FFFFFF')
- header_fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
- thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
- for r_idx, row in enumerate(data, 2):
- for c_idx, val in enumerate(row):
- cell = ws.cell(row=r_idx, column=c_idx+1, value=val)
- cell.border = thin_border
- cell.alignment = Alignment(horizontal='center', vertical='center')
- if r_idx % 2 == 0:
- cell.fill = PatternFill(start_color='D9E2F3', end_color='D9E2F3', fill_type='solid')
复制代码
3.6 保护工作表/工作簿
使用ws.protection设置密码,wb.security.lockStructure保护工作簿结构。
四、踩坑记录与性能提示
1. 中文字体不生效:python-docx需同时设置rFonts的eastAsia属性。
2. PEP 668限制:Ubuntu 24.04使用--break-system-packages或创建虚拟环境。
3. 华为云香港PyPI超时:改用阿里云、清华等国内镜像。
4. TOC目录不显示:python-docx仅写入域代码,需Word打开后手动更新域。
5. 单元格坐标从1开始:openpyxl的行列索引从1起,与Excel一致。
6. 删除唯一工作表报错:工作簿至少保留一个可见工作表,删除最后一个会引发ValueError。
性能测试显示,生成4份入职文档瞬间完成,每份约36KB;24个实验全部在Ubuntu 24.04 + Python 3.12.3环境下跑通,产出Word文件19个、Excel文件7个。
总结
python-docx和openpyxl是处理Office文档的利器,掌握本文全部实验,即可独立完成合同批量生成、数据报表自动化、样式控制等任务。代码可直接套用,注意根据实际环境调整中文字体设置和镜像源。 |