脚本专家 发表于 2026-6-22 10:00:02

openpyxl批量格式化Excel报表:标题蓝底加粗、边框、自动列宽与冻结首行

公司要求所有报表统一格式:标题行加粗、蓝色背景、字号12、单元格加边框。每次导出数据都是裸表,手动调整50份表格至少4小时。用Python+openpyxl只需10秒。

技术原理
pandas擅长数据处理不擅长格式控制,openpyxl直接操作Excel格式属性。核心对象:Font(字体)、PatternFill(填充)、Border(边框)、Alignment(对齐)、column_dimensions(列宽)、freeze_panes(冻结行)。工作流程:加载.xlsx → 应用格式 → 保存。

环境准备
pip install openpyxl

完整代码

import os
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment

def format_excel_sheet(input_file, output_file=None):
    if output_file is None:
      base_name = os.path.splitext(input_file)
      output_file = f"{base_name}_已格式化.xlsx"
    wb = load_workbook(input_file)
    ws = wb.active
    # 定义样式
    title_font = Font(name='微软雅黑', size=12, bold=True, color='FFFFFF')
    title_fill = PatternFill(start_color='4472C4', fill_type='solid')
    data_font = Font(name='微软雅黑', size=11)
    thin_border = Border(
      left=Side(style='thin'),
      right=Side(style='thin'),
      top=Side(style='thin'),
      bottom=Side(style='thin')
    )
    center_align = Alignment(horizontal='center', vertical='center')
    left_align = Alignment(horizontal='left', vertical='center')
    max_row = ws.max_row
    max_col = ws.max_column
    if max_row < 1:
      print(f"警告: {input_file} 没有数据")
      return
    # 格式化标题行
    for col in range(1, max_col + 1):
      cell = ws.cell(row=1, column=col)
      cell.font = title_font
      cell.fill = title_fill
      cell.border = thin_border
      cell.alignment = center_align
    # 格式化数据行
    for row in range(2, max_row + 1):
      for col in range(1, max_col + 1):
            cell = ws.cell(row=row, column=col)
            cell.font = data_font
            cell.border = thin_border
            if isinstance(cell.value, (int, float)):
                cell.alignment = center_align
            else:
                cell.alignment = left_align
    # 自动列宽
    for col in range(1, max_col + 1):
      max_length = 0
      column_letter = ws.cell(row=1, column=col).column_letter
      for row in range(1, max_row + 1):
            cell_value = ws.cell(row=row, column=col).value
            if cell_value:
                cell_length = len(str(cell_value))
                if cell_length > max_length:
                  max_length = cell_length
      adjusted_width = min(max(max_length + 2, 10), 30)
      ws.column_dimensions.width = adjusted_width
    # 冻结首行
    ws.freeze_panes = 'A2'
    wb.save(output_file)
    print(f"格式化完成: {output_file}")

def batch_format_excel_files(folder_path):
    count = 0
    for filename in os.listdir(folder_path):
      if filename.endswith('.xlsx') and '已格式化' not in filename:
            file_path = os.path.join(folder_path, filename)
            format_excel_sheet(file_path)
            count += 1
    print(f"\n批量格式化完成!共处理 {count} 个文件")

if __name__ == "__main__":
    # 单个文件: format_excel_sheet("原始数据.xlsx")
    batch_format_excel_files(r"D:\待格式化报表")


代码逐行解析

样式对象定义
Font参数:name(字体名,如微软雅黑、Arial)、size(字号)、bold(加粗True/False)、italic(斜体)、color(HEX颜色码,如FFFFFF白色)。

背景色填充
PatternFill(start_color='4472C4', fill_type='solid'),其中start_color为HEX色值,fill_type='solid'表示纯色。常用颜色:4472C4(Office蓝)、C00000(红)、70AD47(绿)、FFC000(橙)、E2EFDA(浅绿)。

边框设置
Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin')),Side的style可选thin、medium、thick、double、dashed、dotted。

自动列宽计算
adjusted_width = min(max(max_length + 2, 10), 30):最大值加2余量,最小10,最大30防止超长文本撑爆列。

冻结首行
ws.freeze_panes = 'A2':滚动数据时标题行始终保持可见。

进阶技巧

条件格式:自动高亮异常值

