我正在尝试使用Java Library Jackcess从访问数据库中读取数据。该数据库有几个表和查询,其中一些是链接的表,指向文件系统上的excel表。
我看到我可以使用LinkResolver
拦截链接数据的分辨率,但是它希望有一个成熟的数据库,而不仅仅是一个单个表的数据。
我可以轻松地使用Apache Poi打开Excel文件并提取必要的数据,但是我不知道如何通过LinkResolver中的数据传递数据。
提供Excel文件位置或从Excel文件中读取数据并将其传递给Jackcess的最简单方法是什么?
在此时间点,LinkResolver API仅用于从其他数据库中加载"远程"表实例。它不是用于任何类型的外部文件的通用API。您当然可以通过Jackcess项目提交功能请求。
更新:
截至2.1.7发行版,Jackcess提供了CustomLinkResolver实用程序,以促进来自不访问数据库的文件(使用临时DB(的加载链接表。
我提出了以下最初的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);
}
}