Как создать агрегации, такие как сумма, среднее по меткам строк вместо меток столбцов в сводной таблице Excel, используя Apache Poi? - PullRequest
1 голос
/ 12 июня 2019

Я пытаюсь создать сводную таблицу Excel с использованием библиотеки apache-poi.

База данных

Что я хочу

Когда я пытался добавить несколько агрегаций, Excel сгруппировал их в значения (вы можете увидеть атрибут values ​​в правой части 2-го изображения в метках строк) и поместил values ​​ вколонны.Я хочу создать Excel со значениями в метках строк по умолчанию.

Но когда я добавляю несколько агрегатов, таких как сумма и среднее (как показано на рисунке ниже), отображаются значения в метках столбцов. значения можно перетащить в метки строк в Excel, но мне нужны значения в строках по умолчанию.

Но я могу сгенерировать это в 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 голосов
/ 12 июня 2019

Используя последнюю apache poi версию 4.1.0, больше нет необходимости использовать базовые компоненты низкого уровня для добавления метки столбца, поскольку XSSFPivotTable.addColLabel сейчас.

Но до сих пор нет 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);

  }

 }
}

Атрибут x в элементе field в rowFields или colFields обычно указывает индекс для значения элемента pivotField. Но dataFields может не иметь прямого отношения к pivotField с.

Если есть только один dataField, то есть только одна возможность показать это. Поэтому для этого не требуется элемент field.

Но если имеется несколько dataField с, то в представлении GUI сводной таблицы есть дополнительное поле с именем Values. В сводных таблицах XML это дополнительное поле индексируется с помощью -2.

То есть dataOnRows в pivotTableDefinition определяет, будут ли dataField s отображаться в строках (dataOnRows = "true") или в столбцах (по умолчанию). А атрибут x -2 в элементе field в rowFields или colFields указывает, где дополнительное поле Values расположено в списке полей.

...