简体   繁体   中英

java: How to create a pivot with apache poi?

I'm trying to create an Excel Pivot with apache poi, but I dont really understand how to create the format that I want. I use this code to create, but I get empty values:

XSSFPivotTable pivotTable = sheet.createPivotTable(aref, pos);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 2, colNames[2]);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 3, colNames[3]);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 0, colNames[0]);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1, colNames[1]);

My data looks like this:

在此处输入图片说明

and I want it to look like this:

在此处输入图片说明

How do I achieve that?

Apache poi has only rudimentary support for creating pivot tables. It only creates default pivot tables but is not able creating special settings without falling back to the underlying ooxml-schemas classes.

For your data source the following code creates what apache poi supports by default:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.*;

class CreatePivotTableDefault {

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

  try (XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("ExcelSource.xlsx")); 
       FileOutputStream fileout = new FileOutputStream("ExcelResult.xlsx") ) {

   XSSFSheet dataSheet = workbook.getSheetAt(0);
   XSSFSheet pivotSheet = workbook.createSheet("Pivot");

   AreaReference areaReference = new AreaReference("A1:D5", SpreadsheetVersion.EXCEL2007);

   XSSFPivotTable pivotTable = pivotSheet.createPivotTable(areaReference, new CellReference("A1"), dataSheet);

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

   workbook.write(fileout);

  }

 }
}

This creates a pivot table in outline format, which is the default.

If you wants creating a pivot table which is not in outline format and is not showing subtotals for each field, we need using the underlying ooxml-schemas classes. We need creating the correct pivot table field items. And we need to build a cache definition which has shared elements for those items. See also Apache POI XSSFPivotTable setDefaultSubtotal .

The following code should create the pivot table you wants from your data source:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotField;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.usermodel.*;

class CreatePivotTable {

 static void addRowLabel(XSSFPivotTable pivotTable, XSSFSheet dataSheet, AreaReference areaReference, int column) { 

  DataFormatter formatter = new DataFormatter(java.util.Locale.US);
  //create row label - apache poi creates as much fields for each as rows are in the pivot table data range
  pivotTable.addRowLabel(column);

  //determine unique labels in column
  java.util.TreeSet<String> uniqueItems = new java.util.TreeSet<String>();
  for (int r = areaReference.getFirstCell().getRow()+1; r < areaReference.getLastCell().getRow()+1; r++) {
   uniqueItems.add(formatter.formatCellValue(dataSheet.getRow(r).getCell(column)));
  }
  //System.out.println(uniqueItems);

  //build pivot table and cache
  CTPivotField ctPivotField = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(column);
  int i = 0;
  for (String item : uniqueItems) {
   //take the items as numbered items: <item x="0"/><item x="1"/>
   ctPivotField.getItems().getItemArray(i).unsetT();
   ctPivotField.getItems().getItemArray(i).setX((long)i);
   //build a cache definition which has shared elements for those items 
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(column)
    .getSharedItems().addNewS().setV(item);
   i++;
  }

  //set pivot field settings
  ctPivotField.setOutline(false); // no outline format
  ctPivotField.setDefaultSubtotal(false); // no subtotals for this field

  //remove further items
  if (ctPivotField.getDefaultSubtotal()) i++; //let one default item be if there shall be subtotals
  for (int k = ctPivotField.getItems().getItemList().size()-1; k >= i; k--) {
   ctPivotField.getItems().removeItem(k);
  }
  ctPivotField.getItems().setCount(i);

 }

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

  try (XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("ExcelSource.xlsx")); 
       FileOutputStream fileout = new FileOutputStream("ExcelResult.xlsx") ) {

   XSSFSheet dataSheet = workbook.getSheetAt(0);
   XSSFSheet pivotSheet = workbook.createSheet("Pivot");

   AreaReference areaReference = new AreaReference("A1:D5", SpreadsheetVersion.EXCEL2007);

   XSSFPivotTable pivotTable = pivotSheet.createPivotTable(areaReference, new CellReference("A1"), dataSheet);

   addRowLabel(pivotTable, dataSheet, areaReference, 2);
   addRowLabel(pivotTable, dataSheet, areaReference, 3);
   addRowLabel(pivotTable, dataSheet, areaReference, 0);
   addRowLabel(pivotTable, dataSheet, areaReference, 1);

   workbook.write(fileout);

  }

 }
}

This code is tested using current apache poi 4.1.2 and needs the full jar of all of the schemas ooxml-schemas-1.4.jar (lower versions for older releases) as mentioned in apache poi FAQ-N10025 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM