Apache POI XSSFPivotTable setDefaultSubtotal

我对axisRow pivotFields的setDefaultSubtotal方法有问题。 当我将RowLabel字段的值设置为false时,Excel不喜欢它。 手动设置我想要他们在Excel中的东西,然后保存产生显着不同的XML,对我来说太不同了,以考虑在幕后修复。 我不能(到目前为止)操纵XML来让POI电子表格在Excel中完整地打开。

实际的代码是有点长,难以发布,但这是一个可运行的一块与同样的问题:

private static void sample() throws IOException{ Workbook wb = new XSSFWorkbook(); String[][] data = new String[][]{{"STATUS","PASSED","VALUE"},{"BLUE","Y","20"},{"RED","N","10"},{"BLUE","N","30"}}; XSSFSheet sheet = (XSSFSheet) wb.createSheet("data"); XSSFSheet pivot = (XSSFSheet) wb.createSheet("summary"); for(String[] dataRow : data){ XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); for(String dataCell : dataRow){ XSSFCell cell = row.createCell(row.getPhysicalNumberOfCells()); cell.setCellValue(dataCell); } } XSSFTable table = sheet.createTable(); CTTable cttable = table.getCTTable(); table.setDisplayName("table"); cttable.setRef("A1:C4"); cttable.setId(1); CTTableColumns columns = cttable.addNewTableColumns(); columns.setCount(3); int i = 1; for (String colName : data[0]){ CTTableColumn column = columns.addNewTableColumn(); column.setId(++i); column.setName(colName); } XSSFPivotTable pivotTable = pivot.createPivotTable(new AreaReference("A1:C4", SpreadsheetVersion.EXCEL2007), new CellReference("A4"), sheet); pivotTable.addRowLabel(0); CTPivotField fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(0); fld.setOutline(false); //fld.setDefaultSubtotal(false); // uncomment and Excel has problems pivotTable.addRowLabel(1); fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(1); fld.setOutline(false); //fld.setDefaultSubtotal(false); // uncomment and Excel has problems pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 2, "test"); FileOutputStream fileOut = new FileOutputStream("c:/temp/pivotsample.xlsx"); wb.write(fileOut); wb.close(); } 

在生成POI版本时,这些是归档中的pivotTable XML的位置和pivotFields元素:

 <location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="F10:G11" colPageCount="1"/> <pivotFields count="5"> <pivotField axis="axisRow" showAll="false" compact="true" outline="false" defaultSubtotal="false"> <items count="4"> <item t="default"/> <item t="default"/> <item t="default"/> <item t="default"/> </items> </pivotField> <pivotField dataField="true" showAll="false"/> <pivotField dataField="true" showAll="false"/> <pivotField axis="axisPage" showAll="false"> <items count="4"> <item t="default"/> <item t="default"/> <item t="default"/> <item t="default"/> </items> </pivotField> <pivotField axis="axisRow" showAll="false" compact="true" outline="false" defaultSubtotal="false"> <items count="4"> <item t="default"/> <item t="default"/> <item t="default"/> <item t="default"/> </items> </pivotField> </pivotFields> 

当我在Excel中打开并允许它恢复工作表时,然后在Excel中进行更改以完成我想要的操作,即以表格forms显示两个没有小计的行标签,这是Excel保存的内容:

 <location ref="F10:I15" firstHeaderRow="1" firstDataRow="2" firstDataCol="2" rowPageCount="1" colPageCount="1"/> <pivotFields count="5"> <pivotField axis="axisRow" outline="0" showAll="0" defaultSubtotal="0"> <items count="3"> <item x="0"/> <item x="1"/> <item x="2"/> </items> </pivotField> <pivotField dataField="1" showAll="0"/> <pivotField dataField="1" showAll="0"/> <pivotField axis="axisPage" showAll="0"> <items count="3"> <item x="0"/> <item x="1"/> <item t="default"/> </items> </pivotField> <pivotField axis="axisRow" outline="0" showAll="0" defaultSubtotal="0"> <items count="2"> <item x="0"/> <item x="1"/> </items> </pivotField> </pivotFields> 

