Skip to main content
 首页 » 编程设计

java之如何找出导致 poi 损坏 xlsx/xlsm 文件的原因

2024年05月22日12jirigala

我遇到的问题是 Apache POI 通过读写(例如使用以下代码)“损坏”了一个 xlsm/xlsx 文件

public class Snippet { 
    public static void main(String[] args) throws Exception { 
 
        String str1 = "c:/tmp/spreadsheet.xlsm"; 
        String str2 = "c:/tmp/spreadsheet_poi.xlsm"; 
 
        // open file 
        XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(new File(str1))); 
 
        // save file 
        FileOutputStream out = new FileOutputStream(str2); 
        wb.write(out); 
        wb.close(); 
        out.close(); 
 
    } 
} 

在 Excel 中打开 spreadsheet_poi.xlsm 后,您将收到如下错误

“我们发现 xxx 中的某些内容存在问题。您是否希望我们尽可能多地尝试恢复……”?

如果你说是,你最终会得到一个看起来像这样的日志:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> 
    <logFileName>error145040_01.xml</logFileName> 
    <summary>Errors were detected in file 'C:\tmp\spreadsheet_poi.xlsm'</summary> 
    <repairedParts> 
        <repairedPart>Repaired Part: /xl/worksheets/sheet4.xml part with XML error.  Load error. Line 2, column 0.</repairedPart> 
        <repairedPart>Repaired Part: /xl/worksheets/sheet5.xml part with XML error.  Load error. Line 2, column 0.</repairedPart> 
        <repairedPart>Repaired Part: /xl/worksheets/sheet8.xml part with XML error.  Load error. Line 2, column 0.</repairedPart> 
    </repairedParts> 
</recoveryLog> 

更详细地调试问题的最佳方法是什么(例如找出是什么让 poi “损坏”文件?

请您参考如下方法:

最终我发现调试这个的最佳方法是两件事

  1. 打开受影响的工作簿(例如使用 7zip 并使用 xml 编辑器格式化受影响的工作表(例如 Notepad++ > Plugins > XML Tools > Pretty print(仅限 XML - 带换行符))。保存文件并更新 xlsm 文件后,您将在 Excel 错误日志中获得“真实”行号。替代选项(我没有尝试过但应该根据 POI 邮件列表工作:使用 OOXMLPrettyPrint ( https://svn.apache.org/repos/asf/poi/trunk/src/ooxml/java/org/apache/poi/ooxml/dev/ ) 来格式化文件,然后在 Excel 中重新打开它。
  2. 如果实际行号还没有帮助比较原始 xlsx 文件和 poi 保存的工作表 xml 文件。您会注意到在属性方面存在差异,而且顺序也不同。为了正确比较,我使用了 Beyond Compare 和“其他文件格式”(有关更多信息,请参见 https://weblogs.asp.net/lorenh/comparing-xml-files-with-beyond-compare-3-brilliant)。也许还有另一个同样出色的 diff 工具。

在我的例子中,问题是 poi 以某种方式改变了尺寸设置

<dimension ref="A1:XFD147"/> 

<dimension ref="A1:XFE147"/> 

(XFE 是一个不存在的列)。我通过删除原始 xlsx 文件中的许多空列来修复它。