Группировка столбца с датами и временем (по дате, месяцу и году) в сводной таблице Excel с использованием Java Apache POI - PullRequest
0 голосов
/ 08 октября 2019

В настоящее время я работаю над приложением Java, использующим Java Apache POI для создания сводной таблицы. У меня есть столбец, который содержит значения даты и времени, такие как «21.06.2009 15:17:17»:

+---------------------------------+
| Date                | Values    |
+---------------------|-----------+
| 6/21/2019 15:17:17  | 4.31      |
| 6/21/2019 15:17:42  | 3.00      |
| 6/21/2019 15:17:42  | 1.45      |
| 6/21/2019 16:51:28  | 3.00      |
| 6/24/2019 20:08:33  | 3.00      |
| 6/24/2019 20:08:33  | 4.31      |
| 6/24/2019 20:08:33  | 10.15     |
| 6/25/2019 17:57:05  | 21.55     |
| 6/25/2019 18:12:35  | 4.35      |
+---------------------------------+

, и мне нужно сгруппировать этот столбец в сводной таблице по дням (месяцам, годам)например, используя Java Apache POI

+---------------------------------+
| Result         | Sum of Values  |
+----------------|----------------+
| 21-Jun         | 11.46          |
| 24-Jun         | 17.46          |
| 25-Jun         | 25.9           |
+----------------|----------------+
| Grand Total    | 55.12          |
+---------------------------------+

Любые идеи о том, как это сделать?

PS a аналогичный вопрос уже существует, но остается без ответа

1 Ответ

0 голосов
/ 09 октября 2019

Это не так просто, как вы думаете. Создание сводной таблицы apache poi до сих пор очень элементарно. Это хорошо, поскольку необходимы только сводные таблицы по умолчанию. Excel рассчитает все необходимое при открытии файла. Но если необходимо настроить сводную таблицу, тогда потребуется больше усилий. И apache poi не предоставляет классы и методы для этого напрямую. Необходимо использовать нижележащие классы ooxml-schemas.

В случае вашего запроса нам нужно установить правильный сводный кэш, так как там установлены параметры группы полей. Apache poi устанавливает только элементарный сводный кэш в надежде, что Excel исправит это при открытии файла.

Но чтобы установить правильный сводный кэш, нам нужно сначала определить уникальные данные в столбце данных, который не используется какметка строки. Это связано с тем, что в сводном кеше будут храниться только уникальные данные.

Если это будет сделано, мы сможем построить сводный кеш, а затем установить там параметры группы полей.

Полный пример:

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.TimeZone;
import java.util.GregorianCalendar;

class CreatePivotTableDateValue {

 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\\/yyyy hh:mm:ss"));

   Sheet sheet = workbook.createSheet();

   String[] headers = new String[]{"Date", "Value"};
   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[]{new GregorianCalendar(2019, 5, 21, 15, 17, 17), 4.31},
    new Object[]{new GregorianCalendar(2019, 5, 21, 15, 17, 42), 3.00},
    new Object[]{new GregorianCalendar(2019, 5, 21, 15, 17, 42), 1.45},
    new Object[]{new GregorianCalendar(2019, 5, 21, 16, 51, 28 ), 3.00},
    new Object[]{new GregorianCalendar(2019, 5, 24, 20, 8, 33), 3.00},
    new Object[]{new GregorianCalendar(2019, 5, 24, 20, 8, 33), 4.31},
    new Object[]{new GregorianCalendar(2019, 5, 24, 20, 8, 33), 10.15},
    new Object[]{new GregorianCalendar(2019, 5, 25, 17, 57, 05), 21.55},
    new Object[]{new GregorianCalendar(2019, 5, 25, 18, 12, 35), 4.35 }
   };

   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 GregorianCalendar) {
      cell.setCellValue((GregorianCalendar)rowData[c]);
      cell.setCellStyle(dateStyle);
     } else if (rowData[c] instanceof Double) {
      cell.setCellValue((Double)rowData[c]);
     }
    }
   }

   sheet.setColumnWidth(0, 19 * 256);

   // create default pivot table
   AreaReference areaReference = new AreaReference("A1:B10",  SpreadsheetVersion.EXCEL2007);
   XSSFPivotTable pivotTable = ((XSSFSheet)sheet).createPivotTable(areaReference, new CellReference("D4"));
   pivotTable.addRowLabel(0);
   pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);

   // here ends direct apache poi support

   // customize pivot table
   // determine unique data in data column 0, the row label
   java.util.TreeSet<GregorianCalendar> uniqueItems = new java.util.TreeSet<GregorianCalendar>();
   for (int r = 0; r < data.length; r++) {
    GregorianCalendar calendar = (GregorianCalendar)data[r][0];
    calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
    uniqueItems.add(calendar);
   }

   // we need min date and max date for grouping
   GregorianCalendar minDate = uniqueItems.first();
   GregorianCalendar maxDate = uniqueItems.last();

   // set proper pivot cache
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().setCount(uniqueItems.size());
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().setMinDate(minDate);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().setMaxDate(maxDate);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().setContainsDate(true);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().setContainsString(false);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().setContainsNonDate(false);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().setContainsSemiMixedTypes(false);
   for (GregorianCalendar item : uniqueItems) {
    pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
     .getSharedItems().addNewD().setV(item);
   }

   // set field group settings
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .addNewFieldGroup().setBase(0);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getFieldGroup().addNewRangePr().setGroupBy(org.openxmlformats.schemas.spreadsheetml.x2006.main.STGroupBy.DAYS);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getFieldGroup().getRangePr().setStartDate(minDate);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getFieldGroup().getRangePr().setEndDate(maxDate);

   // at least one grup item in group settings
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getFieldGroup().addNewGroupItems().setCount(1);
   pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getFieldGroup().getGroupItems().addNewS().setV("0");

   workbook.write(fileout);

  }

 }
}
...