简体   繁体   中英

Refresh Pivot table using Apache POI

No/Minimal documentation regarding Apache POI for Pivot tables in the Apache site has got me to write this.

I want to refresh a pivot table in a Work Book using Apache POI.

Please let me know where I can get proper documentation and Examples regarding this.

Kindly follow the followings which i did.

  1. Fill rough data for pivot table in your MyFileName.xlsx file.
  2. Create a Dynamic Range Formula through OFFSET() or Named Table as Source Data for Pivot table and draw pivot table.
  3. Simply Right click your pivot table and choose

    pivotTable Options->Data-> Check Refresh Data when opening File

  4. Open a MyFileName.xlsx file and fill out the data.

That's all... whenever you opening workbook it will be refreshed to current data. :-)

Note: This will not work when you creating Pivot table through POI.

The link codeMan refers to has some advice that looks quite specific to Apache POI & Excel. You'll see that there is no great documentation for a reason here (it's not supported): http://poi.apache.org/spreadsheet/limitations.html

To quote Solitudes answer in codeMans link verbatim:

It is possible. In the PivotCacheDefinition, there is an attribute refreshOnLoad that can be set to true. The cache is then refreshed when the workbook is opened. More information here.

> In POI this can be done by calling the method setRefreshOnLoad(boolean bool), that takes a boolean as parameter, on a CTPivotCacheDefinition

If you need to refresh the pivot table before the file is opened, (for example to then use the pivottable calculated data in further calculations and have POI write this) then I'm not sure that this would be possible at all with POI, and potentially hooking up to excel using a COM solution might be the way to go.

Apart from the limitations , you can check a little information about Package org.apache.poi.hssf.record.pivottable

Though if I will have to do the same, I would create the table/chart manually once and will update the chart using apache poi as I have done here

save your file with PTs as file. xlsm and insert VBA script (ALT+F11):

' Create module and insert this:
Public Const pivotName1 As String = "myPivotName"
Public Const sourceSheetName As String = "source"
Public Const sourceColumnCount As Long = 23

' In "ThisWorkbook" chapter insert this:
Dim lRow As Long

Private Sub Workbook_Open()
Application.ScreenUpdating = False
ActiveWorkbook.Worksheets(sourceSheetName).Activate
' In file should preliminarily insert keyWord "firstOpenFlag" in CV1 cell (sheet sourceSheetName)
' It gona start actions below
If ActiveSheet.Cells(1, 100) = "firstOpenFlag"
Then
ActiveSheet.Cells(1, 100) = ""
lRow = getLastRowForFirstCol(sourceSheetName)
Call updateAllPTCache
ActiveWorkbook.Worksheets(sourceSheetName).Activate
ActiveSheet.Range("A1").Select
End If
Application.ScreenUpdating = True
End Sub

Private Function getLastRowForFirstCol(sourceSheetName As String) As Long
    ActiveWorkbook.Worksheets(sourceSheetName).Activate
    getLastRowForFirstCol = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
    If getLastRowForFirstCol < 2 Then getLastRowForFirstCol = 2
End Function

Private Sub updateAllPTCache()
    Dim pt As PivotTable
    Dim ws As Worksheet
    
    For Each ws In ActiveWorkbook.Worksheets
        For Each pt In ws.PivotTables
            pt.ChangePivotCache ActiveWorkbook.PivotCaches.Create( _
                SourceType:=xlDatabase, _
                SourceData:=sourceSheetName + "!R1C1:R" + CStr(lRow) + "C" + CStr(sourceColumnCount), _
                Version:=xlPivotTableVersion14)
                ' xlPivotTableVersion14 - work in 2013, 2016 exlApp
                ' Downgrade xlPivotTableVersion for backward compatibility
            pt.RefreshTable
        Next pt
    Next ws
End Sub

Drawback: clients xlsApp should be configed to enable VBA scripts

another solution (WO VBA scripts)

In tempalate.xlsx create xlTable object on headers of source record set. Set name to the xlTable, ex. 'mySourceTable'. Also in file preSet for your PivotTable:

  1. sourceRef ='mySourceTable'
  2. check in RefreshOnLoad

In POI:

private void updateXlTableSource() {
        XSSFTable sourceTable = ((XSSFWorkbook)workbook).getTable("mySourceTable");
        CTTable ctTable = sourceTable.getCTTable();
        String sourceRef = getSourceDataRange().formatAsString();
        ctTable.setRef(sourceRef);
        ctTable.getAutoFilter().setRef(sourceRef);
    }

private CellRangeAddress getSourceDataRange() {
        XSSFSheet xssfSheet = (XSSFSheet) workbook.getSheet("sourceSheetName");
        int uBoundSourceDataRow = findFirstEmptyRowFrom(xssfSheet) - 1;
        if (uBoundSourceDataRow < 2) {
            uBoundSourceDataRow = 2;
        }
        int uBoundSourceDataCol = findFirstEmptyColFromFirstRow(xssfSheet) - 1;
        return new CellRangeAddress(0, uBoundSourceDataRow, 0, uBoundSourceDataCol);
    }

Note: check your tempalate.xlsx for unKnown query. Delete if it exists, else it will block PT updating

Drawback: PT's autoFilter contains notexisting elements (elements from PT template).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM