阅读使用Excel工作表的链接表的Access数据库

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

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

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

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

此时,LinkResolver API仅用于从其他数据库加载“远程”表实例。 它不是为任何types的外部文件构build的通用API。 你当然可以用Jackcess项目提交一个function请求。

更新:

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

我想出了一个LinkResolver的初始实现,它使用Excel文件中的内容构build一个临时数据库。 它仍然缺less一些像临时数据库的closures处理和临时文件删除的东西,但它似乎适用于基本目的。

 /** * 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); } }