读取Access数据库,该数据库使用带Excel表的链接表

时间:2017-04-30 19:00:44

标签: java excel apache-poi resolver jackcess

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

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

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

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

2 个答案:

答案 0 :(得分:2)

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

更新:

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

答案 1 :(得分:1)

我想出了以下初始实现的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);
    }
}