如何摆脱使用Apache POI XSSF创建的xlsx文件中的“保存更改?”提示

时间:2016-12-13 12:20:29

标签: java xml excel apache-poi

我正在创建一个新的.xlsx文件,我第一次打开它并关闭它,这个恼人的弹出窗口出现了。这个项目应该创建一个Excel-File,看起来就像我的同事手工做的那样,我在那里发布的xml-File来自他的一个文件。我保存文件的代码工作正常:

private File save() throws IOException {
    Date now = new Date();
    String userHome = System.getProperty("user.home");
    for (int fCounter = -1;; fCounter++) {
        Path path = Paths.get(MessageFormat.format(PATH_FMT, userHome, now, fCounter));
        try (OutputStream out = Files.newOutputStream(path, StandardOpenOption.CREATE_NEW)) {
            this.workBook.write(out);
            this.workBook.close();
            return path.toFile();
        } catch (FileAlreadyExistsException incrCounterAndRetry) {
        }
    }
}

这里有一个关于我如何创建数据透视表的例子(也正常工作):

private void createPivotSid(XSSFSheet sheet) {
    XSSFSheet data = workBook.getSheet("SID Table");

    CellReference cr = new CellReference("A1");
    CellReference c1 = new CellReference(0, 0);
    CellReference c2 = new CellReference(data.getPhysicalNumberOfRows() - 1, data.getRow(0).getLastCellNum() - 1);

    AreaReference ar = new AreaReference(c1, c2);
    XSSFPivotTable pivotTable = sheet.createPivotTable(ar, cr, data);

    pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(5).setAxis(STAxis.AXIS_COL);
    pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(5).addNewItems();
    pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(5).getItems().addNewItem()
            .setT(STItemType.DEFAULT);

    pivotTable.getCTPivotTableDefinition().addNewColFields().addNewField().setX(5);

    pivotTable.addRowLabel(11);
    pivotTable.addRowLabel(12);
    pivotTable.addRowLabel(2);
    pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 1);
}

这一切都运转良好,但我得到了这个烦人的弹出窗口。所以我用google搜索了this question on SO并尝试了他们的建议。简单地评估所有公式的答案不起作用(这里没有公式)。所以我尝试了建议在打开之前编辑xml-File的答案。这里我在创建/设置定义的名称时遇到问题(不确定这是什么,从示例xml复制)。我的代码是:

private void setWorkbookXmlContent() {
    workBook.getCTWorkbook().addNewFileVersion();
    workBook.getCTWorkbook().getFileVersion().setAppName("xl");
    workBook.getCTWorkbook().getFileVersion().setLastEdited("5");
    workBook.getCTWorkbook().getFileVersion().setLowestEdited("5");
    workBook.getCTWorkbook().getFileVersion().setRupBuild("9303");

    workBook.getCTWorkbook().getWorkbookPr().unsetDate1904();
    workBook.getCTWorkbook().getWorkbookPr().setDefaultThemeVersion(124226);

    workBook.getCTWorkbook().getBookViews().getWorkbookViewArray(0).setXWindow(480);
    workBook.getCTWorkbook().getBookViews().getWorkbookViewArray(0).setYWindow(105);
    workBook.getCTWorkbook().getBookViews().getWorkbookViewArray(0).setWindowWidth(27795);
    workBook.getCTWorkbook().getBookViews().getWorkbookViewArray(0).setWindowHeight(14310);
    workBook.getCTWorkbook().getBookViews().getWorkbookViewArray(0).unsetActiveTab();

    workBook.getCTWorkbook().addNewDefinedNames().addNewDefinedName().setName("_xlnm._FilterDatabase");
    workBook.getCTWorkbook().addNewDefinedNames().addNewDefinedName().setLocalSheetId(3);
    workBook.getCTWorkbook().addNewDefinedNames().addNewDefinedName().setHidden(false);
    workBook.getCTWorkbook().addNewDefinedNames().addNewDefinedName().setStringValue("SID Q3 2016'!$A$1:$M$81");

    workBook.getCTWorkbook().addNewCalcPr().setCalcId(145621);

}

