Openpyxl格式未应用至Excel工作簿问题排查
现有一个包含单个工作表「DuckSheet」的Excel工作簿,该工作表有3列,其中两列存储True/False二元值。计划按规则为这两列设置格式:通过字典指定工作表中各列需应用「bad_format」的目标值(例如,若列对应的规则值为True,则该列所有值为True的单元格需应用该格式)。
已编写Python代码,流程为:加载工作簿、调用generate_bad_format生成格式(返回[填充样式,字体样式]列表)、遍历工作表调用apply_formats_by_column按列应用格式。代码运行后,控制台输出显示已选中正确的单元格和格式,但实际Excel文件中无格式效果。
相关代码如下:
workbook_full_file_path = ("ducks.xlsx") duck_checks_by_column = {"DuckSheet": {'IsPecking?': False, 'IsOutofLake': True}} format_bad = generate_bad_format() wb = openpyxl.load_workbook(filename=workbook_full_file_path) for ws in wb: rules = duck_checks_by_column[ws.title] apply_formats_by_column(worksheet=ws, rules_by_column=rules, format_to_apply=format_bad)
def generate_bad_format(): """ Returns: A format as a list of structure [Fill, Font] """ red_fill = PatternFill(start_color='EE1111', end_color='EE1111', fill_type='solid') black_color_font = '000000' black_font = openpyxl.styles.Font(size=11, bold=True, color=black_color_font) bad_format = [red_fill, black_font] return bad_format
def apply_formats_by_column(worksheet, rules_by_column, format_to_apply): """ Args: worksheet: An openpyxl Excel sheet object. rules_by_column: 列名与目标值的字典,目标值指定需应用格式的二元值 format_to_apply: 格式列表,[Fill, Font] Returns: Nothing. 工作表原地格式化 """ last_row = worksheet.max_row + 1 for col_name, value_for_bad_format in rules_by_column.items(): for column_cells in worksheet.iter_cols(1, worksheet.max_column): if column_cells[0].value == col_name: column_number_to_format = column_cells[0].column print(f"TESTING: A column has been found to format:\n\nName: {col_name}\nNumber: {column_number_to_format}") for row in range(1, last_row): cell = worksheet.cell(row=row, column=column_number_to_format) print(f"TESTING: Now formatting this cell: {cell} with:\nFill: {format_to_apply[0]}\nFont: {format_to_apply[1]}") cell.fill = format_to_apply[0] cell.font = format_to_apply[1]
核心错误:未保存工作簿
代码只在内存中修改了工作簿对象,但最后没有调用wb.save()将修改写入磁盘文件。控制台能打印操作记录,但所有格式修改都停留在内存里,根本没保存到Excel文件中,这是格式不生效的直接原因。格式应用逻辑偏离需求
当前代码会给指定列的所有单元格都套上格式,完全没有判断单元格的值是否等于规则里的value_for_bad_format。比如规则要求IsOutofLake列中值为True的单元格才格式化,现在不管单元格是True还是False都会被修改,不符合最初的需求。列遍历逻辑冗余低效
在apply_formats_by_column里,对每个目标列名都要遍历所有列去匹配,没必要。openpyxl支持直接通过列名(比如worksheet['IsPecking?'])获取整列单元格,能大幅简化代码。
修复后的代码示例
主代码(添加保存逻辑)
workbook_full_file_path = "ducks.xlsx" duck_checks_by_column = {"DuckSheet": {'IsPecking?': False, 'IsOutofLake': True}} format_bad = generate_bad_format() wb = openpyxl.load_workbook(filename=workbook_full_file_path) for ws in wb: rules = duck_checks_by_column[ws.title] apply_formats_by_column(worksheet=ws, rules_by_column=rules, format_to_apply=format_bad) # 必须添加:保存修改后的工作簿 wb.save(workbook_full_file_path)
修复后的apply_formats_by_column函数(优化逻辑+匹配规则)
def apply_formats_by_column(worksheet, rules_by_column, format_to_apply): """ Args: worksheet: An openpyxl Excel sheet object. rules_by_column: 列名与目标值的字典,目标值指定需应用格式的二元值 format_to_apply: 格式列表,[Fill, Font] Returns: Nothing. 工作表原地格式化 """ fill_style, font_style = format_to_apply for col_name, target_value in rules_by_column.items(): # 直接通过列名获取整列,跳过第1行的表头单元格 for cell in worksheet[col_name][1:]: # 只给值匹配目标值的单元格应用格式 if cell.value == target_value: print(f"格式化单元格: {cell.coordinate},值为{cell.value}") cell.fill = fill_style cell.font = font_style
内容的提问来源于stack exchange,提问作者acolls_badger

