问题
I am trying to produce an excel pivot table using apache-poi library.
Base data
What I want
When i try to add multiple aggregations, excel was grouping it into values(you can see the values attribute in right side of 2nd image in row labels) and placing values in columns. I want to generate an excel with values in the row labels by default.
But when i add multiple aggregations like sum and average(as shown in the below image), the values are shown in column labels. values can be dragged to row labels in excel but i need the values in rows by default.
But I am able to generate this in java
Code for these aggregations
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);
But there is no function in pivot table to add these aggregations in row labels in apache-poi library.
回答1:
Using the latest apache poi
version 4.1.0
it is no more necessary to use the low level underlying beans for adding a column label since there is XSSFPivotTable.addColLabel now.
But there is not any addRowLabel(DataConsolidateFunction function, int columnIndex)
until now. The addColumnLabel(DataConsolidateFunction function, int columnIndex)
adds data on columns and data fields as col fields. So we need changing that if the need is having data on rows and data fields as row fields.
Complete example:
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);
}
}
}
The x
attribute in a field
element in either rowFields
or colFields
normally specifies the index to a pivotField
item value. But dataFields
might not be directly related to pivotField
s.
If there is only one dataField
then there is only one possibility for showing that. So no field
element is needed for that.
But if there are multiple dataField
s, then there is a additional field named Values
in pivot table's GUI
view. In the pivot tables XML
that additional field is indexed using -2
.
So dataOnRows
in pivotTableDefinition
determines whether dataField
s are shown on rows (dataOnRows = "true"
) or on columns (default). And the x
attribute -2
in a field
element in either rowFields
or colFields
specifies where the additional Values
field is arranged in the list of fields.
来源:https://stackoverflow.com/questions/56556275/how-to-generate-aggregations-like-sum-average-at-row-labels-instead-of-column-l