.xlsx代不能触发数据透视表计算

我需要一些帮助。 我首先要描述我的问题,然后,如果需要,可以阅读下面的代码并查看实现细节。

简短说明:我生成一个包含2张工作表的Excel工作簿:

表1:通用数据。

工作表2:通用数据透视表。

因为一些Apache提供的POI被certificate是越野车,我通过访问底层的XML结构创build了Pivot表。 xlsx文件。 在这里我指出了数据透视表字段和操作(在这种情况下计数)。

我现在正在devise自动JUnittesting来validation这一点,这是我遇到麻烦的地方。

问题:在生成包含文档的XLSX时,数据透视表仅在客户端中打开数据后才填充值。

我想询问是否有方法以编程方式触发数据透视表,然后再在客户端中打开它。 以下是xlsx文档的基础xml(pivotTable1.xml)的两个部分:

在excel客户端打开之前:

<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="A3:D7"/> <pivotFields count="8"> <pivotField showAll="false" axis="axisPage"> <items count="8"> <item t="default"/> <item t="default"/> <item t="default"/> 

在excel客户端打开后

 <pivotFields count="8"> <pivotField axis="axisPage" showAll="0"> <items count="2"> <item x="0"/> <item t="default"/> </items> 

如果我尝试在JUnit中使用生成的Excel,打开它之前,我得到一个NULL: currentWbSheet.getRow(0) 。 如果我先打开文件,然后运行testing,则不会发生这种情况。

你知道一种生成数据透视表的方法,这个数据透视表是按照代数来计算的,或者是如何从我的Java应用程序中触发它的?

我的目标是将这个生成的xlsx与一个已知的(“黄金”)xlsxtesting进行比较,并逐个validation它们的内容是否相同。

代码示例: 创build工作簿表单:

  private void createSheets(XSSFWorkbook wb) { generalDataSheet = wb.createSheet(GENERAL_DATA_SHEET_NAME); pivotTableSheet = wb.createSheet(PIVOT_TABLE_SHEET_NAME); } 

数据透视表的实现和使用细节:

 // Pivot table constants: // where the Table starts with the Report Filter field public static final String PIVOT_TABLE_SOURCE_START = "A1"; // Where the 2nd part of the pivot table starts with the Sum Values field public static final String PIVOT_TABLE_DATA_START = "A3:B3"; private static final String PIVOT_TABLE_NAME = " Pivot Table"; private static final int INTERFACE_NAME_CELL_POS = 0; private static final int PROVIDER_NAME_CELL_POS = 4; private static final int REQUESTER_NAME_CELL_POS = 6; … private void populatePivotTableSheet(List<MyDataSet> list) { //Set position of the pivot table in sheet CellReference pivotTableCellPosition = new CellReference(PIVOT_TABLE_SOURCE_START); //set source area for the pivot table AreaReference pivotTableSourceArea = getDefaultPivotTableSourceArea(list); // create pivot table and set attributespivotTable = new PivotTableMyTools(pivotTableSourceArea, PIVOT_TABLE_NAME); pivotTable.createPivotTable(pivotTableSheet, pivotTableCellPosition); // set the size of the pivot Table - this is because of a bug in regular API pivotTable.setRefField(PIVOT_TABLE_DATA_START); pivotTable.addRowLabelsField(PROVIDER_NAME_CELL_POS); pivotTable.addColumnLabelsField(REQUESTER_NAME_CELL_POS); pivotTable.addReportFilterField(INTERFACE_NAME_CELL_POS); pivotTable.addSumValuesField(DataConsolidateFunction.COUNT,PROVIDER_NAME_CELL_POS); } 

