公司要求所有报表统一格式:标题行加粗、蓝色背景、字号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)[0]
- 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[column_letter].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[1].height = 25
- # 批量设置所有行
- for row in range(1, max_row + 1):
- ws.row_dimensions[row].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格式,配合批量处理函数可快速完成大量报表格式化任务。 |