如何从excel文件中提取外部引用列表

时间:2014-11-05 13:12:07

标签: java excel apache-poi

我正在为一个(不断增长的)非结构化的excel文档集合建立一个自动处理系统。该集合包含旧式.xls文件和新.xlsx文件。在我的基于Java的解决方案中,我已经在使用Apache POI工具包来分析文档。

我尚未解决的一个挑战是如何识别文档之间的链接以便绘制依赖关系。我还没有弄清楚如何方便地提取外部参考列表。对于.xlsx个文件,我有一个解压缩文件的解决方法,并打开包含引用的xml文件。这适用于大型文档集合但效率低下,并且不提供.xls文件的解决方案。

我更倾向于拥有一个不依赖于Microsoft Office或相关库的解决方案,因为解决方案需要在Linux环境中运行。

POI能够以某种方式做到这一点吗?如果没有,我可以进一步调查的建议库/工具/区域是什么?

1 个答案:

答案 0 :(得分:1)

最终,我通过POI源代码工作,并使用反射来获取引用的外部工作簿列表。以下代码经过测试,适用于POI版本3.11 beta。

对于希望在代码中使用此方法的人注意:因为它处理非公共方法和类,所以它可能会发生变化,并且可能在将来中断。

private LinkedList<String> getWorkbookReferences(HSSFWorkbook wb) {
    LinkedList<String> references = new LinkedList<>();

    try {
        // 1. Get InternalWorkbook
        Field internalWorkbookField = HSSFWorkbook.class.getDeclaredField("workbook");
        internalWorkbookField.setAccessible(true);
        InternalWorkbook internalWorkbook = (InternalWorkbook) internalWorkbookField.get(wb);

        // 2. Get LinkTable (hidden class)
        Method getLinkTableMethod;
        getLinkTableMethod = InternalWorkbook.class.getDeclaredMethod("getOrCreateLinkTable", null);

        getLinkTableMethod.setAccessible(true);
        Object linkTable = getLinkTableMethod.invoke(internalWorkbook, null);

        // 3. Get external books method
        Method externalBooksMethod = linkTable.getClass().getDeclaredMethod("getExternalBookAndSheetName", int.class);
        externalBooksMethod.setAccessible(true);

        // 4. Loop over all possible workbooks
        int i = 0;
        String[] names;
        try {
            while( true) {
                names = (String[]) externalBooksMethod.invoke(linkTable, i++) ;                     if (names != null ) {
                    references.add(names[0]);
                }
            }
        }
        catch  ( java.lang.reflect.InvocationTargetException e) {
            if ( !(e.getCause() instanceof java.lang.IndexOutOfBoundsException) ) {
                throw e;
            }
        }
    } catch (NoSuchFieldException | NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e) {
        e.printStackTrace();
    }

    return references;
}