Apache POI向数据透视表添加新列

时间:2015-08-06 00:09:28

标签: apache-poi

我有一个数据透视表,其中包含列标签"总销售额"和"个人销售"。我想在数据透视表中添加一个新列来计算销售百分比(个人销售额/总销售额* 100)。我在将此新计算列添加到数据透视表时遇到问题。

我认为我的问题在于以下代码行。

ctCacheField.setFormula("'Individual Sales'/'Total Sales' * 100")  in
addFormulaToCache method.

注意:上述行中的单个销售额和总销售额是我在数据透视表中的列名。

这是我的完整代码。当我运行此代码时,它会生成Excel。但是当我打开Excel时,我收到错误,我没有看到数据透视表。

        AreaReference a=new AreaReference("Data!A1:C6");
        /* Define the starting Cell Reference for the Pivot Table */
        CellReference b=new CellReference("A1");
        /* Create the Pivot Table */
        XSSFPivotTable pivotTable = sheet1.createPivotTable(a,b);
        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.COUNT, 2, "Total Sales");
          pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1, "Individual Sales");
          addFormulaColumn(pivotTable);

        /* Write output to file */ 
        FileOutputStream output_file = new FileOutputStream(new File("C:\\POI_XLS_Pivot_Example.xlsx")); //create XLSX file
        new_workbook.write(output_file);//write excel document to output stream
        output_file.close(); //close the file
}


private static void addFormulaToCache(XSSFPivotTable pivotTable) {
    CTCacheFields ctCacheFields = pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields();
    CTCacheField ctCacheField = ctCacheFields.addNewCacheField();
    ctCacheField.setName("Field1"); // Any field name
    **ctCacheField.setFormula("'Individual Sales'/'Total Sales' * 100");** //This is where the problem could be
    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("%age Group Difference");
    // 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);
}

1 个答案:

答案 0 :(得分:0)

此问题是另一个问题的后续问题:XSSF (POI) - Adding “formula” column to pivot table

您问题的缺失部分是“个人销售”和“总销售额”是数据透视表中的虚拟列名。假设您的来源是:

Fruit  | Price
Apple  | 1.5
Orange | 1

获得Price * 2的公式自然会是“'Price'* 2”,无论数据透视表中的名称如何。如果您真的希望参考虚构的名称,您的公式会变得更加复杂。对于单元格A1中的数据透视表,对“个人销售”的引用将为:

GETPIVOTDATA("Individual Sales",$A$1,<Filter Name>,<Filter Value>)

但这违背了数据透视表的目的。 作为一个额外的注释,如果你愿意,所有三个valerii ryzhuk的答案都可以放在一个单一的功能中。除了解释答案外,它们不需要拆分。