我想要实现的xml-File看起来像这样(来自我的同事的Excel文件):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="9303"/>
<workbookPr defaultThemeVersion="124226"/>
<bookViews><workbookView xWindow="480" yWindow="45" windowWidth="27795" windowHeight="14370"/></bookViews>
<sheets><sheet name="Overview SID" sheetId="3" r:id="rId1"/><sheet name="Overview Exchange" sheetId="5" r:id="rId2"/><sheet name="Overview Total Cost" sheetId="6" r:id="rId3"/><sheet name="SID Q3 2016" sheetId="1" r:id="rId4"/><sheet name="Exchange Q3 2016" sheetId="2" r:id="rId5"/><sheet name="Total Cost Q3 2016" sheetId="4" r:id="rId6"/></sheets>
<definedNames><definedName name="_xlnm._FilterDatabase" localSheetId="3" hidden="1">'SID Q3 2016'!$A$1:$M$81</definedName></definedNames>
<calcPr calcId="145621"/>
<pivotCaches><pivotCache cacheId="8" r:id="rId7"/><pivotCache cacheId="15" r:id="rId8"/><pivotCache cacheId="21" r:id="rId9"/></pivotCaches>
</workbook>

但我真正得到的是:

<?xml version="1.0" encoding="UTF-8"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="9303"/><workbookPr defaultThemeVersion="124226"/>
<bookViews><workbookView xWindow="480" yWindow="105" windowWidth="27795" windowHeight="14310"/></bookViews>
<sheets><sheet name="SID Table" r:id="rId3" sheetId="1"/><sheet name="Exchange Table" r:id="rId4" sheetId="2"/><sheet name="Total Cost Table" r:id="rId5" sheetId="3"/><sheet name="Overview SID" r:id="rId6" sheetId="4"/><sheet name="Overview Exchange" r:id="rId8" sheetId="5"/><sheet name="Overview Total Cost" r:id="rId10" sheetId="6"/></sheets>
<definedNames><definedName localSheetId="3"/></definedNames>
<definedNames><definedName hidden="1"/></definedNames>
<definedNames><definedName>SID Q3 2016'!$A$1:$M$81</definedName></definedNames>
<definedNames><definedName localSheetId="3"/></definedNames>
<calcPr calcId="145621"/>
<pivotCaches><pivotCache cacheId="2" r:id="rId7"/><pivotCache cacheId="3" r:id="rId9"/><pivotCache cacheId="4" r:id="rId11"/></pivotCaches>
</workbook>

也许某人有我的问题的解决方案或者我可以帮助xml编辑。任何帮助表示赞赏。

更新

我找到了摆脱弹出窗口(pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().setRefreshOnLoad(false);)的方法,但现在我需要在保存之前“评估”所有数据透视表。或者是否可以保存工作簿,然后在新工作簿中打开文件(这应该刷新数据透视表?)然后保存它?

1 个答案:

答案 0 :(得分:0)

如果你对宏很好,你可以创建一个外部帮助器xlsm文件和VBA宏,一旦在Excel应用程序中打开它就可以运行。如果要自动执行此操作,请使用Java中的shell-execute。用户需要安装完整的Excel。

Private Sub Auto_open()
  // you could foreach loop pivottables array
  // but this example uses a predefined instance names
  Dim wb as workbook
  Dim ws as worksheet

  Set wb = Application.Workbooks.Open("c:\data\mypoifile.xlsx", 3, False, 5, "", "", True, xlWindows, "", False, False, 0, False, True, xlNormalLoad)

  set ws = wb.Worksheets("data1")
  ws.PivotTables("PivotTable1").PivotCache.Refresh
  ws.PivotTables("PivotTable2").PivotCache.Refresh
  set ws = wb.Worksheets("data2")
  ws.PivotTables("PivotTable3").PivotCache.Refresh
  ws.PivotTables("PivotTable4").PivotCache.Refresh

  wb.Close(true) // save+close poi file
  ActiveWorkbook.close(false)
End Sub

你可能需要使用这种黑客的原因是POI只是一个简单的&#34; excel文件格式处理程序无需安装Excel即可运行。 POI对真正的Excel运行时UI引擎功能一无所知,许多xls文件格式只在UI引擎级别发生。