【问题来源】
(特别注意首行是奇行还是偶行,这个地方由于游标很绕,所以花了点时间后面补上的)
我们设定了奇偶行后,可能要给一个自己喜欢的颜色,如果是用的easyExcel,那我们可能要绕点弯
【放松下】
如果你在为数不多的easyExcel案例和论坛的贴子花费了很多时间,
去解决这个问题,那可能真的是加班加多了,思路不对了
长达5小时的解题过程
让我得到了适用于部分情况的一个解题思路
【开始啦】
首先,我们需要获得一个奇偶行,
在原生的POI中,通过row.getRowNum() % 2 == 0很快拿到奇偶行,
但是在阿里巴巴封装的easyExcel中,并不是这么简单,
首先找到控制行的样式的地方(这个地方我找了一段时间,其实早就找对了,由于下面的“被污染的样式”,反反复复的)
行数是正常的,但与行对应的样式被我称为“被污染的样式”(自动换行也是样式被污染了,所以也有问题)
当我按正常思路去给奇偶行颜色,它都给了颜色,
经过上百次试错后,巴拉巴拉,我在网上搜索到一条至关重要的消息————新建个样式试试
这一下就对了,然后发现IndexedColors的颜色很单一,而且不方便做奇偶行(颜色太深、太艳...)
按照网络上的两种给颜色方法,发现都不能正常显色,问题出在alibaba中使用的是CellStyle
它是XSSFCellStyle和HSSFCellStyle的接口类,所以我们尝试网络上的方法是肯定有问题的,
于是,分析了源码后,debug出alibaba这里用XSSFCellStyle实现的,所以强转CellStyle,
然后设值,然后就对了。
【代码贴一下】
这部分的代码如下:
private CellStyle initNewCellStyle(ExcelProperty epj, int rowNum) {
CellStyle newCellStyle = context.getWorkbook().createCellStyle();
XSSFCellStyle xsStyle = (XSSFCellStyle)newCellStyle;
// 设置是否换行
boolean isWrapText = epj.isWrapText();
xsStyle.setWrapText(isWrapText);
// 设置奇偶行样式
// 数据首行为奇数行时奇数行不能有颜色
if(startRow % 2 != 0) {
if(rowNum % 2 != 0) {
//颜色转为16进制RGB码
String color = epj.foregroundColorForOddEven();
int r = Integer.parseInt((color.substring(0,2)),16);
int g = Integer.parseInt((color.substring(2,4)),16);
int b = Integer.parseInt((color.substring(4,6)),16);
XSSFColor myColor = new XSSFColor(new Color(r, g, b));
xsStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
xsStyle.setFillForegroundColor(myColor);
}
}else {
// 数据首行为偶数行时偶数行不能有颜色
if(rowNum % 2 == 0) {
//颜色转为16进制RGB码
String color = epj.foregroundColorForOddEven();
int r = Integer.parseInt((color.substring(0,2)),16);
int g = Integer.parseInt((color.substring(2,4)),16);
int b = Integer.parseInt((color.substring(4,6)),16);
XSSFColor myColor = new XSSFColor(new Color(r, g, b));
xsStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
xsStyle.setFillForegroundColor(myColor);
}
}
xsStyle.setBorderBottom(BorderStyle.THIN);
xsStyle.setBorderLeft(BorderStyle.THIN);
xsStyle.setBorderRight(BorderStyle.THIN);
return xsStyle;
}
粘贴下一位不知名的大佬给我的一点灵感:
无论我在解码函数的参数中设置了什么十六进制值,getIndexed函数都将始终返回黑色。
我可能做错了什么?
如果使用XSSF,而不是HSSF,那么解决问题相当容易。只需将样式变量转换为XSSFCellStyle。如果你这样做,那么有一个setFillForegroundColor的版本需要XSSFColor参数,所以你不需要调用getIndexed()。以下是一些示例代码:
XSSFCellStyle style = (XSSFCellStyle)cell.getCellStyle();
XSSFColor myColor = new XSSFColor(Color.RED);
style.setFillForegroundColor(myColor);
但是,如果您使用HSSF,则情况会更加困难。HSSF使用一个调色板,它只是一个颜色数组。传入setFillForegroundColor的短值是调色板中的索引。
所以你的问题是将rgb值转换成调色板索引。你提出的解决方案,使用getIndexed(),是合乎逻辑的,但是,不幸的是,它可以像你想象的那样为XSSFColor工作。
目前,让我们假设将使用默认调色板中的一种颜色而不是使用自定义颜色来满足其要求。在这种情况下,可以使用HSSFPalette和HSSFColor类来解决问题。以下是一些示例代码:
HSSFWorkbook hwb = new HSSFWorkbook();
HSSFPalette palette = hwb.getCustomPalette();
// get the color which most closely matches the color you want to use
HSSFColor myColor = palette.findSimilarColor(255, 0, 0);
// get the palette index of that color
short palIndex = myColor.getIndex();
// code to get the style for the cell goes here
style.setFillForegroundColor(palIndex);
如果想使用默认调色板中尚未存在的自定义颜色,则必须将它们添加到调色板中。HSSFPalette的javadoc定义了可用于这样做的方法。(我要赶工期,没有来得及测试下面这个,不过是有道理的,修改调色板的颜色,然后再取修改后的颜色)
HSSFWorkbook hwb = new HSSFWorkbook();
HSSFPalette palette = hwb.getCustomPalette();
palette.setColorAtIndex((short)9, (byte) r, (byte) g, (byte) b);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setFillForegroundColor((short)9);
其他的东西有时间再说