From 32021ab7eddb2c19993e867bd62c207d186d6562 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Tue, 2 May 2023 23:40:40 -0400 Subject: [PATCH] uxp --- docz/docs/02-getting-started/02-example.mdx | 75 +++-- docz/docs/03-demos/01-frontend/03-angular.md | 2 +- .../docs/03-demos/01-frontend/07-angularjs.md | 31 +- docz/docs/03-demos/01-frontend/08-bundler.md | 16 +- docz/docs/03-demos/01-frontend/09-legacy.md | 9 +- docz/docs/03-demos/02-grid/index.md | 33 +- docz/docs/03-demos/03-net/02-server.md | 297 +++++++----------- docz/docs/03-demos/04-static/01-lume.md | 4 +- docz/docs/03-demos/04-static/05-vitejs.md | 4 +- docz/docs/03-demos/04-static/08-nextjs.md | 14 +- docz/docs/03-demos/04-static/09-nuxtjs.md | 6 +- docz/docs/03-demos/04-static/10-astro.md | 2 +- docz/docs/03-demos/09-cloud/01-salesforce.md | 5 +- docz/docs/03-demos/09-cloud/04-netsuite.md | 11 +- docz/docs/03-demos/09-cloud/09-azure.md | 2 +- .../03-demos/10-extensions/01-extendscript.md | 112 ++++++- docz/docs/03-demos/10-extensions/05-osa.md | 5 +- docz/docs/03-demos/11-bigdata/01-stream.md | 61 ++-- docz/docs/03-demos/11-bigdata/02-worker.md | 78 ++--- docz/docs/06-solutions/01-input.md | 2 +- docz/docs/06-solutions/05-output.md | 43 +-- docz/docusaurus.config.js | 9 + docz/static/extendscript/esidparse.jsx | 2 +- docz/static/extendscript/parse.idjs | 31 ++ docz/static/extendscript/write.idjs | 47 +++ docz/static/server/SheetJSDrash.ts | 78 +++++ 26 files changed, 598 insertions(+), 381 deletions(-) create mode 100644 docz/static/extendscript/parse.idjs create mode 100644 docz/static/extendscript/write.idjs create mode 100644 docz/static/server/SheetJSDrash.ts diff --git a/docz/docs/02-getting-started/02-example.mdx b/docz/docs/02-getting-started/02-example.mdx index 0ff58e36..745469db 100644 --- a/docz/docs/02-getting-started/02-example.mdx +++ b/docz/docs/02-getting-started/02-example.mdx @@ -267,46 +267,46 @@ hosted (no `file:///` access). is a hosted version of the page. -```html +{`\ - + - -``` +`} + @@ -423,50 +423,49 @@ const axios = require("axios"); -Save the following script to `snippet.ts` and run with -`deno run --allow-net --allow-write snippet.ts`: - -```js title="snippet.ts" -// @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'; +Save the following script to `snippet.ts` and run `deno run -A snippet.ts`: +{`\ +// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" +import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs'; +\n\ /* fetch JSON data and parse */ const url = "https://sheetjs.com/data/executive.json"; const raw_data = await (await fetch(url)).json(); - +\n\ /* filter for the Presidents */ const prez = raw_data.filter((row: any) => row.terms.some((term: any) => term.type === "prez")); - +\n\ /* sort by first presidential term */ prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); prez.sort((l,r) => l.start.localeCompare(r.start)); - +\n\ /* flatten objects */ const rows = prez.map((row: any) => ({ name: row.name.first + " " + row.name.last, birthday: row.bio.birthday })); - +\n\ /* 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"); - +\n\ /* fix headers */ XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); - +\n\ /* calculate column width */ const max_width = rows.reduce((w: number, r: any) => Math.max(w, r.name.length), 10); worksheet["!cols"] = [ { wch: max_width } ]; - +\n\ /* create an XLSX file and try to save to Presidents.xlsx */ -XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); -``` +XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true });`} + -Download to `xlsx.mjs` + Save the following script to `snippet.js` and run with `bun snippet.js`: @@ -519,46 +518,46 @@ XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); Save the following script to `snippet.html`: -```html title="snippet.html" +{`\ - + - -``` +`} + Save the following to `package.json`: diff --git a/docz/docs/03-demos/01-frontend/03-angular.md b/docz/docs/03-demos/01-frontend/03-angular.md index 96595d06..68d4b3fc 100644 --- a/docz/docs/03-demos/01-frontend/03-angular.md +++ b/docz/docs/03-demos/01-frontend/03-angular.md @@ -602,7 +602,7 @@ npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} npm start ``` -The traditional site URL is http://localhost:4200/ . Open the page with a web +The traditional site URL is `http://localhost:4200/` . Open the page with a web browser and open the console. In the "Elements" tab, the `app-root` element will have an `ng-version` attribute. diff --git a/docz/docs/03-demos/01-frontend/07-angularjs.md b/docz/docs/03-demos/01-frontend/07-angularjs.md index 02ddc009..e48c9407 100644 --- a/docz/docs/03-demos/01-frontend/07-angularjs.md +++ b/docz/docs/03-demos/01-frontend/07-angularjs.md @@ -5,6 +5,9 @@ pagination_next: demos/grid/index sidebar_position: 7 --- +import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; + :::warning This demo is for the legacy AngularJS framework (version 1). @@ -162,18 +165,18 @@ $scope.exportSheetJS = function() { 1) Save the following to `index.html`: -```html title="index.html" +{`\ SheetJS + AngularJS - - + +

SheetJS + AngularJS demo

- +\n\
@@ -184,7 +187,7 @@ $scope.exportSheetJS = function() {
- +\n\ - -``` +`} +
2) Start a local web server with `npx http-server .` and access the displayed URL with a web browser (typically `http://localhost:8080`) @@ -261,24 +264,24 @@ The HTML table can be directly exported with `XLSX.utils.table_to_book`: 1) Save the following to `index.html`: -```html title="index.html" +{`\ SheetJS + AngularJS - - + +

SheetJS + AngularJS demo

