【问题标题】:Getting Excel fill colors using Apache POI使用 Apache POI 获取 Excel 填充颜色
【发布时间】:2019-01-31 18:56:11
【问题描述】:

我正在使用 Apache POI 3.17 来阅读 Excel 2013 工作簿。工作簿由用户直接在 Excel 中创建和编辑。然后我运行一个使用 POI 读取和处理工作簿的 Java 8 程序。

有些单元格是用颜色编码的,所以我需要获取填充颜色。在许多情况下,这可以正常工作,但有一组灰色/银色不起作用,我不确定为什么。

例如,Excel 单元格如下所示:

我获取填充颜色的代码是:

private String getFillColor(XSSFCell cell) {
    String fColorString = "None";
    if (cell != null) {
        XSSFCellStyle cellStyle = cell.getCellStyle();
        
        short sColorFore = cellStyle.getFillForegroundColor();
        short sColorBack = cellStyle.getFillBackgroundColor();
        XSSFColor xColorFore =  cellStyle.getFillForegroundColorColor();
        XSSFColor xColorBack =  cellStyle.getFillBackgroundColorColor();

        String s = "";
        s += " indexFore=" + sColorFore;
        s += " indexBack=" + sColorBack;
        s += " colorFore=" + ((xColorFore == null) ? "Null" : xColorFore.getARGBHex());
        s += " colorBack=" + ((xColorBack == null) ? "Null" : xColorBack.getARGBHex());
        System.out.println("Cell=" + cell.getAddress() + " " + cell.getStringCellValue() + s);
        
        if (xColorFore != null) {
            fColorString = xColorFore.getARGBHex();
        }8
    }
    return fColorString;
}

对上面的每个示例 Excel 单元格调用时,结果如下:

Cell=BBH52 粉色 indexFore=0 indexBack=64 colorFore=FFF79646 colorBack=null

Cell=BBH53 无填充 indexFore=64 indexBack=64 colorFore=Null colorBack=Null

Cell=BBH54 灰色 1 indexFore=0 indexBack=64 colorFore=FFFFFFFF colorBack=null

Cell=BBH55 灰色 2 indexFore=0 indexBack=64 colorFore=FFFFFFFF colorBack=null

Cell=BBH56 灰色 3 indexFore=0 indexBack=64 colorFore=FFFFFFFF colorBack=null

Cell=BBH57 灰色 4 indexFore=0 indexBack=64 colorFore=FFFFFFFF colorBack=null

Cell=BBH58 灰色 5 indexFore=0 indexBack=64 colorFore=FFFFFFFF colorBack=null

Cell=BBH59 白色 indexFore=0 indexBack=64 colorFore=FFFFFFFF colorBack=null

知道为什么灰色和白色的阴影都转换为 FFFFFFFF 的十六进制值吗?是否有更正确的方法来访问实际的填充颜色?谢谢。

【问题讨论】:

    标签: java excel apache-poi


    【解决方案1】:

    “Excel 2013 工作簿”是以Office Open XML 格式存储的工作簿。那里的颜色可能有一个额外的第四个 alpha 通道,但也可能有ColorType.Tint property 集。所以实际上所有的灰色阴影都是RGB 白色FFFFFF 具有不同的tint 设置。例如在xl/styles.xml 中,Grey 1 是:

    ...
    <fill>
     <patternFill patternType="solid">
      <fgColor theme="0" tint="-0.0499893185216834"/>
      <bgColor indexed="64"/>
     </patternFill>
    </fill>
    ...
    

    主题颜色 0 为白色 FFFFFFtint -0.0499893185216834 将白色变暗为灰色。

    所以我们必须考虑tint。幸运的是apache poiExtendedColor为此提供了方法getRGBWithTint

    因此,如果设置了tint,以下示例也可以正确获取填充颜色:

    import java.io.FileInputStream;
    
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.xssf.usermodel.XSSFColor;
    import org.apache.poi.hssf.util.HSSFColor;
    
    public class ReadExcelColorHavingTint {
    
     private static String getFillColorHex(Cell cell) throws Exception { 
      String fillColorString = "none";
      if (cell != null) {
       CellStyle cellStyle = cell.getCellStyle();
       Color color =  cellStyle.getFillForegroundColorColor();
       if (color instanceof XSSFColor) {
        XSSFColor xssfColor = (XSSFColor)color;
        byte[] argb = xssfColor.getARGB();
        fillColorString = "[" + (argb[0]&0xFF) + ", " + (argb[1]&0xFF) + ", " + (argb[2]&0xFF) + ", " + (argb[3]&0xFF) + "]";
        if (xssfColor.hasTint()) {
         fillColorString += " * " + xssfColor.getTint();
         byte[] rgb = xssfColor.getRGBWithTint();
         fillColorString += " = [" + (argb[0]&0xFF) + ", " + (rgb[0]&0xFF) + ", " + (rgb[1]&0xFF) + ", " + (rgb[2]&0xFF) + "]" ;
        }
       } else if (color instanceof HSSFColor) {
        HSSFColor hssfColor = (HSSFColor)color;
        short[] rgb = hssfColor.getTriplet();
        fillColorString = "[" + rgb[0] + ", " + rgb[1] + ", "  + rgb[2] + "]";
       }
      }
      return fillColorString;
     }
    
     public static void main(String[] args) throws Exception {
      Workbook workbook = WorkbookFactory.create(new FileInputStream("workbook.xlsx"));
      //Workbook workbook = WorkbookFactory.create(new FileInputStream("workbook.xls"));
      Sheet sheet = workbook.getSheetAt(0);
      for (Row row : sheet) {
       for (Cell cell : row) {
    
        System.out.println("Cell=" + cell.getAddress() + " " + cell.toString() + " " + getFillColorHex(cell));
    
       }
      }
     }
    
    }
    

    【讨论】:

    • 完美答案 - 谢谢。我学到了一些东西,现在新代码为我的所有测试用例提供了正确的答案。