uxp
This commit is contained in:
parent
775e72c345
commit
32021ab7ed
@ -267,46 +267,46 @@ hosted (no `file:///` access).
|
||||
|
||||
<https://sheetjs.com/pres.html> is a hosted version of the page.
|
||||
|
||||
```html
|
||||
<CodeBlock language="html" title="snippet.html">{`\
|
||||
<body>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
<script>
|
||||
(async() => {
|
||||
/* 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 => row.terms.some(term => 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 => ({
|
||||
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, r) => 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 });
|
||||
})();
|
||||
</script>
|
||||
<body>
|
||||
```
|
||||
</body>`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="nodejs" label="Command-Line (NodeJS)">
|
||||
@ -423,50 +423,49 @@ const axios = require("axios");
|
||||
<Tabs>
|
||||
<TabItem value="deno" label="Deno">
|
||||
|
||||
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`:
|
||||
|
||||
<CodeBlock language="ts" title="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 });`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="bun" label="Bun">
|
||||
|
||||
Download <https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs> to `xlsx.mjs`
|
||||
<div>Download <a href={`https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs`}>https://cdn.sheetjs.com/xlsx-{current}/package/xlsx.mjs</a> to <code>xlsx.mjs</code></div>
|
||||
|
||||
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"
|
||||
<CodeBlock language="html" title="snippet.html">{`\
|
||||
<body>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
<script>
|
||||
(async() => {
|
||||
/* 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 => row.terms.some(term => 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 => ({
|
||||
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, r) => 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 });
|
||||
})();
|
||||
</script>
|
||||
<body>
|
||||
```
|
||||
</body>`}
|
||||
</CodeBlock>
|
||||
|
||||
Save the following to `package.json`:
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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"
|
||||
<CodeBlock language="html" title="index.html">{`\
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="s5s">
|
||||
<head>
|
||||
<title>SheetJS + AngularJS</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h3><a href="https://sheetjs.com">SheetJS + AngularJS demo</a></h3>
|
||||
|
||||
\n\
|
||||
<div ng-controller="sheetjs">
|
||||
<button ng-click="exportSheetJS()">Export Table</button>
|
||||
<table id="s5s-table">
|
||||
@ -184,7 +187,7 @@ $scope.exportSheetJS = function() {
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
\n\
|
||||
<script>
|
||||
var app = angular.module('s5s', []);
|
||||
app.controller('sheetjs', function($scope, $http) {
|
||||
@ -206,8 +209,8 @@ app.controller('sheetjs', function($scope, $http) {
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
</html>`}
|
||||
</CodeBlock>
|
||||
|
||||
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"
|
||||
<CodeBlock language="html" title="index.html">{`\
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="s5s">
|
||||
<head>
|
||||
<title>SheetJS + AngularJS</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-sanitize.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h3><a href="https://sheetjs.com">SheetJS + AngularJS demo</a></h3>
|
||||
|
||||
\n\
|
||||
<div ng-controller="sheetjs">
|
||||
<button ng-click="exportSheetJS()">Export Table</button>
|
||||
<div ng-bind-html="data" id="tbl"></div>
|
||||
</div>
|
||||
|
||||
\n\
|
||||
<script>
|
||||
var app = angular.module('s5s', ['ngSanitize']);
|
||||
app.controller('sheetjs', function($scope, $http) {
|
||||
@ -298,8 +301,8 @@ app.controller('sheetjs', function($scope, $http) {
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
</html>`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Start a local web server with `npx http-server .` and access the displayed
|
||||
URL with a web browser (typically `http://localhost:8080`)
|
||||
|
@ -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.
|
||||
|
||||
</details>
|
||||
@ -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`
|
||||
</html>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
||||
@ -1251,7 +1251,7 @@ npx webpack --mode=production
|
||||
</html>
|
||||
```
|
||||
|
||||
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/
|
||||
|
@ -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
|
||||
<CodeBlock language="html">{`\
|
||||
<script>
|
||||
dojoConfig = {
|
||||
packages: [
|
||||
{ name: "xlsx", location: "https://cdn.sheetjs.com/xlsx-latest/package/dist", main: "xlsx.full.min" }
|
||||
{ name: "xlsx", location: "https://cdn.sheetjs.com/xlsx-${current}/package/dist", main: "xlsx.full.min" }
|
||||
]
|
||||
}
|
||||
</script>
|
||||
@ -205,8 +206,8 @@ dojoConfig = {
|
||||
require(["dojo/request/xhr", "xlsx"], function(xhr, _XLSX) {
|
||||
/* XLSX-related operations happen in the callback */
|
||||
});
|
||||
</script>
|
||||
```
|
||||
</script>`}
|
||||
</CodeBlock>
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -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
|
||||
```
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid @emotion/react @emotion/styled`}
|
||||
</CodeBlock>
|
||||
|
||||
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
|
||||
<CodeBlock language="html">{`\
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
\n\
|
||||
<!-- table with id \`xport\` -->
|
||||
<table id="xport"><tr><td>SheetJS</td></tr></table>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
\n\
|
||||
<script>
|
||||
/* as long as this script appears after the table, it will be visible */
|
||||
var tbl = document.getElementById("xport");
|
||||
const wb = XLSX.utils.table_to_book(tbl);
|
||||
XLSX.writeFile(wb, "HTMLTable.xlsx");
|
||||
</script>
|
||||
```
|
||||
</script>`}
|
||||
</CodeBlock>
|
||||
|
||||
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
|
||||
```
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Replace `src/App.tsx` with the following code. This is based on the official
|
||||
Material UI Table example. Differences are highlighted.
|
||||
|
@ -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 <input type="file" id="upload" name="upload">
|
||||
// highlight-next-line
|
||||
const file = request.bodyParam<Drash.Types.BodyFile>("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);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||
|
||||
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<Drash.Types.BodyFile>("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(`\
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>SheetJS Spreadsheet to HTML Conversion Service</title>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<pre><h3><a href="//sheetjs.com/">SheetJS</a> Spreadsheet Conversion Service</h3>
|
||||
<b>API</b>
|
||||
|
||||
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.
|
||||
|
||||
<b>Try it out!</b><form action="/" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="file" name="file" />
|
||||
|
||||
Use the file input element to select a file, then click "Submit"
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</pre>
|
||||
</body>
|
||||
</html>`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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 <https://sheetjs.com/pres.numbers>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
||||
## 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
|
||||
```
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express express-formidable`}
|
||||
</CodeBlock>
|
||||
|
||||
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
|
||||
<CodeBlock language="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`}
|
||||
</CodeBlock>
|
||||
|
||||
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
|
||||
```
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify @fastify/multipart`}
|
||||
</CodeBlock>
|
||||
|
||||
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
|
||||
```
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.18.2 formidable@2.1.1`}
|
||||
</CodeBlock>
|
||||
|
||||
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`.
|
||||
|
||||
</details>
|
||||
|
||||
## 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`:
|
||||
|
||||
<CodeBlock language="ts">{`\
|
||||
// @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 <input type="file" id="upload" name="upload">
|
||||
// highlight-next-line
|
||||
const file = request.bodyParam<Drash.Types.BodyFile>("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]]));
|
||||
}
|
||||
}`}
|
||||
</CodeBlock>
|
||||
|
||||
_Writing Data_
|
||||
|
||||
Headers are manually set with `Response#headers.set` while the raw body is set
|
||||
with `Response#send`:
|
||||
|
||||
<CodeBlock language="ts">{`\
|
||||
// @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);
|
||||
}
|
||||
}`}
|
||||
</CodeBlock>
|
||||
|
||||
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||
|
||||
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 <https://sheetjs.com/pres.numbers>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
@ -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!
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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 <https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js>
|
||||
<p>1) Download <a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>https://cdn.sheetjs.com/xlsx-{current}/package/dist/xlsx.full.min.js</a></p>
|
||||
|
||||
:::warning
|
||||
|
||||
|
@ -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.
|
||||
<p><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>The
|
||||
standalone script</a> should be downloaded and uploaded to the File Cabinet.</p>
|
||||
|
||||
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`.
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
||||
<ul>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.extendscript.js`}><code>xlsx.extendscript.js</code></a></li>
|
||||
<li><a href={`https://docs.sheetjs.com/extendscript/parse.jsx`}><code>parse.jsx</code></a></li>
|
||||
</ul>
|
||||
|
||||
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)
|
||||
|
||||
<ul>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.extendscript.js`}><code>xlsx.extendscript.js</code></a></li>
|
||||
<li><a href={`https://docs.sheetjs.com/extendscript/esidparse.jsx`}><code>esidparse.jsx</code></a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
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)
|
||||
|
||||
<ul>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.extendscript.js`}><code>xlsx.extendscript.js</code></a></li>
|
||||
<li><a href={`https://docs.sheetjs.com/extendscript/write.jsx`}><code>write.jsx</code></a></li>
|
||||
</ul>
|
||||
|
||||
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)
|
||||
|
||||
<ul>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.extendscript.js`}><code>xlsx.extendscript.js</code></a></li>
|
||||
<li><a href={`https://docs.sheetjs.com/extendscript/esidwrite.jsx`}><code>esidwrite.jsx</code></a></li>
|
||||
</ul>
|
||||
|
||||
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);
|
||||
```
|
||||
|
||||
<details open><summary><b>Complete Example</b> (click to hide)</summary>
|
||||
|
||||
<Tabs groupId="ccapp">
|
||||
<TabItem value="indesign" label="InDesign">
|
||||
|
||||
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:
|
||||
|
||||
<ul>
|
||||
<li><a href="pathname:///extendscript/parse.idjs"><code>parse.idjs</code></a></li>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}><code>xlsx.full.min.js</code></a></li>
|
||||
</ul>
|
||||
|
||||
Move them to the Scripts Panel folder.
|
||||
|
||||
2) Download and open [`Template.idml`](pathname:///extendscript/Template.idml)
|
||||
|
||||
3) Download <https://sheetjs.com/pres.xlsx>
|
||||
|
||||
4) In the Scripts Panel, double-click "parse". Select the downloaded `pres.xlsx`
|
||||
in the file picker.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
</details>
|
||||
|
||||
### 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 });
|
||||
```
|
||||
|
||||
<details open><summary><b>Complete Example</b> (click to hide)</summary>
|
||||
|
||||
<Tabs groupId="ccapp">
|
||||
<TabItem value="indesign" label="InDesign">
|
||||
|
||||
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:
|
||||
|
||||
<ul>
|
||||
<li><a href="pathname:///extendscript/write.idjs"><code>write.idjs</code></a></li>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}><code>xlsx.full.min.js</code></a></li>
|
||||
</ul>
|
||||
|
||||
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.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
</details>
|
||||
|
@ -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';
|
||||
|
||||
<Tabs groupId="osa">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
|
@ -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
|
||||
<CodeBlock language="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 ( <>
|
||||
<b>URL: </b><input type="text" value={url} onChange={(e) => setUrl(e.target.value)} size="80"/>
|
||||
<button onClick={() => {
|
||||
/* this mantra embeds the worker source in the function */
|
||||
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\
|
||||
function sheet_to_csv_cb(ws, cb, opts, batch = 1000) {
|
||||
XLSX.stream.set_readable(() => ({
|
||||
__done: false,
|
||||
@ -180,7 +183,7 @@ function sheet_to_csv_cb(ws, cb, opts, batch = 1000) {
|
||||
}));
|
||||
return XLSX.stream.to_csv(ws, opts);
|
||||
}
|
||||
|
||||
\n\
|
||||
/* this callback will run once the main context sends a message */
|
||||
self.addEventListener('message', async(e) => {
|
||||
try {
|
||||
@ -188,7 +191,7 @@ self.addEventListener('message', async(e) => {
|
||||
/* Fetch file */
|
||||
const res = await fetch(e.data.url);
|
||||
const ab = await res.arrayBuffer();
|
||||
|
||||
\n\
|
||||
/* Parse file */
|
||||
let len = ab.byteLength;
|
||||
if(len < 1024) len += " bytes"; else { len /= 1024;
|
||||
@ -197,7 +200,7 @@ self.addEventListener('message', async(e) => {
|
||||
postMessage({state: "parsing " + len});
|
||||
const wb = XLSX.read(ab, {dense: true});
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
|
||||
\n\
|
||||
/* Generate CSV rows */
|
||||
postMessage({state: "csv"});
|
||||
const strm = sheet_to_csv_cb(ws, (csv) => {
|
||||
@ -210,7 +213,7 @@ self.addEventListener('message', async(e) => {
|
||||
postMessage({error: String(e.message || e) });
|
||||
}
|
||||
}, false);
|
||||
`])));
|
||||
\`])));
|
||||
/* when the worker sends back data, add it to the DOM */
|
||||
worker.onmessage = function(e) {
|
||||
if(e.data.error) return setHTML(e.data.error);
|
||||
@ -225,8 +228,8 @@ self.addEventListener('message', async(e) => {
|
||||
<pre>State: <b>{state}</b><br/>Number of rows: <b>{cnt}</b></pre>
|
||||
<pre dangerouslySetInnerHTML={{ __html }}/>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
}`}
|
||||
</CodeBlock>
|
||||
|
||||
</details>
|
||||
|
||||
@ -261,10 +264,10 @@ examples using the File System Access API.
|
||||
Typically, the file and stream processing occurs in the Web Worker. CSV rows
|
||||
can be sent back to the main thread in the callback:
|
||||
|
||||
```js title="worker.js"
|
||||
<CodeBlock language="js" title="worker.js">{`\
|
||||
/* 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\
|
||||
function sheet_to_csv_cb(ws, cb, opts, batch = 1000) {
|
||||
XLSX.stream.set_readable(() => ({
|
||||
__done: false,
|
||||
@ -276,7 +279,7 @@ function sheet_to_csv_cb(ws, cb, opts, batch = 1000) {
|
||||
}));
|
||||
return XLSX.stream.to_csv(ws, opts);
|
||||
}
|
||||
|
||||
\n\
|
||||
/* this callback will run once the main context sends a message */
|
||||
self.addEventListener('message', async(e) => {
|
||||
try {
|
||||
@ -284,12 +287,12 @@ self.addEventListener('message', async(e) => {
|
||||
/* Fetch file */
|
||||
const res = await fetch(e.data.url);
|
||||
const ab = await res.arrayBuffer();
|
||||
|
||||
\n\
|
||||
/* Parse file */
|
||||
postMessage({state: "parsing"});
|
||||
const wb = XLSX.read(ab, {dense: true});
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
|
||||
\n\
|
||||
/* Generate CSV rows */
|
||||
postMessage({state: "csv"});
|
||||
const strm = sheet_to_csv_cb(ws, (csv) => {
|
||||
@ -301,8 +304,8 @@ self.addEventListener('message', async(e) => {
|
||||
/* Pass the error message back */
|
||||
postMessage({error: String(e.message || e) });
|
||||
}
|
||||
}, false);
|
||||
```
|
||||
}, false);`}
|
||||
</CodeBlock>
|
||||
|
||||
The main thread will receive messages with CSV rows for further processing:
|
||||
|
||||
@ -322,10 +325,10 @@ worker.onmessage = function(e) {
|
||||
Deno does not support NodeJS streams in normal execution, so a wrapper is used.
|
||||
This example fetches <https://sheetjs.com/pres.numbers> and prints CSV rows:
|
||||
|
||||
```ts title="sheet2csv.ts"
|
||||
// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts"
|
||||
import { stream, Sheet2CSVOpts, WorkSheet } from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
|
||||
|
||||
<CodeBlock language="ts" title="sheet2csv.ts">{`\
|
||||
// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
|
||||
import { stream, Sheet2CSVOpts, WorkSheet } from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
|
||||
\n\
|
||||
interface Resumable { resume:()=>void; };
|
||||
/* Generate row strings from a worksheet */
|
||||
function sheet_to_csv_cb(ws: WorkSheet, cb:(d:string|null)=>void, opts: Sheet2CSVOpts = {}, batch = 1000): Resumable {
|
||||
@ -339,20 +342,20 @@ function sheet_to_csv_cb(ws: WorkSheet, cb:(d:string|null)=>void, opts: Sheet2CS
|
||||
}));
|
||||
return stream.to_csv(ws, opts) as Resumable;
|
||||
}
|
||||
|
||||
\n\
|
||||
/* Callback invoked on each row (string) and at the end (null) */
|
||||
const csv_cb = (d:string|null) => {
|
||||
if(d == null) return;
|
||||
/* The strings include line endings, so raw write ops should be used */
|
||||
Deno.stdout.write(new TextEncoder().encode(d));
|
||||
};
|
||||
|
||||
\n\
|
||||
/* Fetch https://sheetjs.com/pres.numbers, parse, and get first worksheet */
|
||||
import { read } from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
|
||||
import { read } from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
|
||||
const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer();
|
||||
const wb = read(ab, { dense: true });
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
|
||||
\n\
|
||||
/* Create and start CSV stream */
|
||||
sheet_to_csv_cb(ws, csv_cb).resume();
|
||||
```
|
||||
sheet_to_csv_cb(ws, csv_cb).resume();`}
|
||||
</CodeBlock>
|
||||
|
@ -317,22 +317,22 @@ In the following example, the script:
|
||||
- sends the object URL to the main browser context
|
||||
- performs a download action in the main browser context
|
||||
|
||||
```jsx live
|
||||
<CodeBlock language="jsx" live>{`\
|
||||
function SheetJSWriteFileWorker() {
|
||||
const [__html, setHTML] = React.useState("");
|
||||
|
||||
\n\
|
||||
const data = [
|
||||
{ "SheetJS": "வணக்கம்", "in": "สวัสดี", "Web": "你好", "Workers": "가지마" },
|
||||
{ "SheetJS": 1, "in": 2, "Web": 3, "Workers": 4 },
|
||||
];
|
||||
|
||||
\n\
|
||||
return ( <>
|
||||
<button onClick={() => { setHTML("");
|
||||
/* this mantra embeds the worker source in the function */
|
||||
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', async(e) => {
|
||||
try {
|
||||
@ -340,13 +340,13 @@ self.addEventListener('message', async(e) => {
|
||||
const ws = XLSX.utils.json_to_sheet(e.data.data);
|
||||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "Data");
|
||||
|
||||
\n\
|
||||
/* Write XLSB data (Uint8Array) */
|
||||
const u8 = XLSX.write(wb, { bookType: "xlsb", type: "buffer" });
|
||||
|
||||
\n\
|
||||
/* Generate URL */
|
||||
const url = URL.createObjectURL(new Blob([u8]));
|
||||
|
||||
\n\
|
||||
/* Reply with result */
|
||||
postMessage({ url });
|
||||
} catch(e) {
|
||||
@ -354,11 +354,11 @@ self.addEventListener('message', async(e) => {
|
||||
postMessage({error: String(e.message || e).bold() });
|
||||
}
|
||||
}, false);
|
||||
`])));
|
||||
\`])));
|
||||
/* when the worker sends back the data, create a download */
|
||||
worker.onmessage = function(e) {
|
||||
if(e.data.error) return setHTML(e.data.error);
|
||||
|
||||
\n\
|
||||
/* this mantra is the standard HTML5 download attribute technique */
|
||||
const a = document.createElement("a");
|
||||
a.download = "SheetJSWriteFileWorker.xlsb";
|
||||
@ -372,8 +372,8 @@ self.addEventListener('message', async(e) => {
|
||||
}}><b>Click to Start</b></button>
|
||||
<div dangerouslySetInnerHTML={{ __html }}/>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
}`}
|
||||
</CodeBlock>
|
||||
|
||||
</details>
|
||||
|
||||
@ -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
|
||||
<CodeBlock language="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) => {
|
||||
}}/>
|
||||
<div dangerouslySetInnerHTML={{ __html }}/>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
}`}
|
||||
</CodeBlock>
|
||||
|
||||
</details>
|
||||
|
||||
@ -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
|
||||
<CodeBlock language="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 ( <>
|
||||
<b>URL: </b><input type="text" value={url} onChange={(e) => setUrl(e.target.value)} size="80"/><br/>
|
||||
<b>Commit each row: </b><input type="checkbox" ref={ref}/><br/>
|
||||
<button onClick={async() => {
|
||||
/* this mantra embeds the worker source in the function */
|
||||
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\
|
||||
function sheet_to_csv_cb(ws, cb, opts, batch = 1000) {
|
||||
XLSX.stream.set_readable(() => ({
|
||||
__done: false,
|
||||
@ -591,7 +591,7 @@ function sheet_to_csv_cb(ws, cb, opts, batch = 1000) {
|
||||
}));
|
||||
return XLSX.stream.to_csv(ws, opts);
|
||||
}
|
||||
|
||||
\n\
|
||||
/* this callback will run once the main context sends a message */
|
||||
self.addEventListener('message', async(e) => {
|
||||
try {
|
||||
@ -601,14 +601,14 @@ self.addEventListener('message', async(e) => {
|
||||
const res = await fetch(e.data.url);
|
||||
const ab = await res.arrayBuffer();
|
||||
postMessage({time: "fetch", ts: Date.now() - t});
|
||||
|
||||
\n\
|
||||
/* Parse file */
|
||||
postMessage({state: "parsing"});
|
||||
t = Date.now();
|
||||
const wb = XLSX.read(ab, {dense: true});
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
postMessage({time: "parse", ts: Date.now() - t});
|
||||
|
||||
\n\
|
||||
/* Generate CSV rows */
|
||||
postMessage({state: "begin"});
|
||||
t = Date.now();
|
||||
@ -631,11 +631,11 @@ self.addEventListener('message', async(e) => {
|
||||
postMessage({error: String(e.message || e) });
|
||||
}
|
||||
}, false);
|
||||
`])));
|
||||
\`])));
|
||||
/* when the worker sends back data, add it to the DOM */
|
||||
const log = (s, t) => setHTML(h => h + `${s}: ${(t/1000).toFixed(3).padStart(8)} sec\n`);
|
||||
const log = (s, t) => setHTML(h => h + \`\${s}: \${(t/1000).toFixed(3).padStart(8)} sec\\n\`);
|
||||
worker.onmessage = function(e) {
|
||||
if(e.data.error) return setState(`Processing Error: ${e.data.error}`);
|
||||
if(e.data.error) return setState(\`Processing Error: \${e.data.error}\`);
|
||||
else if(e.data.state) {
|
||||
setState(e.data.state);
|
||||
if(e.data.c) setCnt(e.data.c);
|
||||
@ -650,15 +650,15 @@ self.addEventListener('message', async(e) => {
|
||||
suggestedName: "SheetJSStream.csv",
|
||||
types: [ { description: 'csv', accept: { 'text/csv': ['.csv'] } } ]
|
||||
});
|
||||
|
||||
\n\
|
||||
/* post a message to the worker with the URL to fetch */
|
||||
worker.postMessage({url, wFile, each: !!ref.current.checked});
|
||||
} catch(e) { setState(`Selection Error: ${e && e.message || e}`); }
|
||||
} catch(e) { setState(\`Selection Error: \${e && e.message || e}\`); }
|
||||
}}><b>Click to Start</b></button>
|
||||
<pre>State: <b>{state}</b><br/>Count: <b>{cnt}</b> <b>({hz|0} Hz)</b></pre>
|
||||
<pre dangerouslySetInnerHTML={{__html}}/>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
}`}
|
||||
</CodeBlock>
|
||||
|
||||
</details>
|
||||
|
@ -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/
|
||||
|
@ -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';
|
||||
|
||||
<CodeBlock language="ts" title="deno.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\
|
||||
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);`}
|
||||
</CodeBlock>
|
||||
|
||||
</details>
|
||||
|
||||
@ -445,9 +446,9 @@ return new Response(buf, {
|
||||
|
||||
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||
|
||||
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.
|
||||
<p>Download <a href={`https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs`}><code>xlsx.mjs</code></a>.
|
||||
Save the following script to <code>bun.js</code> and run with <code>bun bun.js</code>. Open a web
|
||||
browser and access <code>http://localhost:7262/</code> to download the exported workbook.</p>
|
||||
|
||||
```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
|
||||
<CodeBlock language="html">{`\
|
||||
<body>
|
||||
<style>TABLE { border-collapse: collapse; } TD { border: 1px solid; }</style>
|
||||
<div id="tavolo"></div>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
(async() => {
|
||||
/* fetch and parse workbook -- see the fetch example for details */
|
||||
const workbook = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
|
||||
|
||||
\n\
|
||||
let output = [];
|
||||
/* loop through the worksheet names in order */
|
||||
workbook.SheetNames.forEach(name => {
|
||||
|
||||
\n\
|
||||
/* generate HTML from the corresponding worksheets */
|
||||
const worksheet = workbook.Sheets[name];
|
||||
const html = XLSX.utils.sheet_to_html(worksheet);
|
||||
|
||||
\n\
|
||||
/* add a header with the title name followed by the table */
|
||||
output.push(`<H3>${name}</H3>${html}`);
|
||||
output.push(\`<H3>\${name}</H3>\${html}\`);
|
||||
});
|
||||
/* write to the DOM at the end */
|
||||
tavolo.innerHTML = output.join("\n");
|
||||
tavolo.innerHTML = output.join("\\n");
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
</body>`}
|
||||
</CodeBlock>
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="react" label="React">
|
||||
|
@ -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/' },
|
||||
]
|
||||
}]
|
||||
]
|
||||
|
@ -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");
|
||||
|
31
docz/static/extendscript/parse.idjs
Normal file
31
docz/static/extendscript/parse.idjs
Normal file
@ -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];
|
||||
}
|
||||
}
|
47
docz/static/extendscript/write.idjs
Normal file
47
docz/static/extendscript/write.idjs
Normal file
@ -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 });
|
78
docz/static/server/SheetJSDrash.ts
Normal file
78
docz/static/server/SheetJSDrash.ts
Normal file
@ -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<Drash.Types.BodyFile>("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(`\
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>SheetJS Spreadsheet to HTML Conversion Service</title>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<pre><h3><a href="//sheetjs.com/">SheetJS</a> Spreadsheet Conversion Service</h3>
|
||||
<b>API</b>
|
||||
|
||||
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.
|
||||
|
||||
<b>Try it out!</b><form action="/" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="file" name="file" />
|
||||
|
||||
Use the file input element to select a file, then click "Submit"
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</pre>
|
||||
</body>
|
||||
</html>`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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}.`);
|
Loading…
Reference in New Issue
Block a user