- +\n\
- +\n\ - -``` +`} +
2) Start a local web server with `npx http-server .` and access the displayed URL with a web browser (typically `http://localhost:8080`) diff --git a/docz/docs/03-demos/01-frontend/08-bundler.md b/docz/docs/03-demos/01-frontend/08-bundler.md index 6767211e..801a5071 100644 --- a/docz/docs/03-demos/01-frontend/08-bundler.md +++ b/docz/docs/03-demos/01-frontend/08-bundler.md @@ -85,7 +85,7 @@ npx browserify xlsxworker.js > worker.js npx http-server ``` -5) Access the site http://localhost:8080/ and use the file input element to +5) Access the site `http://localhost:8080/` and use the file input element to select a spreadsheet. @@ -262,7 +262,7 @@ writeFileXLSX(workbook, "Presidents.xlsx"); npx esbuild esbrowser.js --bundle --outfile=esb.browser.js ``` -5) Start a local HTTP server, then go to http://localhost:8080/ +5) Start a local HTTP server, then go to `http://localhost:8080/` ```bash npx http-server . @@ -556,7 +556,7 @@ npx rollup index.js --plugin @rollup/plugin-node-resolve --file bundle.js --form ``` -5) Start a local HTTP server, then go to http://localhost:8080/ +5) Start a local HTTP server, then go to `http://localhost:8080/` ```bash npx http-server . @@ -655,7 +655,7 @@ Unlike other bundlers, Snowpack requires a full page including `HEAD` element. npx snowpack build ``` -5) Start a local HTTP server, then go to http://localhost:8080/ +5) Start a local HTTP server, then go to `http://localhost:8080/` ```bash npx http-server build/ @@ -772,7 +772,7 @@ This command will create the script `lib/web.js` ``` -6) Start a local HTTP server, then go to http://localhost:8080/ +6) Start a local HTTP server, then go to `http://localhost:8080/` ```bash npx http-server build/ @@ -1053,7 +1053,7 @@ web server in the `dist` folder: npx http-server dist/ ``` -Access http://localhost:8080 in your web browser. +Access `http://localhost:8080` in your web browser. @@ -1251,7 +1251,7 @@ npx webpack --mode=production ``` -6) Start a local HTTP server and go to http://localhost:8080/ +6) Start a local HTTP server and go to `http://localhost:8080/` ```bash npx http-server . @@ -1344,7 +1344,7 @@ writeFileXLSX(workbook, "Presidents.xlsx"); npx wmr build ``` -5) Start a local HTTP server in `dist` folder and go to http://localhost:8080/ +5) Start a local HTTP server in `dist` folder and go to `http://localhost:8080/` ```bash npx http-server dist/ diff --git a/docz/docs/03-demos/01-frontend/09-legacy.md b/docz/docs/03-demos/01-frontend/09-legacy.md index e4f80178..3ea846b5 100644 --- a/docz/docs/03-demos/01-frontend/09-legacy.md +++ b/docz/docs/03-demos/01-frontend/09-legacy.md @@ -8,6 +8,7 @@ sidebar_custom_props: --- import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; Over the years, many frameworks have been released. Some were popular years ago but have waned in recent years. There are still many deployments using these @@ -192,11 +193,11 @@ includes details for use with `require`. The demos use the async loading strategy with the SheetJS CDN: -```html +{`\ @@ -205,8 +206,8 @@ dojoConfig = { require(["dojo/request/xhr", "xlsx"], function(xhr, _XLSX) { /* XLSX-related operations happen in the callback */ }); - -``` +`} + diff --git a/docz/docs/03-demos/02-grid/index.md b/docz/docs/03-demos/02-grid/index.md index 7694dbb9..a48a8204 100644 --- a/docz/docs/03-demos/02-grid/index.md +++ b/docz/docs/03-demos/02-grid/index.md @@ -5,6 +5,7 @@ pagination_next: demos/net/index --- import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; Various JavaScript UI components provide a more interactive editing experience. Most are able to interchange with arrays of arrays or arrays of data objects. @@ -202,9 +203,9 @@ function muidg_to_ws(rows: Row[]): WorkSheet { 1) Install dependencies: -```bash -npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz @mui/x-data-grid @emotion/react @emotion/styled -``` +{`\ +npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid @emotion/react @emotion/styled`} + 2) Download [`App.tsx`](pathname:///muidg/App.tsx) and replace `src/App.tsx`. @@ -246,26 +247,36 @@ TABLE elements and when writing to XLSX and other spreadsheet formats. When the page has a raw HTML table, the easiest solution is to attach an `id`: -```html +{`\ + + +\n\ +
SheetJS
- - +\n\ -``` +`} +
When programmatically constructing the table in the browser, retain a reference: ```js +/* assemble table */ var tbl = document.createElement("TABLE"); tbl.insertRow(0).insertCell(0).innerHTML = "SheetJS"; + +/* add to document body */ document.body.appendChild(tbl); + +/* generate workbook and export */ const wb = XLSX.utils.table_to_book(tbl); XLSX.writeFile(wb, "HTMLFlicker.xlsx"); + +/* remove from document body */ document.body.removeChild(tbl); ``` @@ -337,9 +348,9 @@ cd sheetjs-mui 2) Install dependencies: -```bash -npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz @mui/material -``` +{`\ +npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material`} + 3) Replace `src/App.tsx` with the following code. This is based on the official Material UI Table example. Differences are highlighted. diff --git a/docz/docs/03-demos/03-net/02-server.md b/docz/docs/03-demos/03-net/02-server.md index eb067b12..34a8df80 100644 --- a/docz/docs/03-demos/03-net/02-server.md +++ b/docz/docs/03-demos/03-net/02-server.md @@ -3,6 +3,7 @@ title: HTTP Server Processing --- import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; Server-Side JS platforms like NodeJS and Deno have built-in APIs for listening on network interfaces. They provide wrappers for requests and responses. @@ -64,172 +65,13 @@ require("http").createServer(function(req, res) { }).listen(process.env.PORT || 3000); ``` -## Deno - -:::caution - -Many hosted services like Deno Deploy do not offer filesystem access. - -This breaks web frameworks that use the filesystem in body parsing. - -::: - -Deno provides the basic elements to implement a server. It does not provide a -body parser out of the box. - -#### Drash - -In testing, [Drash](https://drash.land/drash/) had an in-memory body parser -which could handle file uploads on hosted services like Deno Deploy. - -_Reading Data_ - -`Request#bodyParam` reads body parameters. For uploaded files, the `content` -property is a `Uint8Array`: - -```ts -// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" -import { read, utils } from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs'; - -import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts"; - -class ParseResource extends Drash.Resource { - public paths = ["/"]; - - public POST(request: Drash.Request, response: Drash.Response) { - // assume a form upload like - // highlight-next-line - const file = request.bodyParam("upload"); - if (!file) throw new Error("File is required!"); - // highlight-next-line - var wb = read(file.content); - return response.html( utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]])); - } -} -``` - -_Writing Data_ - -Headers are manually set with `Response#headers.set` while the raw body is set -with `Response#send`: - -```ts -// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" -import { utils, write } from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs'; - -import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts"; - -class WriteResource extends Drash.Resource { - public paths = ["/export"]; - - public GET(request: Drash.Request, response: Drash.Response): void { - // create some fixed workbook - const data = ["SheetJS".split(""), [5,4,3,3,7,9,5]]; - const ws = utils.aoa_to_sheet(data); - const wb = utils.book_new(); utils.book_append_sheet(wb, ws, "data"); - // write the workbook to XLSX as a Uint8Array - // highlight-next-line - const file = write(wb, { bookType: "xlsx", type: "buffer"}); - // set headers - response.headers.set("Content-Disposition", 'attachment; filename="SheetJSDrash.xlsx"'); - // send data - // highlight-next-line - return response.send("application/vnd.ms-excel", file); - } -} -``` - -
Complete Example (click to show) - -1) Save the following script to `SheetJSDrash.ts`: - -```ts title="SheetJSDrash.ts" -/*! sheetjs (C) 2013-present SheetJS -- https://sheetjs.com */ -// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" -import { read, utils, set_cptable } 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'; -set_cptable(cptable); - -import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts"; - -class ParseResource extends Drash.Resource { - public paths = ["/"]; - - public POST(request: Drash.Request, response: Drash.Response) { - const file = request.bodyParam("file"); - if (!file) throw new Error("File is required!"); - var wb = read(file.content); - return response.html( utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]])); - } - - public GET(request: Drash.Request, response: Drash.Response): void { - return response.html(`\ - - - - SheetJS Spreadsheet to HTML Conversion Service - - - -

