小明的老师要打印学生成绩单,于是制作了一份 Word 文档,每个学生的成绩单为一个表格,如下图所示:
但是核对 Excel 中的成绩时发现存在一些错误,比如小明的班级、小霞的数学成绩:
每个学生(逐行)每个字段(逐列)比对了一番苦不堪言,那我们可不可以用 Python
来帮帮老师呢?
作为无所不能的 Python 大法,这自然不在话下!
下面便介绍如何用 python-docx 读取 Word 文档中的表格数据并与 Excel 中的数据比对
python-docx
是用于创建和更新 Microsoft Word(.docx)文件的 Python 库。
python-docx 托管在 PyPI 上,可以很方便地用 pip 安装:
pip install python-docx
成功安装后,运行以下示例代码1,体验一下效果:
ps.注意在运行目录下准备一张图片:
image.png
# 导包
from docx import Document
from docx.shared import Inches
# 创建空白文档
document = Document()
# 添加标题
document.add_heading('Document Title', 0)
# 添加段落
p = document.add_paragraph('A plain paragraph having some ')
# 添加不同格式的文字
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True
# 添加一级标题
document.add_heading('Heading, level 1', level=1)
# 添加不同样式的段落
document.add_paragraph('Intense quote', style='Intense Quote')
document.add_paragraph(
'first item in unordered list', style='List Bullet'
)
document.add_paragraph(
'first item in ordered list', style='List Number'
)
# 添加图片并设置大小
document.add_picture('image.png', width=Inches(1.25))
records = (
(3, '101', 'Spam'),
(7, '422', 'Eggs'),
(4, '631', 'Spam, spam, eggs, and spam')
)
# 添加表格
table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'
for qty, id, desc in records:
row_cells = table.add_row().cells
row_cells[0].text = str(qty)
row_cells[1].text = id
row_cells[2].text = desc
# 添加分页
document.add_page_break()
# 保存文档
document.save('demo.docx')
下面我们就可以借助 python-docx 来实现文章一开始的需求了,简单分为以下几步:
read_docx_tables
函数:document = Document(docx_file)
for table in document.tables:
for r in table.rows:
k, v = cells[0].text, cells[1].text; value_dict[k] = v
(这里针对双列键值对型的表格,数据存储为字典中的键值对)xlrd
库读取 test.xlsx
文件,不做详解xlsxwriter
库生成 test_mapped.xlsx
文件,不做详解#!/usr/bin/env python
# -*- coding: utf-8 -*-
import xlrd
import xlsxwriter
from docx import Document
docx_name = 'test.docx'
input_excel = 'test.xlsx'
output_excel = 'test_mapped.xlsx'
def read_docx_tables(docx_file):
"""
读取 Word 文档中双列键值对型的表格
:param docx_file: 文档文件名
:return: [{key1: value1, ...}, ...]
"""
# 创建文档对象,获得word文档
document = Document(docx_file)
# 读取表格集中的值
doc_tables_values = []
for table in document.tables:
value_dict = {
}
for r in table.rows:
cells = r.cells
k, v = cells[0].text, cells[1].text
value_dict[k] = v
doc_tables_values.append(value_dict)
return doc_tables_values
def docx_vs_xlsx():
print('Running...')
docx_tables = read_docx_tables(docx_name)
# 读取旧的 Excel
bk = xlrd.open_workbook(input_excel)
sh = bk.sheet_by_index(0)
nrows = sh.nrows # 获取行数
ncols = sh.ncols # 获取列数
titles = sh.row_values(0) # 获取标题行
# 写入新的 Excel
workbook = xlsxwriter.Workbook(output_excel)
worksheet = workbook.add_worksheet()
cell_format_yellow = workbook.add_format({
'fg_color': '#FFFF00',
})
cell_format_green = workbook.add_format({
'fg_color': '#92D050',
})
# 边读边写
for row in range(nrows):
doc_values = []
if row != 0:
doc_values = docx_tables[row-1]
print(doc_values['姓名'])
for col in range(ncols):
xls_value = sh.cell_value(row, col)
if row == 0:
worksheet.write(row, col, xls_value)
continue
doc_value = doc_values[titles[col]]
# 数据一致则填充绿色,否则填充黄色并显示 doc_value
if xls_value == doc_value:
worksheet.write(row, col, xls_value, cell_format_green)
else:
worksheet.write(row, col, doc_value, cell_format_yellow)
print('Row', row + 2, end='\t')
workbook.close()
print('\rSucceeded!')
if __name__ == '__main__':
docx_vs_xlsx()
代码运行后便可得到黄绿标记的 test_mapped.xlsx
,与原始表格对比图如下:
小明老师再也不用盯着两份文件“找不同”啦~~~
Python-docx 官方文档 ↩︎