You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI 5.2.5生成XLSX文件XML解析错误修复求助

问题:Apache POI 5.2.5生成的XLSX文件在Excel中打开报错,表格对象丢失

问题现象

  • 使用Apache POI 5.2.5生成.xlsx文件,将字节数组返回给客户端下载,本地打开时弹出错误提示:We found a problem with some content in *.xlsx. Do you want us to try to recover it as much as we can
  • 确认后文件可打开,但表格对象丢失;谷歌表格可正常打开并显示表格边框
  • 直接在服务器保存文件也存在该问题,排除客户端因素

错误日志

Mac上打开文件时的recovery log:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <logFileName>Repair Result to <FILE_NAME>0.xml</logFileName>
    <summary>Errors were detected in file '<FILE_PATH>.xlsx'</summary>
    <removedParts summary="Following is a list of removed parts:">
        <removedPart>Removed Part: /xl/tables/table1.xml part with XML error.  (Table) Xml parsing error Line 2, column 70.</removedPart>
    </removedParts>
</recoveryLog>

生成的/xl/tables/table1.xml内容:

<?xml version="1.0" encoding="UTF-8"?>
<table id="1" displayName="Data Table" name="Data_Table" ref="A1:H3" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"/>

错误原因

Excel的OpenXML规范要求,表格(Table)必须包含<tableColumns>和<tableStyleInfo>核心节点。当前生成的table XML仅包含基础属性,缺少这两个必填结构,导致Excel判定XML无效,进而移除表格对象。谷歌表格对规范的兼容性更宽松,所以能正常识别。

修复方案

修改createTable方法,补充表格的列定义和样式信息,确保生成符合OpenXML规范的表格结构:

修改后的完整createTable方法

private void createTable(XSSFSheet sheet, int startRow, int startCol, CellStyle headerStyle, CellStyle dataStyle, List<DATA_OBJECT> data) {
    // 创建表头行
    Row headerRow = sheet.createRow(startRow);
    // 替换为实际的表头名称数组
    String[] HEADER_NAMES = {"列1", "列2", "列3", "列4", "列5", "列6", "列7", "列8"};
    for (int x = 0; x < HEADER_NAMES.length; x++) {
        createCell(headerRow, startCol + x, HEADER_NAMES[x], headerStyle);
    }

    // 创建数据行
    for (int i = 0; i < data.size(); i++) {
        DATA_OBJECT data_object = data.get(i);
        Row dataRow = sheet.createRow(startRow + i + 1);
        // 替换为实际的数据填充逻辑
        createCell(dataRow, startCol, data_object.getRelevantValue1(), dataStyle);
        createCell(dataRow, startCol + 1, data_object.getRelevantValue2(), dataStyle);
        // ... 依次填充所有列
    }

    // 修正endRow计算:原代码误用baseHoldings,改为传入的data列表
    int endRow = startRow + data.size();
    int endCol = startCol + HEADER_NAMES.length - 1; // 列索引从0开始,需减1

    // 设置自动筛选
    sheet.setAutoFilter(new CellRangeAddress(startRow, endRow, startCol, endCol));

    // 调整列宽
    for (int i = startCol; i <= endCol; i++) {
        sheet.autoSizeColumn(i);
        sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 1000);
    }

    // 创建Excel表格
    XSSFTable table = sheet.createTable(null);
    CTTable cttable = table.getCTTable();

    // 设置表格基础属性
    cttable.setDisplayName("Data Table");
    cttable.setId(1);
    cttable.setName("Data_Table");
    cttable.setRef(new CellRangeAddress(startRow, endRow, startCol, endCol).formatAsString());

    // 添加表格列定义(必填)
    CTTableColumns ctTableColumns = cttable.addNewTableColumns();
    ctTableColumns.setCount(HEADER_NAMES.length); // 列数需与实际一致
    for (int i = 0; i < HEADER_NAMES.length; i++) {
        CTTableColumn ctTableColumn = ctTableColumns.addNewTableColumn();
        ctTableColumn.setId(i + 1); // ID从1开始递增
        ctTableColumn.setName(HEADER_NAMES[i]);
    }

    // 添加表格样式信息(必填)
    CTTableStyleInfo ctTableStyleInfo = cttable.addNewTableStyleInfo();
    ctTableStyleInfo.setName("TableStyleMedium2"); // 使用Excel内置样式,可按需替换
    ctTableStyleInfo.setShowColumnStripes(false);
    ctTableStyleInfo.setShowRowStripes(true);
    ctTableStyleInfo.setShowFirstColumn(false);
    ctTableStyleInfo.setShowLastColumn(false);
}

关键修复点

  1. 修正endRow计算错误:原代码误用baseHoldings.size(),改为data.size()
  2. 添加<tableColumns>节点:定义表格的列ID和名称,数量需与实际列数匹配
  3. 添加<tableStyleInfo>节点:指定表格使用的样式,即使使用默认样式也必须声明

修复后生成的table1.xml会包含完整的结构,Excel可以正常识别表格对象,不再弹出错误提示。

内容的提问来源于stack exchange,提问作者Gal Mor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 15:54:50