XSSF(POI) – 将“公式”列添加到数据透视表

我正在使用POI 3.12-beta1:

<!-- Apache POI (for Excel) --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.12-beta1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.12-beta1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>ooxml-schemas</artifactId> <version>1.1</version> </dependency> 

我正在尝试创build一个计算的数据透视表列,它被定义为: = 'Ended' / 'Generated' * 100

我继续在Excel中手动编辑工作表,以使其正常工作。当我将*.xlsx文件反转为ZIP目录并查看它时,我在\xl\pivotCache\pivotCacheDefinition1.xmlfind了以下代码:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <pivotCacheDefinition xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId1" refreshOnLoad="1" refreshedBy="vyasrav" refreshedDate="42110.580247453705" createdVersion="3" refreshedVersion="3" minRefreshableVersion="3" recordCount="352"> <cacheSource type="worksheet"> <worksheetSource ref="A1:O353" sheet="Data"/> </cacheSource> <cacheFields count="16"> <!-- OMITTED --> <cacheField name="Avg Pct Processed" numFmtId="0" formula="'Ended' / 'Generated' * 100" databaseField="0"/> </cacheFields> </pivotCacheDefinition> 

所以我回到我的Java程序,并添加以下代码自动生成它,但它没有注册数据列“15”,我得到一个IndexOutOfBounds错误。

 // Add pivot (pivot table): Sheet pivotSheet = workbook.createSheet("Pivot"); LOGGER.trace("Created sheet: '" + String.valueOf(pivotSheet) + "'."); XSSFPivotTable pivotTable = ((XSSFSheet)pivotSheet).createPivotTable(new AreaReference(tableRange), new CellReference("A1"), dataSheet); CTPivotTableDefinition ctPivotTableDefinition = pivotTable.getCTPivotTableDefinition(); CTPivotTableStyle ctPivotTableStyle = ctPivotTableDefinition.getPivotTableStyleInfo(); ctPivotTableStyle.setName("PivotStyleMedium4"); // Row Labels: pivotTable.addRowLabel(...); // ... ... // Add column 15 (this is a calculated column): CTCacheFields ctCacheFields = pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields(); CTCacheField ctCacheField = ctCacheFields.addNewCacheField(); ctCacheField.setName("Avg Pct Processed"); ctCacheField.setFormula("'Ended' / 'Generated' * 100"); // Column Labels: pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 8, "Sum of Generated"); pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 12, "Sum of Ended"); pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 13, "Sum of Unended"); pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 15, "Average of Processed Percent"); ... 

发生在上面粗体行上的IndexOutOfBoundsException的StackTrace是:

 线程“main”中的exceptionjava.lang.IndexOutOfBoundsException
    在org.openxmlformats.schemas.spreadsheet.xml.x2006.main.impl.CTPivotFieldsImpl.setPivotFieldArray(Unknown Source)
    在org.apache.poi.xssf.usermodel.XSSFPivotTable.addDataColumn(XSSFPivotTable.java:372)
    在org.apache.poi.xssf.usermodel.XSSFPivotTable.addColumnLabel(XSSFPivotTable.java:296)
    在com ... 

有谁知道我怎么能使用兴趣点产生这个专栏?

编辑:

我尝试使用两个:

 CTPivotTableDefinition ctPivotTableDefinition = pivotTable.getCTPivotTableDefinition(); 

 CTCacheField ctCacheField = ctCacheFields.insertNewCacheField(15); 

在任何一种情况下,执行此行时都会得到相同的exception:

 pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 15, "Average of Processed Percent"); 

请注意,我尝试注释添加新列标签的行,当我这样做时,如果在Excel 2010中打开工作簿,启动时会出现以下错误消息:

 已从/xl/pivotTables/pivotTable1.xml部分删除function:数据透视表(数据透视表视图)
删除logging:从/xl/workbook.xml部分(工作簿)的工作簿属性 

谢谢!

我下一步解决了你的问题:

 //... get or create pivotTable //Use first column as row label pivotTable.addRowLabel(0); // 1. Add Formula to cache addFormulaToCache(pivotTable); // 2. Add PivotField for Formula column addPivotFieldForNewColumn(pivotTable); // 3. Add all column labels before our function.. pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1); //Set the third column as filter pivotTable.addColumnLabel(DataConsolidateFunction.AVERAGE, 2); // 4. Add formula column addFormulaColumn(pivotTable); 

这里是方法的实现:

 private static void addFormulaToCache(XSSFPivotTable pivotTable) { CTCacheFields ctCacheFields = pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields(); CTCacheField ctCacheField = ctCacheFields.addNewCacheField(); ctCacheField.setName("Field1"); // Any field name ctCacheField.setFormula("'Ended' / 'Generated' * 100"); ctCacheField.setDatabaseField(false); ctCacheField.setNumFmtId(0); ctCacheFields.setCount(ctCacheFields.sizeOfCacheFieldArray()); //!!! update count of fields directly } private static void addPivotFieldForNewColumn(XSSFPivotTable pivotTable) { CTPivotField pivotField = pivotTable.getCTPivotTableDefinition().getPivotFields().addNewPivotField(); pivotField.setDataField(true); pivotField.setDragToCol(false); pivotField.setDragToPage(false); pivotField.setDragToRow(false); pivotField.setShowAll(false); pivotField.setDefaultSubtotal(false); } private static void addFormulaColumn(XSSFPivotTable pivotTable) { CTDataFields dataFields; if(pivotTable.getCTPivotTableDefinition().getDataFields() != null) { dataFields = pivotTable.getCTPivotTableDefinition().getDataFields(); } else { // can be null if we have not added any column labels yet dataFields = pivotTable.getCTPivotTableDefinition().addNewDataFields(); } CTDataField dataField = dataFields.addNewDataField(); dataField.setName("Avg Pct Processed"); // set index of cached field with formula - it is the last one!!! dataField.setFld(pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCount()-1); dataField.setBaseItem(0); dataField.setBaseField(0); }