ZDDC/tables/js/export.js
2026-06-11 13:32:31 -05:00

79 lines
2.8 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// export.js — CSV download of the current table view.
//
// Exports what the user sees: filter + sort applied, columns in the
// order declared by the spec. Values pass through util.formatCell so
// date / number / boolean cells match their on-screen rendering.
// RFC 4180 quoting (double-quote any cell with a comma, newline, or
// quote; escape inner quotes by doubling). UTF-8 BOM prepended so
// Excel detects the encoding without a manual import-wizard step.
(function (app) {
'use strict';
function csvEscape(value) {
if (value == null) return '';
const str = String(value);
if (/[",\r\n]/.test(str)) {
return '"' + str.replace(/"/g, '""') + '"';
}
return str;
}
function buildCsv(rows, columns, util) {
const lines = [];
lines.push(columns.map(function (c) {
return csvEscape(c.title || c.field || '');
}).join(','));
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
const cells = columns.map(function (c) {
const raw = util.resolveField(row.data, c.field);
return csvEscape(util.formatCell(raw, c.format));
});
lines.push(cells.join(','));
}
return lines.join('\r\n') + '\r\n';
}
function suggestFilename() {
const titleEl = document.getElementById('table-title');
const raw = (titleEl && titleEl.textContent) ? titleEl.textContent : 'table';
const base = raw.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '') || 'table';
const stamp = new Date().toISOString().slice(0, 10);
return base + '-' + stamp + '.csv';
}
function download(csv, filename) {
const blob = new Blob(['' + csv], { type: 'text/csv;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(function () { URL.revokeObjectURL(url); }, 1000);
}
function invoke() {
const ctx = app.context || {};
const columns = Array.isArray(ctx.columns) ? ctx.columns : [];
if (columns.length === 0) {
return;
}
const state = app.state;
const util = app.modules.util;
const filtered = app.modules.filters.apply(state.rows, columns, state.filter, util.resolveField);
const sorted = app.modules.sort.apply(filtered, state.sort, columns, util);
const csv = buildCsv(sorted, columns, util);
download(csv, suggestFilename());
}
app.modules.exportCsv = {
invoke: invoke,
buildCsv: buildCsv,
csvEscape: csvEscape
};
})(window.tablesApp);