隐藏小计-Apache POI

时间:2019-10-25 14:28:42

标签: java apache-poi pivot-table

按照下面的代码,我不想添加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();

}}

1 个答案:

答案 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();
 }
}