Java 如何使用poi为透视表中的行标签设置默认值

Java 如何使用poi为透视表中的行标签设置默认值,java,excel,apache-poi,Java,Excel,Apache Poi,我正在使用excel报表。我需要生成透视表,其中某些特定字段作为行标签中的默认值,而不是选择所有字段。我正在使用ApachePOI 我尝试了很多方法,但没有找到任何答案 到目前为止,ApachePOI中的透视表创建还只是初级的 Apache-poi添加的透视字段项与数据源中的行一样多,类型为“default”()。这是因为他们不想查看数据,所以他们假设的值与数据源中的行相同。这很好,因为Excel将在打开时重建其pivot缓存 但是如果我们想要预选项目,那么这是不好的。然后我们必须知道有哪些

我正在使用excel报表。我需要生成透视表,其中某些特定字段作为行标签中的默认值,而不是选择所有字段。我正在使用ApachePOI


我尝试了很多方法,但没有找到任何答案

到目前为止,ApachePOI中的透视表创建还只是初级的

Apache-poi
添加的透视字段项与数据源中的行一样多,类型为“default”(
)。这是因为他们不想查看数据,所以他们假设的值与数据源中的行相同。这很好,因为Excel将在打开时重建其pivot缓存

但是如果我们想要预选项目,那么这是不好的。然后我们必须知道有哪些项目可以预选

因此,我们至少需要尽可能多的项目来预选编号项目:
。我们必须构建一个缓存定义,其中包含这些项的共享元素

为了满足这一要求,我们需要确定数据源中所有行的唯一标签。然后,对于每个唯一标签,将项目作为编号项目。然后构建一个缓存定义,其中包含这些项的共享元素。然后将所有不需要的项目设置为隐藏

