Using the following code, cell value changes made to my Excel Spreadsheet are not saved:
OPCPackage pkg = OPCPackage.open(inputFile);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
ModifyWorkbook();
pkg.close();
The following is a workaround I wrote, but I don't understand why it's necessary.
OPCPackage pkg = OPCPackage.open(inputFile);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
ModifyWorkbook();
File tmp = File.createTempFile("tempSpreadsheet", ".xlsx");
FileOutputStream newExcelFile = new FileOutputStream(tmp);
wb.write(newExcelFile);
newExcelFile.close();
tmp.deleteOnExit();
pkg.close();
The javadocs and guides on the subject indicate that the .close() method should save and close. Checks on the values of the cells modified, prior to closing, indicate that the changes ARE made, but the pkg.close() method alone is not sufficient to write those changes to the file when closed.
A call to OPCPackage.close()
will close the underlying OOXML file structure. What it won't do is cause XSSF (or any of the X??F formats) to write their changes out. So, you'll write out an un-changed file....
If you're doing low level modifications, you can open the OPCPackage, make changes, then call close to write them out. If you're doing high level stuff, you open the OPCPackage, work with the UserModel code to make changes, then ask the usermodel to write out its changes. It's this last step that's important.
Your current code is somewhat like:
File f = new File("test.txt");
Sting s = readFileCompletely(f);
s = s.replaceAll("foo", "bar");
f.close();
// Why hasn't the file contents changed?
Reading the file in and modifying the high level objects isn't enough, you also need to tell the high level objects to write out the changes. (The high level objects cache things in memory for performance reasons)
Calling close
on an (XSSF)Workbook will call OPCP.close which javadoc states:
Calling
myWorkbook.close()
should write the changes to file it was open from.
However, the current version (3.15) seems to have problems doing so. The reason itself is unknown to me, but I discovered that calling myWorkbook.write()
will commit not only the changes to the output stream, but also to your current instance after calling close.
A reasonable workaround could therefore be:
try (OutputStream bos = ByteStreams.nullOutputStream()){
workbook.write(bos);
workbook.close();
} catch (IOException e) {
log.error("Could not write Output File", e);
}
Here done with Guavas ByteStreams. Feel free to use other null output stream implementations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With