如何使用apache poi在excel透视表中生成汇总,平均值,行标签而不是列标签之类的聚合?

时间:2019-06-12 06:56:10

标签: java excel apache-poi pivot-table

我正在尝试使用apache-poi库生成一个Excel数据透视表。

Base data

What I want

当我尝试添加多个聚合时,Excel会将其分组为(您可以在行标签的第二张图片的右侧看到values属性)并放置 >在列中。我想默认使用行标签中的值生成一个excel。

但是当我添加总和和平均值之类的多个聚合时(如下图所示),会显示在列标签中。可以将拖到excel中的行标签上,但默认情况下我需要行中的值。

But I am able to generate this in java

这些聚合的代码

XSSFWorkbook wb = new XSSFWorkbook();
            XSSFSheet sheet = wb.createSheet();

            //Create some data to build the pivot table on
            setCellData(sheet);
            XSSFPivotTable pivotTable = null;
            try {
                pivotTable = sheet.createPivotTable(new AreaReference("A1:I8", SpreadsheetVersion.EXCEL2007), new CellReference("M10"));
            } catch (Exception ex) {
                System.out.println("In sheet: " + ex);
            }
            //Configure the pivot table
            //Use first column as row label
            pivotTable.addRowLabel(0);
            pivotTable.addRowLabel(1);

            pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(2).setAxis(STAxis.AXIS_COL);
            pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(2).addNewItems();
            pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(2).getItems().addNewItem()
                    .setT(STItemType.DEFAULT);
            pivotTable.getCTPivotTableDefinition().addNewColFields().addNewField().setX(1);
           //this.addCalculatedColumnToPivotTable(pivotTable, "field1", "average of count ab", "'count'");
            //Sum up the second column
            pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 3);
            //Set the third column as filter
            pivotTable.addColumnLabel(DataConsolidateFunction.AVERAGE, 3);

但是枢纽分析表中没有功能可将这些聚合添加到apache-poi库的行标签中。

1 个答案:

答案 0 :(得分:0)

使用最新的apache poi版本4.1.0,由于现在已有XSSFPivotTable.addColLabel,因此不再需要使用底层底层bean添加列标签。

但是到目前为止,还没有任何addRowLabel(DataConsolidateFunction function, int columnIndex)addColumnLabel(DataConsolidateFunction function, int columnIndex)将列和数据字段上的数据添加为col字段。因此,如果需要将行中的数据和数据字段作为行字段,则需要进行更改。

完整示例:

import java.io.FileOutputStream;

import org.apache.poi.ss.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xssf.usermodel.*;

import java.util.GregorianCalendar;

class CreatePivotTable {

 public static void main(String[] args) throws Exception {

  try (Workbook workbook = new XSSFWorkbook(); 
       FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {

   DataFormat format = workbook.createDataFormat();
   CellStyle dateStyle = workbook.createCellStyle();
   dateStyle.setDataFormat(format.getFormat("M\\/d\\/yy"));

   Sheet sheet = workbook.createSheet();

   String[] headers = new String[]{"Column1", "Column2", "Date", "Count"};
   Row row = sheet.createRow(0);
   Cell cell;
   for (int c = 0; c < headers.length; c++) {
    cell = row.createCell(c); cell.setCellValue(headers[c]);
   }

   Object[][] data = new Object[][]{
    new Object[]{"A", "B", new GregorianCalendar(2019, 0, 1), 2d},
    new Object[]{"A", "B", new GregorianCalendar(2019, 0, 1), 4d},
    new Object[]{"A", "B", new GregorianCalendar(2019, 0, 2), 1d},
    new Object[]{"A", "B", new GregorianCalendar(2019, 0, 2), 7d},
    new Object[]{"A", "C", new GregorianCalendar(2019, 0, 1), 5d},
    new Object[]{"A", "C", new GregorianCalendar(2019, 0, 1), 5d},
    new Object[]{"A", "C", new GregorianCalendar(2019, 0, 2), 2d},
    new Object[]{"A", "C", new GregorianCalendar(2019, 0, 2), 8d}
   };
   for (int r = 0; r < data.length; r++) {
    row = sheet.createRow(r+1);
    Object[] rowData = data[r];
    for (int c = 0; c < rowData.length; c++) {
     cell = row.createCell(c);
     if (rowData[c] instanceof String) {
      cell.setCellValue((String)rowData[c]);
     } else if (rowData[c] instanceof GregorianCalendar) {
      cell.setCellValue((GregorianCalendar)rowData[c]);
      cell.setCellStyle(dateStyle);
     } else if (rowData[c] instanceof Double) {
      cell.setCellValue((Double)rowData[c]);
     }
    }
   }

   XSSFPivotTable pivotTable = ((XSSFSheet)sheet).createPivotTable(new AreaReference("A1:D9", SpreadsheetVersion.EXCEL2007), new CellReference("M10"));

   pivotTable.addRowLabel(0);
   pivotTable.addRowLabel(1);

   pivotTable.addColLabel(2);

   // the default sets data on columns and data fields as col fields
   pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 3);
   pivotTable.addColumnLabel(DataConsolidateFunction.AVERAGE, 3);

   // now changing from the default
   // set dataOnRows
   pivotTable.getCTPivotTableDefinition().setDataOnRows(true);

   // add a new row field for data fields 
   pivotTable.getCTPivotTableDefinition().getRowFields().addNewField().setX(-2);
   pivotTable.getCTPivotTableDefinition().getRowFields().setCount(3);

   // remove data fields from col fields
   pivotTable.getCTPivotTableDefinition().getColFields().removeField(1);
   pivotTable.getCTPivotTableDefinition().getColFields().setCount(1);

   workbook.write(fileout);

  }

 }
}

xfieldrowFields元素中的colFields属性通常指定pivotField项目值的索引。但是dataFields可能与pivotField没有直接关系。

如果只有一个dataField,那么只有一种可能性可以显示出来。因此,不需要field元素。

但是,如果有多个dataField,则在透视表的Values视图中还有一个名为GUI的附加字段。在数据透视表XML中,其他字段使用-2编制索引。

因此,dataOnRows中的pivotTableDefinition确定dataField是显示在行(dataOnRows = "true")还是列(默认)上。 x-2的{​​{1}}元素中的field属性rowFields指定了附加colFields字段在以下列表中的排列位置领域。