java - 通过 Apache POI 添加计算字段时遇到问题
问题描述
我正在尝试通过 Apache POI 添加计算字段,当只有一个非计算字段而其他字段是计算字段时我遇到了问题我在打开下面的 excel 表时遇到错误
但是当有多个非计算字段时,excel表不会抛出任何错误并且计算字段显示正常。
这是我的代码:
public static void main(String[] args) throws FileNotFoundException, IOException, InvalidFormatException {
createPivotTable();
}
private static void createPivotTable() throws IOException, FileNotFoundException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("1econtent");
XSSFSheet sheet1 = wb.createSheet("1e");
sheet1.setDisplayGridlines(false);
setCellData(sheet,wb);
AreaReference source = new AreaReference("A1:F5", SpreadsheetVersion.EXCEL2007);
CellReference position = new CellReference(0,0);
XSSFPivotTable pivotTable = sheet1.createPivotTable(source, position,wb.getSheet("1econtent"));
pivotTable.addRowLabel(2);
pivotTable.addRowLabel(0);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 3);
CTCacheFields ctCacheFields = pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields();
CTCacheField ctCacheField = ctCacheFields.addNewCacheField();
ctCacheField.setName("Field");
ctCacheField.setFormula("'Actuals' / 'Estimates'");
ctCacheField.setDatabaseField(false);
ctCacheFields.setCount(ctCacheFields.sizeOfCacheFieldArray());
CTPivotField pivotField = pivotTable.getCTPivotTableDefinition().getPivotFields().addNewPivotField();
pivotField.setDataField(true);
pivotField.setDragToCol(false);
pivotField.setDragToPage(false);
pivotField.setDragToRow(false);
pivotField.setShowAll(false);
pivotField.setDefaultSubtotal(false);
CTDataFields dataFields;
if(pivotTable.getCTPivotTableDefinition().getDataFields() != null) {
dataFields = pivotTable.getCTPivotTableDefinition().getDataFields();
} else {
dataFields = pivotTable.getCTPivotTableDefinition().addNewDataFields();
}
CTDataField dataField = dataFields.addNewDataField();
dataField.setName("Calculated Field");
dataField.setFld(pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCount()-1);
dataField.setBaseItem(0);
dataField.setBaseField(0);
DataFormat dataformat = pivotTable.getParentSheet().getWorkbook().createDataFormat();
short numFmtId = dataformat.getFormat("0.0%");
dataField.setNumFmtId(numFmtId);
try (FileOutputStream fileOut = new FileOutputStream("Output.xlsx")) {
wb.write(fileOut);
}
}
}
public static void setCellData(XSSFSheet sheet,XSSFWorkbook wb){
Row row1 = sheet.createRow(0);
// Create a cell and put a value in it.
Cell cell11 = row1.createCell(0);
cell11.setCellValue("Names");
Cell cell12 = row1.createCell(1);
cell12.setCellValue("Age");
Cell cell13 = row1.createCell(2);
cell13.setCellValue("Dept");
Cell cell14 = row1.createCell(3);
cell14.setCellValue("Salary");
Cell cell15 = row1.createCell(4);
cell15.setCellValue("Actuals");
Cell cell16 = row1.createCell(5);
cell16.setCellValue("Estimates");
Row row2 = sheet.createRow(1);
Cell cell21 = row2.createCell(0);
cell21.setCellValue("Adam");
Cell cell22 = row2.createCell(1);
cell22.setCellValue(22);
Cell cell23 = row2.createCell(2);
cell23.setCellValue("Sales");
Cell cell24 = row2.createCell(3);
cell24.setCellValue(10);
Cell cell25 = row2.createCell(4);
cell25.setCellValue(12);
Cell cell26 = row2.createCell(5);
cell26.setCellValue(60);
Row row3 = sheet.createRow(2);
Cell cell31 = row3.createCell(0);
cell31.setCellValue("Bran");
Cell cell32 = row3.createCell(1);
cell32.setCellValue(24);
Cell cell33 = row3.createCell(2);
cell33.setCellValue("Finance");
Cell cell34 = row3.createCell(3);
cell34.setCellValue(20);
Cell cell35 = row3.createCell(4);
cell35.setCellValue(24);
Cell cell36 = row3.createCell(5);
cell36.setCellValue(60);
Row row4 = sheet.createRow(3);
Cell cell41 = row4.createCell(0);
cell41.setCellValue("Jane");
Cell cell42 = row4.createCell(1);
cell42.setCellValue(23);
Cell cell43 = row4.createCell(2);
cell43.setCellValue("IT");
Cell cell44 = row4.createCell(3);
cell44.setCellValue(30);
Cell cell45 = row4.createCell(4);
cell45.setCellValue(30);
Cell cell46 = row4.createCell(5);
cell46.setCellValue(60);
Row row5 = sheet.createRow(4);
Cell cell211 = row5.createCell(0);
cell211.setCellValue("Dave");
Cell cell221 = row5.createCell(1);
cell221.setCellValue(30);
Cell cell231 = row5.createCell(2);
cell231.setCellValue("Sales");
Cell cell241 = row5.createCell(3);
cell241.setCellValue(50);
Cell cell251 = row5.createCell(4);
cell251.setCellValue(6);
Cell cell261 = row5.createCell(5);
cell261.setCellValue(60);
}
添加一个或多个列标签时没有错误。有人可以帮我解决这个问题。
预期输出只有一个非计算列和一个计算列,如下所示。
解决方案
如果有多个数据字段作为列字段,则数据透视表定义中有一个元素colFields
至少需要一个元素。field
但apache poi
如果只设置了一个列标签,则不会添加该字段,因为如果只存在一个列字段则不需要它。
但是由于您在低级别添加了一个数据字段作为列字段,因此它缺少该 colFields
字段。这就是在打开文件时出现错误的原因Excel
。
如果设置了多个列标签,则apache poi
添加该colFields
字段。这就是为什么它起作用的原因。
因此,在创建数据字段的低级别之后,将以下内容添加到您的代码中:
...
// at least one field in colFields is needed if there are multiple data fields
CTColFields colFields;
if(pivotTable.getCTPivotTableDefinition().getColFields() != null) {
colFields = pivotTable.getCTPivotTableDefinition().getColFields();
} else {
colFields = pivotTable.getCTPivotTableDefinition().addNewColFields();
}
CTField field;
if (colFields.getFieldList().size() == 0) {
field = colFields.addNewField();
field.setX(-2);
}
...
colFields
如果不存在,这会添加一个新元素。field
如果该元素尚未存在,它会在那里添加该元素。
再次完整的例子:
import java.io.FileOutputStream;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
class CreatePivotTableCalculatedFields {
public static void main(String[] args) throws Exception {
createPivotTable();
}
private static void createPivotTable() throws Exception {
try (XSSFWorkbook wb = new XSSFWorkbook();
FileOutputStream fileOut = new FileOutputStream("Output.xlsx")) {
XSSFSheet dataSheet = wb.createSheet("1econtent");
XSSFSheet pivotSheet = wb.createSheet("1e");
setCellData(dataSheet, wb);
AreaReference source = new AreaReference("A1:F5", SpreadsheetVersion.EXCEL2007);
CellReference position = new CellReference(0,0);
XSSFPivotTable pivotTable = pivotSheet.createPivotTable(source, position,wb.getSheet("1econtent"));
pivotTable.addRowLabel(2);
pivotTable.addRowLabel(0);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 3);
pivotSheet.setDisplayGridlines(false);
wb.setSelectedTab(1);
wb.setActiveSheet(1);
// customize pivot table
CTCacheFields ctCacheFields = pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields();
CTCacheField ctCacheField = ctCacheFields.addNewCacheField();
ctCacheField.setName("Field");
ctCacheField.setFormula("'Actuals' / 'Estimates'");
ctCacheField.setDatabaseField(false);
ctCacheFields.setCount(ctCacheFields.sizeOfCacheFieldArray());
CTPivotField pivotField = pivotTable.getCTPivotTableDefinition().getPivotFields().addNewPivotField();
pivotField.setDataField(true);
pivotField.setDragToCol(false);
pivotField.setDragToPage(false);
pivotField.setDragToRow(false);
pivotField.setShowAll(false);
pivotField.setDefaultSubtotal(false);
CTDataFields dataFields;
if(pivotTable.getCTPivotTableDefinition().getDataFields() != null) {
dataFields = pivotTable.getCTPivotTableDefinition().getDataFields();
} else {
dataFields = pivotTable.getCTPivotTableDefinition().addNewDataFields();
}
CTDataField dataField = dataFields.addNewDataField();
dataField.setName("Calculated Field");
dataField.setFld(pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCount()-1);
dataField.setBaseItem(0);
dataField.setBaseField(0);
DataFormat dataformat = pivotTable.getParentSheet().getWorkbook().createDataFormat();
short numFmtId = dataformat.getFormat("0.0%");
dataField.setNumFmtId(numFmtId);
// at least one field in colFields is needed if there are multiple data fields
CTColFields colFields;
if(pivotTable.getCTPivotTableDefinition().getColFields() != null) {
colFields = pivotTable.getCTPivotTableDefinition().getColFields();
} else {
colFields = pivotTable.getCTPivotTableDefinition().addNewColFields();
}
CTField field;
if (colFields.getFieldList().size() == 0) {
field = colFields.addNewField();
field.setX(-2);
}
wb.write(fileOut);
}
}
public static void setCellData(XSSFSheet sheet, XSSFWorkbook wb){
Object[][] data = new Object[][] {
new Object[] {"Names", "Age", "Dept", "Salary", "Actuals", "Estimates"},
new Object[] {"Adam", 22d, "Sales", 10d, 12d, 60d},
new Object[] {"Bran", 24d, "Finance", 20d, 24d, 60d},
new Object[] {"Jane", 23d, "IT", 30d, 30d, 60d},
new Object[] {"Dave", 30d, "Sales", 50d, 6d, 60d}
};
XSSFRow row;
XSSFCell cell;
for (int r = 0; r < data.length; r++) {
row = sheet.createRow(r);
for (int c = 0 ; c < data[r].length; c++) {
cell = row.createCell(c);
if (data[r][c] instanceof String) {
cell.setCellValue((String)data[r][c]);
} else if (data[r][c] instanceof Double) {
cell.setCellValue((Double)data[r][c]);
}
}
}
}
}
推荐阅读
- redisgraph - 目前是否可以在 redis-graph 中进行匹配交集查询?
- html - Woocommerce 产品选项 - 突出显示所选选项
- android - 带有 Glide 的 ImageSwitcher
- c# - 映射到模型
- inno-setup - 显示使用 Inno Setup 在安装期间执行的操作列表
- jquery - 在 dataTable ajax 请求期间,隐藏的表单控件永远不会被初始化
- java - Spring REST 响应显示原始 Java 对象而不是 JSON 元素
- javascript - 如何模拟非异步方法以使用 Jest 引发异常?
- python - 列表包含 NULL 字节,CSV DictReader
- javascript - 无法使用reactjs从firebase获取对象数组