使用openpyxl迁移Excel模板列样式时仅首列生效的解决问询
解决列样式无法批量迁移的问题
问题原因
- 原代码仅处理CSV中有内容的单元格,空单元格完全未被处理——而Openpyxl不会自动将列的默认样式同步到空单元格,必须手动设置。
- 如果CSV某行的列数少于模板中设置样式的列数,后续列的单元格根本不会被遍历到,样式自然丢失。
修复方案
完整版代码(覆盖所有列)
下面的代码会处理所有需要的单元格,不管CSV里有没有数据,确保所有列样式都能保留:
import openpyxl import csv import sys import copy def apply_column_style(worksheet, cell): """把对应列的样式复制到单元格""" column_letter = cell.column_letter column_props = worksheet.column_dimensions.get(column_letter) if not column_props: return # 逐一复制样式属性 if column_props.fill: cell.fill = copy.copy(column_props.fill) if column_props.font: cell.font = copy.copy(column_props.font) if column_props.alignment: cell.alignment = copy.copy(column_props.alignment) if column_props.number_format: cell.number_format = copy.copy(column_props.number_format) def integrate_template_with_csv(template_path, csv_path, output_path): # 加载模板文件 template_wb = openpyxl.load_workbook(template_path) template_ws = template_wb.active # 读取CSV数据 with open(csv_path, newline='') as csvfile: csvreader = csv.reader(csvfile) csv_data = list(csvreader) # 确定要处理的最大行、列数:既要覆盖CSV数据,也要包含模板里设了样式的列 max_rows = max(len(csv_data), template_ws.max_row) styled_cols = template_ws.column_dimensions.keys() max_cols = 0 if csv_data: max_cols = max(len(row) for row in csv_data) if styled_cols: styled_col_indices = [openpyxl.utils.column_index_from_string(col) for col in styled_cols] max_cols = max(max_cols, max(styled_col_indices)) # 遍历所有单元格:先应用样式,再填数据 for row_idx in range(1, max_rows + 1): for col_idx in range(1, max_cols + 1): cell = template_ws.cell(row=row_idx, column=col_idx) if isinstance(cell, openpyxl.cell.cell.MergedCell): continue # 应用列样式 apply_column_style(template_ws, cell) # 填充CSV数据(如果对应位置有数据) if row_idx <= len(csv_data) and col_idx <= len(csv_data[row_idx-1]): cell_value = csv_data[row_idx-1][col_idx-1] if cell_value: cell.value = cell_value # 保存结果 template_wb.save(output_path) if __name__ == "__main__": output_path = sys.argv[1] csv_path = sys.argv[2] template_path = sys.argv[3] integrate_template_with_csv(template_path, csv_path, output_path) print(f"Data has been successfully integrated and saved as '{output_path}' file.")
关键修改点
- 去掉了原代码里判断单元格为空才应用样式的逻辑,新增
apply_column_style函数直接把列样式复制到每个单元格。 - 计算最大行、列数,确保模板里设了样式的列哪怕CSV没数据也会被处理。
- 先给所有单元格应用样式,再填充数据,避免样式被覆盖。
简化版(只处理CSV涉及的列)
如果不需要管CSV范围外的列,只修改原循环部分即可:
# 替换原integrate_template_with_csv里的填充循环 for row_idx, row_data in enumerate(csv_data, start=1): for col_idx, cell_value in enumerate(row_data, start=1): template_cell = template_ws.cell(row=row_idx, column=col_idx) if isinstance(template_cell, openpyxl.cell.cell.MergedCell): continue target_cell = template_ws.cell(row=row_idx, column=col_idx) # 直接应用列样式,不管单元格有没有值 apply_column_style(template_ws, target_cell) if cell_value: target_cell.value = cell_value
补充说明
Openpyxl里的列样式是「默认样式」,Excel显示时会自动套用,但保存文件时不会自动把默认样式写入每个单元格——必须手动复制,才能在输出文件里保留样式。用copy.copy()是为了避免多个单元格共用同一个样式实例,导致修改一个全变的问题。
内容的提问来源于stack exchange,提问作者Kim
相关产品推荐
相关产品推荐

