【问题标题】:How can I create an Apache POI Pivot using another workbook as data source?如何使用另一个工作簿作为数据源创建 Apache POI Pivot?
【发布时间】:2021-03-10 10:39:06
【问题描述】:

如何使用另一个工作簿作为数据源来创建 Apache POI Pivot? AreaReference 不接受工作簿作为参数,而只接受 sheetName。

/** Data source sheet */
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet dataSourceSheet = wb.createSheet("dataSourceSheet");

CellReference position = new CellReference(0, 0, true, true);
AreaReference source = new AreaReference(
                       new CellReference("dataSourceSheet", 0, 0, true, true),
                       new CellReference("dataSourceSheet", 100, 100, true, true),
                       null);
            
/** Pivot */
XSSFWorkbook wbPivot = new XSSFWorkbook();
XSSFSheet pivotSheet = wbPivot.createSheet("myPivot");
XSSFPivotTable pivotTable = pivotSheet.createPivotTable(source, position); /* ???? */

【问题讨论】:

    标签: apache-poi pivot-table


    【解决方案1】:

    到目前为止,这不是apache poi 提供的任何东西。如果知道Excel 在这种情况下存储了什么,就可以做到。

    创建数据透视表的主要原理是相同的。不同之处在于数据透视缓存的工作表源附加包含一个rId,它指的是与源工作簿的外部关系。因此,额外的任务是创建与源工作簿的外部关系,并将 rId 设置为数据透视缓存的工作表源。

    以下代码显示了如何做到这一点:

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.FileInputStream;
    
    import org.apache.poi.ss.SpreadsheetVersion;
    import org.apache.poi.ss.util.AreaReference;
    import org.apache.poi.ss.util.CellReference;
    import org.apache.poi.ss.usermodel.DataConsolidateFunction;
    import org.apache.poi.openxml4j.opc.TargetMode;
    import org.apache.poi.xssf.usermodel.*;
    
    class CreatePivotTable {
    
     public static void main(String[] args) throws Exception {
    
      String[] headers = new String[] { "Company", "Status", "Counter" };
      Object[][] sheetData = {
       {"Company 1", "OK", "x"},
       {"Company 1", "NOK", "x"},
       {"Company 2", "NOK", "x"},
       {"Company 1", "OK", "x"},
       {"Company 3", "OK", "x"},
       {"Company 1", "NOK", "x"},
      };
    
      //File sourceWorkbookFile = new File("C:/Users/axelr/Documents/PivotData.xlsx");
      //File pivotWorkbookFile = new File("C:/Users/axelr/Documents/PivotTable.xlsx");
      File sourceWorkbookFile = new File("PivotData.xlsx");
      File pivotWorkbookFile = new File("PivotTable.xlsx");
      
      // creating source workbook  
      try (XSSFWorkbook workbook = new XSSFWorkbook(); 
           FileOutputStream fileout = new FileOutputStream(sourceWorkbookFile) ) {
    
       XSSFSheet dataSheet = workbook.createSheet("Data");
       XSSFRow row;
       XSSFCell cell;
       int r = 0;
       row = dataSheet.createRow(r++);
       int c = 0;
       for (String header : headers) {
        cell = row.createCell(c++);
        cell.setCellValue(header);
       }
       for (Object[] dataRow : sheetData) {
        row = dataSheet.createRow(r++);
        c = 0;
        for (Object value : dataRow) {
         cell = row.createCell(c++);
         if (value instanceof String) {
          cell.setCellValue((String)value);
         } //else if...
        }
       } 
       workbook.write(fileout);
      }
      
      // creating pivot workbook  
      try (XSSFWorkbook sourceWorkbook = new XSSFWorkbook(new FileInputStream(sourceWorkbookFile));
           XSSFWorkbook pivotWorkbook = new XSSFWorkbook(); 
           FileOutputStream fileout = new FileOutputStream(pivotWorkbookFile) ) {
               
       XSSFSheet dataSheet = sourceWorkbook.getSheet("Data");
       XSSFSheet pivotSheet = pivotWorkbook.createSheet("Pivot");
    
       AreaReference areaReference = new AreaReference(
        new CellReference(0, 0),
        new CellReference(dataSheet.getLastRowNum(), dataSheet.getRow(0).getLastCellNum()-1),
        SpreadsheetVersion.EXCEL2007);
    
       XSSFPivotTable pivotTable = pivotSheet.createPivotTable(areaReference, new CellReference("A4"), dataSheet);
       
       XSSFPivotCacheDefinition pivotCacheDefinition = pivotTable.getPivotCacheDefinition();
       String rId =  pivotCacheDefinition.getPackagePart().addRelationship( 
        sourceWorkbookFile.toURI(), 
        TargetMode.EXTERNAL, 
        "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath")
        .getId();
       pivotCacheDefinition.getCTPivotCacheDefinition().getCacheSource().getWorksheetSource().setId(rId); 
    
       pivotTable.addRowLabel(0);
       pivotTable.addRowLabel(1);
       pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 2);
    
       pivotWorkbook.write(fileout);
    
      }
    
     }
    }
    

    此代码已使用当前apache poi 版本4.1.25.0.0 进行测试和工作。

    【讨论】:

    • 您的解决方案适用于 XSSFWorkbook;但我需要使用流工作簿“SXSSFWorkbook”。我注意到它似乎不适用于这些:SXSSFWorkbook swb = new SXSSFWorkbook(wb); /* 因为我需要管理大量数据 / FileOutputStream fileOut = new FileOutputStream(sourceWorkbookFile); swb.write(fileOut); / ...并关闭文件。 */ XSSFWorkbook sourceWorkbook = new XSSFWorkbook(new FileInputStream(sourceWorkbookFile); 在使用 dataSheet 为“pivotSheet.createPivotTable(...)”定义“AreaReference”时,它不起作用。您有任何解决方案吗?提前致谢。跨度>
    • @Stefano:抱歉,没有。在我看来,使用SXSSFWorkbook 是一条死胡同。根本不可能将内容流式传输到*.xlsx 文件中。一个人可能能够将内容流式传输到单个 XML 文件中,但在流式传输时保持这些文件之间的关系完好无损几乎是不可能的。所以我不会为此烦恼。
    猜你喜欢
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多