feat(export): support XLSX comment headers
This commit is contained in:
4 files changed
+311
-28
No files matched your search
@@ -2012,13 +2012,11 @@ async function exportDataXlsx(row: ObjectBrowserRow) {
|
||||
|
||||
try {
|
||||
columnInfos = await api.getColumns(props.connection.id, props.database, schema || props.database, row.name, props.catalog);
|
||||
const hasComments = hasXlsxHeaderComments(columnInfos.map((column) => column.comment));
|
||||
const result = await showObjectBrowserXlsxHeaderDialog(hasComments);
|
||||
const result = await showObjectBrowserXlsxHeaderDialog(hasXlsxHeaderComments(columnInfos.map((column) => column.comment)));
|
||||
if (result === null) return;
|
||||
headerMode = result;
|
||||
} catch {
|
||||
// Column fetch failed, fallback to export without comments
|
||||
columnInfos = undefined;
|
||||
// Export still works with field-name headers when column metadata is unavailable.
|
||||
}
|
||||
|
||||
await exportTableData(row, "xlsx", columnInfos, headerMode);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const source = readFileSync(new URL("../ObjectBrowser.vue", import.meta.url), "utf8");
|
||||
|
||||
function functionBody(name: string): string {
|
||||
const signature = new RegExp(`(?:async\\s+)?function\\s+${name}\\s*\\([^)]*\\)\\s*(?::\\s*[^\\{]+)?\\{`, "m").exec(source);
|
||||
if (!signature) throw new Error(`Missing function ${name}`);
|
||||
const bodyStart = signature.index + signature[0].length;
|
||||
let depth = 1;
|
||||
for (let index = bodyStart; index < source.length; index += 1) {
|
||||
if (source[index] === "{") depth += 1;
|
||||
else if (source[index] === "}") depth -= 1;
|
||||
if (depth === 0) return source.slice(bodyStart, index);
|
||||
}
|
||||
throw new Error(`Unclosed function ${name}`);
|
||||
}
|
||||
|
||||
describe("ObjectBrowser XLSX export", () => {
|
||||
it("asks for a header mode before opening the save dialog when comments exist", () => {
|
||||
const dialog = functionBody("showObjectBrowserXlsxHeaderDialog");
|
||||
const exportDataXlsx = functionBody("exportDataXlsx");
|
||||
|
||||
expect(dialog).toContain('if (!hasComments) return Promise.resolve("name")');
|
||||
expect(exportDataXlsx).toContain("hasXlsxHeaderComments(columnInfos.map((column) => column.comment))");
|
||||
expect(exportDataXlsx.indexOf("await showObjectBrowserXlsxHeaderDialog(")).toBeLessThan(exportDataXlsx.indexOf('await exportTableData(row, "xlsx", columnInfos, headerMode)'));
|
||||
});
|
||||
|
||||
it("falls back to field-name headers when column metadata is unavailable", () => {
|
||||
const exportDataXlsx = functionBody("exportDataXlsx");
|
||||
|
||||
expect(exportDataXlsx).toContain("catch {\n // Export still works with field-name headers when column metadata is unavailable.\n }");
|
||||
expect(exportDataXlsx).toContain('await exportTableData(row, "xlsx", columnInfos, headerMode)');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user