SheetJS Spreadsheet Conversion Service

-API - -Send a POST request to http://localhost:3000/ with the file in the "file" body parameter: - -$ curl -X POST -F"file=@test.xlsx" http://localhost:3000/ - -The response will be an HTML TABLE generated from the first worksheet. - -Try it out!
- - - -Use the file input element to select a file, then click "Submit" - - -
-
- -`, - ); - } -} - -const server = new Drash.Server({ - hostname: "", - port: 3000, - protocol: "http", - resources: [ ParseResource ], -}); - -server.run(); - -console.log(`Server running at ${server.address}.`); -``` - -2) Run the server: - -```bash -deno run --allow-net SheetJSDrash.ts -``` - -3) Download the test file - -4) Open http://localhost:3000/ in your browser. - -Click "Choose File" and select `pres.numbers`. Then click "Submit" - -The page should show the contents of the file as an HTML table. - -
- ## NodeJS When processing small files, the work is best handled in the server response handler function. This approach is used in the "Framework Demos" section. When processing large files, the direct approach will freeze the server. NodeJS -provides "Worker Threads" for this exact use case. +provides ["Worker Threads"](#worker-threads) for this exact use case. ### Framework Demos @@ -289,9 +131,9 @@ app.listen(+process.env.PORT||3000); 1) Install dependencies: -```bash -npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz express express-formidable -``` +{`\ +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express express-formidable`} + 2) Start server (note: it will not print anything to console when running) @@ -308,7 +150,7 @@ curl -X POST -F upload=@pres.numbers http://localhost:3000/upload The response should show the data in CSV rows. -4) Test GET requests by opening http://localhost:3000/download in your browser. +4) Test GET requests by opening `http://localhost:3000/download` in your browser. It should prompt to download `SheetJSExpress.xlsx` @@ -362,13 +204,13 @@ export class SheetjsController { 1) Create a new project: -```bash +{`\ npx @nestjs/cli new -p npm sheetjs-nest cd sheetjs-nest -npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz npm i --save-dev @types/multer -mkdir -p upload -``` +mkdir -p upload`} + 2) Create a new controller and a new module: @@ -417,7 +259,7 @@ curl -X POST -F upload=@pres.numbers http://localhost:3000/sheetjs/upload The response should show the data in CSV rows. -4) Test GET requests by opening http://localhost:3000/sheetjs/download in your browser. +4) Test GET requests by opening `http://localhost:3000/sheetjs/download` in your browser. It should prompt to download `SheetJSNest.xlsx` @@ -538,9 +380,9 @@ fastify.listen({port: process.env.PORT || 3000}, (err, addr) => { if(err) throw 1) Install dependencies: -```bash -npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz fastify @fastify/multipart -``` +{`\ +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify @fastify/multipart`} + 2) Start server @@ -557,7 +399,7 @@ curl -X POST -F upload=@pres.numbers http://localhost:3000/ The response should show the data in CSV rows. -4) Test GET requests by opening http://localhost:3000/ in your browser. +4) Test GET requests by opening `http://localhost:3000/` in your browser. It should prompt to download `SheetJSFastify.xlsx` @@ -603,9 +445,9 @@ Versions: NodeJS 18.15.0 + ExpressJS 4.18.2 + Formidable 2.1.1 1) Install the dependencies: -```bash -npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz express@4.18.2 formidable@2.1.1 -``` +{`\ +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.18.2 formidable@2.1.1`} + 2) Create a worker script `worker.js` that listens for messages. When a message is received, it will read the file from the filesystem, generate and pass back a @@ -697,3 +539,106 @@ curl -X POST -F upload=@pres.numbers http://localhost:7262/ -J -O This will generate `SheetJSPool.xlsx`. + +## Deno + +:::caution + +Many hosted services like Deno Deploy do not offer filesystem access. + +This breaks web frameworks that use the filesystem in body parsing. + +::: + +Deno provides the basic elements to implement a server. It does not provide a +body parser out of the box. + +#### Drash + +In testing, [Drash](https://drash.land/drash/) had an in-memory body parser +which could handle file uploads on hosted services like Deno Deploy. + +_Reading Data_ + +`Request#bodyParam` reads body parameters. For uploaded files, the `content` +property is a `Uint8Array`: + +{`\ +// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" +import { read, utils } from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs'; +\n\ +import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts"; +\n\ +class ParseResource extends Drash.Resource { + public paths = ["/"]; +\n\ + public POST(request: Drash.Request, response: Drash.Response) { + // assume a form upload like + // highlight-next-line + const file = request.bodyParam("upload"); + if (!file) throw new Error("File is required!"); + // highlight-next-line + var wb = read(file.content); + return response.html( utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]])); + } +}`} + + +_Writing Data_ + +Headers are manually set with `Response#headers.set` while the raw body is set +with `Response#send`: + +{`\ +// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" +import { utils, write } from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs'; +\n\ +import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts"; +\n\ +class WriteResource extends Drash.Resource { + public paths = ["/export"]; +\n\ + public GET(request: Drash.Request, response: Drash.Response): void { + // create some fixed workbook + const data = ["SheetJS".split(""), [5,4,3,3,7,9,5]]; + const ws = utils.aoa_to_sheet(data); + const wb = utils.book_new(); utils.book_append_sheet(wb, ws, "data"); + // write the workbook to XLSX as a Uint8Array + // highlight-next-line + const file = write(wb, { bookType: "xlsx", type: "buffer"}); + // set headers + response.headers.set("Content-Disposition", 'attachment; filename="SheetJSDrash.xlsx"'); + // send data + // highlight-next-line + return response.send("application/vnd.ms-excel", file); + } +}`} + + +
Complete Example (click to show) + +1) Download [`SheetJSDrash.ts`](pathname:///server/SheetJSDrash.ts): + +```bash +curl -LO https://docs.sheetjs.com/server/SheetJSDrash.ts +``` + +2) Run the server: + +```bash +deno run --allow-net SheetJSDrash.ts +``` + +3) Download the test file + +4) Open `http://localhost:7262/` in your browser. + +Click "Choose File" and select `pres.numbers`. Then click "Submit" + +The page should show the contents of the file as an HTML table. + +5) Open `http://localhost:7262/export` in your browser. + +The page should attempt to download `SheetJSDrash.xlsx` . Open the new file. + +
diff --git a/docz/docs/03-demos/04-static/01-lume.md b/docz/docs/03-demos/04-static/01-lume.md index 5ff78373..7e689836 100644 --- a/docz/docs/03-demos/04-static/01-lume.md +++ b/docz/docs/03-demos/04-static/01-lume.md @@ -156,7 +156,7 @@ curl -L -o _data/pres.numbers https://sheetjs.com/pres.numbers deno task lume --serve ``` -To verify it works, access http://localhost:3000 from your web browser. Open +To verify it works, access `http://localhost:3000` from your web browser. Open `_data/pres.numbers` and add a new row to the bottom of the sheet. The page will refresh and show the new contents. @@ -179,6 +179,6 @@ This will create a static site in the `_site` folder, which can be served with: npx http-server _site ``` -Accessing the page http://localhost:8080 will show the page contents. +Accessing the page `http://localhost:8080` will show the page contents. This site is self-contained and ready for deployment! diff --git a/docz/docs/03-demos/04-static/05-vitejs.md b/docz/docs/03-demos/04-static/05-vitejs.md index c22ecc46..ee32198d 100644 --- a/docz/docs/03-demos/04-static/05-vitejs.md +++ b/docz/docs/03-demos/04-static/05-vitejs.md @@ -186,7 +186,7 @@ curl -L -o data/pres.xlsx https://sheetjs.com/pres.xlsx npm run dev ``` -Open a browser window to the displayed URL (typically http://localhost:5173 ) +Open a browser window to the displayed URL (typically `http://localhost:5173` ) 5) Replace the component `src/components/HelloWorld.vue` with: @@ -272,7 +272,7 @@ npm run build npx http-server dist/ ``` -The terminal will display a url like http://127.0.0.1:8080. Access that page +The terminal will display a URL ( `http://127.0.0.1:8080` ). Access that page with a web browser. 11) To confirm that only the raw data is present in the page, view the page diff --git a/docz/docs/03-demos/04-static/08-nextjs.md b/docz/docs/03-demos/04-static/08-nextjs.md index caa9bd1e..487c4429 100644 --- a/docz/docs/03-demos/04-static/08-nextjs.md +++ b/docz/docs/03-demos/04-static/08-nextjs.md @@ -244,16 +244,16 @@ npx next@13.1.1 Open a web browser and access: -- http://localhost:3000 landing page -- http://localhost:3000/getStaticProps shows data from the first sheet -- http://localhost:3000/getServerSideProps shows data from the first sheet -- http://localhost:3000/getStaticPaths shows a list (3 sheets) +- `http://localhost:3000` landing page +- `http://localhost:3000/getStaticProps` shows data from the first sheet +- `http://localhost:3000/getServerSideProps` shows data from the first sheet +- `http://localhost:3000/getStaticPaths` shows a list (3 sheets) The individual worksheets are available at -- http://localhost:3000/sheets/0 -- http://localhost:3000/sheets/1 -- http://localhost:3000/sheets/2 +- `http://localhost:3000/sheets/0` +- `http://localhost:3000/sheets/1` +- `http://localhost:3000/sheets/2` 6) Stop the server and run a production build: diff --git a/docz/docs/03-demos/04-static/09-nuxtjs.md b/docz/docs/03-demos/04-static/09-nuxtjs.md index ec5c44c4..2f0d716e 100644 --- a/docz/docs/03-demos/04-static/09-nuxtjs.md +++ b/docz/docs/03-demos/04-static/09-nuxtjs.md @@ -238,7 +238,7 @@ This will create a static site in the `dist` folder, which can be served with: npx http-server dist ``` -Accessing the page http://localhost:8080 will show the page contents. Verifying +Accessing the page `http://localhost:8080` will show the page contents. Verifying the static nature is trivial: make another change in Excel and save. The page will not change. @@ -398,7 +398,7 @@ npx nuxi typecheck npx yarn run dev ``` -Loading http://localhost:3000/pres should show some JSON data: +Loading `http://localhost:3000/pres` should show some JSON data: ```json { @@ -462,6 +462,6 @@ This will create a static site in `.output/public`, which can be served with: npx http-server .output/public ``` -Accessing http://localhost:8080/pres will show the page contents. Verifying +Accessing `http://localhost:8080/pres` will show the page contents. Verifying the static nature is trivial: make another change in Excel and save. The page will not change. diff --git a/docz/docs/03-demos/04-static/10-astro.md b/docz/docs/03-demos/04-static/10-astro.md index 365567fb..335fb3dc 100644 --- a/docz/docs/03-demos/04-static/10-astro.md +++ b/docz/docs/03-demos/04-static/10-astro.md @@ -248,6 +248,6 @@ AstroJS will place the generated site in the `dist` subfolder. npx http-server dist ``` -Open a web browser and access the displayed URL (usually http://localhost:8080). +Open a web browser and access the displayed URL ( `http://localhost:8080` ). View the page source and confirm that no JS was added to the page. It only contains the content from the file in an HTML table. diff --git a/docz/docs/03-demos/09-cloud/01-salesforce.md b/docz/docs/03-demos/09-cloud/01-salesforce.md index 7192ce7c..4900bbd0 100644 --- a/docz/docs/03-demos/09-cloud/01-salesforce.md +++ b/docz/docs/03-demos/09-cloud/01-salesforce.md @@ -4,6 +4,9 @@ pagination_prev: demos/local/index pagination_next: demos/extensions/index --- +import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; + Salesforce apps can use third-party libraries in "Lightning Web Components". This demo assumes familiarity with Lightning Web Components. Salesforce has a @@ -118,7 +121,7 @@ The [standalone script](/docs/getting-started/installation/standalone) can be do added as a static resource. Due to Salesforce naming restrictions, it will have to be renamed to `sheetjs.js` when adding the static resource. -1) Download +

1) Download https://cdn.sheetjs.com/xlsx-{current}/package/dist/xlsx.full.min.js

