2016-04-15 18 views
1

私には問題があります。 私はまず自分の問題を説明します。そして、必要ならば、以下のコードを読んで実装の詳細を見ることができます。.xlsx生成でピボットテーブル計算を起動できません。

短い説明:

シート1:一般的なデータ 私は2枚を含むExcelブックを生成します。

シート2:汎用データにピボットテーブル。

POIを提供していたApacheの中には、バグがあることが証明されているため、Pivo​​tの基になるXML構造にアクセスしてPivotテーブルを作成しました。 xlsxドキュメント。ここでは、ピボットテーブルのフィールドと操作(この場合はCOUNT)を示します。

これを確認する自動JUnitテストを設計中です。これが問題に遭遇しました。

問題:ドキュメントを含むXLSXを生成する場合、ピボットテーブルが唯一の私は、クライアントで開く後の値で満たさ

クライアントでこれを開く前にピボットテーブルをプログラムでトリガーする方法があるかどうかを尋ねます。 Excelクライアントで開く前に

:Excelクライアントに

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

を開いた後

<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"/> 

ここ はXLSXドキュメントの基礎となるXML(pivotTable1.xml)の2つの部分であります生成されたExcelをJUnitで使用しようとすると、そのファイルを開く前に次のようにNULLが返されます。 currentWbSheet.getRow(0) ファイルを最初に開いてからテストを実行すると、これは起こりません。

ピボットテーブルを生成時に計算する方法、またはJavaアプリケーションからトリガする方法をピボットテーブルを生成する方法を知っていますか?

私の目標は、この生成されたxlsxを既知の( "ゴールデン")テストxlsxとセルごとに比較し、その内容が同一であることを確認することです。

コードサンプル: ワークブックシート作成:

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); 
} 

私は、メソッドの一部を上書きする私自身のピボットテーブルクラスを使用しています:

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(); 
     } 
    } 

答えて

0

に対する回避策この問題を私は一緒に出荷することができますVBScriptのアプリケーションを作成します私のプラグインとそれはプラグインからトリガーすることができます。

。このアプリケーションが実行するアクションは、Excelクライアントでパラメータとして受け取ったExcelファイルを開き、ファイルを保存してクライアントを閉じます。

。これにより、Excelが実行するPivotテーブルの生成手順がトリガされ、Pivo​​tテーブルを含むExcelが自動的に生成されます。

欠点:

。私はこれを実行するためにJavaライブラリの外に出なければなりません。

。エクセルクライアントを開く/保存して閉じるという余分な手順を実行する必要があります。私のWScript回避策について のコードは次のようになります。

excelOpenSave.vbs:

on error resume next 

薄暗いファイル名
ファイル名= 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(); 
    } 
}