XLSX custprops strip ns [ci skip]

This commit is contained in:
SheetJS 2022-08-15 01:20:14 -04:00
parent 838ee58a49
commit 917a69e394
56 changed files with 81 additions and 1008 deletions

@ -5,7 +5,7 @@ function parse_cust_props(data/*:string*/, opts) {
var m = data.match(custregex);
if(m) for(var i = 0; i != m.length; ++i) {
var x = m[i], y = parsexmltag(x);
switch(y[0]) {
switch(strip_ns(y[0])) {
case '<?xml': break;
case '<Properties': break;
case '<property': name = unescapexml(y.name); break;

@ -18,57 +18,60 @@ can be installed with Bash on Windows or with `cygwin`.
### Included Demos
**JavaScript APIs**
- [`XMLHttpRequest and fetch`](https://docs.sheetjs.com/docs/getting-started/demos/network)
- [`Clipboard Data`](https://docs.sheetjs.com/docs/getting-started/demos/clipboard)
- [`Typed Arrays for Machine Learning`](https://docs.sheetjs.com/docs/getting-started/demos/ml)
- [`LocalStorage and SessionStorage`](https://docs.sheetjs.com/docs/getting-started/demos/database#localstorage-and-sessionstorage)
- [`Web SQL Database`](https://docs.sheetjs.com/docs/getting-started/demos/database#websql)
- [`IndexedDB`](https://docs.sheetjs.com/docs/getting-started/demos/database#indexeddb)
- [`XMLHttpRequest and fetch`](https://docs.sheetjs.com/docs/demos/network)
- [`Clipboard Data`](https://docs.sheetjs.com/docs/demos/clipboard)
- [`Typed Arrays for Machine Learning`](https://docs.sheetjs.com/docs/demos/ml)
- [`LocalStorage and SessionStorage`](https://docs.sheetjs.com/docs/demos/database#localstorage-and-sessionstorage)
- [`Web SQL Database`](https://docs.sheetjs.com/docs/demos/database#websql)
- [`IndexedDB`](https://docs.sheetjs.com/docs/demos/database#indexeddb)
**Frameworks**
- [`Angular.JS`](https://docs.sheetjs.com/docs/getting-started/demos/legacy#angularjs)
- [`Angular.JS`](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
- [`Angular 2+ and Ionic`](angular2/)
- [`Knockout`](https://docs.sheetjs.com/docs/getting-started/demos/legacy#knockoutjs)
- [`React, React Native and NextJS`](react/)
- [`VueJS, WeeX and NuxtJS`](vue/)
- [`Knockout`](https://docs.sheetjs.com/docs/demos/legacy#knockoutjs)
- [`React and NextJS`](react/)
- [`VueJS`](vue/)
**Front-End UI Components**
- [`canvas-datagrid`](https://docs.sheetjs.com/docs/getting-started/demos/grid#canvas-datagrid)
- [`canvas-datagrid`](https://docs.sheetjs.com/docs/demos/grid#canvas-datagrid)
- [`x-spreadsheet`](xspreadsheet/)
- [`react-data-grid`](react/modify/)
- [`vue3-table-light`](vue/modify/)
- [`angular-ui-grid`](https://docs.sheetjs.com/docs/getting-started/demos/grid#angular-ui-grid)
- [`angular-ui-grid`](https://docs.sheetjs.com/docs/demos/grid#angular-ui-grid)
**Platforms and Integrations**
- [`Command-Line Tools`](https://docs.sheetjs.com/docs/getting-started/demos/cli)
- [`Command-Line Tools`](https://docs.sheetjs.com/docs/demos/cli)
- [`iOS and Android Mobile Applications`](https://docs.sheetjs.com/docs/demos/mobile)
- [`NodeJS Server-Side Processing`](server/)
- [`Electron`](https://docs.sheetjs.com/docs/getting-started/demos/desktop#electron)
- [`NW.js`](https://docs.sheetjs.com/docs/getting-started/demos/desktop#nwjs)
- [`Chrome / Chromium Extension`](https://docs.sheetjs.com/docs/getting-started/demos/chromium)
- [`Google Sheets API`](https://docs.sheetjs.com/docs/getting-started/demos/gsheet)
- [`ExtendScript for Adobe Apps`](https://docs.sheetjs.com/docs/getting-started/demos/extendscript)
- [`NetSuite SuiteScript`](https://docs.sheetjs.com/docs/getting-started/demos/netsuite)
- [`SalesForce Lightning Web Components`](https://docs.sheetjs.com/docs/getting-started/demos/salesforce)
- [`Excel JavaScript API`](https://docs.sheetjs.com/docs/getting-started/demos/excel)
- [`Headless Automation`](https://docs.sheetjs.com/docs/getting-started/demos/headless)
- [`Swift JSC and Other JavaScript Engines`](https://docs.sheetjs.com/docs/getting-started/demos/engines)
- [`Content Management and Static Sites`](https://docs.sheetjs.com/docs/demos/content)
- [`Electron`](https://docs.sheetjs.com/docs/demos/desktop#electron)
- [`NW.js`](https://docs.sheetjs.com/docs/demos/desktop#nwjs)
- [`Tauri`](https://docs.sheetjs.com/docs/demos/desktop#tauri)
- [`Chrome and Chromium Extensions`](https://docs.sheetjs.com/docs/demos/chromium)
- [`Google Sheets API`](https://docs.sheetjs.com/docs/demos/gsheet)
- [`ExtendScript for Adobe Apps`](https://docs.sheetjs.com/docs/demos/extendscript)
- [`NetSuite SuiteScript`](https://docs.sheetjs.com/docs/demos/netsuite)
- [`SalesForce Lightning Web Components`](https://docs.sheetjs.com/docs/demos/salesforce)
- [`Excel JavaScript API`](https://docs.sheetjs.com/docs/demos/excel)
- [`Headless Automation`](https://docs.sheetjs.com/docs/demos/headless)
- [`Swift JSC and Other JavaScript Engines`](https://docs.sheetjs.com/docs/demos/engines)
- [`"serverless" functions`](function/)
- [`Databases and Structured Data Stores`](https://docs.sheetjs.com/docs/getting-started/demos/database)
- [`NoSQL, K/V, and Unstructured Data Stores`](https://docs.sheetjs.com/docs/getting-started/demos/nosql)
- [`Legacy Internet Explorer`](oldie/)
- [`Databases and Structured Data Stores`](https://docs.sheetjs.com/docs/demos/database)
- [`NoSQL and Unstructured Data Stores`](https://docs.sheetjs.com/docs/demos/nosql)
- [`Legacy Internet Explorer`](https://docs.sheetjs.com/docs/demos/legacy#internet-explorer)
**Bundlers and Tooling**
- [`browserify`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#browserify)
- [`bun`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#bun)
- [`esbuild`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#esbuild)
- [`parcel`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#parcel)
- [`requirejs`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#requirejs)
- [`rollup`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#rollup)
- [`snowpack`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#snowpack)
- [`swc`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#swc)
- [`systemjs`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#systemjs)
- [`vite`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#vite)
- [`webpack`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#webpack)
- [`wmr`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#wmr)
- [`browserify`](https://docs.sheetjs.com/docs/demos/bundler#browserify)
- [`bun`](https://docs.sheetjs.com/docs/demos/bundler#bun)
- [`esbuild`](https://docs.sheetjs.com/docs/demos/bundler#esbuild)
- [`parcel`](https://docs.sheetjs.com/docs/demos/bundler#parcel)
- [`requirejs`](https://docs.sheetjs.com/docs/demos/bundler#requirejs)
- [`rollup`](https://docs.sheetjs.com/docs/demos/bundler#rollup)
- [`snowpack`](https://docs.sheetjs.com/docs/demos/bundler#snowpack)
- [`swc`](https://docs.sheetjs.com/docs/demos/bundler#swc)
- [`systemjs`](https://docs.sheetjs.com/docs/demos/bundler#systemjs)
- [`vite`](https://docs.sheetjs.com/docs/demos/bundler#vite)
- [`webpack`](https://docs.sheetjs.com/docs/demos/bundler#webpack)
- [`wmr`](https://docs.sheetjs.com/docs/demos/bundler#wmr)
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,6 +1,6 @@
# Other JS Engines and Deployments
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/engines)
[The new demo](https://docs.sheetjs.com/docs/demos/engines)
includes more detailed instructions and more JS engines.

@ -2,9 +2,9 @@
The content has been reorganized;
- [The "Legacy Frameworks" section](https://docs.sheetjs.com/docs/getting-started/demos/legacy#angularjs)
- [The "Legacy Frameworks" section](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
covers the AngularJS basics.
- [The "Angular UI Grid" section](https://docs.sheetjs.com/docs/getting-started/demos/legacy#angularjs)
- [The "Angular UI Grid" section](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
covers the integration with Angular UI Grid.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -32,14 +32,3 @@ ios browser: ionic
android: ionic
cd SheetJSIonic; ionic cordova prepare $@ </dev/null; ionic cordova emulate $@ </dev/null; cd -
.PHONY: nativescript
nativescript:
bash ./nscript.sh
.PHONY: ns-ios ns-android
ns-ios: nativescript
cd SheetJSNS; ns run ios; cd -
ns-android: nativescript
cd SheetJSNS; ns run android; cd -

@ -101,24 +101,9 @@ $ npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
The default angular-cli configuration requires no additional configuration.
Some deployments use the SystemJS loader, which does require configuration. The
SystemJS example shows the required meta and map settings:
```js
SystemJS.config({
meta: {
'xlsx': {
exports: 'XLSX' // <-- tell SystemJS to expose the XLSX variable
}
},
map: {
'xlsx': 'xlsx.full.min.js', // <-- make sure xlsx.full.min.js is in same dir
'fs': '', // <--|
'crypto': '', // <--| suppress native node modules
'stream': '' // <--|
}
});
```
Some deployments use the SystemJS loader, which does require configuration.
[SystemJS](https://docs.sheetjs.com/docs/demos/bundler#systemjs)
demo in the SheetJS CE docs describe the required settings.
## Ionic
@ -157,29 +142,7 @@ this.file.writeFile(url, filename, blob, {replace: true});
## NativeScript
Reproducing the full project is a little bit tricky. The included `nscript.sh`
script performs the necessary installation steps and adds the necessary shims
for `async` support. Due to incompatibilities with NativeScript and TypeScript
definitions, apps should require the `xlsx.full.min.js` file directly:
```typescript
const XLSX = require("./xlsx.full.min.js");
```
The `ISO_8859_1` encoding from the text module specifies `"binary"` strings.
`File#readText` and `File#writeText` reads and writes files:
```typescript
/* read a workbook */
const bstr: string = await file.readText(encoding.ISO_8859_1);
const wb = XLSX.read(bstr, { type: "binary" });
/* write a workbook */
const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
await file.writeText(wbout, encoding.ISO_8859_1);
```
Note: some versions of NativeScript do not properly support typed arrays or
binary strings. See <https://github.com/NativeScript/NativeScript/issues/9586>
[The new demo](https://docs.sheetjs.com/docs/demos/mobile#nativescript)
is updated for NativeScript 8 and uses more idiomatic data patterns.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,10 +0,0 @@
#!/bin/bash
if [ ! -e SheetJSNS ]; then
ns create SheetJSNS --ng
cd SheetJSNS
npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
cd ..
fi
<../../dist/xlsx.full.min.js sed 's/require("fs")/null/g' > SheetJSNS/src/app/xlsx.full.min.js
cp nscript.ts SheetJSNS/src/app/app.component.ts

@ -1,82 +0,0 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
import { Component } from '@angular/core';
import { encoding } from '@nativescript/core/text';
import { File, Folder, knownFolders, path } from '@nativescript/core/file-system';
import { Dialogs } from '@nativescript/core';
import { Page, GridLayout, WebView, DockLayout, Button } from '@nativescript/core';
import * as XLSX from './xlsx.full.min';
@Component({
selector: 'ns-app',
template: `
<Page>
<GridLayout rows="auto, *, auto">
<!-- data converted to HTML and rendered in web view -->
<WebView row="1" src="{{html}}"></WebView>
<DockLayout row="2" dock="bottom" stretchLastChild="false">
<Button text="Import File" (tap)="import()" style="padding: 10px"></Button>
<Button text="Export File" (tap)="export()" style="padding: 10px"></Button>
</DockLayout>
</GridLayout>
</Page>
`
})
export class AppComponent {
html: string = "";
constructor() {
const ws = XLSX.utils.aoa_to_sheet([[1,2],[3,4]]);
this.html = XLSX.utils.sheet_to_html(ws);
};
/* Import button */
async import() {
const filename: string = "SheetJSNS.csv";
/* find appropriate path */
const target: Folder = knownFolders.documents() || knownFolders.ios.sharedPublic();
const url: string = path.normalize(target.path + "///" + filename);
const file: File = File.fromPath(url);
try {
/* get binary string */
const bstr: string = await file.readText(encoding.ISO_8859_1);
/* read workbook */
const wb = XLSX.read(bstr, { type: "binary" });
/* grab first sheet */
const wsname: string = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* update table */
this.html = XLSX.utils.sheet_to_html(ws);
Dialogs.alert(`Attempting to read to ${filename} in ${url}`);
} catch(e) {
Dialogs.alert(e.message);
}
};
/* Export button */
async export() {
const wb = XLSX.read(this.html, { type: "string" });
const filename: string = "SheetJSNS.csv";
/* generate binary string */
const wbout: string = XLSX.write(wb, { bookType: 'csv', type: 'binary' });
/* find appropriate path */
const target: Folder = knownFolders.documents() || knownFolders.ios.sharedPublic();
const url: string = path.normalize(target.path + "///" + filename);
const file: File = File.fromPath(url);
/* attempt to save binary string to file */
await file.writeText(wbout, encoding.ISO_8859_1);
Dialogs.alert(`Wrote to ${filename} in ${url}`);
};
}

@ -1,6 +1,6 @@
# Typed Arrays and Math
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/ml) includes
[The new demo](https://docs.sheetjs.com/docs/demos/ml) includes
interactive examples as well as strategies for CSV and JS Array interchange.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,6 +1,6 @@
# Browserify
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/bundler#browserify)
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#browserify)
includes a more concise example.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,6 +1,6 @@
# Chrome and Chromium
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/chromium)
[The new demo](https://docs.sheetjs.com/docs/demos/chromium)
includes more up-to-date details.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -2,10 +2,10 @@
This demo has been split up for clarity:
- <https://docs.sheetjs.com/docs/getting-started/demos/database> covers SQL and
- <https://docs.sheetjs.com/docs/demos/database> covers SQL and
structured data (including CRUD operations)
- https://docs.sheetjs.com/docs/getting-started/demos/nosql covers unstructured
- https://docs.sheetjs.com/docs/demos/nosql covers unstructured
data including "NoSQL" data stores.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,6 +1,6 @@
# canvas-datagrid
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/grid#canvas-datagrid)
[The new demo](https://docs.sheetjs.com/docs/demos/grid#canvas-datagrid)
includes a live example and improved explanations.

@ -8,6 +8,6 @@ Demos have been integrated in the [documentation](https://docs.sheetjs.com) :
- <https://docs.sheetjs.com/docs/example> writing JS data to a spreadsheet
- <https://docs.sheetjs.com/docs/solutions/input> input strategies
- <https://docs.sheetjs.com/docs/solutions/output> output strategies
- <https://docs.sheetjs.com/docs/getting-started/demos/cli#deno> `deno compile`
- <https://docs.sheetjs.com/docs/demos/cli#deno> `deno compile`
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,6 +1,6 @@
# Electron
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/desktop#electron)
[The new demo](https://docs.sheetjs.com/docs/demos/desktop#electron)
includes an improved example and detailed explanations.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,6 +1,6 @@
# Adobe ExtendScript
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/extendscript)
[The new demo](https://docs.sheetjs.com/docs/demos/extendscript)
has a more focused Photoshop example as well as notes about other extensibility
frameworks shipping with newer versions of Creative Cloud apps.

@ -1,7 +1,3 @@
.PHONY: microcule
microcule: mcstream.js
microcule $<
.PHONY: aws
aws: lambda-proxy

@ -43,32 +43,6 @@ var workbook = XLSX.readFile("path/to/file.xlsb");
XLSX.writeFile(workbook, "output/path/file.csv");
```
The `mcstream.js` demo uses the `microcule` framework to show a simple body
converter. It accepts raw data from a POST connection, parses as a workbook,
and streams back the first worksheet as CSV:
<details>
<summary><b>Code Sketch</b> (click to show)</summary>
```js
const XLSX = require('xlsx');
module.exports = (hook) => {
/* process_RS from the main README under "Streaming Read" section */
process_RS(hook.req, (wb) => {
hook.res.writeHead(200, { 'Content-Type': 'text/csv' });
/* get first worksheet */
const ws = wb.Sheets[wb.SheetNames[0]];
/* generate CSV stream and pipe to response */
const stream = XLSX.stream.to_csv(ws);
stream.pipe(hook.res);
});
};
```
</details>
#### Report Generation
For an existing platform that already generates JSON or CSV or HTML output, the

@ -1,22 +0,0 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env node */
// cat file.xlsx | curl --header 'content-type: application/octet-stream' --data-binary @- "http://localhost:3000/"
const XLSX = require('xlsx');
const process_RS = (stream, cb) => {
var buffers = [];
stream.on('data', function(data) { buffers.push(data); });
stream.on('end', function() {
var buffer = Buffer.concat(buffers);
var workbook = XLSX.read(buffer, {type:"buffer"});
cb(workbook);
});
};
module.exports = (hook) => {
process_RS(hook.req, (wb) => {
hook.res.writeHead(200, { 'Content-Type': 'text/csv' });
const stream = XLSX.stream.to_csv(wb.Sheets[wb.SheetNames[0]]);
stream.pipe(hook.res);
});
};

@ -3,7 +3,7 @@
The old demo used a deprecated version of the Google Sheets API to export data
from Google Sheets Documents.
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/gsheet) uses
[The new demo](https://docs.sheetjs.com/docs/demos/gsheet) uses
the new Google Sheets API to read and write data.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,6 +1,6 @@
# Headless Browsers
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/headless)
[The new demo](https://docs.sheetjs.com/docs/demos/headless)
has a more focused table export example as well as a demo script for Chromium
automation with Puppeteer and multi-browser automation with Playwright.

@ -1,6 +1,6 @@
# Knockout
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/legacy#knockoutjs)
[The new demo](https://docs.sheetjs.com/docs/demos/legacy#knockoutjs)
includes a live example and improved explanations.

@ -1,6 +1,6 @@
# NW.js
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/desktop#nwjs)
[The new demo](https://docs.sheetjs.com/docs/demos/desktop#nwjs)
includes an improved example and detailed explanations.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,156 +1,6 @@
# Internet Explorer
The modern upload and download strategies are not available in older versions of
IE, but there are approaches using older technologies like ActiveX and Flash.
<details>
<summary><b>Live Demos</b> (click to show)</summary>
<http://oss.sheetjs.com/sheetjs/ajax.html> uses XMLHttpRequest to download test
files and convert to CSV.
<https://oss.sheetjs.com/sheetjs/> demonstrates reading files with `FileReader`.
Older versions of IE do not support HTML5 File API but do support Base64.
On OSX you can get the Base64 encoding with:
```bash
$ <target_file base64 | pbcopy
```
On Windows XP and up you can get the Base64 encoding using `certutil`:
```cmd
> certutil -encode target_file target_file.b64
```
(note: You have to open the file and remove the header and footer lines)
</details>
## Upload Strategies
#### IE10 and IE11 FileReader
IE10 and IE11 support the standard HTML5 FileReader API:
```js
function handle_fr(e) {
var files = e.target.files, f = files[0];
var reader = new FileReader();
reader.onload = function(e) {
var data = new Uint8Array(e.target.result);
var wb = XLSX.read(data, {type: 'array'});
process_wb(wb);
};
reader.readAsArrayBuffer(f);
}
input_dom_element.addEventListener('change', handle_fr, false);
```
#### ActiveX-based Upload
Through the `Scripting.FileSystemObject` object model, a script in the VBScript
scripting language can read from an arbitrary path on the filesystem. The shim
includes a special `IE_LoadFile` function to read binary strings from file. This
should be called from a file input `onchange` event:
```js
var input_dom_element = document.getElementById("file");
function handle_ie() {
/* get data from selected file */
var path = input_dom_element.value;
var bstr = IE_LoadFile(path);
/* read workbook */
var wb = XLSX.read(bstr, {type: 'binary'});
/* DO SOMETHING WITH workbook HERE */
}
input_dom_element.attachEvent('onchange', handle_ie);
```
## Download Strategies
#### IE10 and IE11 File API
As part of the File API implementation, IE10 and IE11 provide the `msSaveBlob`
and `msSaveOrOpenBlob` functions to save blobs to the client computer. This
approach is embedded in `XLSX.writeFile` and no additional shims are necessary.
#### Flash-based Download
It is possible to write to the file system using a SWF. `Downloadify` library
implements one solution. Since a genuine click is required, there is no way to
force a download. The demo generates a button for each desired output format.
#### ActiveX-based Download
Through the `Scripting.FileSystemObject` object model, a script in the VBScript
scripting language can write to an arbitrary path on the filesystem. The shim
includes a special `IE_SaveFile` function to write binary strings to file. It
attempts to write to the Downloads folder or Documents folder or Desktop.
This approach can be triggered, but it requires the user to enable ActiveX. It
is embedded as a strategy in `writeFile` and used only if the shim script is
included in the page and the relevant features are enabled on the target system.
## Demo
#### Download
The included demo starts from an array of arrays, generating an editable HTML
table with `aoa_to_sheet` and adding it to the page:
```js
var ws = XLSX.utils.aoa_to_sheet(aoa);
var html_string = XLSX.utils.sheet_to_html(ws, { id: "table", editable: true });
document.getElementById("container").innerHTML = html_string;
```
The included download buttons use `table_to_book` to construct a new workbook
based on the table and `writeFile` to force a download:
```js
var elt = document.getElementById('table');
var wb = XLSX.utils.table_to_book(elt, { sheet: "Sheet JS" });
XLSX.writeFile(wb, filename);
```
The shim is included in the HTML page, unlocking the ActiveX pathway if enabled
in browser settings.
The corresponding SWF buttons are displayed in environments where Flash is
available and `Downloadify` is supported. The easiest solution involves writing
to a Base64 string and passing to the library:
```js
Downloadify.create(element_id, {
/* the demo includes the other options required by Downloadify */
filename: "test.xlsx",
data: function() { return XLSX.write(wb, {bookType:"xlsx", type:'base64'}); },
dataType: 'base64'
});
```
#### Upload
The demo also includes an HTML file input element for updating the data table:
```js
var ws = wb.Sheets[wb.SheetNames[0]];
var html_string = XLSX.utils.sheet_to_html(ws, { id: "table", editable: true });
document.getElementById("container").innerHTML = html_string;
```
The specific strategy is determined based on the presence of `IE_LoadFile`:
```js
var handler = typeof IE_LoadFile !== 'undefined' ? handle_ie : handle_fr;
if(input_dom_element.attachEvent) input_dom_element.attachEvent('onchange', handler);
else input_dom_element.addEventListener('change', handler, false);
```
[The new demo](https://docs.sheetjs.com/docs/demos/legacy#internet-explorer)
includes a live example and easier integration bundle.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1 +0,0 @@
!function(){function t(t){this.message=t}var r="undefined"!=typeof exports?exports:self,e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=new Error,t.prototype.name="InvalidCharacterError",r.btoa||(r.btoa=function(r){for(var o,n,a=String(r),i=0,c=e,d="";a.charAt(0|i)||(c="=",i%1);d+=c.charAt(63&o>>8-i%1*8)){if(n=a.charCodeAt(i+=.75),n>255)throw new t("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");o=o<<8|n}return d}),r.atob||(r.atob=function(r){var o=String(r).replace(/=+$/,"");if(o.length%4==1)throw new t("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,a,i=0,c=0,d="";a=o.charAt(c++);~a&&(n=i%4?64*n+a:a,i++%4)?d+=String.fromCharCode(255&n>>(-2*i&6)):0)a=e.indexOf(a);return d})}();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

@ -1,3 +0,0 @@
/* Downloadify 0.2 (c) 2009 by Douglas Neiner. Licensed under the MIT license */
/* See http://github.com/dcneiner/Downloadify for license and more info */
(function(){Downloadify=window.Downloadify={queue:{},uid:new Date().getTime(),getTextForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getData();return""},getFileNameForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getFilename();return""},getDataTypeForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getDataType();return""},saveComplete:function(a){var b=Downloadify.queue[a];if(b)b.complete();return true},saveCancel:function(a){var b=Downloadify.queue[a];if(b)b.cancel();return true},saveError:function(a){var b=Downloadify.queue[a];if(b)b.error();return true},addToQueue:function(a){Downloadify.queue[a.queue_name]=a},getUID:function(a){if(a.id=="")a.id='downloadify_'+Downloadify.uid++;return a.id}};Downloadify.create=function(a,b){var c=(typeof(a)=="string"?document.getElementById(a):a);return new Downloadify.Container(c,b)};Downloadify.Container=function(d,e){var f=this;f.el=d;f.enabled=true;f.dataCallback=null;f.filenameCallback=null;f.data=null;f.filename=null;var g=function(){f.options=e;if(!f.options.append)f.el.innerHTML="";f.flashContainer=document.createElement('span');f.el.appendChild(f.flashContainer);f.queue_name=Downloadify.getUID(f.flashContainer);if(typeof(f.options.filename)==="function")f.filenameCallback=f.options.filename;else if(f.options.filename)f.filename=f.options.filename;if(typeof(f.options.data)==="function")f.dataCallback=f.options.data;else if(f.options.data)f.data=f.options.data;var a={queue_name:f.queue_name,width:f.options.width,height:f.options.height};var b={allowScriptAccess:'always'};var c={id:f.flashContainer.id,name:f.flashContainer.id};if(f.options.enabled===false)f.enabled=false;if(f.options.transparent===true)b.wmode="transparent";if(f.options.downloadImage)a.downloadImage=f.options.downloadImage;swfobject.embedSWF(f.options.swf,f.flashContainer.id,f.options.width,f.options.height,"10",null,a,b,c);Downloadify.addToQueue(f)};f.enable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(true);f.enabled=true};f.disable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(false);f.enabled=false};f.getData=function(){if(!f.enabled)return"";if(f.dataCallback)return f.dataCallback();else if(f.data)return f.data;else return""};f.getFilename=function(){if(f.filenameCallback)return f.filenameCallback();else if(f.filename)return f.filename;else return""};f.getDataType=function(){if(f.options.dataType)return f.options.dataType;return"string"};f.complete=function(){if(typeof(f.options.onComplete)==="function")f.options.onComplete()};f.cancel=function(){if(typeof(f.options.onCancel)==="function")f.options.onCancel()};f.error=function(){if(typeof(f.options.onError)==="function")f.options.onError()};g()};Downloadify.defaultOptions={swf:'media/downloadify.swf',downloadImage:'images/download.png',width:100,height:30,transparent:true,append:false,dataType:"string"}})();if(typeof(jQuery)!="undefined"){(function($){$.fn.downloadify=function(b){return this.each(function(){b=$.extend({},Downloadify.defaultOptions,b);var a=Downloadify.create(this,b);$(this).data('Downloadify',a)})}})(jQuery)};if(typeof(MooTools)!='undefined'){Element.implement({downloadify:function(a){a=$merge(Downloadify.defaultOptions,a);return this.store('Downloadify',Downloadify.create(this,a))}})};

Binary file not shown.

@ -1,152 +0,0 @@
<!DOCTYPE html>
<!-- (C) 2013-present SheetJS http://sheetjs.com -->
<!-- vim: set ts=2: -->
<html>
<head>
<title>SheetJS JS-XLSX In-Browser HTML Table Demo</title>
<meta charset="utf-8" />
<style>
.xport, .btn {
display: inline;
text-align:center;
}
a { text-decoration: none }
#data-table, #data-table th, #data-table td { border: 1px solid black }
</style>
</head>
<body>
<!-- SheetJS js-xlsx library -->
<script type="text/javascript" src="shim.min.js"></script>
<script type="text/javascript" src="xlsx.full.min.js"></script>
<!-- Downloadify Flash fallback for IE 9 and below if ActiveX is unavailable -->
<!--[if lte IE 9]>
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript" src="downloadify.min.js"></script>
<script type="text/javascript" src="base64.min.js"></script>
<![endif]-->
<script>
function doit(type, fn, dl) {
var elt = document.getElementById('data-table');
var wb = XLSX.utils.table_to_book(elt, {sheet:"Sheet JS"});
return dl ?
XLSX.write(wb, {bookType:type, bookSST:true, type: 'base64'}) :
XLSX.writeFile(wb, fn || ('test.' + (type || 'xlsx')));
}
</script>
<pre>
<h3><a href="//sheetjs.com/">SheetJS</a> JS-XLSX In-Browser HTML Table Demo</h3>
<b>Compatibility notes:</b>
- Editable table leverages the HTML5 contenteditable feature, supported in most browsers.
- IE6-9 requires ActiveX to upload files and ActiveX or Flash to download files.
- iOS Safari file download may not work. <a href="https://github.com/eligrey/FileSaver.js/issues/12">This is a known issue</a>.
<b>Update Spreadsheet:</b> (submit file to update table; file parsed in browser)
<input type="file" id="file" />
<b>Editable Data Table:</b> (click a cell to edit it)
</pre>
<div id="container"></div>
<script type="text/javascript">
/* initial table */
var aoa = [
["This", "is", "a", "Test"],
["வணக்கம்", "สวัสดี", "你好", "가지마"],
[1, 2, 3, 4],
["Click", "to", "edit", "cells"]
];
var ws = XLSX.utils.aoa_to_sheet(aoa);
var html_string = XLSX.utils.sheet_to_html(ws, { id: "data-table", editable: true });
document.getElementById("container").innerHTML = html_string;
</script>
<br />
<pre><b>Export it!</b></pre>
<table id="xport">
<tr><td><pre>XLSX Excel 2007+ XML</pre></td><td>
<p id="xportxlsx" class="xport"><input type="submit" value="Export to XLSX!" onclick="doit('xlsx');"></p>
<p id="xlsxbtn" class="btn">Flash required for actually downloading the generated file.</p>
</td></tr>
<tr><td><pre>XLSB Excel 2007+ Binary</pre></td><td>
<p id="xportxlsb" class="xport"><input type="submit" value="Export to XLSB!" onclick="doit('xlsb');"></p>
<p id="xlsbbtn" class="btn">Flash required for actually downloading the generated file.</p>
</td></tr>
<tr><td><pre>XLS Excel 97-2004 Binary</pre></td><td>
<p id="xportbiff8" class="xport"><input type="submit" value="Export to XLS!" onclick="doit('biff8', 'test.xls');"></p>
<p id="biff8btn" class="btn">Flash required for actually downloading the generated file.</p>
</td></tr>
<tr><td><pre>ODS</pre></td><td>
<p id="xportods" class="xport"><input type="submit" value="Export to ODS!" onclick="doit('ods');"></p>
<p id="odsbtn" class="btn">Flash required for actually downloading the generated file.</p>
</td></tr>
<tr><td><pre>Flat ODS</pre></td><td>
<p id="xportfods" class="xport"><input type="submit" value="Export to FODS!" onclick="doit('fods', 'test.fods');"></p>
<p id="fodsbtn" class="btn">Flash required for actually downloading the generated file.</p>
</td></tr>
</table>
<pre><b>Powered by the <a href="//sheetjs.com/opensource">community version of js-xlsx</a></b></pre>
<script type="text/javascript">
var input_dom_element = document.getElementById("file");
function process_wb(wb) {
var ws = wb.Sheets[wb.SheetNames[0]];
var html_string = XLSX.utils.sheet_to_html(ws, { id: "data-table", editable: true });
document.getElementById("container").innerHTML = html_string;
}
function handle_ie() {
var path = input_dom_element.value;
var data = IE_LoadFile(path);
var wb = XLSX.read(data, {type: 'binary'});
process_wb(wb);
}
function handle_fr(e) {
var files = e.target.files, f = files[0];
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
data = new Uint8Array(data);
var wb = XLSX.read(data, {type: 'array'});
process_wb(wb);
};
reader.readAsArrayBuffer(f);
}
var handler = typeof IE_LoadFile !== 'undefined' ? handle_ie : handle_fr;
if(input_dom_element.attachEvent) input_dom_element.attachEvent('onchange', handler);
else input_dom_element.addEventListener('change', handler, false);
function tableau(pid, iid, fmt, ofile) {
if(typeof Downloadify !== 'undefined') Downloadify.create(pid,{
swf: 'downloadify.swf',
downloadImage: 'download.png',
width: 100,
height: 30,
filename: ofile, data: function() { return doit(fmt, ofile, true); },
transparent: false,
append: false,
dataType: 'base64',
onComplete: function(){ alert('Your File Has Been Saved!'); },
onCancel: function(){ alert('You have cancelled the saving of this file.'); },
onError: function(){ alert('You must put something in the File Contents or there will be nothing to save!'); }
}); else document.getElementById(pid).innerHTML = "";
}
tableau('biff8btn', 'xportbiff8', 'biff8', 'test.xls');
tableau('odsbtn', 'xportods', 'ods', 'test.ods');
tableau('fodsbtn', 'xportfods', 'fods', 'test.fods');
tableau('xlsbbtn', 'xportxlsb', 'xlsb', 'test.xlsb');
tableau('xlsxbtn', 'xportxlsx', 'xlsx', 'test.xlsx');
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-36810333-1']);
_gaq.push(['_setDomainName', 'sheetjs.com']);
_gaq.push(['_setAllowLinker', true]);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>

@ -1 +0,0 @@
../../dist/shim.min.js

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
../../dist/xlsx.full.min.js

@ -1,6 +1,6 @@
# Parcel
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/bundler#parcel)
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#parcel)
includes a more concise example.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -74,33 +74,8 @@ function make_cols(refstr/*:string*/) {
## React Native
<img src="screen.png" width="400px"/>
Reproducing the full project is straightforward:
```bash
$ make native # build the project
$ make ios # build and run the iOS demo
$ make android # build and run the android demo
```
The app will prompt before reading and after writing data. The printed location
depends on the environment:
- android: path in the device filesystem
- iOS simulator: local path to file
- iOS device: a path accessible from iTunes App Documents view
Components used in the demo:
- [`react-native-table-component`](https://npm.im/react-native-table-component)
- [`react-native-file-access`](https://npm.im/react-native-file-access)
React Native does not provide a native component for reading and writing files.
The sample script `react-native.js` uses `react-native-file-access` and has
notes for integrations with `react-native-fetch-blob` and `react-native-fs`.
Note: for real app deployments, the `UIFileSharingEnabled` flag must be manually
set in the iOS project `Info.plist` file.
[The new demo](https://docs.sheetjs.com/docs/demos/mobile#react-native) uses
up-to-date file I/O and file picker libraries.
## Server-Rendered React Components with Next.js

@ -1,27 +0,0 @@
#!/bin/bash
# xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
# Create starter project
if [ ! -e SheetJS ]; then react-native init SheetJS --version="0.67.2"; fi
# Install dependencies
cd SheetJS; npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz react-native-table-component; cd -
cd SheetJS; npm i -S react-native-file-access@2.x; cd -
# cd SheetJS; npm i -S react-native-fs; cd -
# cd SheetJS; npm i -S react-native-fetch-blob; cd -
# Copy demo assets
if [ ! -e SheetJS/logo.png ]; then
curl -O http://oss.sheetjs.com/assets/img/logo.png
mv logo.png SheetJS/logo.png
fi
if [ -e SheetJS/index.ios.js ]; then
cp react-native.js SheetJS/index.ios.js
cp react-native.js SheetJS/index.android.js
else
cp react-native.js SheetJS/index.js
fi
# Link
cd SheetJS; RNFB_ANDROID_PERMISSIONS=true react-native link; cd -

@ -1,179 +0,0 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
import * as XLSX from 'xlsx';
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button,
Alert,
Image,
ScrollView,
TouchableWithoutFeedback
} from 'react-native';
import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
// react-native-file-access
var Base64 = function() {
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return {
encode: function(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
for (var i = 0; i < input.length; ) {
c1 = input.charCodeAt(i++);
e1 = c1 >> 2;
c2 = input.charCodeAt(i++);
e2 = (c1 & 3) << 4 | c2 >> 4;
c3 = input.charCodeAt(i++);
e3 = (c2 & 15) << 2 | c3 >> 6;
e4 = c3 & 63;
if (isNaN(c2)) {
e3 = e4 = 64;
} else if (isNaN(c3)) {
e4 = 64;
}
o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
}
return o;
},
decode: function(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
input = input.replace(/[^\w\+\/\=]/g, "");
for (var i = 0; i < input.length; ) {
e1 = map.indexOf(input.charAt(i++));
e2 = map.indexOf(input.charAt(i++));
c1 = e1 << 2 | e2 >> 4;
o += String.fromCharCode(c1);
e3 = map.indexOf(input.charAt(i++));
c2 = (e2 & 15) << 4 | e3 >> 2;
if (e3 !== 64) {
o += String.fromCharCode(c2);
}
e4 = map.indexOf(input.charAt(i++));
c3 = (e3 & 3) << 6 | e4;
if (e4 !== 64) {
o += String.fromCharCode(c3);
}
}
return o;
}
};
}();
import { Dirs, FileSystem } from 'react-native-file-access';
const DDP = Dirs.DocumentDir + "/";
const readFile = (path, enc) => FileSystem.readFile(path, "base64");
const writeFile = (path, data, enc) => FileSystem.writeFile(path, data, "base64");
const input = res => Base64.decode(res);
const output = str => Base64.encode(str);
// react-native-fs
/*
import { writeFile, readFile, DocumentDirectoryPath } from 'react-native-fs';
const DDP = DocumentDirectoryPath + "/";
const input = res => res;
const output = str => str;
*/
// react-native-fetch-blob
/*
import RNFetchBlob from 'react-native-fetch-blob';
const { writeFile, readFile, dirs:{ DocumentDir } } = RNFetchBlob.fs;
const DDP = DocumentDir + "/";
const input = res => res.map(x => String.fromCharCode(x)).join("");
const output = str => str.split("").map(x => x.charCodeAt(0));
*/
const make_cols = refstr => Array.from({length: XLSX.utils.decode_range(refstr).e.c + 1}, (x,i) => XLSX.utils.encode_col(i));
const make_width = refstr => Array.from({length: XLSX.utils.decode_range(refstr).e.c + 1}, () => 60);
export default class SheetJS extends Component {
constructor(props) {
super(props);
this.state = {
data: [[2,3,4],[3,4,5]],
widthArr: [60, 60, 60],
cols: make_cols("A1:C2")
};
this.importFile = this.importFile.bind(this);
this.exportFile = this.exportFile.bind(this);
};
importFile() {
Alert.alert("Rename file to sheetjs.xlsx", "Copy to " + DDP, [
{text: 'Cancel', onPress: () => {}, style: 'cancel' },
{text: 'Import', onPress: () => {
readFile(DDP + "sheetjs.xlsx", 'ascii').then((res) => {
/* parse file */
const wb = XLSX.read(input(res), {type:'binary'});
/* convert first worksheet to AOA */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const data = XLSX.utils.sheet_to_json(ws, {header:1});
/* update state */
this.setState({ data: data, cols: make_cols(ws['!ref']), widthArr: make_width(ws['!ref']) });
}).catch((err) => { Alert.alert("importFile Error", "Error " + err.message); });
}}
]);
}
exportFile() {
/* convert AOA back to worksheet */
const ws = XLSX.utils.aoa_to_sheet(this.state.data);
/* build new workbook */
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
/* write file */
const wbout = XLSX.write(wb, {type:'binary', bookType:"xlsx"});
const file = DDP + "sheetjsw.xlsx";
writeFile(file, output(wbout), 'ascii').then((res) =>{
Alert.alert("exportFile success", "Exported to " + file);
}).catch((err) => { Alert.alert("exportFile Error", "Error " + err.message); });
};
render() {
return (
<ScrollView contentContainerStyle={styles.container} vertical={true}>
<Text style={styles.welcome}> </Text>
<Text style={styles.welcome}>SheetJS React Native Demo</Text>
<Text style={styles.instructions}>Import Data</Text>
<Button onPress={this.importFile} title="Import data from a spreadsheet" color="#841584" />
<Text style={styles.instructions}>Export Data</Text>
<Button disabled={!this.state.data.length} onPress={this.exportFile} title="Export data to XLSX" color="#841584" />
<Text style={styles.instructions}>Current Data</Text>
<ScrollView style={styles.table} horizontal={true} >
<Table style={styles.table}>
<TableWrapper>
<Row data={this.state.cols} style={styles.thead} textStyle={styles.text} widthArr={this.state.widthArr}/>
</TableWrapper>
<TouchableWithoutFeedback>
<ScrollView vertical={true}>
<TableWrapper>
<Rows data={this.state.data} style={styles.tr} textStyle={styles.text} widthArr={this.state.widthArr}/>
</TableWrapper>
</ScrollView>
</TouchableWithoutFeedback>
</Table>
</ScrollView>
</ScrollView>
);
};
};
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF' },
welcome: { fontSize: 20, textAlign: 'center', margin: 10 },
instructions: { textAlign: 'center', color: '#333333', marginBottom: 5 },
thead: { height: 40, backgroundColor: '#f1f8ff' },
tr: { height: 30 },
text: { marginLeft: 5 },
table: { width: "100%" }
});
AppRegistry.registerComponent('SheetJS', () => SheetJS);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

@ -1,6 +1,6 @@
# RequireJS
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/bundler#requirejs)
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#requirejs)
includes a live example and improved explanations.

@ -1,6 +1,6 @@
# Rollup
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/bundler#rollup)
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#rollup)
includes a simple example and improved explanations.

@ -1,2 +0,0 @@
systemjs/
xlsx.full.min.js

@ -1,6 +1,6 @@
# SystemJS Demos
[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/bundler#systemjs)
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#systemjs)
includes a live example and improved explanations.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,2 +0,0 @@
SheetJS
.nuxt

@ -1,16 +1,3 @@
.PHONY: vue
vue: ## Simple server for vue
python -mSimpleHTTPServer
.PHONY: nuxt
nuxt: ## nuxt.js demo
npm i https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz @nuxt/content
npx nuxt
.PHONY: weex
weex: ## Build weex project
bash ./weex.sh
.PHONY: ios
ios: weex ## weex ios sim
cd SheetJS; weexpack run ios; cd -
python -mSimpleHTTPServer || python3 -mhttp.server

@ -70,57 +70,14 @@ function make_cols(refstr/*:string*/) {
}
```
## WeeX
## Mobile Apps
<img src="screen.png" width="400px"/>
[The new demo](https://docs.sheetjs.com/docs/demos/mobile#quasar) uses the
Quasar Framework in a VueJS + Vite project to generate a native iOS app.
Reproducing the full project is a little bit tricky. The included `weex.sh`
script performs the necessary installation steps.
## Nuxt Content
WeeX is a framework for building real mobile apps, akin to React Native. The
ecosystem is not quite as mature as React Native, missing basic features like
document access. As a result, this demo uses the `stream.fetch` API to upload
Base64-encoded documents to <https://hastebin.com> and download a precomputed
[Base64-encoded workbook](http://sheetjs.com/sheetjs.xlsx.b64).
Using NodeJS it is straightforward to convert to/from Base64:
```js
/* convert sheetjs.xlsx -> sheetjs.xlsx.b64 */
var buf = fs.readFileSync("sheetjs.xlsx");
fs.writeFileSync("sheetjs.xlsx.b64", buf.toString("base64"));
/* convert sheetjs.xls.b64 -> sheetjs.xls */
var str = fs.readFileSync("sheetjs.xls.b64").toString();
fs.writeFileSync("sheetjs.xls", new Buffer(str, "base64"));
```
## Other Demos
### Nuxt Content
`@nuxt/content` parser can be extended to support spreadsheet hot reload:
```js
// nuxt.config.js
import { readFile, utils } from 'xlsx';
const parseXLSX = (file, { path }) => {
const wb = readFile(path);
const o = wb.SheetNames.map(name => ({ name, data: utils.sheet_to_json(wb.Sheets[name])}));
return { data: o };
}
export default {
content: {
extendParser: {
".numbers": parseXLSX,
".xlsx": parseXLSX,
".xls": parseXLSX
// ... other extensions
}
}
}
```
[The new demo](https://docs.sheetjs.com/docs/demos/content#nuxtjs) includes a
complete example starting from `create-nuxt-app`.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

Binary file not shown.

@ -25,7 +25,7 @@
</head>
<body>
<pre>
<b><a href="http://sheetjs.com">SheetJS + VueJS2 demo</a></b>
<b><a href="http://sheetjs.com">SheetJS + VueJS3 demo</a></b>
The core library can be used as-is in Vue applications.
The <a href="https://github.com/sheetjs/js-xlsx">Community Edition README</a> details some common use cases.

@ -1,66 +0,0 @@
<!-- xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com -->
<template>
<div class="container">
<image :src="logoUrl" class="logo"></image>
<text class="welcome">SheetJS WeeX Demo {{version}}</text>
<text class="instructions">Import Data</text>
<text :style="{ color: '#841584' }" @click="importFile">Download spreadsheet</text>
<text class="instructions">Export Data</text>
<text :style="{ color: data.length ? '#841584' : '#CDCDCD', disabled: !data.length }" @click="exportFile">Upload XLSX</text>
<text style="instructions">Current Data</text>
<scroller class="scroller">
<div class="row" v-for="(row, ridx) in data" :key="ridx">
<text>ROW {{ridx + 1}}</text>
<text v-for="(cell, cidx) in row" :key="cidx">CELL {{get_label(ridx, cidx)}}:{{cell}}</text>
</div>
</scroller>
</div>
</template>
<style>
.container { height: 100%; flex: 1; justify-content: center; align-items: center; background-color: '#F5FCFF'; }
.logo { width: 256px; height: 256px; }
.welcome { font-size: 40; text-align: 'center'; margin: 10; }
.instructions { padding-top: 20px; color:#888; font-size: 24px;}
.scroller { height: 500px; border-width: 3px; width: 700px; }
.loading { justify-content: center; }
</style>
<script>
import * as XLSX from 'xlsx';
const modal = weex.requireModule('modal');
const stream