:::warning diff --git a/docz/docs/03-demos/09-cloud/04-netsuite.md b/docz/docs/03-demos/09-cloud/04-netsuite.md index c705a124..77481929 100644 --- a/docz/docs/03-demos/09-cloud/04-netsuite.md +++ b/docz/docs/03-demos/09-cloud/04-netsuite.md @@ -4,6 +4,12 @@ pagination_prev: demos/local/index pagination_next: demos/extensions/index --- +import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; + +The [AMD script](/docs/getting-started/installation/amd) can be uploaded to the +file cabinet and referenced in the `define` call in SuiteScripts. + This demo discusses the key SheetJS operations. Familiarity with SuiteScript 2 is assumed. The following sections of the SuiteScript documentation should be perused before reading this demo: @@ -19,9 +25,8 @@ The library plays nice with each script type, including RESTlets and Suitelets. ## Installation -[This script](https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js) -plays nice with SuiteScript `define`. It should be downloaded and uploaded to -the File Cabinet. +

The +standalone script should be downloaded and uploaded to the File Cabinet.

After uploading, create a JSON configuration file (or add the alias to an existing config file). The reference points to the file and omits the `.js`. diff --git a/docz/docs/03-demos/09-cloud/09-azure.md b/docz/docs/03-demos/09-cloud/09-azure.md index eb783b96..674cd2a1 100644 --- a/docz/docs/03-demos/09-cloud/09-azure.md +++ b/docz/docs/03-demos/09-cloud/09-azure.md @@ -157,7 +157,7 @@ curl -LO https://sheetjs.com/pres.numbers curl -X POST -F "upload=@pres.numbers" http://localhost:7071/api/SheetJSAzure ``` -To test downloads, access http://localhost:7071/api/SheetJSAzure and download +To test downloads, access `http://localhost:7071/api/SheetJSAzure` and download the generated file. Confirm it is a valid file. 6) Deploy to Azure. Replace `NAME_OF_FUNCTION_APP` with the name: diff --git a/docz/docs/03-demos/10-extensions/01-extendscript.md b/docz/docs/03-demos/10-extensions/01-extendscript.md index 9aba9516..7213c5db 100644 --- a/docz/docs/03-demos/10-extensions/01-extendscript.md +++ b/docz/docs/03-demos/10-extensions/01-extendscript.md @@ -4,8 +4,10 @@ pagination_prev: demos/cloud/index pagination_next: demos/bigdata/index --- +import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import CodeBlock from '@theme/CodeBlock'; Photoshop, InDesign and other Adobe Creative Suite applications offer extension support. Over the years there have been a few different JavaScript platforms: @@ -30,7 +32,7 @@ This demo was verified in the following deployments: | Photoshop | ExtendScript | 2023-04-15 | | InDesign | ExtendScript | 2023-04-15 | | InDesign | CEP | 2023-04-30 | -| InDesign | UXP | 2023-04-15 | +| InDesign | UXP | 2023-05-02 | ::: @@ -74,8 +76,11 @@ author (`activeDocument.info.author`) will be changed accordingly. 0) Download the [test workbook](pathname:///files/SheetJS.xlsb). 1) Download the following scripts: -- [`xlsx.extendscript.js`](https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.extendscript.js) -- [`parse.jsx`](pathname:///extendscript/parse.jsx) + + and place in the scripts directory. @@ -104,8 +109,12 @@ the Layers window is "Title") will be set to the name of the first worksheet. [InDesign template](pathname:///extendscript/Template.indd) 1) Download the following scripts: -- [`xlsx.extendscript.js`](https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.extendscript.js) -- [`esidparse.jsx`](pathname:///extendscript/esidparse.jsx) + + + Move to the scripts directory. To find the directory, activate Scripts panel (Windows > Utilities > Scripts), click `☰`, and select "Reveal in Explorer". @@ -154,8 +163,11 @@ will be "Author" and cell `B1` will be the active Photoshop document Author. The PS author is available as `activeDocument.info.author`. 1) Download the following scripts: -- [`xlsx.extendscript.js`](https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.extendscript.js) -- [`write.jsx`](pathname:///extendscript/write.jsx) + + and place in the scripts directory. @@ -182,8 +194,11 @@ object will be scanned and a new worksheet will be created. 0) Download the [InDesign document](pathname:///extendscript/Filled.indd) 1) Download the following scripts: -- [`xlsx.extendscript.js`](https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.extendscript.js) -- [`esidwrite.jsx`](pathname:///extendscript/esidwrite.jsx) + + Move to the scripts directory. To find the directory, activate Scripts panel (Windows > Utilities > Scripts), click `☰`, and select "Reveal in Explorer". @@ -310,17 +325,21 @@ If prompted, give administrator privileges. ## UXP -UXP uses bundled scripts with `.psjs` (PS) or `.idjs` (InDesign) extension. The -official samples use `webpack` to build bundles. +UXP uses scripts with `.psjs` (PS) or `.idjs` (InDesign) file extensions. -[The "Frameworks" instructions](/docs/getting-started/installation/frameworks) -describe installation steps for traditional `webpack` projects. +[The "Standalone" scripts](/docs/getting-started/installation/frameworks) can +be loaded directly in UXP scripts with `require`: + +```js +// assuming xlsx.full.min.js is in the same folder as the idjs / psjs script +const XLSX = require("./xlsx.full.min.js"); +``` Filesystem access is provided by the UXP storage module: ```js -const storage = require("uxp").storage; -const ufs = storage.localFileSystem; +const UXP = require("uxp"); +const storage = UXP.storage, ufs = storage.localFileSystem; ``` ### Reading Files @@ -337,6 +356,38 @@ const ab = await file.read({ format: storage.formats.binary }); const wb = XLSX.read(ab); ``` +
Complete Example (click to hide) + + + + +0) Open the "Scripts Panel" folder. + +To find this folder: Open the Scripts panel in InDesign (Window > Utilities > +Scripts). In the Scripts panel, right-click "User" and select "Reveal". This +will open a Finder (macOS) or Explorer (Windows) window. Open "Scripts Panel" + +1) Download the following scripts: + + + +Move them to the Scripts Panel folder. + +2) Download and open [`Template.idml`](pathname:///extendscript/Template.idml) + +3) Download + +4) In the Scripts Panel, double-click "parse". Select the downloaded `pres.xlsx` +in the file picker. + + + + +
+ ### Writing Files The `getFileForSaving` method resolves to a `File` object. The workbook should @@ -351,3 +402,34 @@ const file = await ufs.getFileForSaving("SheetJSUXP.xlsx"); /* write data */ await file.write(buf, { data: storage.formats.binary }); ``` + +
Complete Example (click to hide) + + + + +0) Open the "Scripts Panel" folder. + +To find this folder: Open the Scripts panel in InDesign (Window > Utilities > +Scripts). In the Scripts panel, right-click "User" and select "Reveal". This +will open a Finder (macOS) or Explorer (Windows) window. Open "Scripts Panel" + +1) Download the following scripts: + + + +Move them to the Scripts Panel folder. + +2) Download and open [`Filled.idml`](pathname:///extendscript/Filled.idml) + +3) In the Scripts Panel, double-click "Write". Click "Save" in the dialog. + +4) When the process finishes, open `SheetJSUXP.xlsx` and verify the contents. + + + + +
diff --git a/docz/docs/03-demos/10-extensions/05-osa.md b/docz/docs/03-demos/10-extensions/05-osa.md index 3367fe02..d20f7a52 100644 --- a/docz/docs/03-demos/10-extensions/05-osa.md +++ b/docz/docs/03-demos/10-extensions/05-osa.md @@ -5,6 +5,8 @@ pagination_next: demos/bigdata/index --- import current from '/version.js'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; Open Scripting Architecture (OSA), a built-in feature in macOS introduced in 1993, enables users to communicate with applications with a standardized @@ -23,9 +25,6 @@ This demo was last tested on 2023 April 18 in macOS Monterey. ## Integration details -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - diff --git a/docz/docs/03-demos/11-bigdata/01-stream.md b/docz/docs/03-demos/11-bigdata/01-stream.md index 36eca90c..c0ff6709 100644 --- a/docz/docs/03-demos/11-bigdata/01-stream.md +++ b/docz/docs/03-demos/11-bigdata/01-stream.md @@ -6,6 +6,9 @@ sidebar_custom_props: summary: Dense Mode + Incremental CSV / HTML / JSON Export --- +import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; + For maximal compatibility, the library reads entire files at once and generates files at once. Browsers and other JS engines enforce tight memory limits. In these cases, the library offers strategies to optimize for memory or space by @@ -154,21 +157,21 @@ is an XLS file over 50 MB `https://raw.githubusercontent.com/SheetJS/libreoffice_test-files/master/calc/xlsx-import/perf/8-by-300000-cells.xlsx` is an XLSX file with 300000 rows (approximately 20 MB) -```jsx live +{`\ function SheetJSFetchCSVStreamWorker() { const [__html, setHTML] = React.useState(""); const [state, setState] = React.useState(""); const [cnt, setCnt] = React.useState(0); const [url, setUrl] = React.useState("https://oss.sheetjs.com/test_files/large_strings.xlsx"); - +\n\ return ( <> URL: setUrl(e.target.value)} size="80"/>
); -} -``` +}`} + @@ -422,30 +422,30 @@ element is used to select a file, the script: - sends the string to the main browser context - adds the HTML to the page in the main browser context -```jsx live +{`\ function SheetJSDragDropWorker() { const [__html, setHTML] = React.useState(""); /* suppress default behavior for drag and drop */ function suppress(e) { e.stopPropagation(); e.preventDefault(); } - +\n\ /* this worker is shared between drag-drop and file input element */ - const worker = new Worker(URL.createObjectURL(new Blob([`\ + const worker = new Worker(URL.createObjectURL(new Blob([\`\\ /* load standalone script from CDN */ -importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"); - +importScripts("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"); +\n\ /* this callback will run once the main context sends a message */ self.addEventListener('message', (e) => { try { /* Read file data */ const ab = new FileReaderSync().readAsArrayBuffer(e.data.file); - +\n\ /* Parse file */ const wb = XLSX.read(ab, {dense: true}); const ws = wb.Sheets[wb.SheetNames[0]]; - +\n\ /* Generate HTML */ const html = XLSX.utils.sheet_to_html(ws); - +\n\ /* Reply with result */ postMessage({ html }); } catch(e) { @@ -453,7 +453,7 @@ self.addEventListener('message', (e) => { postMessage({html: String(e.message || e).bold() }); } }, false); - `]))); + \`]))); /* when the worker sends back the HTML, add it to the DOM */ worker.onmessage = function(e) { setHTML(e.data.html); }; return ( <> @@ -469,8 +469,8 @@ self.addEventListener('message', (e) => { }}/>
); -} -``` +}`} + @@ -558,7 +558,7 @@ is an XLS file over 50 MB. The generated CSV file is about 55 MB. `https://raw.githubusercontent.com/SheetJS/libreoffice_test-files/master/calc/xlsx-import/perf/8-by-300000-cells.xlsx` is an XLSX file with 300000 rows (approximately 20 MB) yielding a CSV of 10 MB. -```jsx live +{`\ function SheetJSFetchCSVStreamFile() { const [state, setState] = React.useState(""); const [__html, setHTML] = React.useState(""); @@ -566,16 +566,16 @@ function SheetJSFetchCSVStreamFile() { const [hz, setHz] = React.useState(0); const [url, setUrl] = React.useState("https://oss.sheetjs.com/test_files/large_strings.xlsx"); const ref = React.useRef(null); - +\n\ return ( <> URL: setUrl(e.target.value)} size="80"/>
Commit each row:
State: {state}
Count: {cnt} ({hz|0} Hz)
    );
