





















from docx import Document def merge_cells_horizontally(table, row: int, start_col: int, end_col: int) -> None: """水平合并单元格 :param table: 表格对象 :param row: 行索引(从0开始) :param start_col: 起始列索引 :param end_col: 结束列索引 """ if start_col >= end_col: raise ValueError("结束列必须大于起始列") cell = table.cell(row, start_col) for col in range(start_col + 1, end_col + 1): cell.merge(table.cell(row, col))
def merge_cells_vertically(table, col: int, start_row: int, end_row: int) -> None: """垂直合并单元格 :param table: 表格对象 :param col: 列索引(从0开始) :param start_row: 起始行索引 :param end_row: 结束行索引 """ if start_row >= end_row: raise ValueError("结束行必须大于起始行") cell = table.cell(start_row, col) for row in range(start_row + 1, end_row + 1): cell.merge(table.cell(row, col))
def create_sample_document(output_path: str) -> None: doc = Document() doc.add_heading('表格单元格合并演示', level=1) # 创建5x5表格 table = doc.add_table(rows=5, cols=5) # 填充基础数据 for row_idx in range(5): for col_idx in range(5): table.cell(row_idx, col_idx).text = f"({row_idx},{col_idx})" # 水平合并示例 merge_cells_horizontally(table, 0, 1, 3) table.cell(0, 1).text = "水平合并单元格" # 垂直合并示例 merge_cells_vertically(table, 4, 1, 3) table.cell(1, 4).text = "垂直合并单元格" # 复杂合并示例 for row in range(2, 5): merge_cells_horizontally(table, row, 0, 2) merge_cells_vertically(table, 0, 2, 4) table.cell(2, 0).text = "复杂合并" doc.save(output_path)
import os from docx import Document from docx.shared import Cm, Pt ,Inches from docx.oxml.shared import OxmlElement, qn from docx.enum.table import WD_ROW_HEIGHT_RULE from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_ALIGN_VERTICAL def set_page_format(doc): """设置A4纸张,并调整页边距为窄边距,以容纳3个表格""" section = doc.sections[0] section.page_width = Cm(21.0) # A4宽度 section.page_height = Cm(29.7) # A4高度 section.left_margin = Cm(1.2) section.right_margin = Cm(1.2) section.top_margin = Cm(1.2) section.bottom_margin = Cm(1.2) def set_cell_font(cell, text, bold=False, size_pt=12): """设置单元格文本及字体(宋体,默认12号)""" cell.text = text paragraph = cell.paragraphs[0] run = paragraph.runs[0] if paragraph.runs else paragraph.add_run(text) run.font.name = '宋体' run.font.size = Pt(size_pt) run.font.bold = bold # 垂直居中 cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT def add_reimbursement_table(doc, data): """添加一个完整的费用报销单(标题+表格)""" # 1. 添加标题“费用报销单”并居中加粗 title_para = doc.add_paragraph() title_para.alignment = WD_ALIGN_PARAGRAPH.CENTER run = title_para.add_run("\n费用报销单") run.font.size = Pt(14) run.font.bold = True run.font.name = '宋体' # 2. 创建表格:6行4列 table = doc.add_table(rows=6, cols=6) table.style = 'Table Grid' # 带边框的表格样式 # 可选:统一设置每行最小高度,避免过于拥挤 for row in table.rows: row.height = Cm(0.7) # 获取所有单元格的引用 (行索引0~5) merge_cells_horizontally(table, 0, 2, 5) # 表格第1行的第3列到第6列合并 # 第1行:附单据 | 张数 set_cell_font(table.cell(0, 0), "附单据", bold=False) set_cell_font(table.cell(0, 1), f"{data['attach_num']}张") table.rows[0].height_rule = WD_ROW_HEIGHT_RULE.AT_LEAST # 行高设置 table.rows[0].height = Pt(20) # 行高设置 # 第2行:公司 | {公司名} | 日期 | {日期} merge_cells_horizontally(table, 1, 1, 3) # 表格第2行的第2列到第4列合并 set_cell_font(table.cell(1, 0), "公司", bold=False) set_cell_font(table.cell(1, 1), data['company']) set_cell_font(table.cell(1, 4), "日期", bold=False) set_cell_font(table.cell(1, 5), data['date']) table.rows[1].height_rule = WD_ROW_HEIGHT_RULE.AT_LEAST # 行高设置 table.rows[1].height = Pt(26) # 行高设置 # 第3行:申请金额(大写) | 大写金额 | 小写金额 | 小写金额值 merge_cells_horizontally(table, 2, 1, 3) # 表格第2行的第2列到第4列合并 set_cell_font(table.cell(2, 0), "申请金额\n(大写)", bold=False) set_cell_font(table.cell(2, 1), data['amount_cn']) set_cell_font(table.cell(2, 4), "小写(¥)", bold=False) set_cell_font(table.cell(2, 5), data['amount_num']) table.rows[2].height_rule = WD_ROW_HEIGHT_RULE.AT_LEAST # 行高设置 table.rows[2].height = Pt(40) # 行高设置 # 第4行:用途说明 + 合并后四列 set_cell_font(table.cell(3, 0), "经办人", bold=False) set_cell_font(table.cell(3, 1), data['handler']) # 合并第4行的第3,4,5,6列 table.cell(3, 2).merge(table.cell(3, 3)).merge(table.cell(3, 4)).merge(table.cell(3, 5)) table.rows[3].height_rule = WD_ROW_HEIGHT_RULE.AT_LEAST # 行高设置 table.rows[3].height = Pt(26) # 行高设置 # 第5行:主管 | (空白) | 合并后四列 set_cell_font(table.cell(4, 0), "主管", bold=False) set_cell_font(table.cell(4, 1), "") # 合并第4行的第3,4,5,6列 table.cell(4, 2).merge(table.cell(4, 3)).merge(table.cell(4, 4)).merge(table.cell(4, 5)) table.rows[4].height_rule = WD_ROW_HEIGHT_RULE.AT_LEAST # 行高设置 table.rows[4].height = Pt(26) # 行高设置 # 第四行 第五行,后四列在行合并 | 添加报销用途 merge_cells_vertically(table,2,3,4) set_cell_font(table.cell(4, 2), "用途说明:\n {}".format(data['purpose'] ), bold=False) # 第6行:出纳 | (空白) |出纳 | (空白) | 领款人 | (空白) set_cell_font(table.cell(5, 0), "会计", bold=False) set_cell_font(table.cell(5, 1), "") # 留白 set_cell_font(table.cell(5, 2), "出纳", bold=False) set_cell_font(table.cell(5, 3), "") set_cell_font(table.cell(5, 4), "领款人", bold=False) set_cell_font(table.cell(5, 5), "") table.rows[5].height_rule = WD_ROW_HEIGHT_RULE.AT_LEAST # 行高设置 table.rows[5].height = Pt(26) # 行高设置 # 表格后添加一个空行(隔开下一个报销单),不要太多,避免溢出页面 doc.add_paragraph("") # 3. 设置第一行的左、上、右边框为灰色 set_first_row_top_borders( table, color="#808080", # 灰色 size=6, # 0.7磅 style="dashed" # 实线single ) # 水平合并单元格 def merge_cells_horizontally(table, row: int, start_col: int, end_col: int) -> None: """水平合并单元格 :param table: 表格对象 :param row: 行索引(从0开始) :param start_col: 起始列索引 :param end_col: 结束列索引 """ if start_col >= end_col: raise ValueError("结束列必须大于起始列") cell = table.cell(row, start_col) for col in range(start_col + 1, end_col + 1): cell.merge(table.cell(row, col)) # 垂直合并单元格 def merge_cells_vertically(table, col: int, start_row: int, end_row: int) -> None: """垂直合并单元格 :param table: 表格对象 :param col: 列索引(从0开始) :param start_row: 起始行索引 :param end_row: 结束行索引 """ if start_row >= end_row: raise ValueError("结束行必须大于起始行") cell = table.cell(start_row, col) for row in range(start_row + 1, end_row + 1): cell.merge(table.cell(row, col)) # 设置单个单元格的边框颜色 def set_cell_border(cell, **kwargs): """ 设置单元格边框颜色和样式 参数: cell: 单元格对象 **kwargs: 边框属性,如: top={"sz": 12, "val": "single", "color": "#FF0000"} left={"sz": 12, "val": "single", "color": "#00FF00"} bottom={"sz": 12, "val": "single", "color": "#0000FF"} right={"sz": 12, "val": "single", "color": "#000000"} insideH={"sz": 12, "val": "single", "color": "#CCCCCC"} # 水平内边框 insideV={"sz": 12, "val": "single", "color": "#CCCCCC"} # 垂直内边框 尺寸单位: 1磅 = 8个单位 (sz=12 表示 1.5磅) 颜色格式: 十六进制 "#RRGGBB" 或 "auto" """ tc = cell._tc tcPr = tc.get_or_add_tcPr() # 创建边框元素 tcBorders = OxmlElement('w:tcBorders') # 为每个边框方向设置属性 for edge in ('top', 'left', 'bottom', 'right', 'insideH', 'insideV'): edge_data = kwargs.get(edge) if edge_data: edge_element = OxmlElement(f'w:{edge}') # 设置尺寸 if 'sz' in edge_data: edge_element.set(qn('w:sz'), str(edge_data['sz'])) # 设置线型 (single, double, dotted, dashed, etc.) if 'val' in edge_data: edge_element.set(qn('w:val'), edge_data['val']) # 设置颜色 if 'color' in edge_data: edge_element.set(qn('w:color'), edge_data['color']) # 设置阴影 (可选) if 'shadow' in edge_data: edge_element.set(qn('w:shadow'), edge_data['shadow']) # 设置空格 (可选) if 'space' in edge_data: edge_element.set(qn('w:space'), str(edge_data['space'])) tcBorders.append(edge_element) tcPr.append(tcBorders) # 设置整个表格的边框颜色 def set_table_border(table, **kwargs): """ 设置整个表格所有单元格的边框 参数: table: 表格对象 **kwargs: 同 set_cell_border 示例: set_table_border(table, top={"sz": 12, "val": "single", "color": "#FF0000"}, left={"sz": 12, "val": "single", "color": "#FF0000"}, bottom={"sz": 12, "val": "single", "color": "#FF0000"}, right={"sz": 12, "val": "single", "color": "#FF0000"}, insideH={"sz": 8, "val": "single", "color": "#0000FF"}, insideV={"sz": 8, "val": "single", "color": "#0000FF"}) """ for row in table.rows: for cell in row.cells: set_cell_border(cell, **kwargs) # 设置表格第一行所有单元格的左、上、右边框为指定颜色 def set_first_row_top_borders(table, color="#808080", size=12, style="single"): """ 设置表格第一行所有单元格的左、上、右边框为指定颜色 参数: table: 表格对象 color: 边框颜色(十六进制),默认灰色 "#808080" size: 边框粗细(1/8磅),默认12(1.5磅) style: 边框样式,如 "single", "dotted", "dashed" 等 """ # 获取第一行 first_row = table.rows[0] # 遍历第一行的所有单元格 for cell in first_row.cells: set_cell_border( cell, top={"sz": size, "val": style, "color": color}, # 顶部边框 left={"sz": size, "val": style, "color": color}, # 左侧边框 right={"sz": size, "val": style, "color": color} # 右侧边框 # 注意:没有设置 bottom,所以底部边框保持默认 ) def main(): # 创建新文档 doc = Document() set_page_format(doc) # ------------------------------------------------------------ # 配置数据:生成3个报销单,每个报销单的变量值不同 # ------------------------------------------------------------ reimbursements = [ { "attach_num": "8", # 附单据张数 "company": "西安服务公司", "date": "2026.4.23", "amount_cn": "叁佰柒拾贰元贰角贰分", "amount_num": "372.22", "handler": "李某某", "purpose": "交通" }, { "attach_num": "2", "company": "西安服务有限公司", "date": "2026.4.23", "amount_cn": "壹仟叁佰伍拾玖元叁角捌分", "amount_num": "1359.38", "handler": "李某某", "purpose": "餐饮" }, { "attach_num": "3", "company": "汽车服务有限公司", "date": "2026.4.23", "amount_cn": "肆佰伍拾陆元整", "amount_num": "456.00", "handler": "王芳", "purpose": "办公用品" } ] # 依次添加3个报销单表格(根据数据列表) for idx, data in enumerate(reimbursements): add_reimbursement_table(doc, data) # 保存生成的Word文件 output_path = "费用报销单_A4_三张.docx" doc.save(output_path) print(f"生成成功!文件已保存为:{output_path}") print("可直接打开该文件使用Word打印(A4纸张,三个表格竖向排列)。") if __name__ == "__main__": main()
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。