Python3.8环境下xlsx转CSV再回导时如何捕获还原原文件样式
Python 3.8 环境下Excel样式捕获与落地方案
核心工具选型
- openpyxl是完全适配Python 3.8的开源工具,不存在无法直接调用样式类的问题,你之前觉得调用门槛高,本质是没有理清它的样式存储逻辑:openpyxl读取xlsx时会把每个单元格的字体、填充、边框、对齐、数字格式等样式信息直接绑定到
cell对象的对应属性上,不需要手动操作全局样式表类。 - 不需要走自定义XML存储样式的冗余路径,用openpyxl完成样式提取+回写即可,整套逻辑和现有pandas处理CSV的流程100%兼容,不需要改动原有数据读写的核心代码。
可直接复用的实现逻辑
在现有代码基础上,仅需要新增两个轻量环节,不需要重构原有流程:
- 提取数据阶段:保留原有pandas读xlsx、写CSV的逻辑,同步用openpyxl加载源xlsx,逐单元格读取样式信息,序列化为JSON文件和CSV配套存储。
- 回写数据阶段:保留原有pandas读CSV、写基础xlsx的逻辑,同步用openpyxl加载刚生成的xlsx文件,把之前存储的样式信息逐单元格回写,对齐原文件的视觉效果。
对应代码片段
样式提取代码(嵌入原有saveData函数即可)
from openpyxl import load_workbook import json # 原有pandas读写逻辑保持不变 read_excel = pd.read_excel(EXCEL_PATH_FROM) read_excel.to_csv(CSV_PATH, index=None, header=True) # 新增样式提取逻辑 wb_source = load_workbook(EXCEL_PATH_FROM, data_only=False) ws_source = wb_source.active style_map = {} # 遍历所有单元格提取样式 for row in ws_source.iter_rows(): for cell in row: style_map[cell.coordinate] = { 'font': cell.font.__dict__, 'fill': cell.fill.__dict__, 'border': cell.border.__dict__, 'alignment': cell.alignment.__dict__, 'number_format': cell.number_format } # 额外提取工作表级别的样式(列宽、行高、合并单元格) col_width = {col: ws_source.column_dimensions[col].width for col in ws_source.column_dimensions} row_height = {row: ws_source.row_dimensions[row].height for row in ws_source.row_dimensions} merged_ranges = [str(rng) for rng in ws_source.merged_cells.ranges] style_map['__sheet_meta__'] = { 'col_width': col_width, 'row_height': row_height, 'merged_ranges': merged_ranges } # 将样式映射存储为JSON,和CSV放在同一路径 with open(CSV_PATH.replace('.csv', '_style_meta.json'), 'w', encoding='utf-8') as f: json.dump(style_map, f, ensure_ascii=False, indent=2)
样式回写代码(嵌入原有createFromData函数即可)
from openpyxl import load_workbook from openpyxl.styles import Font, PatternFill, Border, Alignment import json # 原有pandas读写逻辑保持不变 csv = pd.read_csv(CSV_PATH) excel = pd.ExcelWriter(EXCEL_PATH_TO, engine='xlsxwriter') csv.to_excel(excel, index=None) excel.save() # 新增样式回写逻辑 wb_target = load_workbook(EXCEL_PATH_TO) ws_target = wb_target.active with open(CSV_PATH.replace('.csv', '_style_meta.json'), 'r', encoding='utf-8') as f: style_map = json.load(f) # 回写工作表元信息 sheet_meta = style_map.pop('__sheet_meta__') for col, width in sheet_meta['col_width'].items(): ws_target.column_dimensions[col].width = width for row, height in sheet_meta['row_height'].items(): ws_target.row_dimensions[row].height = height for rng in sheet_meta['merged_ranges']: ws_target.merge_cells(rng) # 逐单元格回写样式 for coord, style_attr in style_map.items(): cell = ws_target[coord] cell.font = Font(**style_attr['font']) cell.fill = PatternFill(**style_attr['fill']) cell.border = Border(**style_attr['border']) cell.alignment = Alignment(**style_attr['alignment']) cell.number_format = style_attr['number_format'] wb_target.save(EXCEL_PATH_TO)
关键注意点
- 整个流程完全不改动原有pandas处理数据的逻辑,仅在原有流程前后增加两个轻量的openpyxl处理环节,对现有业务的侵入性为零。
- 原计划的“转XML存储样式”思路完全没有必要,JSON格式的结构化样式信息和openpyxl的原生对象映射度最高,不需要做XML格式的解析、转换,减少额外的开发量。
- xlsxwriter作为纯写入引擎,不支持加载已生成的xlsx文件修改内容,不适合做样式回写环节,和现有流程的兼容性远不如openpyxl。
内容的提问来源于stack exchange,提问作者Alex Marasco
相关产品推荐
相关产品推荐

