2016-04-15 10 views
1

Ich brauche Hilfe mit einem Problem, das ich habe. Ich werde zuerst mein Problem beschreiben und dann, wenn Sie müssen, können Sie den folgenden Code lesen und die Implementierungsdetails sehen.Kann die Pivot-Tabelle-Berechnung für .xlsx-Generierung nicht auslösen

Kurzbeschreibung: I erzeugen eine Excel-Arbeitsmappe mit 2 Blatt:

Blatt 1: allgemeine Daten.

Blatt 2: Pivot-Tabelle über die generischen Daten.

Da einige der von Apache bereitgestellten POI fehlerhaft waren, habe ich die Pivot - Tabelle erstellt, indem ich auf die zugrunde liegende XML - Struktur der. xlsx Dokument. In diesem gebe ich die Felder und Operationen der Pivot-Tabelle an (COUNT in diesem Fall).

Ich entwerfe jetzt automatische JUnit-Tests, um dies zu überprüfen, und das ist, wo ich in Schwierigkeiten geriet.

Problem: Wenn die XLSX- Erzeugen das Dokument enthält, wobei die Pivot-Tabelle füllt nur mit Werten nach ich es in dem Client.

Ich möchte fragen, ob es eine Möglichkeit gibt, die Pivot-Tabelle programmgesteuert auszulösen, bevor ich diese im Client öffne. Hier gibt es 2 Sektionen der zugrunde liegenden XML des xlsx doc (pivotTable1.xml):

Vor dem Öffnen in Excel Client:

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

Nach dem Öffnen in Excel-Client

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

Wenn ich versuche, das generierte Excel in einer JUnit zu verwenden, bekomme ich vor dem Öffnen einen NULL: currentWbSheet.getRow(0). Das passiert nicht, wenn ich zuerst die Datei öffne und dann den Test starte.

Wissen Sie, wie Sie die Pivot-Tabelle so generieren können, dass die Pivot-Tabelle bei der Generierung berechnet wird oder wie sie aus meiner Java-Anwendung ausgelöst wird?

Mein Ziel ist es, diese erzeugte xlsx gegen einen bekannten ("goldenen") Test xlsx Zelle für Zelle zu vergleichen und zu verifizieren, dass ihr Inhalt identisch ist.

Codebeispiele: Arbeitsmappe Blatt Erstellung:

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

Pivot-Tabelle Implementierung und Nutzung Details:

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

ich den Quellbereich wie für die Pivot-Tabelle erhalten:

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

ich dann meine eigene Pivot-Tabelle-Klasse einige der Methoden zu überschreiben:

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

Antwort

0

Um Abhilfe dieses Problem werde ich eine VBScript Anwendung erschaffen, die ich zusammen versenden mit mein Plugin und das kann vom Plugin ausgelöst werden.

. Die Aktionen, die diese Anwendung ausführt, sind: Öffnen Sie eine Excel-Datei, die als Parameter im Excel-Client empfangen wird, speichern Sie die Datei und schließen Sie den Client.

. Das sollte die Pivot-Tabellengenerierungsschritte auslösen, die Excel ausführt, und es mir ermöglichen, das vollständige Excel mit der Pivot-Tabelle automatisch zu generieren.

Nachteile:

. Ich muss außerhalb Java-Bibliotheken erreichen, um dies durchzuführen.

. Ich muss die zusätzlichen Schritte ausführen: Öffnen/Speichern und Schließen des Excel-Clients. Der Code für meine wscript Abhilfe sieht wie folgt aus:

excelOpenSave.vbs:

on error resume next 

Dim Dateiname
filename = WScript.Arguments (0)

‚WScript.Echo Dateiname

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 

Mein Java-Code lautet:

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