使用python-docx在文档的书签下方添加表格包含以下三个流程:
比如我们在一个文档【书签1】中,希望在书签1
这个位置下面插入一个表格,使用方法如下:
比如随便插入一个dataframe:
# 1. 把要插入的数据调整为dataframe格式
dataframe = pd.DataFrame(np.random.randint(0, 10, size=(10, 4)))
dataframe.columns = [f"列{_ + 1}" for _ in dataframe.columns]
完整的代码如下:
from docx import Document, oxml
import pandas as pd
import numpy as np
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
def get_bookmark_par_element_start(document, bookmark_name):
"""查找标签的起始位置(所在的段落)"""
doc_element = document.part.element
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
for bookmark in bookmarks_list:
name = bookmark.get(qn('w:name'))
if name == bookmark_name:
par = bookmark.getparent()
if not isinstance(par, oxml.CT_P):
return 2
else:
return par, bookmark.get(qn('w:id'))
return 1
def set_bookmark_df(document, bookmark_name, table):
"""
:param document:
:param bookmark_name:
:param table:
:return:
"""
bookmark_par, _id = get_bookmark_par_element_start(document, bookmark_name)
bookmark_par_parent = bookmark_par.getparent()
# 下面是将表格移动到书签所在位置下方
index = bookmark_par_parent.index(bookmark_par)
base_paragraphs = document.paragraphs[index]
base_paragraphs._p.addnext(table._tbl)
# 设置 table 的边框,用法与 cell 类似
def set_table_boarder(table, **kwargs):
"""
Set table`s border
Usage:
set_table_border(
cell,
top={"sz": 12, "val": "single", "color": "#FF0000"},
bottom={"sz": 12, "color": "#00FF00", "val": "single"},
left={"sz": 24, "val": "dashed"},
right={"sz": 12, "val": "dashed"},
)
"""
borders = OxmlElement('w:tblBorders')
for tag in ('bottom', 'top', 'left', 'right', 'insideV', 'insideH'):
edge_data = kwargs.get(tag)
if edge_data:
any_border = OxmlElement(f'w:{tag}')
for key in ["sz", "val", "color", "space", "shadow"]:
if key in edge_data:
any_border.set(qn(f'w:{key}'), str(edge_data[key]))
borders.append(any_border)
table._tbl.tblPr.append(borders)
return table
def set_table_singleBoard(table):
"""为表格添加边框"""
return set_table_boarder(
table,
top={"sz": 4, "val": "single", "color": "#000000"},
bottom={"sz": 4, "val": "single", "color": "#000000"},
left={"sz": 4, "val": "single", "color": "#000000"},
right={"sz": 4, "val": "single", "color": "#000000"},
insideV={"sz": 4, "val": "single", "color": "#000000"},
insideH={"sz": 4, "val": "single", "color": "#000000"}
)
def convert_df_to_table(document, dataframe: pd.DataFrame, index_list=None, column_list=None):
"""把table转为dataframe
:param document: 文档对象
:param dataframe: dataframe格式数据
:param index_list: 最左边一列显示的内容
:param column_list: (第一行)列名称需要显示的内容
"""
rows = dataframe.shape[0]
cols = dataframe.shape[1]
if index_list is not None:
cols += 1
if column_list is not None:
rows += 1
table = document.add_table(rows=rows, cols=cols)
row_i = 0
col_i = 0
if index_list is not None:
raise
if column_list is not None:
hdr_cells = table.rows[row_i].cells
for _col_i, _v in enumerate(column_list):
hdr_cells[_col_i].text = str(_v)
row_i += 1
for _i, series_info in enumerate(dataframe.iterrows()):
series = series_info[1]
hdr_cells = table.rows[row_i + _i].cells
for _c_i, _cell_value in enumerate(series):
hdr_cells[col_i + _c_i].text = str(_cell_value)
return table
def main():
path = '测试1.docx'
document = Document(path)
# 1. 把要插入的数据调整为dataframe格式
dataframe = pd.DataFrame(np.random.randint(0, 10, size=(10, 4)))
dataframe.columns = [f"列{_ + 1}" for _ in dataframe.columns]
# 2. 插入表格并移动表格到书签下方
table = convert_df_to_table(document, dataframe, column_list=dataframe.columns.tolist())
table = set_table_singleBoard(table) # 表格添加边框
set_bookmark_df(document, '书签1', table)
# 3. 保存修改后的结果
document.save('测试2.docx') # 保存后导出
if __name__ == '__main__':
main()