Apache POI 4.0:如何从java.awt.Color转换为XSSFColor

7

org.apache.poi 4.0移除了只使用java.awt.ColorXSSFColor构造函数。在org.apache.poi 3.7中,只需编写以下语句即可轻松创建对象:

Color inputColor = Color.RED;
XSSFColor test = new XSSFColor(inputColor);

然而,这个构造函数在4.0版本中不再起作用。文档https://poi.apache.org/apidocs/dev/org/apache/poi/xssf/usermodel/XSSFColor.html显示了几个其他的构造函数,但是我希望尽可能少地更改代码。所以我的问题是,在apache poi 4.0中,从java.awt.Color创建XSSFColor的最佳方法是什么?
根据评论中的要求,这是我的测试代码,使用建议style.setFillForegroundColor(new XSSFColor(java.awt.Color.RED, null));。用LibreOffice 6.1打开会出现错误(尝试修复,但失败)。注释掉正常工作的POI 3.7版本。
@Test
public void testPOI40() throws FileNotFoundException, IOException {
    Workbook workbook = new XSSFWorkbook();
    XSSFSheet fSheet = (XSSFSheet) workbook.createSheet("new Sheet");
    XSSFRow hRow = fSheet.createRow((short) 0);
    //header
    String[] astrHeaders = new String[]{"Header1", "Header2", "Header3", "Header4"};
    for (int col = 0; col < astrHeaders.length; col++) {
        XSSFCell cell = hRow.createCell((short) col);
        XSSFCellStyle tempHeaderStyle = (XSSFCellStyle) workbook.createCellStyle();
        tempHeaderStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        tempHeaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cell.setCellValue(astrHeaders[col]);
        cell.setCellStyle(tempHeaderStyle);
    }        
    //body
    Double[] astrContent = new Double[]{1.3, 0.3, 0.87, 1.0};     
    Color[] colors = new Color[] {Color.RED,Color.BLUE,Color.WHITE,Color.GREEN};        
    XSSFRow fRow = fSheet.createRow((short) 1);
    for (int iCol = 0; iCol < 4; iCol++) {
        XSSFCell cell = fRow.createCell((short) iCol);
        XSSFCellStyle tempBodyStyle = (XSSFCellStyle) workbook.createCellStyle();
        cell.setCellValue(astrContent[iCol]);
        //working with POI 3.17
        //tempBodyStyle.setFillForegroundColor(new XSSFColor(colors[iCol]));
        tempBodyStyle.setFillForegroundColor(new XSSFColor(colors[iCol],null));
        tempBodyStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cell.setCellStyle(tempBodyStyle);
    }        
    FileOutputStream fileOut = new FileOutputStream(new File("testfile.xlsx"));
    BufferedOutputStream bos = new BufferedOutputStream(fileOut);
    workbook.write(bos);
    fileOut.close();
}

解决方案:
fileout.close();替换为bos.close();即可解决问题。如评论中Alex Richter所建议的tempBodyStyle.setFillForegroundColor(new XSSFColor(Color.RED,null));是一个好的解决方案,我会接受这个答案。


感谢您的回答,但是第一种方法生成的表格在尝试打开时报告为已损坏。第二种方法失败,因为setColor(Color)ExtendedColor中具有受保护的访问权限。 - ptstone
2
抱歉,但是在使用apache poi 4.0.0并从头开始创建XSSFWorkbook时,style.setFillForegroundColor(new XSSFColor(java.awt.Color.RED, null));对我有效。请提供一个最小完整可验证的示例,以显示它失败的地方。 - Axel Richter
谢谢,我现在已经将您的建议添加到主帖中的测试中了。 - ptstone
只是为了澄清,代码并不会导致错误,但输出文件无法读取(但使用POI 3.7的版本(请参见注释部分)是可读的)。 - ptstone
2
损坏与颜色无关。您正在将FileOutputStream包装在BufferedOutputStream中,但仅关闭内部的FileOutputStream而不是BufferedOutputStream。执行workbook.write(bos); bos.close();,它就会起作用。至少对我来说是这样的。在以前的apache poi版本中可能已经起作用了,因为Workbook.write在准备好时关闭了所有流。现在不再这样做了。 - Axel Richter
你是对的!之前没有注意到这个问题,因为在POI 3.7中它可以正常工作,但确实是缺少了bos.close()。如果你想把style.setFillForegroundColor(new XSSFColor(java.awt.Color.RED, null));作为答案,我肯定会接受。 - ptstone
1个回答

10
如果你将FileOutputStream包装在BufferedOutputStream中,但是只关闭内部的FileOutputStream而不关闭BufferedOutputStream,那么BufferedOutputStream仍然保持打开状态,文件将不会拥有所有字节。

这就是为什么文件受损的原因。

因此,文件受损与构造XSSFColor无关。构造函数style.setFillForegroundColor(new XSSFColor(java.awt.Color.RED, null));是有效的。

请改用以下方式:

...
FileOutputStream fileOut = new FileOutputStream(new File("testfile.xlsx"));
BufferedOutputStream bos = new BufferedOutputStream(fileOut);
workbook.write(bos); 
bos.close();
workbook.close();
...

在早期的apache poi版本中,这可能起作用,因为XSSFWorkbook.write在准备好后关闭了所有流。但现在它不再这样做了。这是正确的,因为write不应该关闭流。

但是,由于POIXMLDocument实现了java.io.Closeable,至少workbook.close()应该关闭所有流。但它也没有这样做。因此,在apache poi 4.0.0中显式地关闭所有流是必要的。


2
再次感谢。你能否在答案中添加一行 tempBodyStyle.setFillForegroundColor(new XSSFColor(Color.RED,null));,以便那些只寻找一行代码来替换旧方法(而不是对我的示例感兴趣)的人可以使用? - ptstone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接