Это не так просто, как вы думаете. Создание сводной таблицы 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);
}
}
}