Получение исключения при изменении порядка RowLabel при скрытии промежуточного итога -Apache POI - PullRequest
0 голосов
/ 25 октября 2019

Согласно приведенному ниже коду я не хочу добавлять 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 Ответ

1 голос
/ 25 октября 2019

Проблема в том, как вы строите определение сводной таблицы и определение сводного кэша. Это необходимо сделать, поскольку 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();
 }
}
...