From a1f9f5e4d9a9a243413604a41efaa0969dfaa712 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sat, 6 Aug 2022 21:57:38 -0400 Subject: [PATCH] systemjs --- .../04-getting-started/03-demos/09-bundler.md | 188 ++++++++++++++++++ docz/static/systemjs/main.js | 129 ++++++++++++ docz/static/systemjs/systemjs.html | 77 +++++++ 3 files changed, 394 insertions(+) create mode 100644 docz/static/systemjs/main.js create mode 100644 docz/static/systemjs/systemjs.html diff --git a/docz/docs/04-getting-started/03-demos/09-bundler.md b/docz/docs/04-getting-started/03-demos/09-bundler.md index db1a7e0..c92870a 100644 --- a/docz/docs/04-getting-started/03-demos/09-bundler.md +++ b/docz/docs/04-getting-started/03-demos/09-bundler.md @@ -771,6 +771,194 @@ Click on "Click here to export" to generate a file. +## SystemJS + +With configuration, SystemJS supports both browser and NodeJS deployments. + +:::caution + +This demo was written against SystemJS 0.19, the most popular SystemJS version. +used with Angular applications. In the years since the release, Angular and +other tools using SystemJS have switched to Webpack. + +::: + + + + +SystemJS fails by default because the library does not export anything in the +web browser. The `meta` configuration option can be used to expose `XLSX`: + +```js +SystemJS.config({ + meta: { + 'xlsx': { + exports: 'XLSX' // <-- tell SystemJS to expose the XLSX variable + } + }, + map: { + 'xlsx': 'https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js', + 'fs': '', // <--| + 'crypto': '', // <--| suppress native node modules + 'stream': '' // <--| + } +}); +SystemJS.import('main.js'); // load `main.js` +``` + +The `main.js` script can freely `require("xlsx")`. + +:::caution Web Workers + +Web Workers can load the SystemJS library with `importScripts`, but the imported +code cannot assign the original worker's `onmessage` callback. The recommended +approach is to expose a global from the required script, For example, supposing +the shared name is `_cb`, the primary worker script would call the callback: + +```js title="worker.js" +/* main worker script */ +importScripts('system.js'); + +SystemJS.config({ /* ... browser config ... */ }); + +onmessage = function(evt) { + SystemJS.import('workermain.js').then(function() { _cb(evt); }); +}; +``` + +The worker script would define and expose the function: + +```js title="workermain.js" +/* Loaded with SystemJS import */ +var XLSX = require('xlsx'); + +_cb = function(evt) { /* ... do work here ... */ }; +``` + +::: + + + + +:::caution + +While SystemJS works in NodeJS, the built-in `require` should be preferred. + +::: + +The NodeJS module entrypoint is `xlsx/xlsx.js` and should be mapped: + +```js +SystemJS.config({ + map: { + "xlsx": "./node_modules/xlsx/xlsx.js" + } +}); +``` + +The standalone scripts require a hint that the script assigns a global: + +```js +SystemJS.config({ + meta: { + "standalone": { format: "global" } + }, + map: { + "standalone": "xlsx.full.min.js" + } +}); +``` + + + +
Complete Example (click to show) + + + + +The [Live demo](pathname:///systemjs/systemjs.html) loads SystemJS from the +CDN, uses it to load the standalone script from the SheetJS CDN and emulate +a `require` implementation when loading [`main.js`](pathname:///systemjs/main.js) + +"View Source" works on the main HTML page and the `main.js` script. + + + + +1) Install the dependencies: + +
{`\
+$ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz systemjs@0.19`}
+
+ +2) Save the following script to `SheetJSystem.js`: + +```js title="SheetJSystem.js" +const SystemJS = require('systemjs'); + +// highlight-start +SystemJS.config({ + map: { + 'xlsx': 'node_modules/xlsx/xlsx.js', + 'fs': '@node/fs', + 'crypto': '@node/crypto', + 'stream': '@node/stream' + } +}); +// highlight-end + +SystemJS.import('xlsx').then(async function(XLSX) { + + /* fetch JSON data and parse */ + const url = "https://sheetjs.com/executive.json"; + const raw_data = await (await fetch(url)).json(); + + /* filter for the Presidents */ + const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); + + /* flatten objects */ + const rows = prez.map(row => ({ + name: row.name.first + " " + row.name.last, + birthday: row.bio.birthday + })); + + /* generate worksheet and workbook */ + const worksheet = XLSX.utils.json_to_sheet(rows); + const workbook = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); + + /* fix headers */ + XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); + + /* calculate column width */ + const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); + worksheet["!cols"] = [ { wch: max_width } ]; + + /* create an XLSX file and try to save to Presidents.xlsx */ + XLSX.writeFile(workbook, "Presidents.xlsx"); + +}); +``` + +3) Run in NodeJS: + +```bash +node SheetJSystem.js +``` + +If the demo worked, `Presidents.xlsx` will be created. + +:::note + +As it uses `fetch`, this demo requires Node 18. + +::: + +
+
+ +
+ ## Vite :::caution diff --git a/docz/static/systemjs/main.js b/docz/static/systemjs/main.js new file mode 100644 index 0000000..8bfe87a --- /dev/null +++ b/docz/static/systemjs/main.js @@ -0,0 +1,129 @@ +/* sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ +/*jshint browser:true */ +/*global XLSX */ +var XLSX = require('xlsx'); + +var global_wb; + +var process_wb = (function() { + var OUT = document.getElementById('out'); + var HTMLOUT = document.getElementById('htmlout'); + + var get_format = (function() { + var radios = document.getElementsByName( "format" ); + return function() { + for(var i = 0; i < radios.length; ++i) if(radios[i].checked || radios.length === 1) return radios[i].value; + }; + })(); + + var to_json = function to_json(workbook) { + var result = {}; + workbook.SheetNames.forEach(function(sheetName) { + var roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]); + if(roa.length) result[sheetName] = roa; + }); + return JSON.stringify(result, 2, 2); + }; + + var to_csv = function to_csv(workbook) { + var result = []; + workbook.SheetNames.forEach(function(sheetName) { + var csv = XLSX.utils.sheet_to_csv(workbook.Sheets[sheetName]); + if(csv.length){ + result.push("SHEET: " + sheetName); + result.push(""); + result.push(csv); + } + }); + return result.join("\n"); + }; + + var to_fmla = function to_fmla(workbook) { + var result = []; + workbook.SheetNames.forEach(function(sheetName) { + var formulae = XLSX.utils.get_formulae(workbook.Sheets[sheetName]); + if(formulae.length){ + result.push("SHEET: " + sheetName); + result.push(""); + result.push(formulae.join("\n")); + } + }); + return result.join("\n"); + }; + + var to_html = function to_html(workbook) { + HTMLOUT.innerHTML = ""; + workbook.SheetNames.forEach(function(sheetName) { + var htmlstr = XLSX.write(workbook, {sheet:sheetName, type:'string', bookType:'html'}); + HTMLOUT.innerHTML += htmlstr; + }); + return ""; + }; + + return function process_wb(wb) { + global_wb = wb; + var output = ""; + switch(get_format()) { + case "form": output = to_fmla(wb); break; + case "html": output = to_html(wb); break; + case "json": output = to_json(wb); break; + default: output = to_csv(wb); + } + if(OUT.innerText === undefined) OUT.textContent = output; + else OUT.innerText = output; + if(typeof console !== 'undefined') console.log("output", new Date()); + }; +})(); + +var setfmt = window.setfmt = function setfmt() { if(global_wb) process_wb(global_wb); }; + +var b64it = window.b64it = (function() { + var tarea = document.getElementById('b64data'); + return function b64it() { + if(typeof console !== 'undefined') console.log("onload", new Date()); + var wb = XLSX.read(tarea.value, {type:'base64', WTF:false}); + process_wb(wb); + }; +})(); + +var do_file = (function() { + return function do_file(files) { + var f = files[0]; + var reader = new FileReader(); + reader.onload = function(e) { + if(typeof console !== 'undefined') console.log("onload", new Date()); + var data = e.target.result; + data = new Uint8Array(data); + process_wb(XLSX.read(data, {type: 'array'})); + }; + reader.readAsArrayBuffer(f); + }; +})(); + +(function() { + var drop = document.getElementById('drop'); + if(!drop.addEventListener) return; + + function handleDrop(e) { + e.stopPropagation(); + e.preventDefault(); + do_file(e.dataTransfer.files); + } + + function handleDragover(e) { + e.stopPropagation(); + e.preventDefault(); + e.dataTransfer.dropEffect = 'copy'; + } + + drop.addEventListener('dragenter', handleDragover, false); + drop.addEventListener('dragover', handleDragover, false); + drop.addEventListener('drop', handleDrop, false); +})(); + +(function() { + var xlf = document.getElementById('xlf'); + if(!xlf.addEventListener) return; + function handleFile(e) { do_file(e.target.files); } + xlf.addEventListener('change', handleFile, false); +})(); diff --git a/docz/static/systemjs/systemjs.html b/docz/static/systemjs/systemjs.html new file mode 100644 index 0000000..18a4288 --- /dev/null +++ b/docz/static/systemjs/systemjs.html @@ -0,0 +1,77 @@ + + + + + + +SheetJS Live Demo + + + +
+SheetJS Data Preview Live Demo
+(Base64 text works back to IE6; drag and drop works back to IE10)
+
+Source Code Repo
+Issues?  Something look weird?  Click here and report an issue
+Output Format: 
+
Drop a spreadsheet file here to see sheet data
+ ... or click here to select a file + + +
+Advanced Demo Options: +
+

+
+
+ + + + +