UYOU
数据透视表定义中有一个元素,如果有多个数据字段作为列字段,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]); } } } } }