Python使用xlwings如何批量获取/设置Excel同范围不同单元格颜色
xlwings 批量读写多色单元格区域填充色
基础用法回顾
使用xlwings原生的.color属性可以很方便地读写单元格颜色,在区域为单色时运行正常:
import xlwings as xw # 定义RGB色值 green = (226, 239, 218) red = (252, 228, 214) grey = (242, 242, 242) # 连接目标Excel文件 wb = xw.Book(EXCEL_FILENAME) sht = wb.sheets[EXCEL_SHEETNAME] # 给整个区域设置灰色 sht.range("A1:C7").color = grey print(sht.range("A1:C7").color) # 输出 (242, 242, 242) # 给子区域设置对应颜色 sht['A1'].color = green print(sht.range("A1").color) # 输出 (226, 239, 218) sht['B2:B6'].color = green sht['A4:A6'].color = red print(sht.range("A4:A6").color) # 输出 (252, 228, 214) sht['C1'].color = red sht['C3:C7'].color = red
原生属性的局限:当区域内包含多种不同填充色时,.color无法返回各单元格的对应色值,只会返回固定值(0, 0, 0):
print(sht.range("A1:C7").color) # 多色场景下输出 (0, 0, 0)
xlwings原生已经支持批量获取区域的值、公式,返回和单元格位置一一对应的二维结构,使用逻辑统一:
# 批量获取区域值 print(sht.range("A1:C7").value) # 输出示例: [[1.0, 'b1', 3.0], [2.0, 3.0, None], [3.0, 'b3', 'c3'], [6.0, 'b4', 'c4'], [5.0, 'b5', 'c5'], [6.0, 'b6', 'c6'], [7.0, 'b7', 'c7']] # 批量获取区域公式 print(sht.range("A1:C7").formula) # 输出示例: (('1', 'b1', '=A1+2'), ('2', '=A2+1', ''), ('3', 'b3', 'c3'), ('=A3+3', 'b4', 'c4'), ('5', 'b5', 'c5'), ('6', 'b6', 'c6'), ('7', 'b7', 'c7'))
实现方案
通过直接调用Excel底层API一次性读写整个区域的颜色属性,避免逐单元格循环的性能损耗,实现和.value、.formula完全一致的调用体验,无需手动拆分同色连续区域。
批量读取颜色(返回pandas DataFrame)
import pandas as pd import xlwings as xw def get_range_colors(rng: xw.Range) -> pd.DataFrame: """ 批量读取指定区域所有单元格的填充色,返回行列与Excel完全对齐的DataFrame 无填充/白色填充的单元格返回None,色值格式为(R,G,B)元组,和原生.color属性兼容 """ # 一次性读取整个区域的底层颜色值(Excel原生为BGR格式整数) raw_colors = rng.api.Interior.Color row_count, col_count = rng.rows.count, rng.columns.count # 处理全区域单色场景:API直接返回单个整数值 if isinstance(raw_colors, (int, float)): b = raw_colors // 65536 g = (raw_colors % 65536) // 256 r = raw_colors % 256 color_grid = [[(r, g, b) for _ in range(col_count)] for _ in range(row_count)] else: # 多色场景:API返回二维数组,逐值转换为RGB格式 color_grid = [] for row in raw_colors: current_row = [] for val in row: # 16777215为Excel默认白色/无填充色值 if val == 16777215: current_row.append(None) else: b = val // 65536 g = (val % 65536) // 256 r = val % 256 current_row.append((r, g, b)) color_grid.append(current_row) # 生成带Excel原生行号、列名索引的DataFrame return pd.DataFrame( color_grid, index=list(range(rng.row, rng.row + row_count)), columns=[xw.utils.col_name(rng.column + i) for i in range(col_count)] )
批量写入颜色(支持二维列表/DataFrame)
def set_range_colors(rng: xw.Range, color_grid): """ 批量设置区域填充色,支持传入嵌套列表或pandas DataFrame 元素为(R,G,B)元组时设置对应颜色,为None时清除单元格填充 """ row_count, col_count = rng.rows.count, rng.columns.count # 提取DataFrame的值(如果传入的是DataFrame) grid_data = color_grid.values if hasattr(color_grid, 'values') else color_grid # 校验输入尺寸匹配 if len(grid_data) != row_count or any(len(r) != col_count for r in grid_data): raise ValueError("传入的颜色矩阵尺寸与目标区域不匹配") # 转换为Excel底层需要的BGR格式整数矩阵 bgr_grid = [] for row in grid_data: current_row = [] for color in row: if color is None: current_row.append(xw.constants.ColorIndex.xlNone) else: r, g, b = color current_row.append(b * 65536 + g * 256 + r) bgr_grid.append(current_row) # 一次性写入整个区域 rng.api.Interior.Color = bgr_grid
使用示例
# 单次调用读取A1:C7全区域颜色,返回DataFrame color_df = get_range_colors(sht.range("A1:C7")) print(color_df) # 输出示例(和之前手动设置的颜色完全对应): # A B C # 1 (226, 239, 218) (242, 242, 242) (252, 228, 214) # 2 (242, 242, 242) (226, 239, 218) (242, 242, 242) # 3 (242, 242, 242) (226, 239, 218) (252, 228, 214) # 4 (252, 228, 214) (226, 239, 218) (252, 228, 214) # 5 (252, 228, 214) (226, 239, 218) (252, 228, 214) # 6 (252, 228, 214) (226, 239, 218) (252, 228, 214) # 7 (242, 242, 242) (242, 242, 242) (252, 228, 214) # 批量写入颜色示例 new_colors = [[green, grey, red] for _ in range(7)] set_range_colors(sht.range("A1:C7"), new_colors)
说明
- 所有读写操作均为单次COM调用,无逐单元格循环,万级单元格区域操作也可在毫秒级完成
- 自动兼容单色、多色场景,不需要提前识别同色连续块
- 色值格式和xlwings原生
.color属性完全兼容,无额外适配成本 - 支持清除填充、返回行列对齐的结构化数据,和原生
.value、.formula的使用逻辑完全统一
内容的提问来源于stack exchange,提问作者Romain Capron
相关产品推荐
相关产品推荐

