如何获取Excel单元格字体颜色,解决workbook.getFontAt().getColor()返回异常问题
问题解决方法
根因说明
你调用的getColor()是POI的旧API,仅返回调色板的索引色编号:
- 只有预设的标准索引色能返回正确编号,自定义RGB色、条件格式生成的动态颜色都会返回默认值0
- 字体索引一致不代表实际颜色相同,存在父样式继承、自定义色覆盖索引的情况
分步处理方案
1. 优先直接获取单元格实际生效字体(推荐)
POI 3.14及以上版本可以直接调用下面的方法获取字体,避免索引读取出错:
// 同时兼容.xls(HSSF)和.xlsx(XSSF)格式 Font font = cell.getCellStyle().getFont(workbook);
注意:如果使用的POI版本低于3.14,依然可以用你原来的
workbook.getFontAt(cell.getCellStyle().getFontIndex())获取字体,后续颜色读取逻辑不变。
2. 按格式类型读取实际RGB颜色值
不要用getColor()的返回值判断,直接读取颜色的RGB数值判断:
处理.xls格式
if (font instanceof HSSFFont) { HSSFFont hssfFont = (HSSFFont) font; HSSFColor color = hssfFont.getHSSFColor((HSSFWorkbook) workbook); if (color != null) { short[] rgb = color.getTriplet(); // 红色字体的红通道值接近255,绿、蓝通道接近0 boolean isRedFont = rgb[0] > 200 && rgb[1] < 50 && rgb[2] < 50; } }
处理.xlsx格式
if (font instanceof XSSFFont) { XSSFFont xssfFont = (XSSFFont) font; XSSFColor color = xssfFont.getXSSFColor(); if (color != null) { byte[] rgb = color.getRGB(); // 转换byte为无符号值再判断 int r = rgb[0] & 0xFF; int g = rgb[1] & 0xFF; int b = rgb[2] & 0xFF; boolean isRedFont = r > 200 && g < 50 && b < 50; } }
3. 红色为条件格式生成的额外处理
如果红色字体是Excel条件格式自动生成的,不是手动设置的单元格样式,直接读取cell.getCellStyle()拿不到动态样式,需要计算条件格式生效结果:
// 以XSSF格式为例 SheetConditionalFormatting scf = cell.getSheet().getSheetConditionalFormatting(); ConditionalFormattingEvaluator evaluator = new ConditionalFormattingEvaluator((XSSFWorkbook) workbook, scf); XSSFConditionalFormattingRule activeRule = evaluator.getConditionalFormattingResult(cell).getActiveRule(); if (activeRule != null) { XSSFFontFormatting fontFmt = activeRule.getFontFormatting(); if (fontFmt.isFontColorModified()) { XSSFColor color = fontFmt.getFontColor(); // 按上述XSSF颜色读取逻辑判断是否为红色即可 } }
内容的提问来源于stack exchange,提问作者kris82pl
相关产品推荐
相关产品推荐

