按照下面的代码,我不想添加addRowLabel(1)但需要addRowLabel(2)。在运行该应用程序并打开数据透视表后,它的给定异常,但是如果添加addRowLabel(1)(当前已注释),它的工作将按预期进行。添加逻辑以隐藏小计后,就会发生这种情况。这是apache POI的预期行为还是可以解决? 请在下面找到代码。 注意:隐藏小计时会出现此问题。
package com.test.pivottables;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.*;
import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
class TestPivotTables {
public static void main(String[] args) throws IOException{
Workbook wb = new XSSFWorkbook();
String[][] data = new String[][]{{"STATUS","PASSED","DATA","VALUE"},
{"BLUE","Y","TTT","20"},
{"RED","N","UUU","10"},{"BLUE","N","PPP","30"}};
XSSFSheet sheet = (XSSFSheet) wb.createSheet("data");
XSSFSheet pivot = (XSSFSheet) wb.createSheet("summary");
for(String[] dataRow : data){
XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
for(String dataCell : dataRow){
XSSFCell cell =
row.createCell(row.getPhysicalNumberOfCells());
cell.setCellValue(dataCell);
}
}
XSSFTable table = sheet.createTable();
CTTable cttable = table.getCTTable();
table.setDisplayName("table");
cttable.setRef("A1:D4");
cttable.setId(1);
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(3);
int i = 1;
for (String colName : data[0]){
CTTableColumn column = columns.addNewTableColumn();
column.setId(++i);
column.setName(colName);
}
XSSFPivotTable pivotTable = pivot.createPivotTable(new
AreaReference("A1:D4", SpreadsheetVersion.EXCEL2007),
new CellReference("A4"), sheet);
pivotTable.addRowLabel(0);
pivotTable.addRowLabel(2);
//pivotTable.addRowLabel(1);
List<Integer> iterList = new ArrayList<Integer>();
iterList.add(0);
iterList.add(2);
//iterList.add(1);
pivotTable.getCTPivotTableDefinition().setRowHeaderCaption("Colour");
for (int j=0;j<iterList.size();j++) {
CTPivotField ctPivotField =
pivotTable.getCTPivotTableDefinition().getPivotFields().
getPivotFieldList().get(iterList.get(j));
for (i = 0; i < sheet.getLastRowNum()-1; i++) {
if(ctPivotField.getItems().getItemArray(i)!=null) {
ctPivotField.getItems().getItemArray(i).unsetT();
ctPivotField.getItems().getItemArray(i).setX((long)i);
}
}
for (i = sheet.getLastRowNum(); i > sheet.getLastRowNum()-2; i--)
{
if(ctPivotField.getItems().getItemArray(i)!=null) {
ctPivotField.getItems().removeItem(i);
}
}
ctPivotField.getItems().setCount(2);
Set<String> collection = new HashSet<String>();
int ctr = 0;
Row row = null;
Cell cell = null;
boolean isNull = false;
do{
try{
row = sheet.getRow(ctr);
cell = row.getCell(0);
collection.add(cell.toString());
ctr++;
} catch(Exception e) {
isNull = true;
}
}while(isNull!=true);
if(collection!=null && collection.size()>0) {
Iterator value = collection.iterator();
while (value.hasNext()) {
pivotTable.getPivotCacheDefinition().
getCTPivotCacheDefinition().getCacheFields().
getCacheFieldList().get(j).getSharedItems().addNewS().
setV(value.next().toString());
}
}
ctPivotField.setAutoShow(false);
ctPivotField.setDefaultSubtotal(false);
ctPivotField.setSubtotalTop(false);
ctPivotField.setSubtotalCaption(null);
ctPivotField.setCompact(false);
}
System.out.println("----end---");
pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 3, "test");
FileOutputStream fileOut = new FileOutputStream("pivotsample1.xlsx");
wb.write(fileOut);
wb.close();
}}
答案 0 :(得分:1)
问题是如何构建数据透视表定义和数据透视表缓存定义。之所以必须这样做,是因为apache poi
为每个行标签创建的字段与数据透视表数据范围内的行一样多。当对枢轴字段进行特殊设置时,这是错误的。您尝试这样做,但是做错了。
我无法详细说明您到底在哪里出错,因为那会花费很多精力。但是需要做的是:
对于作为行标签的每一列:
然后构建数据透视表和缓存。
对于每个唯一标签:
然后从数据透视表定义中删除其他项。但是,如果应该有小计,请在其中保留一个默认元素。如果没有,那就没有。
完整示例:
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.*;
import java.io.*;
import java.util.ArrayList;
import java.util.TreeSet;
import java.util.List;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
class TestPivotTables {
public static void main(String[] args) throws IOException{
Workbook wb = new XSSFWorkbook();
String[][] data = new String[][]{
{"STATUS","PASSED","DATA","VALUE"},
{"BLUE","Y","TTT","20"},
{"RED","N","UUU","10"},
{"BLUE","N","PPP","30"}
};
XSSFSheet sheet = (XSSFSheet) wb.createSheet("data");
XSSFSheet pivot = (XSSFSheet) wb.createSheet("summary");
for(String[] dataRow : data){
XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
for(String dataCell : dataRow){
XSSFCell cell = row.createCell(row.getPhysicalNumberOfCells());
cell.setCellValue(dataCell);
}
}
AreaReference areaReference = new AreaReference("A1:D4", SpreadsheetVersion.EXCEL2007);
XSSFPivotTable pivotTable = pivot.createPivotTable(areaReference, new CellReference("A4"), sheet);
pivotTable.getCTPivotTableDefinition().setRowHeaderCaption("Colour");
List<Integer> iterList = new ArrayList<Integer>();
iterList.add(0);
iterList.add(2);
iterList.add(1);
for (Integer j : iterList) {
//create row label - apache poi creates as much fields for each as rows are in the pivot table data range
pivotTable.addRowLabel(j);
//determine unique labels in column j
TreeSet<String> uniqueItems = new java.util.TreeSet<String>();
for (int r = areaReference.getFirstCell().getRow()+1; r < areaReference.getLastCell().getRow()+1; r++) {
uniqueItems.add(sheet.getRow(r).getCell(j).getStringCellValue());
}
System.out.println(uniqueItems);
//build pivot table and cache
CTPivotField ctPivotField = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(j);
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
//<sharedItems><s v="BLUE"/><s v="RED"/></sharedItems>
pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(j)
.getSharedItems().addNewS().setV(item);
i++;
}
ctPivotField.setAutoShow(false);
ctPivotField.setDefaultSubtotal(false);
//ctPivotField.setSubtotalTop(false);
//ctPivotField.setSubtotalCaption(null);
ctPivotField.setCompact(false);
//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);
}
System.out.println("----end---");
pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 3, "test");
FileOutputStream fileOut = new FileOutputStream("pivotsample1.xlsx");
wb.write(fileOut);
fileOut.close();
wb.close();
}
}