java: Как создать сводную точку с apache poi? - PullRequest
0 голосов
/ 27 марта 2020

Я пытаюсь создать Excel Pivot с apache poi, но я не совсем понимаю, как создать нужный мне формат. Я использую этот код для создания, но я получаю пустые значения:

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

Мои данные выглядят так:

enter image description here

и Я хочу, чтобы это выглядело так:

enter image description here

Как мне этого добиться?

1 Ответ

1 голос
/ 27 марта 2020

Apache poi имеет только элементарную поддержку для создания сводных таблиц. Он только создает сводные таблицы по умолчанию, но не может создавать специальные параметры без возврата к базовым ooxml-schemas классам.

Для вашего источника данных следующий код создает то, что apache poi поддерживает по умолчанию:

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

  }

 }
}

Это создает сводную таблицу в формате структуры, которая является значением по умолчанию.

Если вы хотите создать сводную таблицу, которая не в формате структуры и не показывает промежуточные итоги для каждого поля, нам нужно использовать базовые ooxml-schemas классы. Нам нужно создать правильные элементы поля сводной таблицы. И нам нужно создать определение кэша, в котором есть общие элементы для этих элементов. См. Также Apache POI XSSFPivotTable setDefaultSubtotal .

Следующий код должен создать сводную таблицу, которую вы хотите получить из своего источника данных:

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

  }

 }
}

Этот код протестирован с использованием текущая apache poi 4.1.2 и требует полного jar всех схем ooxml-schemas-1.4.jar (более низкие версии для более старых выпусков), как указано в apache poi FAQ-N10025 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...