XSSFWorkbook 写入时会在 Spring 使用 JDBC 启动应用程序中创建损坏的 .xlsx 文档
XSSFWorkbook when written creates a corrupted .xlsx document in Spring Boot application using JDBC
对于一个项目,我需要创建一个 .xlsm
excel 文档,自动填写一个模板文件。问题是,输出已损坏,无法被 Excel 365 或 Apache POI 读取。
我已将其提炼为以下最小示例,它可以 运行 在 main
方法中。为了完全安全,它使用 .xlsx
格式。
public static void main(String[] args) {
XSSFWorkbook document = new XSSFWorkbook();
XSSFSheet spreadsheet = document.createSheet("Test");
spreadsheet.createRow(0).createCell(0).setCellValue("Testie test");
// Output .xlsx file
FileOutputStream stream;
try {
stream = new FileOutputStream("test_output.xlsx");
document.write(stream);
stream.flush();
stream.close();
} catch (IOException e) {
System.err.println("Error" + e.getMessage());
e.printStackTrace();
}
...
创建的文件test_output.xlsx
无法被Excel365打开,大小只有4kb,而手动创建的文件会占用9kb,输出一定是少了什么我没有指定?
我正在使用通过 Gradle 使用
导入的 Apache POI 3.17 版
compile('org.apache.poi:poi-ooxml:3.17')
还有 Apache POI 3.13 版本是 2016 年之前的版本。两种情况都不走运。
当main方法扩展后也重新打开刚刚创建的同一个文件,如下图
...
// Try to read it again
try {
document = new XSSFWorkbook("test_output.xlsx");
System.out.println(document.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
} catch (IOException e) {
e.printStackTrace();
}
}
然后我会遇到以下异常
java.io.IOException: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Can't read content types part !
at org.apache.poi.POIXMLDocument.openPackage(POIXMLDocument.java:91)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:340)
...
另一方面,如果将所有 XSSF*
替换为 HSSF*
并将文件类型制作成 .xls
文件,那么输出的文档就可以了,但我需要创建工作 Excel 365 文档,而不是 Excel 2003 文档。
下面是手工制作的.xlsx
文档中的[Content_Types].xml
文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
</Types>
虽然下面是[Content_Types].xml
在POI创建的文件.xlsx
<?xml version = '1.0' encoding = 'UTF-8' standalone = 'yes'?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default ="rels"/>
<Default ="xml"/>
<Override ="/docProps/app.xml"/>
<Override ="/docProps/core.xml"/>
<Override ="/xl/sharedStrings.xml"/>
<Override ="/xl/styles.xml"/>
<Override ="/xl/workbook.xml"/>
<Override ="/xl/worksheets/sheet1.xml"/>
</Types>
根据@AxelRichter 的建议,当在 build.gradle
中删除所有其他依赖项时,[Content_Types]。xml 如下所示。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default ContentType="application/vnd.openxmlformats-package.relationships+xml" Extension="rels"/>
<Default ContentType="application/xml" Extension="xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" PartName="/docProps/app.xml"/>
<Override ContentType="application/vnd.openxmlformats-package.core-properties+xml" PartName="/docProps/core.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" PartName="/xl/sharedStrings.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" PartName="/xl/styles.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" PartName="/xl/workbook.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" PartName="/xl/worksheets/sheet1.xml"/>
</Types>
并且上面的代码运行没有问题,文件可以在Office 365中打开。问题出在导入
compile('com.oracle.jdbc:ojdbc8:12.2.0.1')
这会在 Apache POI 使用的 XML 解析器的类路径中产生冲突,这意味着 Excel 部分需要在另一个项目中完成,Gradle 处理依赖关系问题。
对于一个项目,我需要创建一个 .xlsm
excel 文档,自动填写一个模板文件。问题是,输出已损坏,无法被 Excel 365 或 Apache POI 读取。
我已将其提炼为以下最小示例,它可以 运行 在 main
方法中。为了完全安全,它使用 .xlsx
格式。
public static void main(String[] args) {
XSSFWorkbook document = new XSSFWorkbook();
XSSFSheet spreadsheet = document.createSheet("Test");
spreadsheet.createRow(0).createCell(0).setCellValue("Testie test");
// Output .xlsx file
FileOutputStream stream;
try {
stream = new FileOutputStream("test_output.xlsx");
document.write(stream);
stream.flush();
stream.close();
} catch (IOException e) {
System.err.println("Error" + e.getMessage());
e.printStackTrace();
}
...
创建的文件test_output.xlsx
无法被Excel365打开,大小只有4kb,而手动创建的文件会占用9kb,输出一定是少了什么我没有指定?
我正在使用通过 Gradle 使用
导入的 Apache POI 3.17 版compile('org.apache.poi:poi-ooxml:3.17')
还有 Apache POI 3.13 版本是 2016 年之前的版本。两种情况都不走运。
当main方法扩展后也重新打开刚刚创建的同一个文件,如下图
...
// Try to read it again
try {
document = new XSSFWorkbook("test_output.xlsx");
System.out.println(document.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
} catch (IOException e) {
e.printStackTrace();
}
}
然后我会遇到以下异常
java.io.IOException: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Can't read content types part !
at org.apache.poi.POIXMLDocument.openPackage(POIXMLDocument.java:91)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:340)
...
另一方面,如果将所有 XSSF*
替换为 HSSF*
并将文件类型制作成 .xls
文件,那么输出的文档就可以了,但我需要创建工作 Excel 365 文档,而不是 Excel 2003 文档。
下面是手工制作的.xlsx
文档中的[Content_Types].xml
文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
</Types>
虽然下面是[Content_Types].xml
在POI创建的文件.xlsx
<?xml version = '1.0' encoding = 'UTF-8' standalone = 'yes'?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default ="rels"/>
<Default ="xml"/>
<Override ="/docProps/app.xml"/>
<Override ="/docProps/core.xml"/>
<Override ="/xl/sharedStrings.xml"/>
<Override ="/xl/styles.xml"/>
<Override ="/xl/workbook.xml"/>
<Override ="/xl/worksheets/sheet1.xml"/>
</Types>
根据@AxelRichter 的建议,当在 build.gradle
中删除所有其他依赖项时,[Content_Types]。xml 如下所示。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default ContentType="application/vnd.openxmlformats-package.relationships+xml" Extension="rels"/>
<Default ContentType="application/xml" Extension="xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" PartName="/docProps/app.xml"/>
<Override ContentType="application/vnd.openxmlformats-package.core-properties+xml" PartName="/docProps/core.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" PartName="/xl/sharedStrings.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" PartName="/xl/styles.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" PartName="/xl/workbook.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" PartName="/xl/worksheets/sheet1.xml"/>
</Types>
并且上面的代码运行没有问题,文件可以在Office 365中打开。问题出在导入
compile('com.oracle.jdbc:ojdbc8:12.2.0.1')
这会在 Apache POI 使用的 XML 解析器的类路径中产生冲突,这意味着 Excel 部分需要在另一个项目中完成,Gradle 处理依赖关系问题。