From b71c65775b61795ea9994d5d1b76a94b8a81625d Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sun, 31 Jul 2022 19:45:34 -0400 Subject: [PATCH] cli --- .../04-getting-started/03-demos/13-cli.md | 60 +++++++++++++++ .../docs/04-getting-started/03-demos/index.md | 2 +- docz/docs/06-solutions/01-input.md | 6 +- docz/docs/06-solutions/05-output.md | 74 +++++++++++++++---- 4 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 docz/docs/04-getting-started/03-demos/13-cli.md diff --git a/docz/docs/04-getting-started/03-demos/13-cli.md b/docz/docs/04-getting-started/03-demos/13-cli.md new file mode 100644 index 0000000..4934f8f --- /dev/null +++ b/docz/docs/04-getting-started/03-demos/13-cli.md @@ -0,0 +1,60 @@ +--- +sidebar_position: 13 +title: Command-Line Tools +--- + +import current from '/version.js'; + +With the availability of JS engines and the success of server-side runtimes, it +is natural to want command-line tools for various workflows. + +This demo covers a number of strategies for building standalone processors. The +goal is to generate CSV output from an arbitrary spreadsheet file. + +## Deno + +`deno compile` generates a standalone executable that includes the entire JS +runtime as well as user JS code. + +When compiling, the `--allow-read` option must be specified to allow the script +to read files from the filesystem with `Deno.readFileSync`. + +
Complete Example (click to show) + +1) Save the following script to `sheet2csv.ts`: + +```ts title="sheet2csv.ts" +/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ +// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" +import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs'; +import * as cptable from 'https://cdn.sheetjs.com/xlsx-latest/package/dist/cpexcel.full.mjs'; +XLSX.set_cptable(cptable); + +/* Read and parse workbook */ +const filename = Deno.args[0]; +if(!filename) { + console.error("usage: sheet2csv [sheetname]"); + Deno.exit(1); +} +const workbook = XLSX.readFile(filename); + +/* Find worksheet */ +const sheetname = Deno.args[1] || workbook.SheetNames[0]; +if(!workbook.Sheets[sheetname]) { + console.error(`error: workbook missing sheet ${sheetname}`); + Deno.exit(1); +} + +/* Generate CSV and print to stdout */ +console.log(XLSX.utils.sheet_to_csv(workbook.Sheets[sheetname])); +``` + +2) Build `sheet2csv` with `deno compile`: + +```bash +deno compile -r --allow-read sheet2csv.ts +``` + +`sheet2csv` is a generated executable that you can run. + +
\ No newline at end of file diff --git a/docz/docs/04-getting-started/03-demos/index.md b/docz/docs/04-getting-started/03-demos/index.md index 44b6460..54d04e6 100644 --- a/docz/docs/04-getting-started/03-demos/index.md +++ b/docz/docs/04-getting-started/03-demos/index.md @@ -34,8 +34,8 @@ The demo projects include small runnable examples and short explainers. ### Platforms and Integrations +- [`Command-Line Tools`](./cli) - [`NodeJS Server-Side Processing`](https://github.com/SheetJS/SheetJS/tree/master/demos/server/) -- [`Deno`](https://github.com/SheetJS/SheetJS/tree/master/demos/deno/) - [`Electron`](https://github.com/SheetJS/SheetJS/tree/master/demos/electron/) - [`NW.js`](https://github.com/SheetJS/SheetJS/tree/master/demos/nwjs/) - [`Chrome / Chromium Extension`](https://github.com/SheetJS/SheetJS/tree/master/demos/chrome/) diff --git a/docz/docs/06-solutions/01-input.md b/docz/docs/06-solutions/01-input.md index bf64f8a..a74bd66 100644 --- a/docz/docs/06-solutions/01-input.md +++ b/docz/docs/06-solutions/01-input.md @@ -173,9 +173,11 @@ import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs' const workbook = XLSX.readFile("test.xlsx");`} +:::note -Applications reading files must be invoked with the `--allow-read` flag. The -[`deno` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/deno/) has more examples +Applications reading files must be invoked with the `--allow-read` flag. + +::: diff --git a/docz/docs/06-solutions/05-output.md b/docz/docs/06-solutions/05-output.md index 60b7348..02ed1b2 100644 --- a/docz/docs/06-solutions/05-output.md +++ b/docz/docs/06-solutions/05-output.md @@ -217,8 +217,11 @@ import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs' XLSX.writeFile(workbook, "test.xlsx");`} -Applications writing files must be invoked with the `--allow-write` flag. The -[`deno` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/deno/) has more examples +:::note + +Applications writing files must be invoked with the `--allow-write` flag. + +::: @@ -832,31 +835,76 @@ Readable Stream. - `XLSX.stream.to_html` is the streaming version of `XLSX.utils.sheet_to_html`. - `XLSX.stream.to_json` is the streaming version of `XLSX.utils.sheet_to_json`. -
- nodejs convert to CSV and write file (click to show) + + + +In a CommonJS context, NodeJS Streams immediately work with SheetJS. This +example reads a worksheet passed as an argument to the script, pulls the first +worksheet, converts to CSV and writes to `out.csv`: ```js -var output_file_name = "out.csv"; -var stream = XLSX.stream.to_csv(worksheet); +const XLSX = require("xlsx"); + +const workbook = XLSX.readFile(process.argv[2]); +const worksheet = workbook.Sheets[workbook.SheetNames[0]]; +// highlight-next-line +const stream = XLSX.stream.to_csv(worksheet); + +const output_file_name = "out.csv"; +// highlight-next-line stream.pipe(fs.createWriteStream(output_file_name)); ``` -
- -
- nodejs write JSON stream to screen (click to show) +`stream.to_json` uses Object-mode streams. A `Transform` stream can be used to +generate a normal stream for streaming to a file or the screen: ```js /* to_json returns an object-mode stream */ +// highlight-next-line var stream = XLSX.stream.to_json(worksheet, {raw:true}); -/* the following stream converts JS objects to text via JSON.stringify */ +/* this Transform stream converts JS objects to text and prints to screen */ var conv = new Transform({writableObjectMode:true}); conv._transform = function(obj, e, cb){ cb(null, JSON.stringify(obj) + "\n"); }; +conv.pipe(process.stdout); -stream.pipe(conv); conv.pipe(process.stdout); +// highlight-next-line +stream.pipe(conv); ``` -
+
+ + +Deno does not support NodeJS streams in normal execution, so a wrapper is used. +This demo converts a worksheet to CSV and prints each row to the screen: + +```ts +// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" +import {utils, stream, set_cptable} from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs'; + +/* `Readable` will be compatible with how SheetJS uses `stream.Readable` */ +function NodeReadableCB(cb:(d:any)=>void) { + var rd = { + __done: false, + _read: function() {}, + push: function(d: any) { if(!this.__done) cb(d); if(d == null) this.__done = true; }, + resume: function pump() {for(var i = 0; i < 10000 && !this.__done; ++i) rd._read(); if(!rd.__done) setTimeout(pump, 0); } + }; + return rd; +} +function NodeReadable(rd: any) { return function() { return rd; }; } +/* The callback gets each CSV row. It will be `null` when the stream is drained */ +const rt = NodeReadableCB((d: any) => { if(d != null) console.log(d); }); +const Readable = NodeReadable(rt); +stream.set_readable(Readable); + +/* wire up and start the stream */ +const rd = stream.to_csv(worksheet); +rd.resume(); +``` + + + + pipes write streams to nodejs response.