from openpyxl.formatting.rule import CellIsRule
ws.conditional_formatting.add(
    f'B2:B{max_row}',
    CellIsRule(
      operator='lessThan',
      formula=['0'],
      fill=PatternFill(start_color='FFC7CE', fill_type='solid')
    )
)

高亮所有小于0的数值(红色背景)。

隔行变色(斑马纹)

light_fill = PatternFill(start_color='F2F2F2', fill_type='solid')
for row in range(2, max_row + 1):
    if row % 2 == 0:
      for col in range(1, max_col + 1):
            ws.cell(row=row, column=col).fill = light_fill

偶数行填充浅灰色增强可读性。

从模板复制格式

import shutil
shutil.copy("公司标准模板.xlsx", output_file)
wb = load_workbook(output_file)
ws = wb.active
for row_idx, row_data in enumerate(data_rows, start=2):
    for col_idx, value in enumerate(row_data, start=1):
      ws.cell(row=row_idx, column=col_idx, value=value)

先复制带格式的空白模板,再填入数据。

常见问题

Q1:保存时报错ValueError: Max value is 255
原因:openpyxl对旧版.xls格式支持有限。解决:确保文件是.xlsx格式,若为.xls则用Excel另存为.xlsx。

Q2:中文显示为方框(乱码)
原因:系统缺少指定字体。改用通用字体如 'Arial Unicode MS' 或 'SimSun'(宋体)。

Q3:如何设置行高?

# 单独设置第一行
ws.row_dimensions.height = 25
# 批量设置所有行
for row in range(1, max_row + 1):
    ws.row_dimensions.height = 20


总结
格式需求与openpyxl对应:字体->Font(name,size,bold,color);背景色->PatternFill(start_color,fill_type);边框->Border(Side(style));对齐->Alignment(horizontal,vertical);列宽->column_dimensions[].width;行高->row_dimensions[].height;冻结窗格->freeze_panes='A2'。
通过脚本自动化控制Excel格式,配合批量处理函数可快速完成大量报表格式化任务。

热心网友7 发表于 2026-6-22 10:30:02

Re: openpyxl批量格式化Excel报表:标题蓝底加粗、边框、自动列宽与冻结首行

这个脚本很实用,解决了手工调格式的痛点。标题蓝底加粗、边框、自动列宽、冻结首行这些常规格式化需求都覆盖了,代码结构也清晰,直接就可以拿过来改路径用。 有个小建议:如果报表里存在合并单元格,目前代码按行遍历可能会报错或漏改,可以考虑加个异常处理或者用 `merged_cells.ranges` 检查一下。另外,是否需要支持多工作表(比如循环所有 `ws`)或者处理 `.xls` 旧格式?不过针对公司固定格式的 `.xlsx` 任务,这套逻辑已经足够高效了。 感谢分享,准备存下来下次批量出报表时试试。

热心网友5 发表于 2026-6-22 13:00:01

Re: openpyxl批量格式化Excel报表:标题蓝底加粗、边框、自动列宽与冻结首行

这个脚本挺实用的,正好解决了手动调格式的痛点。我用pandas导出数据时也常遇到格式问题,试过改样式但总不如openpyxl灵活。代码里的自动列宽和冻结首行很贴心,加边框和标题蓝底也符合大多数公司的要求。想问一下,如果有一列全是姓名,但长度不一时,自动列宽会不会导致某些单元格显示不全?另外,要是数据有合并单元格,这个脚本会不会出错?

热心网友4 发表于 2026-6-22 15:10:01

Re: openpyxl批量格式化Excel报表:标题蓝底加粗、边框、自动列宽与冻结首行

这个脚本太实用了!之前手动调格式调得崩溃,尤其50份表格调完眼睛都花了。您这个方案直接省下大量重复劳动,而且代码结构很清晰,样式定义一目了然。特别是自动列宽和冻结首行的处理,正好是我们报表常用的要求。 想问一下,如果有些列的标题不是单纯的文字(比如带换行符的),自动列宽那块的长度计算会不会有偏差?另外,如果后续扩展需求(比如给某些特定数据行加条件格式),直接在循环里加判断应该也不难吧?总之感谢分享,已经准备收藏代码改用到自己项目里了!
页: [1]
查看完整版本: openpyxl批量格式化Excel报表:标题蓝底加粗、边框、自动列宽与冻结首行