-}
-```
+}`}
+
 
 
diff --git a/docz/docs/06-solutions/01-input.md b/docz/docs/06-solutions/01-input.md
index 79adb4c7..e125ae44 100644
--- a/docz/docs/06-solutions/01-input.md
+++ b/docz/docs/06-solutions/01-input.md
@@ -370,7 +370,7 @@ Deno must be run with the `--allow-net` flag to enable network requests:
 deno run --allow-net test-server.ts
 ```
 
-To test, submit a POST request to http://localhost:7262 including a file:
+To test, submit a POST request to `http://localhost:7262` with an attachment:
 
 ```bash
 curl -X POST -F "file=@test.xlsx" http://localhost:7262/
diff --git a/docz/docs/06-solutions/05-output.md b/docz/docs/06-solutions/05-output.md
index 61d13753..906fba74 100644
--- a/docz/docs/06-solutions/05-output.md
+++ b/docz/docs/06-solutions/05-output.md
@@ -7,6 +7,7 @@ sidebar_position: 5
 import current from '/version.js';
 import Tabs from '@theme/Tabs';
 import TabItem from '@theme/TabItem';
+import CodeBlock from '@theme/CodeBlock';
 
 ## Writing Workbooks
 
@@ -395,15 +396,15 @@ evt.respondWith(new Response(buf, {
 Save the following script to `deno.ts` and run with `deno run -A deno.ts`.  Open
 a web browser and access `http://localhost:7262/` to download the workbook.
 
