Apache POI 不应用某些颜色索引
Apache POI not applying certain color indices
Java 8 和 Apache POI 4.1.x 在这里。我有一些 Java 代码可以将对象列表写入 Excel 文件并且它的工作 完美 很好,除了一些基于颜色的单元格样式我我正在尝试申请:
public void applyPriceListDataCellStyle(PriceListItem priceListItem, Cell cell) {
short colorIndex;
switch(priceListItem.getChangeType()) {
case ADDITION:
colorIndex = IndexedColors.YELLOW.getIndex();
break;
case DELETION:
XSSFColor purple = new XSSFColor(new java.awt.Color(120,81,169), new DefaultIndexedColorMap());
colorIndex = purple.getIndex();
break;
case PRICE_ADJUSTMENT_INCREASE:
colorIndex = IndexedColors.RED.getIndex();
break;
case PRICE_ADJUSTMENT_DECREASE:
colorIndex = IndexedColors.GREEN.getIndex();
break;
default:
// NO_CHANGE (leave unstyled)
colorIndex = IndexedColors.WHITE.getIndex();
break;
}
Map<String,Object> cellProps = new HashMap<>();
cellProps.put(CellUtil.FILL_FOREGROUND_COLOR, colorIndex);
cellProps.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
CellUtil.setCellStyleProperties(cell, cellProps);
}
上面,applyPriceListDataCellStyle
方法在 从 Row
对象创建 Cell
之后被调用。然后将 cell
实例作为参数传递给此方法,连同我的 PriceListItem
bean(这是我写入 Excel 文件中每一行的数据)。
PriceListItem
bean 有一个 ChangeType
属性(枚举),它规定单元格在最终 Excel 文件中应显示的颜色。
在运行时,我在每个 ChangeType
值的 5 个不同行(因此 5 个不同 PriceListItems
)的单元格上调用此方法,我得到的输出如下所示:
所以:
- 第 1 行,即“
NO_CHANGE
”(映射到 IndexedColors.WHITE
)工作得很好,正如预期的那样
- 第 2 行是“
ADDITION
”(映射到 IndexedColors.YELLOW
),如预期的那样工作得很好
- 第 3 行是“
DELETION
”(映射到我的自定义 purple
颜色)显示为墨黑色 - 错误!
- 第 4 行,即“
PRICE_ADJUSTMENT_INCREASE
”(映射到 IndexedColors.RED
)显示为灰色 -- 错误!
- 第 5 行,即“
PRICE_ADJUSTMENT_DECREASE
”(映射到 IndexedColors.GREEN
)出现较浅的灰色阴影 -- 错误!
我在哪里设置这些不同行的单元格的颜色?
apache poi
CellUtil only works using org.apache.poi.ss.*
. It cannot work using a XSSFColor
because org.apache.poi.ss.usermodel.CellStyle
has no method to get/set fill foreground color from a XSSFColor
. It only works using short
color indexes from IndexedColors。因此是黑色,因为在你的代码中 purple.getIndex()
总是 returns 0
。因此,如果要使用 CellUtil
,这是推荐的,则从 IndexedColors
中选择一种颜色,而不是创建自定义颜色。例如有IndexedColors.VIOLET
但是其他错误的情况对我来说是不可重现的。以下 Minimal, Reproducible Example 按预期对我有效。它需要一个 price-list-template.xlsx
至少有一个工作表。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellUtil;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PoiColors {
public static void main(String[] args) throws IOException {
List<PriceListItem> priceList = new ArrayList<>();
PriceListItem noChange = new PriceListItem();
noChange.modelNumber = "123";
noChange.price = BigDecimal.valueOf(1.99);
noChange.changeType = ChangeType.NO_CHANGE;
PriceListItem addition = new PriceListItem();
addition.modelNumber = "456";
addition.price = BigDecimal.valueOf(2.99);
addition.changeType = ChangeType.ADDITION;
PriceListItem deletion = new PriceListItem();
deletion.modelNumber = "789";
deletion.price = BigDecimal.valueOf(3.99);
deletion.changeType = ChangeType.DELETION;
PriceListItem increase = new PriceListItem();
increase.modelNumber = "234";
increase.price = BigDecimal.valueOf(4.99);
increase.changeType = ChangeType.PRICE_ADJUSTMENT_INCREASE;
PriceListItem decrease = new PriceListItem();
decrease.modelNumber = "345";
decrease.price = BigDecimal.valueOf(5.99);
decrease.changeType = ChangeType.PRICE_ADJUSTMENT_DECREASE;
priceList.add(noChange);
priceList.add(addition);
priceList.add(deletion);
priceList.add(increase);
priceList.add(decrease);
new PoiColors().exportPriceList(priceList, "acme.xlsx");
}
private void exportPriceList(
List<PriceListItem> priceList,
String targetAbsPath) throws IOException {
// set variables based on specified format
String templateName = "price-list-template.xlsx";
// load the template
InputStream inp = this.getClass().getClassLoader().getResource(templateName).openStream();
Workbook workbook = WorkbookFactory.create(inp);
Sheet sheet = workbook.getSheetAt(0);
workbook.setSheetName(workbook.getSheetIndex(sheet), "ACME");
// plug in the header/metadata info and format some headers so they get autosized properly
Row row2 = CellUtil.getRow(1, sheet);
Cell c2 = CellUtil.getCell(row2, 2);
c2.setCellValue("ACME");
// create the data rows and apply styling
// start at row #11 which is where data rows begin
int rowNum = 11;
// rip through the items and write them to the rows; apply styling as appropriate
for (PriceListItem priceListItem : priceList) {
Row nextRow = sheet.createRow(rowNum);
Cell changeType = nextRow.createCell(0);
changeType.setCellValue(priceListItem.changeType.name());
applyPriceListDataCellStyle(priceListItem, changeType);
Cell modelNumber = nextRow.createCell(1);
modelNumber.setCellValue(priceListItem.modelNumber);
applyPriceListDataCellStyle(priceListItem, modelNumber);
Cell price = nextRow.createCell(2);
price.setCellValue(priceListItem.price.doubleValue());
applyPriceListDataCellStyle(priceListItem, price);
rowNum++;
}
// resize the columns appropriately
for (int c = 0; c < 3; c++) {
sheet.autoSizeColumn(c);
}
// export to file system
FileOutputStream fos = new FileOutputStream(targetAbsPath);
workbook.write(fos);
fos.close();
inp.close();
workbook.close();
}
private void applyPriceListDataCellStyle(PriceListItem priceListItem, Cell cell) {
short colorIndex;
switch(priceListItem.changeType) {
case ADDITION:
colorIndex = IndexedColors.YELLOW.getIndex();
break;
case DELETION:
colorIndex = IndexedColors.VIOLET.getIndex();
break;
case PRICE_ADJUSTMENT_INCREASE:
colorIndex = IndexedColors.RED.getIndex();
break;
case PRICE_ADJUSTMENT_DECREASE:
colorIndex = IndexedColors.GREEN.getIndex();
break;
default:
// NO_CHANGE (leave unstyled)
colorIndex = IndexedColors.WHITE.getIndex();
break;
}
Map<String,Object> cellProps = new HashMap<>();
cellProps.put(CellUtil.FILL_FOREGROUND_COLOR, colorIndex);
cellProps.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
CellUtil.setCellStyleProperties(cell, cellProps);
}
}
class PriceListItem {
public String modelNumber;
public BigDecimal price;
public ChangeType changeType;
}
enum ChangeType {
NO_CHANGE,
ADDITION,
DELETION,
PRICE_ADJUSTMENT_INCREASE,
PRICE_ADJUSTMENT_DECREASE
}
结果是 acme.xlsx
,看起来像这样:
使用 IndexedColors
在 Office Open XML
/xl/styles.xml
中设置颜色如下:
...
<fill>
<patternFill patternType="solid">
<fgColor indexed="13"/>
<bgColor indexed="64"/>
</patternFill>
</fill>
...
索引颜色不是由 RGB
给出的,而是取自默认调色板。如果您怀疑您的电子表格计算应用程序使用与 Excel
不同的默认调色板,那么您可以使用以下代码进行测试:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellUtil;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class TestIndexedColors {
public static void main(String[] args) throws Exception {
String templateName = "price-list-template.xlsx";
InputStream inp = TestIndexedColors.class.getClassLoader().getResource(templateName).openStream();
Workbook workbook = WorkbookFactory.create(inp);
Sheet sheet = workbook.getSheetAt(0);
Row row; Cell cell; int r = 11;
Map<String,Object> cellProps;
for (IndexedColors color : IndexedColors.values()) {
row = sheet.createRow(r++);
cell = row.createCell(0); cell.setCellValue(color.getIndex());
cell = row.createCell(1); cell.setCellValue(color.name());
cell = row.createCell(2);
cellProps = new HashMap<>();
cellProps.put(CellUtil.FILL_FOREGROUND_COLOR, color.getIndex());
cellProps.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
CellUtil.setCellStyleProperties(cell, cellProps);
}
FileOutputStream out = new FileOutputStream("acme.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
它需要一个 price-list-template.xlsx
至少有一个工作表。结果 acme.xlsx
使用当前默认调色板显示所有可能的索引颜色的索引、名称和颜色。
Java 8 和 Apache POI 4.1.x 在这里。我有一些 Java 代码可以将对象列表写入 Excel 文件并且它的工作 完美 很好,除了一些基于颜色的单元格样式我我正在尝试申请:
public void applyPriceListDataCellStyle(PriceListItem priceListItem, Cell cell) {
short colorIndex;
switch(priceListItem.getChangeType()) {
case ADDITION:
colorIndex = IndexedColors.YELLOW.getIndex();
break;
case DELETION:
XSSFColor purple = new XSSFColor(new java.awt.Color(120,81,169), new DefaultIndexedColorMap());
colorIndex = purple.getIndex();
break;
case PRICE_ADJUSTMENT_INCREASE:
colorIndex = IndexedColors.RED.getIndex();
break;
case PRICE_ADJUSTMENT_DECREASE:
colorIndex = IndexedColors.GREEN.getIndex();
break;
default:
// NO_CHANGE (leave unstyled)
colorIndex = IndexedColors.WHITE.getIndex();
break;
}
Map<String,Object> cellProps = new HashMap<>();
cellProps.put(CellUtil.FILL_FOREGROUND_COLOR, colorIndex);
cellProps.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
CellUtil.setCellStyleProperties(cell, cellProps);
}
上面,applyPriceListDataCellStyle
方法在 从 Row
对象创建 Cell
之后被调用。然后将 cell
实例作为参数传递给此方法,连同我的 PriceListItem
bean(这是我写入 Excel 文件中每一行的数据)。
PriceListItem
bean 有一个 ChangeType
属性(枚举),它规定单元格在最终 Excel 文件中应显示的颜色。
在运行时,我在每个 ChangeType
值的 5 个不同行(因此 5 个不同 PriceListItems
)的单元格上调用此方法,我得到的输出如下所示:
所以:
- 第 1 行,即“
NO_CHANGE
”(映射到IndexedColors.WHITE
)工作得很好,正如预期的那样 - 第 2 行是“
ADDITION
”(映射到IndexedColors.YELLOW
),如预期的那样工作得很好 - 第 3 行是“
DELETION
”(映射到我的自定义purple
颜色)显示为墨黑色 - 错误! - 第 4 行,即“
PRICE_ADJUSTMENT_INCREASE
”(映射到IndexedColors.RED
)显示为灰色 -- 错误! - 第 5 行,即“
PRICE_ADJUSTMENT_DECREASE
”(映射到IndexedColors.GREEN
)出现较浅的灰色阴影 -- 错误!
我在哪里设置这些不同行的单元格的颜色?
apache poi
CellUtil only works using org.apache.poi.ss.*
. It cannot work using a XSSFColor
because org.apache.poi.ss.usermodel.CellStyle
has no method to get/set fill foreground color from a XSSFColor
. It only works using short
color indexes from IndexedColors。因此是黑色,因为在你的代码中 purple.getIndex()
总是 returns 0
。因此,如果要使用 CellUtil
,这是推荐的,则从 IndexedColors
中选择一种颜色,而不是创建自定义颜色。例如有IndexedColors.VIOLET
但是其他错误的情况对我来说是不可重现的。以下 Minimal, Reproducible Example 按预期对我有效。它需要一个 price-list-template.xlsx
至少有一个工作表。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellUtil;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PoiColors {
public static void main(String[] args) throws IOException {
List<PriceListItem> priceList = new ArrayList<>();
PriceListItem noChange = new PriceListItem();
noChange.modelNumber = "123";
noChange.price = BigDecimal.valueOf(1.99);
noChange.changeType = ChangeType.NO_CHANGE;
PriceListItem addition = new PriceListItem();
addition.modelNumber = "456";
addition.price = BigDecimal.valueOf(2.99);
addition.changeType = ChangeType.ADDITION;
PriceListItem deletion = new PriceListItem();
deletion.modelNumber = "789";
deletion.price = BigDecimal.valueOf(3.99);
deletion.changeType = ChangeType.DELETION;
PriceListItem increase = new PriceListItem();
increase.modelNumber = "234";
increase.price = BigDecimal.valueOf(4.99);
increase.changeType = ChangeType.PRICE_ADJUSTMENT_INCREASE;
PriceListItem decrease = new PriceListItem();
decrease.modelNumber = "345";
decrease.price = BigDecimal.valueOf(5.99);
decrease.changeType = ChangeType.PRICE_ADJUSTMENT_DECREASE;
priceList.add(noChange);
priceList.add(addition);
priceList.add(deletion);
priceList.add(increase);
priceList.add(decrease);
new PoiColors().exportPriceList(priceList, "acme.xlsx");
}
private void exportPriceList(
List<PriceListItem> priceList,
String targetAbsPath) throws IOException {
// set variables based on specified format
String templateName = "price-list-template.xlsx";
// load the template
InputStream inp = this.getClass().getClassLoader().getResource(templateName).openStream();
Workbook workbook = WorkbookFactory.create(inp);
Sheet sheet = workbook.getSheetAt(0);
workbook.setSheetName(workbook.getSheetIndex(sheet), "ACME");
// plug in the header/metadata info and format some headers so they get autosized properly
Row row2 = CellUtil.getRow(1, sheet);
Cell c2 = CellUtil.getCell(row2, 2);
c2.setCellValue("ACME");
// create the data rows and apply styling
// start at row #11 which is where data rows begin
int rowNum = 11;
// rip through the items and write them to the rows; apply styling as appropriate
for (PriceListItem priceListItem : priceList) {
Row nextRow = sheet.createRow(rowNum);
Cell changeType = nextRow.createCell(0);
changeType.setCellValue(priceListItem.changeType.name());
applyPriceListDataCellStyle(priceListItem, changeType);
Cell modelNumber = nextRow.createCell(1);
modelNumber.setCellValue(priceListItem.modelNumber);
applyPriceListDataCellStyle(priceListItem, modelNumber);
Cell price = nextRow.createCell(2);
price.setCellValue(priceListItem.price.doubleValue());
applyPriceListDataCellStyle(priceListItem, price);
rowNum++;
}
// resize the columns appropriately
for (int c = 0; c < 3; c++) {
sheet.autoSizeColumn(c);
}
// export to file system
FileOutputStream fos = new FileOutputStream(targetAbsPath);
workbook.write(fos);
fos.close();
inp.close();
workbook.close();
}
private void applyPriceListDataCellStyle(PriceListItem priceListItem, Cell cell) {
short colorIndex;
switch(priceListItem.changeType) {
case ADDITION:
colorIndex = IndexedColors.YELLOW.getIndex();
break;
case DELETION:
colorIndex = IndexedColors.VIOLET.getIndex();
break;
case PRICE_ADJUSTMENT_INCREASE:
colorIndex = IndexedColors.RED.getIndex();
break;
case PRICE_ADJUSTMENT_DECREASE:
colorIndex = IndexedColors.GREEN.getIndex();
break;
default:
// NO_CHANGE (leave unstyled)
colorIndex = IndexedColors.WHITE.getIndex();
break;
}
Map<String,Object> cellProps = new HashMap<>();
cellProps.put(CellUtil.FILL_FOREGROUND_COLOR, colorIndex);
cellProps.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
CellUtil.setCellStyleProperties(cell, cellProps);
}
}
class PriceListItem {
public String modelNumber;
public BigDecimal price;
public ChangeType changeType;
}
enum ChangeType {
NO_CHANGE,
ADDITION,
DELETION,
PRICE_ADJUSTMENT_INCREASE,
PRICE_ADJUSTMENT_DECREASE
}
结果是 acme.xlsx
,看起来像这样:
使用 IndexedColors
在 Office Open XML
/xl/styles.xml
中设置颜色如下:
...
<fill>
<patternFill patternType="solid">
<fgColor indexed="13"/>
<bgColor indexed="64"/>
</patternFill>
</fill>
...
索引颜色不是由 RGB
给出的,而是取自默认调色板。如果您怀疑您的电子表格计算应用程序使用与 Excel
不同的默认调色板,那么您可以使用以下代码进行测试:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellUtil;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class TestIndexedColors {
public static void main(String[] args) throws Exception {
String templateName = "price-list-template.xlsx";
InputStream inp = TestIndexedColors.class.getClassLoader().getResource(templateName).openStream();
Workbook workbook = WorkbookFactory.create(inp);
Sheet sheet = workbook.getSheetAt(0);
Row row; Cell cell; int r = 11;
Map<String,Object> cellProps;
for (IndexedColors color : IndexedColors.values()) {
row = sheet.createRow(r++);
cell = row.createCell(0); cell.setCellValue(color.getIndex());
cell = row.createCell(1); cell.setCellValue(color.name());
cell = row.createCell(2);
cellProps = new HashMap<>();
cellProps.put(CellUtil.FILL_FOREGROUND_COLOR, color.getIndex());
cellProps.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
CellUtil.setCellStyleProperties(cell, cellProps);
}
FileOutputStream out = new FileOutputStream("acme.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
它需要一个 price-list-template.xlsx
至少有一个工作表。结果 acme.xlsx
使用当前默认调色板显示所有可能的索引颜色的索引、名称和颜色。