我已经尝试了几乎所有的东西,并且我理解Excel格式,但它依赖于pivotCacheRecords,所以最终我不得不编写代码来填充它。 如果有人可以看到为什么这个代码失败,我会很感激一个指针。

另请参见如何在“Apache POI数据透视表”报告filter中设置默认值 。

到目前为止,如果在数据范围内存在行,apache poi会添加types为“default”( <item t="default"/> )的枢轴字段项目。 这是因为他们不想查看数据,所以他们会假设与数据中的行数不同的值。

这很好,因为Excel将在打开时重build其透视caching。 但是如果我们想改变默认值,那么这就不好了。 那么我们必须知道有什么项目。

因此,我们至less需要与数据中的不同项目一样多的项目,如数字项目: <item x="0"/><item x="1"/>

我们需要构build一个具有这些项目共享元素的caching定义。

例:

 import org.apache.poi.xssf.usermodel.*; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.*; import org.apache.poi.ss.*; import java.io.*; import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; class PivotTableTest6 { public static void main(String[] args) throws IOException{ Workbook wb = new XSSFWorkbook(); String[][] data = new String[][]{{"STATUS","PASSED","VALUE"},{"BLUE","Y","20"},{"RED","N","10"},{"BLUE","N","30"}}; XSSFSheet sheet = (XSSFSheet) wb.createSheet("data"); XSSFSheet pivot = (XSSFSheet) wb.createSheet("summary"); for(String[] dataRow : data){ XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); for(String dataCell : dataRow){ XSSFCell cell = row.createCell(row.getPhysicalNumberOfCells()); cell.setCellValue(dataCell); } } XSSFTable table = sheet.createTable(); CTTable cttable = table.getCTTable(); table.setDisplayName("table"); cttable.setRef("A1:C4"); cttable.setId(1); CTTableColumns columns = cttable.addNewTableColumns(); columns.setCount(3); int i = 1; for (String colName : data[0]){ CTTableColumn column = columns.addNewTableColumn(); column.setId(++i); column.setName(colName); } XSSFPivotTable pivotTable = pivot.createPivotTable(new AreaReference("A1:C4", SpreadsheetVersion.EXCEL2007), new CellReference("A4"), sheet); pivotTable.addRowLabel(0); CTPivotField fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(0); fld.setOutline(false); /* Apache poi adds 4 pivot field items of type "default" (<item t="default"/>) here. This is because there are 4 rows (A1:C4) and, because they don't have a look at the data, they are assuming max 4 different values. This is fine because Excel will rebuild its pivot cache while opening. But if we want changing defaults, then this is not fine. Then we must know what items there are. So we need at least as much items, as are different ones in the data, as numbered items: <item x="0"/><item x="1"/> And we must build a cache definition which has shared elements for those items. */ for (i = 0; i < 2; i++) { //take the first 2 items as numbered items: <item x="0"/><item x="1"/> fld.getItems().getItemArray(i).unsetT(); fld.getItems().getItemArray(i).setX((long)i); } for (i = 3; i > 1; i--) { //remove further items fld.getItems().removeItem(i); } //set new items count fld.getItems().setCount(2); //build a cache definition which has shared elements for those items //<sharedItems><sv="Y"/><sv="N"/></sharedItems> pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldList().get(0).getSharedItems().addNewS().setV("Y"); pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldList().get(0).getSharedItems().addNewS().setV("N"); fld.setDefaultSubtotal(false); pivotTable.addRowLabel(1); fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(1); fld.setOutline(false); pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 2, "test"); FileOutputStream fileOut = new FileOutputStream("pivotsample6.xlsx"); wb.write(fileOut); wb.close(); } }