-```ts title="deno.ts"
-// @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';
-
+{`\
+// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
+import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
+\n\
 const wb = XLSX.utils.book_new();
 XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet([
   ["a","b","c"], [1,2,3]
 ]), "Sheet1");
-
+\n\
 async function doNotAwaitThis(conn: Deno.Conn) {
   for await (const e of Deno.serveHttp(conn)) e.respondWith(new Response(
     XLSX.write(wb, {type:"buffer", bookType:"xlsx"}),
@@ -416,12 +417,12 @@ async function doNotAwaitThis(conn: Deno.Conn) {
     }
   ));
 }
-
+\n\
 /* standard Deno web server */
 const server = Deno.listen({ port: 7262 });
-console.log(`HTTP webserver running.  Access it at:  http://localhost:7262/`);
-for await (const conn of server) doNotAwaitThis(conn);
-```
+console.log(\`HTTP webserver running.  Access it at:  http://localhost:7262/\`);
+for await (const conn of server) doNotAwaitThis(conn);`}
+
 
 
 
@@ -445,9 +446,9 @@ return new Response(buf, {
 
 
Complete Example (click to show) -Download [`xlsx.mjs`](https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs). -Save the following script to `bun.js` and run with `bun bun.js`. Open a web -browser and access `http://localhost:7262/` to download the exported workbook. +

Download xlsx.mjs. +Save the following script to bun.js and run with bun bun.js. Open a web +browser and access http://localhost:7262/ to download the exported workbook.

```js title="bun.js" import * as XLSX from "./xlsx.mjs"; @@ -695,33 +696,33 @@ Combining with `fetch`, constructing a site from a workbook is straightforward: This example assigns the `innerHTML` of a DIV element: -```html +{`\
- + - -``` +`} +
diff --git a/docz/docusaurus.config.js b/docz/docusaurus.config.js index a217475e..19e1c343 100644 --- a/docz/docusaurus.config.js +++ b/docz/docusaurus.config.js @@ -193,6 +193,7 @@ const config = { { from: '/docs/demos/excelapi', to: '/docs/demos/extensions/excelapi/' }, { from: '/docs/demos/chromium', to: '/docs/demos/extensions/chromium/' }, /* cloudata */ + { from: '/docs/demos/cloudata', to: '/docs/demos/cloud/' }, { from: '/docs/demos/cloudata/gsheet', to: '/docs/demos/cloud/gsheet/' }, { from: '/docs/demos/cloudata/airtable', to: '/docs/demos/cloud/airtable/' }, /* hosting */ @@ -214,6 +215,14 @@ const config = { { from: '/docs/demos/ml', to: '/docs/demos/bigdata/ml/' }, { from: '/docs/demos/worker', to: '/docs/demos/bigdata/worker/' }, { from: '/docs/demos/stream', to: '/docs/demos/bigdata/stream/' }, + /* installation */ + { from: '/docs/installation/standalone', to: '/docs/getting-started/installation/standalone/' }, + { from: '/docs/installation/frameworks', to: '/docs/getting-started/installation/frameworks/' }, + { from: '/docs/installation/nodejs', to: '/docs/getting-started/installation/nodejs/' }, + { from: '/docs/installation/amd', to: '/docs/getting-started/installation/amd/' }, + { from: '/docs/installation/extendscript', to: '/docs/getting-started/installation/extendscript/' }, + { from: '/docs/installation/deno', to: '/docs/getting-started/installation/deno/' }, + { from: '/docs/installation/bun', to: '/docs/getting-started/installation/bun/' }, ] }] ] diff --git a/docz/static/extendscript/esidparse.jsx b/docz/static/extendscript/esidparse.jsx index 8fb28021..e6f2eee5 100644 --- a/docz/static/extendscript/esidparse.jsx +++ b/docz/static/extendscript/esidparse.jsx @@ -11,7 +11,7 @@ function main_parse() { var data = XLSX.utils.sheet_to_json(workbook.Sheets[wsname], { header: 1, raw: false }); /* Set title */ - app.activeDocument.textFrames.itemByName("Title").texts[0].contents = wsname; + app.activeDocument.textFrames.itemByName("Title").texts.item(0).contents = wsname; /* Set table */ var tabeller = app.activeDocument.textFrames.itemByName("Table Frame"); diff --git a/docz/static/extendscript/parse.idjs b/docz/static/extendscript/parse.idjs new file mode 100644 index 00000000..db62b9ca --- /dev/null +++ b/docz/static/extendscript/parse.idjs @@ -0,0 +1,31 @@ +const UXP = require("uxp"); +const XLSX = require("./xlsx.full.min.js"); +const storage = UXP.storage, ufs = storage.localFileSystem; + +/* show file picker (single file, no folders) */ +const file = await ufs.getFileForOpening({ types: ["xlsx", "xls", "xlsb"] }); +/* read data into an ArrayBuffer */ +const ab = await file.read({ format: storage.formats.binary }); +/* parse with SheetJS */ +const wb = XLSX.read(ab), wsname = wb.SheetNames[0]; +const data = XLSX.utils.sheet_to_json(wb.Sheets[wsname], { header: 1, raw: false }); + +/* Set title */ +app.activeDocument.textFrames.itemByName("Title").texts.item(0).contents = wsname; + +/* Set table */ +var tabeller = app.activeDocument.textFrames.itemByName("Table Frame"); +var columns = data[0].length; +for(var R = 0; R < data.length; ++R) columns = Math.max(columns, data[R].length); +var table = tabeller.tables.add({ + headerRowCount: 1, + bodyRowCount: data.length - 1, + columnCount: columns +}); +for(R = 0; R < data.length; ++R) { + if(data[R] == null) continue; + for(var C = 0; C < data[R].length; ++C) { + if(data[R][C] == null) continue; + table.rows.item(R).cells.item(C).contents = data[R][C]; + } +} diff --git a/docz/static/extendscript/write.idjs b/docz/static/extendscript/write.idjs new file mode 100644 index 00000000..ebd07b52 --- /dev/null +++ b/docz/static/extendscript/write.idjs @@ -0,0 +1,47 @@ +const UXP = require("uxp"); +const XLSX = require("./xlsx.full.min.js"); +const storage = UXP.storage, ufs = storage.localFileSystem; + +function workbook_add_table(wb, table) { + /* Collect Data */ + var data = []; + var cnt = table.rows.count(); + for(var R = 0; R < cnt; ++R) { + var row = table.rows.item(R); + data[R] = []; + var ccnt = row.cells.count(); + for(var C = 0; C < ccnt; ++C) { + var value = row.cells.item(C).contents; + data[R][C] = value; + } + } + + if(data.length == 0) return; + + /* Create Worksheet */ + var ws = XLSX.utils.aoa_to_sheet(data); + + /* Create new Workbook and add worksheet */ + XLSX.utils.book_append_sheet(wb, ws); +} + +/* Create new Workbook */ +var wb = XLSX.utils.book_new(); + +/* Find all tables and add them to workbook */ +var tfcnt = app.activeDocument.textFrames.count(); +for(var i = 0; i < tfcnt; ++i) { + var tf = app.activeDocument.textFrames.item(i); + var tcnt = tf.tables.count(); + if(tcnt == 0) continue; + for(var j = 0; j < tcnt; ++j) workbook_add_table(wb, tf.tables.item(j)); +} + + + +/* generate XLSX with type: "buffer" */ +const buf = XLSX.write(wb, { type: "buffer", bookType: "xlsx" }); +/* show file picker */ +const file = await ufs.getFileForSaving("SheetJSUXP.xlsx"); +/* write data */ +await file.write(buf, { data: storage.formats.binary }); diff --git a/docz/static/server/SheetJSDrash.ts b/docz/static/server/SheetJSDrash.ts new file mode 100644 index 00000000..4ec41736 --- /dev/null +++ b/docz/static/server/SheetJSDrash.ts @@ -0,0 +1,78 @@ +/*! sheetjs (C) SheetJS -- https://sheetjs.com */ +// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" +import { read, utils, write, set_cptable } 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'; +set_cptable(cptable); + +import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts"; + +class ParseResource extends Drash.Resource { + public paths = ["/"]; + + public POST(request: Drash.Request, response: Drash.Response) { + const file = request.bodyParam("file"); + if (!file) throw new Error("File is required!"); + var wb = read(file.content); + return response.html( utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]])); + } + + public GET(request: Drash.Request, response: Drash.Response): void { + return response.html(`\ + + + + SheetJS Spreadsheet to HTML Conversion Service + + + +

SheetJS Spreadsheet Conversion Service

+API + +Send a POST request to http://localhost:7262/ with the file in the "file" body parameter: + +$ curl -X POST -F"file=@test.xlsx" http://localhost:7262/ + +The response will be an HTML TABLE generated from the first worksheet. + +Try it out!
+ + + +Use the file input element to select a file, then click "Submit" + + +
+
+ +`, + ); + } +} + +class WriteResource extends Drash.Resource { + public paths = ["/export"]; + + public GET(request: Drash.Request, response: Drash.Response): void { + // create some fixed workbook + const data = ["SheetJS".split(""), [5,4,3,3,7,9,5]]; + const ws = utils.aoa_to_sheet(data); + const wb = utils.book_new(); utils.book_append_sheet(wb, ws, "data"); + // write the workbook to XLSX as a Uint8Array + const file = write(wb, { bookType: "xlsx", type: "buffer"}); + // set headers + response.headers.set("Content-Disposition", 'attachment; filename="SheetJSDrash.xlsx"'); + // send data + return response.send("application/vnd.ms-excel", file); + } +} + +const server = new Drash.Server({ + hostname: "", + port: 7262, + protocol: "http", + resources: [ ParseResource, WriteResource ], +}); + +server.run(); + +console.log(`Server running at ${server.address}.`);