SXSSFWorkbook 无法写入数据,文档似乎已经关闭
Posted
技术标签:
【中文标题】SXSSFWorkbook 无法写入数据,文档似乎已经关闭【英文标题】:SXSSFWorkbook Cannot write data, document seems to have been closed already 【发布时间】:2021-10-25 16:34:19 【问题描述】:我在将数据写入 SXSSFWorkbook 文件时遇到异常。我可以使用 XSSFWorkbook 做同样的事情,而且效果很好。
java.io.IOException: Cannot write data, document seems to have been closed already
at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:230)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.write(SXSSFWorkbook.java:953)
at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:79)
at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:61)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:266)
这是我的代码。
public static Response createResponseUsingStreaming() throws IOException
SXSSFWorkbook workbook = report.generateStreamingExcelReport(100);
StreamingOutput outputStream = workbook::write;
final String contentType = "application/vnd.ms-excel";
Response.ResponseBuilder responseBuilder = Response.ok(outputStream);
responseBuilder.header("Content-Disposition", "attachment; filename=test");
responseBuilder.header("Access-Control-Expose-Headers", "Content-Disposition");
responseBuilder.header("Content-Type", contentType);
Response response = responseBuilder.build();
if (null != workbook)
workbook.dispose();
workbook.close();
return response;
public SXSSFWorkbook generateStreamingExcelReport(int rowAccessWindowSize)
List<List<String>> rows = createRawData();
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(rowAccessWindowSize);
createExcelSummaryPage(sxssfWorkbook);
createExcelDetailPage(rows, sxssfWorkbook);
return sxssfWorkbook;
在创建新的 SXSSFWorkbook 时设置了 OPCPackage,想知道在哪里设置为 null。
public final void write(OutputStream stream) throws IOException
OPCPackage p = getPackage();
if(p == null)
throw new IOException("Cannot write data, document seems to have been closed already");
//force all children to commit their changes into the underlying OOXML Package
// TODO Shouldn't they be committing to the new one instead?
Set<PackagePart> context = new HashSet<>();
onSave(context);
context.clear();
//save extended and custom properties
getProperties().commit();
p.save(stream);
【问题讨论】:
您是否检查过createExcelSummaryPage
或createExcelDetailPage
是否正在关闭工作簿?否则,Response
和 Response.ResponseBuilder
到底是什么?如果这些是异步的,那么当responseBuilder.build()
调用workbook::write
时,工作簿可能已经关闭。
否,createExcelSummaryPage 或 createExcelDetailPage 没有关闭工作簿。我正在使用 REST API 下载报告,而 Response 和 Response.ResponseBuilder 是我用来构建响应的 javax 库。
所以Response
和Response.ResponseBuilder
是javax.ws.rs.core.*
-classes?然后我建议标记java-ee
以吸引Java EE
用户回答这个问题。因为我没有使用Java EE
,所以我无能为力。
【参考方案1】:
如果您可以使用XSSFWorkbook
,您应该可以使用您的XSSFWorkbook
使用SXSSFWorkbook
。
这是一个简单的工作示例:
public void createExcelFileUsingSXSSFWorkbook(XSSFWorkbook wb)
SXSSFWorkbook wbSXSSF = new SXSSFWorkbook(wb);
try
Path path = Files.createFile(Path.of("test.xlsx"));
try (OutputStream outputStream = Files.newOutputStream(path))
wbSXSSF.write(outputStream);
wbSXSSF.close();
catch (IOException e2)
e2.printStackTrace();
catch (IOException e1)
e1.printStackTrace();
【讨论】:
【参考方案2】:我能够按以下方式解决此问题
outputStream = outputStream1 ->
sxssfWorkbook.write(outputStream1);
sxssfWorkbook.dispose();
sxssfWorkbook.close();
;
工作簿正在写入 responseBuilder.build()
,所以我必须将 write()、dispose() 和 close() 烘焙到输出流中才能正常工作
【讨论】:
以上是关于SXSSFWorkbook 无法写入数据,文档似乎已经关闭的主要内容,如果未能解决你的问题,请参考以下文章
HSSFWorkbook-SXSSFWorkbook导出excel文件获取大小记录
java excel poi 中的SXSSFWorkbook wb = new SXSSFWorkbook(workbook, 1000);是啥意思?
poi的XSSFWorkbook转SXSSFWorkbook发现的问题