我得到数据透视表的源区域如下所示:

 private AreaReference getDefaultPivotTableSourceArea(Object linkSetList) { List< MyDataSet > list = (List< MyDataSet >) DataSetList; // construct the target area of the Pivot table // start cell is calculated as for ex: "General data!A2" CellReference c1 = new CellReference(GENERAL_DATA_SHEET_NAME + "!" + PIVOT_TABLE_SOURCE_START); String colName = CellReference.convertNumToColString(COLUMN_HEADERS.length - 1); // end cell is calculated as for ex: "General data!H5" CellReference c2 = new CellReference(GENERAL_DATA_SHEET_NAME + "!" + colName + (list.size() + 1)); return new AreaReference(c1, c2); } 

然后我使用我自己的Pivot表类来覆盖一些方法:

  public class PivotTableMyTools extends XSSFPivotTable implements IPivotTableMyTools { private XSSFSheet pivotTableSheet; // Sheet displaying information in pivot private AreaReference sourceDataArea; private XSSFPivotTable pivotTable; private int numberOfDataFields; private String pivotTableName; public PivotTableMyTools(AreaReference sourceDataArea, String pivotTableName) { this.sourceDataArea = sourceDataArea; numberOfDataFields = 0; this.pivotTableName = pivotTableName; } @Override public void createPivotTable(XSSFSheet destinationSheet, CellReference pivotTableCellPosition) { pivotTableSheet = destinationSheet; pivotTable = pivotTableSheet.createPivotTable(sourceDataArea, pivotTableCellPosition); pivotTable.getCTPivotTableDefinition().setName(pivotTableName); } // int fieldID is the ID of the field in the list of fields to be added to // the report (column headers of the source data area) @Override public void addReportFilterField(int fieldID) { int lastColIndex = getSourceAreaLastColumnIndex(); // create new pivot field with Column Specifications try { // throws index out of bounds checkColumnIndexOutOfBounds(fieldID, lastColIndex); // add pivot field to PivotTable, lastColindex also indicates the // number of columns addNewPivotField(fieldID, lastColIndex, STAxis.AXIS_PAGE); // Columns labels colField should be added. addNewCTPageField(fieldID); } catch (IndexOutOfBoundsException e) { Activator.logInfo("Column index is out of bounds"); Activator.logError(e.getMessage()); } } private void addNewCTPageField(int columnIndex) { CTPageFields pageFields; if (pivotTable.getCTPivotTableDefinition().getPageFields() != null) { pageFields = pivotTable.getCTPivotTableDefinition().getPageFields(); } else { pageFields = pivotTable.getCTPivotTableDefinition().addNewPageFields(); } // Set the fld and hier attributes CTPageField pageField = pageFields.addNewPageField(); pageField.setFld(columnIndex); pageField.setHier(-1); // set the count attribute pageFields.setCount(pageFields.sizeOfPageFieldArray()); } @Override public void addRowLabelsField(int columnIndex) { pivotTable.addRowLabel(columnIndex); } @Override public void addColumnLabelsField(int columnIndex) { int lastColIndex = getSourceAreaLastColumnIndex(); // create new pivot field with Column Specifications try { // throws index out of bounds checkColumnIndexOutOfBounds(columnIndex, lastColIndex); // add pivot field to PivotTable, lastColindex also indicates the // number of columns addNewPivotField(columnIndex, lastColIndex, STAxis.AXIS_COL); // Columns labels colField should be added. addNewCTColField(columnIndex); } catch (IndexOutOfBoundsException e) { Activator.logInfo("Column index is out of bounds"); Activator.logError(e.getMessage()); } } @Override public void addSumValuesField(DataConsolidateFunction function, int fieldID) { // pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, // PROVIDER_NAME_CELL_POS, "Provider count"); try { CTPivotField pivotField = getPivotField(fieldID); pivotField.setDataField(true); } catch (IndexOutOfBoundsException e) { Activator.logInfo("The selected column is out of current range"); Activator.logError(e.getMessage()); } addNewCTDataField(fieldID, "Count of Provider"); } private void addNewCTDataField(int fieldID, String fieldName) { numberOfDataFields++; CTDataFields dataFields = pivotTable.getCTPivotTableDefinition().addNewDataFields(); CTDataField dataField = dataFields.addNewDataField(); dataField.setName(fieldName); dataField.setFld(fieldID); dataField.setSubtotal(STDataConsolidateFunction.COUNT); dataField.setBaseField(0); dataField.setBaseItem(0); dataFields.setCount(numberOfDataFields); } private CTPivotField getPivotField(int fieldID) throws IndexOutOfBoundsException { CTPivotFields pivotFields = pivotTable.getCTPivotTableDefinition().getPivotFields(); if (null == pivotFields) throw new IndexOutOfBoundsException(); return pivotFields.getPivotFieldArray(4); } @Override public AreaReference getPivotTableSourceArea() { return sourceDataArea; } @Override public int getSourceAreaLastColumnIndex() { return (sourceDataArea.getLastCell().getCol() - sourceDataArea.getFirstCell().getCol()); } @Override public void setRefField(String pivotTableFieldArea) { CTLocation location = pivotTable.getCTPivotTableDefinition().getLocation(); location.setRef("A3:D7"); } /***************** private methods ***********************************/ private void addNewCTColField(int columnIndex) { CTColFields colFields; if (pivotTable.getCTPivotTableDefinition().getColFields() != null) { colFields = pivotTable.getCTPivotTableDefinition().getColFields(); } else { colFields = pivotTable.getCTPivotTableDefinition().addNewColFields(); } colFields.addNewField().setX(columnIndex); colFields.setCount(colFields.sizeOfFieldArray()); } private void addNewPivotField(int columnIndex, int numberOfItems, Enum axisValue) { IPivotFieldARTools pivotField = new PivotFieldARTools(); pivotField.setAxis(axisValue); pivotField.createItemsList(numberOfItems); pivotField.addToPivotTable(columnIndex, pivotTable); } private void checkColumnIndexOutOfBounds(int columnIndex, int lastColIndex) throws IndexOutOfBoundsException { if (columnIndex > lastColIndex && columnIndex < 0) { throw new IndexOutOfBoundsException(); } } 

解决这个问题,我将创build一个VBScript应用程序,我可以与我的插件一起出货,并可以从插件触发。

。 此应用程序将执行的操作是:在Excel客户端中打开作为参数接收的Excel文件,然后保存该文件并closures客户端。

。 这应该触发Excel执行的数据透视表生成步骤,并允许我使用数据透视表自动生成完整的Excel。

缺点:

。 我必须到达外部Java库来执行此操作。

。 我必须执行额外的步骤:打开/保存和closuresExcel客户端。 我的wscript解决方法的代码如下所示:

excelOpenSave.vbs:

 on error resume next 

昏迷文件名
filename = WScript.Arguments(0)

'WScript.Echo文件名

 Set objExcel = CreateObject("Excel.Application") objExcel.DisplayAlerts = False Set objWorkbook = objExcel.Workbooks.Open(filename) objExcel.Visible = true objWorkbook.RefreshAll objExcel.ActiveWorkbook.Save objExcel.ActiveWorkbook.Close SaveChanges=True objExcel.Application.Quit 'WScript.Echo "Finished." 'always deallocate after use... Set objWorkbook = Nothing Set objExcel = Nothing WScript.Quit 

我的Java代码是:

 public static void triggerOpenSaveCloseScript(String file) { String projPath = System.getProperty("user.dir"); String script = projPath + "\\Script\\excelOpenSave.vbs"; String command = "CScript " + script + " " + file; int exitValue = 0; try { Runtime rt = Runtime.getRuntime(); Process pr = rt.exec(command); exitValue = pr.waitFor(); //wait until script finishes } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { System.out.println("CScript exited with error: " + exitValue); e.printStackTrace(); } }