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

79 lines
2.8 KiB
JavaScript
Raw 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);