【问题标题】:Read an Access database which uses linked tables with Excel sheets读取使用带有 Excel 工作表的链接表的 Access 数据库
【发布时间】:2017-09-28 08:14:24
【问题描述】:

我正在尝试使用 Java 库 Jackcess 从 Access 数据库中读取数据。该数据库有几个表和查询,其中一些是指向文件系统上 Excel 工作表的链接表。

我看到我可以使用LinkResolver 来拦截链接数据的解析,但它需要一个成熟的数据库,而不仅仅是一个表的数据。

我可以轻松使用Apache POI打开Excel文件并提取必要的数据,但我不知道如何在LinkResolver中传递数据。

提供 Excel 文件的位置或从 Excel 文件中读取数据并将其传递回 Jackcess 以便成功加载链接数据的最简单方法是什么?

【问题讨论】:

  • 您是否有理由需要通过 Jackcess API 专门加载数据(而不是仅通过 POI 访问相关数据)?
  • 我想实际读取 Access 数据库中的数据,Excel 文件只是某些查询所必需的,Jackcess 失败,链接未正确解析。
  • 我不认为我理解。你不能避免从 Jackcess 中读取“远程”表吗?还是您使用 ucanaccess 对多个表运行实际的 sql 查询?
  • 我正在尝试自动验证数据库中的内容,但是当我读取包含此表的查询的 sql 时,它会失败,因为它会尝试解析链接。
  • 啊,明白了。有道理。

标签: java excel apache-poi resolver jackcess


【解决方案1】:

此时,LinkResolver API 仅用于从其他数据库加载“远程”表实例。它不是为任何类型的外部文件构建的通用 API。您当然可以向 Jackcess 项目提交功能请求。

更新:

从 2.1.7 版本开始,jackcess 提供了CustomLinkResolver 实用程序,以方便从不是访问数据库的文件中加载链接表(使用临时数据库)。

【讨论】:

  • 非常感谢,它现在与 2.1.7 配合得很好,对我来说自定义代码更少了,是的!
  • @centic - 太棒了,很高兴它有帮助!
【解决方案2】:

我想出了以下 LinkResolver 的初始实现,它使用 Excel 文件中的内容构建一个临时数据库。它仍然缺少一些东西,比如临时数据库的关闭处理和临时文件删除,但它似乎可以用于基本目的。

/**
 * Sample LinkResolver which reads the data from an Excel file
 * The data is read from the first sheet and needs to contain a
 * header-row with column-names and then data-rows with string/numeric values.
 */
public class ExcelFileLinkResolver implements LinkResolver {
    private final LinkResolver parentResolver;
    private final String fileNameInDB;
    private final String tableName;
    private final File excelFile;

    public ExcelFileLinkResolver(LinkResolver parentResolver, String fileNameInDB, File excelFile, String tableName) {
        this.parentResolver = parentResolver;
        this.fileNameInDB = fileNameInDB;
        this.excelFile = excelFile;
        this.tableName = tableName;
    }

    @Override
    public Database resolveLinkedDatabase(Database linkerDb, String linkeeFileName) throws IOException {
        if(linkeeFileName.equals(fileNameInDB)) {
            // TODO: handle close or create database in-memory if possible
            File tempFile = File.createTempFile("LinkedDB", ".mdb");
            Database linkedDB = DatabaseBuilder.create(Database.FileFormat.V2003, tempFile);

            try (Workbook wb = WorkbookFactory.create(excelFile, null, true)) {
                TableBuilder tableBuilder = new TableBuilder(tableName);

                Table table = null;
                List<Object[]> rows = new ArrayList<>();
                for(org.apache.poi.ss.usermodel.Row row : wb.getSheetAt(0)) {
                    if(table == null) {
                        for(Cell cell : row) {
                            tableBuilder.addColumn(new ColumnBuilder(cell.getStringCellValue()
                                    // column-names cannot contain some characters
                                    .replace(".", ""),
                                    DataType.TEXT));
                        }

                        table = tableBuilder.toTable(linkedDB);
                    } else {
                        List<String> values = new ArrayList<>();
                        for(Cell cell : row) {
                            if(cell.getCellTypeEnum() == CellType.NUMERIC) {
                                values.add(Double.toString(cell.getNumericCellValue()));
                            } else {
                                values.add(cell.getStringCellValue());
                            }
                        }
                        rows.add(values.toArray());
                    }
                }
                Preconditions.checkNotNull(table, "Did not have a row in " + excelFile);
                table.addRows(rows);
            } catch (InvalidFormatException e) {
                throw new IllegalStateException(e);
            }

            return linkedDB;
        }
        return parentResolver.resolveLinkedDatabase(linkerDb, linkeeFileName);
    }
}

【讨论】:

  • 嘿,我实际上回到这个问题来发布类似的建议。我在想 jackcess 可以有一个 LinkResolver 的基类,它为您提供了从另一个文件加载数据并将其拉入临时数据库的钩子。
  • 是的,如果能在此处获得更多支持,那就太好了。与此同时,我似乎在这里遇到了一些额外的障碍,因为 jackcess 似乎有时会在主数据库中寻找表格,而不是链接的表格。
  • 是的,这不会让我感到惊讶。链接的东西没有被大量使用(我知道),并且将 Table 实例从一个数据库传递到另一个数据库有点粗略。如果您发现错误,请在项目主站点report them
  • 我创建了一个feature reques 来跟踪这个想法。我已经完成了大部分代码,只需要打磨边缘。
  • 非常感谢!我会尽快尝试。与此同时,我成功地将 Excel 文件链接到临时数据库中的表中,看起来我现在适合一些验证/验证代码 :)
猜你喜欢
  • 1970-01-01
  • 2020-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
相关资源
最近更新 更多