diff --git a/.eslintrc.json b/.eslintrc.json index a4fd4c85..1fef0810 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,7 +2,7 @@ "extends": "eslint:recommended", "parserOptions": { "sourceType": "module", - "ecmaVersion": 8 + "ecmaVersion": 9 }, "env": { "browser": true, diff --git a/src/fileAttachment.js b/src/fileAttachment.js index a1da5bb9..fe731633 100644 --- a/src/fileAttachment.js +++ b/src/fileAttachment.js @@ -1,5 +1,6 @@ import {require as requireDefault} from "d3-require"; import sqlite, {SQLiteDatabaseClient} from "./sqlite.js"; +import xlsx, {XlsxWorkbook} from "./xlsx.js"; async function remote_fetch(file) { const response = await fetch(await file.url()); @@ -62,6 +63,10 @@ class FileAttachment { const db = new SQL.Database(new Uint8Array(buffer)); return new SQLiteDatabaseClient(db); } + async xlsx(options) { + const [XLSX, buffer] = await Promise.all([xlsx(requireDefault), this.arrayBuffer()]); + return new XlsxWorkbook(await XLSX.read(buffer, {cellDates: true, ...options, type: "buffer"})); + } } export function NoFileAttachments(name) { diff --git a/src/xlsx.js b/src/xlsx.js new file mode 100644 index 00000000..9a822280 --- /dev/null +++ b/src/xlsx.js @@ -0,0 +1,20 @@ +let XLSX; // set lazily + +export default async function xslx(require) { + return XLSX = await require("xlsx@0.17.0/dist/xlsx.mini.min.js"); +} + +export class XlsxWorkbook { + constructor(workbook) { + Object.defineProperties(this, { + _: {value: workbook} + }); + } + sheetNames() { + return this._.SheetNames.slice(); + } + sheet(name, options) { + if (!Object.prototype.hasOwnProperty.call(this._.Sheets, name)) throw new Error("unknown sheet"); + return XLSX.utils.sheet_to_json(this._.Sheets[name], options); + } +}