让我们举一个完整的例子,创建您在问题图片中显示的内容。您的问题中的代码不完整,所以我必须预测您作为数据源拥有哪些数据。请尽量避免在进一步的问题,并始终提供。否则你将无法得到进一步的答案

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 CreatePivotTablePercentAndFilter {

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

  try (Workbook workbook = new XSSFWorkbook(); 
       FileOutputStream fileout = new FileOutputStream("ooxml-pivottable.xlsx") ) {

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

   setCellData(dataSheet);

   AreaReference areaReference = new AreaReference("A1:D5", SpreadsheetVersion.EXCEL2007);

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

   pivotTable.addRowLabel(0);

   pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);
   pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1,"% of value");

   pivotTable.getCTPivotTableDefinition().getDataFields().getDataFieldArray(1).setShowDataAs(
    org.openxmlformats.schemas.spreadsheetml.x2006.main.STShowDataAs.PERCENT_OF_COL);
   DataFormat dataformat = workbook.createDataFormat();
   short numFmtId = dataformat.getFormat("0.00%");
   pivotTable.getCTPivotTableDefinition().getDataFields().getDataFieldArray(1).setNumFmtId(numFmtId);

   /*   
   Apache poi adds 5 pivot field items of type "default" (<item t="default"/>) for each row label here. 
   This is because there are 5 rows (A1:D5) and, because they don't want have a look at the data, 
   they are assuming max 5 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 preselect being 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.

   To fulfill that we need determine the unique labels in column. 
   Then for each unique label take the item as numbered item. 
   Then build a cache definition which has shared elements for those items. 
   Then set all not wanted items hidden.
   */

   //determine unique labels in column 0
   java.util.TreeSet<String> uniqueItems = new java.util.TreeSet<String>();
   for (int r = areaReference.getFirstCell().getRow()+1; r < areaReference.getLastCell().getRow()+1; r++) {
    uniqueItems.add(dataSheet.getRow(r).getCell(areaReference.getFirstCell().getCol()).getStringCellValue());
   }
   System.out.println(uniqueItems);
   int i = 0;
   for (String item : uniqueItems) {
    //take the items as numbered items: <item x="0"/><item x="1"/><item x="2"/>
    pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).getItems().getItemArray(i).unsetT();
    pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).getItems().getItemArray(i).setX((long)i);
    //build a cache definition which has shared elements for those items 
    //<sharedItems><s v="Jack"/><s v="Jane"/><s v="Tarzan"/><s v="Terk"/></sharedItems>
    pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().addNewS().setV(item);
    i++;
   }

   //Now we can predefinite a filter.
   //If the need is selecting multiple items, first MultipleItemSelectionAllowed needs to be set.
   pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).setMultipleItemSelectionAllowed(true);
   //Then set H(idden) true for all items which not shall be selected. All except "Jane" in this case.
   i = 0;
   for (String item : uniqueItems) {
    if (!"Jane".equals(item))
     pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).getItems().getItemArray(i).setH(true);
    i++;
   }

   workbook.write(fileout);
  }
 }

 static void setCellData(Sheet sheet) {
  Row row;
  Cell cell;
  Object[][] data = new Object[][]{
   new Object[]{"Names", "Values", "ColC", "ColD"},
   new Object[]{"Jane", 10d, "?", "?"},
   new Object[]{"Tarzan", 5d, "?", "?"},
   new Object[]{"Terk", 10d, "?", "?"},
   new Object[]{"Jack", 10d, "?", "?"}
  };
  for (int r = 0; r < data.length; r++) {
   row = sheet.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 Double) {
     cell.setCellValue((Double)rowData[c]);
    }
   }
  }
 }
}
import java.io.FileOutputStream;
导入org.apache.poi.ss.*;
导入org.apache.poi.ss.usermodel.*;
导入org.apache.poi.ss.util.*;
导入org.apache.poi.xssf.usermodel.*;
类CreatePivotTablePercentAndFilter{
公共静态void main(字符串[]args)引发异常{
尝试(工作簿=新XSSFWORKWORK();
FileOutputStream fileout=新的FileOutputStream(“ooxml pivottable.xlsx”)){
工作表数据透视表=工作簿.createSheet(“数据透视”);
工作表数据表=工作簿.createSheet(“数据”);
setCellData(数据表);
AreaReference AreaReference=新的AreaReference(“A1:D5”,电子表格版本.EXCEL2007);
XSSFPivotTable数据透视表=((XSSFSheet)数据透视表).createPivotTable(区域引用,新单元格引用(“A4”),数据表);
数据透视表.addRowLabel(0);
数据透视表.addColumnLabel(DataConsolidateFunction.SUM,1);
数据透视表.addColumnLabel(DataConsolidateFunction.SUM,1,“%的值”);
数据透视表.getCTPivotTableDefinition().getDataFields().getDataFieldArray(1).setShowDataAs(
org.openxmlformats.schemas.spreadsheetml.x2006.main.STShowDataAs.PERCENT OF COL);
DataFormat DataFormat=工作簿.createDataFormat();
短numFmtId=dataformat.getFormat(“0.00%”);
数据透视表.getCTPivotTableDefinition().getDataFields().getDataFieldArray(1).setNumFmtId(numFmtId);
/*   
ApachePOI为这里的每个行标签添加了5个类型为“default”()的透视字段项。
这是因为共有5行(A1:D5),因为它们不想查看数据,
他们假设最多有5个不同的值。
这很好,因为Excel将在打开时重建其pivot缓存。
但是如果我们想要预选项目,那么这是不好的。那么我们必须知道有哪些项目可以预选。
所以我们需要至少和我们想要的一样多的物品来预选被编号的物品:。。。
我们必须构建一个缓存定义,其中包含这些项的共享元素。
为了实现这一点,我们需要确定列中的唯一标签。
然后,对于每个唯一标签,将项目作为编号项目。
然后构建一个缓存定义,其中包含这些项的共享元素。
然后将所有不需要的项目设置为隐藏。
*/
//确定列0中的唯一标签
java.util.TreeSet uniqueItems=new java.util.TreeSet();
对于(int r=areaReference.getFirstCell().getRow()+1;rimport 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 CreatePivotTablePercentAndFilter {

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

  try (Workbook workbook = new XSSFWorkbook(); 
       FileOutputStream fileout = new FileOutputStream("ooxml-pivottable.xlsx") ) {

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

   setCellData(dataSheet);

   AreaReference areaReference = new AreaReference("A1:D5", SpreadsheetVersion.EXCEL2007);

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

   pivotTable.addRowLabel(0);

   pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);
   pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1,"% of value");

   pivotTable.getCTPivotTableDefinition().getDataFields().getDataFieldArray(1).setShowDataAs(
    org.openxmlformats.schemas.spreadsheetml.x2006.main.STShowDataAs.PERCENT_OF_COL);
   DataFormat dataformat = workbook.createDataFormat();
   short numFmtId = dataformat.getFormat("0.00%");
   pivotTable.getCTPivotTableDefinition().getDataFields().getDataFieldArray(1).setNumFmtId(numFmtId);

   /*   
   Apache poi adds 5 pivot field items of type "default" (<item t="default"/>) for each row label here. 
   This is because there are 5 rows (A1:D5) and, because they don't want have a look at the data, 
   they are assuming max 5 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 preselect being 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.

   To fulfill that we need determine the unique labels in column. 
   Then for each unique label take the item as numbered item. 
   Then build a cache definition which has shared elements for those items. 
   Then set all not wanted items hidden.
   */

   //determine unique labels in column 0
   java.util.TreeSet<String> uniqueItems = new java.util.TreeSet<String>();
   for (int r = areaReference.getFirstCell().getRow()+1; r < areaReference.getLastCell().getRow()+1; r++) {
    uniqueItems.add(dataSheet.getRow(r).getCell(areaReference.getFirstCell().getCol()).getStringCellValue());
   }
   System.out.println(uniqueItems);
   int i = 0;
   for (String item : uniqueItems) {
    //take the items as numbered items: <item x="0"/><item x="1"/><item x="2"/>
    pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).getItems().getItemArray(i).unsetT();
    pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).getItems().getItemArray(i).setX((long)i);
    //build a cache definition which has shared elements for those items 
    //<sharedItems><s v="Jack"/><s v="Jane"/><s v="Tarzan"/><s v="Terk"/></sharedItems>
    pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(0)
    .getSharedItems().addNewS().setV(item);
    i++;
   }

   //Now we can predefinite a filter.
   //If the need is selecting multiple items, first MultipleItemSelectionAllowed needs to be set.
   pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).setMultipleItemSelectionAllowed(true);
   //Then set H(idden) true for all items which not shall be selected. All except "Jane" in this case.
   i = 0;
   for (String item : uniqueItems) {
    if (!"Jane".equals(item))
     pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(0).getItems().getItemArray(i).setH(true);
    i++;
   }

   workbook.write(fileout);
  }
 }

 static void setCellData(Sheet sheet) {
  Row row;
  Cell cell;
  Object[][] data = new Object[][]{
   new Object[]{"Names", "Values", "ColC", "ColD"},
   new Object[]{"Jane", 10d, "?", "?"},
   new Object[]{"Tarzan", 5d, "?", "?"},
   new Object[]{"Terk", 10d, "?", "?"},
   new Object[]{"Jack", 10d, "?", "?"}
  };
  for (int r = 0; r < data.length; r++) {
   row = sheet.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 Double) {
     cell.setCellValue((Double)rowData[c]);
    }
   }
  }
 }
}