
本文详解如何使用 openpyxl 准确获取 excel(.xlsx)中合并单元格的实际背景色,避免因直接遍历导致颜色丢失或错位,提供可直接运行的健壮代码与关键注意事项。
本文详解如何使用 openpyxl 准确获取 excel(.xlsx)中合并单元格的实际背景色,避免因直接遍历导致颜色丢失或错位,提供可直接运行的健壮代码与关键注意事项。
在处理 Excel 文件样式信息时,一个常见但易被忽视的问题是:合并单元格(merged cells)的填充色仅存储在其起始单元格(top-left cell)中,其余合并区域内的单元格本身不保存 fill 属性。因此,若直接遍历每个坐标位置调用 cell.fill.start_color.index,非起始位置的合并单元格将返回默认(如 00000000 或 FFFFFFFF),导致颜色矩阵出现“空洞”或不一致——正如问题截图中第4行颜色断裂所示。
要真正还原用户在 Excel 中所见的视觉效果(即整块合并区域呈现统一背景色),必须显式识别单元格是否属于某个合并范围,并将其映射回对应合并区域的起始单元格(start_cell),再读取该单元格的填充色。
以下是推荐的完整实现方案(基于 openpyxl 3.1+,兼容 .xlsx):
from openpyxl import load_workbook
import numpy as np
import pandas as pd
def get_background_colors(excel_file: str) -> pd.DataFrame:
wb = load_workbook(excel_file, data_only=True, keep_styles=True) # ⚠️ 必须设 keep_styles=True!
ws = wb[wb.sheetnames[0]]
rows, cols = ws.max_row, ws.max_column
color_matrix = np.empty((rows, cols), dtype=object)
for i in range(1, rows + 1):
for j in range(1, cols + 1):
target_cell = ws.cell(row=i, column=j)
bg_color = "00000000" # fallback: transparent black
# Step 1: Check if current cell is inside any merged range
matched = False
for mcr in ws.merged_cells.ranges: # 注意:新版 openpyxl 使用 .ranges
if mcr.min_row <= i <= mcr.max_row and mcr.min_col <= j <= mcr.max_col:
# Get the top-left cell of this merged range — where style is stored
start_cell = ws.cell(row=mcr.min_row, column=mcr.min_col)
if start_cell.fill and start_cell.fill.start_color:
bg_color = start_cell.fill.start_color.rgb or "00000000"
matched = True
break
# Step 2: If not merged, use its own fill
if not matched and target_cell.fill and target_cell.fill.start_color:
bg_color = target_cell.fill.start_color.rgb or "00000000"
color_matrix[i-1, j-1] = str(bg_color)
return pd.DataFrame(color_matrix)
# 使用示例
df_colors = get_background_colors("example.xlsx")
print(df_colors.head())✅ 关键要点说明:
- keep_styles=True 是硬性要求:若省略,cell.fill 将为 None,所有颜色读取失败;
- ws.merged_cells.ranges 返回 MergedCellRange 对象列表(非旧版 merged_cells 的 NamedRange),需用 .min_row/.max_row/.min_col/.max_col 判断归属;
- 合并单元格的所有样式(含背景、字体、边框)均只保留在起始单元格,其他位置无冗余存储;
- start_color.rgb 返回标准 ARGB 十六进制字符串(如 "FF4472C4"),首两位 FF 表示不透明度(Alpha),可按需截取后6位作为 RGB 值;
- 不建议依赖 bfill 等后处理方式“修补”颜色——它无法区分真实颜色差异与合并导致的缺失,且破坏行列语义。
? 进阶提示:若需同时提取字体色、边框或条件格式色,逻辑同理——始终优先定位其所属合并区域的起始单元格,再读取对应属性。
通过上述方法,您将获得与 Excel 界面完全一致的背景色分布矩阵,为自动化报表校验、样式一致性分析或低代码数据看板提供可靠样式基础。


















