我正在尝试使用 Apache poi 创建数据透视表,除了一种情况外,一切正常。当我尝试在列和值(聚合器)中使用相同的列时,它不起作用。
例如,这是我的工作表,我想在列和值中添加“冰淇淋”列,然后它不起作用。
添加下面的列是枢轴代码:
addColumnLabel(pivotTable, dataSheet, areaReference, 0, true);
addColumnLabel(XSSFPivotTable pivotTable, Sheet dataSheet, AreaReference areaReference,
int column, boolean isColumn) {
try {
DataFormatter formatter = new DataFormatter(java.util.Locale.US);
java.util.TreeSet<String> uniqueItems = new java.util.TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (int r = areaReference.getFirstCell().getRow() + 1; r < areaReference.getLastCell().getRow()
+ 1; r++) {
uniqueItems.add(formatter.formatCellValue(dataSheet.getRow(r).getCell(column)));
}
if (isColumn) {
//pivotTable.addColLabel(column);
int lastColIndex = areaReference.getLastCell().getCol() - areaReference.getFirstCell().getCol();
CTPivotFields pivotFields = pivotTable.getCTPivotTableDefinition().getPivotFields();
CTPivotField pivotField = CTPivotField.Factory.newInstance();
CTItems items = pivotField.addNewItems();
pivotField.setAxis(STAxis.AXIS_COL);
pivotField.setShowAll(false);
for (int i = 0; i <= lastColIndex; i++) {
items.addNewItem().setT(STItemType.DEFAULT);
}
items.setCount(items.sizeOfItemArray());
pivotFields.setPivotFieldArray(column, pivotField);
// colfield should be added for the second one.
CTColFields colFields;
if (pivotTable.getCTPivotTableDefinition().getColFields() != null) {
colFields = pivotTable.getCTPivotTableDefinition().getColFields();
} else {
colFields = pivotTable.getCTPivotTableDefinition().addNewColFields();
}
colFields.addNewField().setX(column);
colFields.setCount(colFields.sizeOfFieldArray());
}
} catch (Exception e) {
e.printStackTrace();
}
}
并使用以下行添加聚合器:
pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 0, "Count of icecream");
Excel 正在导出,但显示修复并自动关闭。如果有人可以提供帮助,那就太好了。
输出应该是这样的:
Apache POI 不支持枢轴字段同时作为轴字段(行标签和/或列标签)和数据字段(小计字段)。
XSSFPivotTable.addRowLabel
将数据透视字段设置为具有轴设置和项目,但它会删除数据字段属性(如果存在)。
XSSFPivotTable.addColumnLabel
将数据透视表字段设置为具有数据字段属性的数据字段,但删除轴设置和项目(如果存在)。另外,它添加了一个数据字段,其中包含给定的小计和名称。
因此,如果您首先对同一字段执行
addRowLabel
,然后执行 addColumnLabel
,那么您将获得正确的数据字段,但获得没有轴设置和项目的数据透视字段。那失败了。
如果您首先对同一字段执行
addColumnLabel
,然后执行 addRowLabel
,那么您将获得正确的数据字段和具有轴设置和项目但没有数据字段属性的数据透视字段。那也失败了。
最短的解决方法是首先对同一字段执行
addColumnLabel
,然后执行 addRowLabel
,然后再次添加已删除的数据字段属性。
完整的示例,您创建正确的枢轴项目的努力放在一边:
import java.io.FileOutputStream;
import org.apache.poi.ss.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xssf.usermodel.*;
class CreatePivotTable {
public static void main(String[] args) throws Exception {
try (Workbook workbook = new XSSFWorkbook();
FileOutputStream fileout = new FileOutputStream("./Excel.xlsx") ) {
Sheet pivotSheet = workbook.createSheet("Pivot");
Sheet dataSheet = workbook.createSheet("Data");
Row row;
Cell cell;
Object[][] data = new Object[][]{
new Object[]{"icecream", "company"},
new Object[]{"blueberry", "abc"},
new Object[]{"mango", "xyz"},
new Object[]{"vanilla", "pqr"},
new Object[]{"blueberry", "abc"},
new Object[]{"mango", "xyz"},
new Object[]{"blueberry", "abc"},
new Object[]{"vanilla", "pqr"},
new Object[]{"blueberry", "abc"},
new Object[]{"vanilla", "pqr"}
};
for (int r = 0; r < data.length; r++) {
row = dataSheet.createRow(r);
Object[] rowData = data[r];
for (int c = 0; c < rowData.length; c++) {
cell = row.createCell(c);
if (rowData[c] instanceof String) {
cell.setCellValue((String)rowData[c]);
}
}
}
AreaReference areaReference = new AreaReference(
new CellReference(0,0),
new CellReference(data.length-1, data[0].length-1),
SpreadsheetVersion.EXCEL2007);
XSSFPivotTable pivotTable = ((XSSFSheet)pivotSheet).createPivotTable(areaReference, new CellReference("A4"), dataSheet);
// following sets pivot field 0 to be a data field having data field attribute but removes axis settings and items if present
// then it adds a data field having given subtotal and name for it
pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 0, "Count of icecream");
// following sets pivot field 0 to have axis settings and items
// but it removes data field attribute if present
pivotTable.addRowLabel(0);
// following re-adds data field attribute
pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).setDataField(true);
workbook.write(fileout);
}
}
}