如何使用apache poi实现数据透视表的标签过滤器?

问题描述 投票:0回答:1

我在 Sheet1 上以表格格式存储数据enter image description here。利用 Sheet1 中的这些数据,我在 Sheet2 上生成了一个新的数据透视表 enter image description here .

我正在寻找解决方案,在列标签上应用标签过滤器,以使用 apache poi 库在数据透视表中专门显示“高复杂性”列。

enter image description here

我尝试了 stackoverflow 中的几个代码示例,但没有任何效果。

java excel apache apache-poi pivot-table
1个回答
0
投票

到目前为止,如果数据透视字段用作轴字段,那么 apache poi 会添加与数据范围中存在的行一样多的“默认”类型(

<item t="default"/>
)的数据透视字段项。这是因为他们不想查看数据,因此他们假设与数据中的行一样多的不同值。

这很好,因为 Excel 在打开时会重建其数据透视缓存。但如果我们想要预选项目,那么这就不行了。那么我们必须知道有哪些项目可以预选。

因此,我们至少需要与我们想要预选的项目一样多的编号项目:

<item x="0"/><item x="1"/><item x="2"/>...

我们需要构建一个缓存定义,其中包含这些项目的共享元素。

为此,需要确定 B 列(列索引 1)(复杂性列)中的唯一标签。

然后使用这些独特的项目构建数据透视缓存。

之后我们就可以过滤了。这是通过将所有未选定的项目设置为 H(idden)来完成的。

完整示例:

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.*;

class CreatePivotTableItemFilter {

 public static void main(String[] args) throws Exception {

  try (Workbook workbook = new XSSFWorkbook(); 
       FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {

   Sheet pivotSheet = workbook.createSheet("Pivot");
   Sheet dataSheet = workbook.createSheet("Data");

   Row row;
   Cell cell;
   Object[][] data = new Object[][]{
    new Object[]{"Header", "Complexity"},
    new Object[]{"A", "High"},
    new Object[]{"B", "Low"},
    new Object[]{"C", "Moderate"},
    new Object[]{"D", "High"},
    new Object[]{"E", "High"},
    new Object[]{"F", "Low"},
    new Object[]{"G", "Low"}
   };
   for (int r = 0; r < data.length; r++) {
    row = dataSheet.createRow(r);
    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 Number) {
      cell.setCellValue(((Number)rowData[c]).doubleValue());
     }
    }
   }

   AreaReference areaReference = new AreaReference(
    new CellReference(0,0),
    new CellReference(data.length-1, data[0].length-1),
    SpreadsheetVersion.EXCEL2007);

   XSSFPivotTable pivotTable = ((XSSFSheet)pivotSheet).createPivotTable(areaReference, new CellReference("A4"), dataSheet);

   pivotTable.addRowLabel(0);
   pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 1, "Count of complexity");
   pivotTable.addColLabel(1);
   //Method addColLabel removes the dataField setting. So we need set it new.
   pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(1)
    .setDataField(true);
   
/*   
   Apache poi adds 8 pivot field items of type "default" (<item t="default"/>) for each pivot field. 
   This is because there are 8 rows (A1:B8) and, because they don't have a look at the data, 
   they are assuming max 8 different values. This is fine because Excel will rebuild its pivot cache while opening. 
   But if we want preselect items, then this is not fine. Then we must know what items there are that can be preselected.
   So we need at least as much items as we want preselecting as numbered items: <item x="0"/><item x="1"/><item x="2"/>... 
   And we must build a cache definition which has shared elements for those items.
*/

   //determine unique labels in column B (colimn index 1)
   DataFormatter formatter = new DataFormatter(java.util.Locale.US);
   int colIdx = 1;
   java.util.TreeSet<String> uniqueItems = new java.util.TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
   for (int r = areaReference.getFirstCell().getRow()+1; r < areaReference.getLastCell().getRow()+1; r++) {
    uniqueItems.add(formatter.formatCellValue(dataSheet.getRow(r).getCell(colIdx)));
   }
   //System.out.println(uniqueItems);

   //build pivot cache using uniqueItems
   org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotField ctPivotField 
    = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(colIdx);
   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 
    pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(colIdx)
     .getSharedItems().addNewS().setV(item);
    i++;
   }
  
   String filterText = "High";
   
   //If the need is selecting multiple items, first MultipleItemSelectionAllowed needs to be set.
   ctPivotField.setMultipleItemSelectionAllowed(true);
   //Then set H(idden) true for all items which not shall be selected. Second ("Low") and third ("Moderate") in this case.
   i = 0;
   for (String item : uniqueItems) {
    if (!item.equals(filterText)) {
     ctPivotField.getItems().getItemArray(i).setH(true);
    }
    i++;
   }
   
   workbook.write(fileout);

  }

 }
}
© www.soinside.com 2019 - 2024. All rights reserved.