alasql-browser

This commit is contained in:
SheetJS 2023-04-09 17:13:24 -04:00
parent e7e2d1a709
commit 15c8071586
5 changed files with 299 additions and 17 deletions

@ -72,7 +72,7 @@ function localStorage_to_sheet() {
:::note
This demo was last tested on 2023 February 26.
This demo was last tested on 2023 April 09.
:::
@ -141,7 +141,7 @@ array of pairs. Consider the following data in Local Storage:
|:---:|:----------|
| "b" | "Logical" |
| "n" | "Numeric" |
| "s" | "Textual" |
| "s" | "Textual" |
The natural representation is an array of arrays:
@ -155,6 +155,13 @@ The natural representation is an array of arrays:
#### Exporting Storage
:::note
Web Storage iteration order is not defined. By using indices as keys, the row
objects approach has an ordering. That does not apply to the general case.
:::
In modern browsers, `Object.entries` will generate an array of key/value pairs.
`XLSX.utils.aoa_to_sheet` will interpret that array as a worksheet with 2 cols:
@ -177,3 +184,50 @@ function ws_to_localStorage(ws) {
aoa.forEach(([key, val]) => localStorage.setItem(key, val));
}
```
### Live Demo
:::note
This demo was last tested on 2023 April 09.
:::
This example fills `localStorage` with 10 random keys and 10 random values,
generates a worksheet from the data and writes to a new file.
```jsx live
function SheetJSRandomStorage() {
const [out, setOut] = React.useState("");
const [rows, setRows] = React.useState([]);
const xport = React.useCallback(async() => {
// reset and populate localStorage
localStorage.clear();
var data = [];
for(let i = 0, last = 0; i < 10; ++i) {
var k = ((Math.random() * 20)|0) + last;
var v = (Math.random() * 16777216).toString(36);
localStorage.setItem(k, v);
data.push([k,v]);
last = k;
}
setRows(Object.entries(localStorage));
// create new worksheet from localStorage
const aoa = Object.entries(localStorage);
const new_ws = XLSX.utils.aoa_to_sheet(aoa);
// create and export workbook
const new_wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(new_wb, new_ws, "Sheet1");
XLSX.writeFile(new_wb, "SheetJSRandomStorage.xlsx");
});
return ( <>
{out && ( <><a href={url}>{url}</a><pre>{out}</pre></> )}
{rows.length && (<table><tr><th>Key</th><th>Value</th></tr>
{rows.map(([k,v]) => (<tr><td>{k}</td><td>{v}</td></tr>))}
</table>) || null}
<br/><button onClick={xport}><b>Export!</b></button>
</> );
}
```

@ -6,6 +6,10 @@ sidebar_custom_props:
sql: true
---
<head>
<script src="/alasql/alasql.js"></script>
</head>
import current from '/version.js';
AlaSQL is a pure JavaScript in-memory SQL database. It has built-in support for
@ -15,7 +19,180 @@ This demo covers basic concepts pertaining to data import and export. The
official documentation includes advanced examples and deployment tips as well as
strategies for general data processing in AlaSQL expressions.
## NodeJS Usage
:::note
This demo was tested in the following environments:
| Environment | AlaSQL | Date |
|:--------------------|:-------|:----------:|
| NodeJS | 3.1.0 | 2023-02-23 |
| Standalone (Chrome) | 3.0.0 | 2023-04-09 |
:::
## Live Demo
This demo fetches <https://sheetjs.com/pres.numbers>, performs a `SELECT` query
using the built-in AlaSQL + SheetJS integration, then displays the result. Using
the result as a data source, the demo will write to a new spreadsheet.
<details><summary><b>Demo AlaSQL Queries</b> (click to show)</summary>
```sql title="AlaSQL Query for reading data from a workbook"
SELECT `Index`, -- "Index" field is the "Index" column of the sheet
UPPER(`Name`) AS `Nom` -- "Nom" field will be uppercase of "Name" column
FROM XLSX(?, { -- Parse the workbook bytes passed to alasql.promise
autoExt: false -- This option is required in the browser
})
```
```sql title="AlaSQL Query for writing data to a workbook"
SELECT * -- use every field from every row in dataset
INTO XLSX( -- export data to file
"SheetJSAlaSQL.xlsx" -- filename for export
) FROM ?
```
</details>
:::caution
If the live demo shows a message
```
alasql undefined
```
please refresh the page. This is a known bug in the documentation generator.
:::
```jsx live
function SheetJSAlaSQL() {
const q1 = "SELECT `Index`, UPPER(`Name`) AS `Nom` FROM XLSX(?,{autoExt:false})";
const q2 = `SELECT * INTO XLSX("SheetJSAlaSQL.xlsx") FROM ?`;
const url = "https://sheetjs.com/pres.numbers";
const [rows, setRows] = React.useState([]);
const loadURL = React.useCallback(async() => {
if(typeof alasql=="undefined") return setRows([{Nom:"alasql undefined"}]);
const blob = await (await fetch(url)).blob();
const data = URL.createObjectURL(blob);
const res = await alasql.promise(q1,[data]);
setRows(res);
await alasql.promise(q2, [res]);
}, []);
return ( <>
<pre><b>URL: </b>{url}<br/><b>Import: </b>{q1}<br/><b>Export: </b>{q2}</pre>
<table><tr><th>Index</th><th>Nom</th></tr>
{rows.map(({Nom, Index}) => <tr><td>{Index}</td><td>{Nom}</td></tr>)}
</table>
<button onClick={loadURL}>Click to start</button>
</> );
}
```
## Browser
#### Standalone Scripts
The [Standalone scripts](/docs/getting-started/installation/standalone) should
be loaded before the `alasql` script:
```html
<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.jsdelivr.net/npm/alasql"></script>
```
#### Frameworks and Bundlers
`alasql` uses an older version of the library. It can be overridden through a
`package.json` override. The lines should be added *before* installing `alasql`:
<pre><code parentName="pre" {...{"className": "language-json"}}>{`\
{
/* add this part before "name" */
/* highlight-start */
"overrides": {
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
},
/* highlight-end */
"name": "my-project",
/* ... more fields ... */
`}
</code></pre>
After adding the override, AlaSQL can be installed through `npm`:
```bash
npm install --save alasql
```
In imports, the SheetJS library must be passed to AlaSQL as shown below:
```js
import * as alasql from 'alasql';
import * as XLSX from 'xlsx';
alasql.utils.isBrowserify = false;
alasql.utils.global.XLSX = XLSX;
```
### Reading Files
The `XLSX` "from" target expects a filename. In the browser, AlaSQL uses object
URLs which can be created from `Blob` or `File` objects.
The following snippet fetches data and passes to AlaSQL:
```js
const blob = await (await fetch("https://sheetjs.com/pres.numbers")).blob();
const data = URL.createOjectURL(blob);
const res = await alasql.promise("SELECT * FROM XLSX(?, {autoExt: false}", [data]);
```
By default, the `XLSX` "from" target automatically adds a `.xlsx` extension. To
read URLs, the `autoExt: false` option should be passed as the second argument:
```sql
SELECT `Name`, `Index` FROM XLSX(
? --<< this will be the URL passed into `alasql.promise`
// highlight-start
, { --<< options are supplied as the second argument to XLSX operator
autoExt: false --<< do not automatically add ".xlsx" extension!
}
// highlight-end
) WHERE `Index` < 45
```
By default the workbook is parsed and `sheet_to_json` is used to pull data:
```js
(async() => {
const blob = await (await fetch("https://sheetjs.com/pres.numbers")).blob();
const data = URL.createOjectURL(blob);
const aoo = await alasql.promise("SELECT * FROM XLSX(?, {autoExt: false}", [data]);
console.log(aoo); // [ { Name: "Bill Clinton", Index: 42 }, ...]
})();
```
### Writing Files
The `XLSX` "into" target calls `XLSX.writeFile` under the hood:
```js
const { promise: alasql } = require("alasql");
(async() => {
const data = [
{ Name: "Bill Clinton", Index: 42 },
{ Name: "Someone Else", Index: 47 }
];
await alasql(`SELECT * INTO XLSX("PresMod5.xlsx") FROM ?`, [data]);
/* PresMod5.xlsx will be created */
})();
```
## NodeJS
:::caution
@ -32,7 +209,7 @@ strategies for general data processing in AlaSQL expressions.
:::
#### Reading Files
### Reading Files
By default, the `XLSX` "from" target automatically adds a `.xlsx` extension. To
read files with an arbitrary filename, the `autoExt: false` option should be
@ -55,12 +232,12 @@ By default the workbook is parsed and `sheet_to_json` is used to pull data:
const { promise: alasql } = require("alasql");
(async() => {
const aoo = await alasql(`SELECT * from XLSX("pres.xlsb", {autoExt: false})`);
const aoo = await alasql(`SELECT * from XLSX("pres.xlsx", {autoExt: false})`);
console.log(aoo); // [ { Name: "Bill Clinton", Index: 42 }, ...]
})();
```
#### Writing Files
### Writing Files
The `XLSX` "into" target calls `XLSX.writeFile` under the hood:
@ -72,19 +249,13 @@ const { promise: alasql } = require("alasql");
{ Name: "Bill Clinton", Index: 42 },
{ Name: "Someone Else", Index: 47 }
];
await alasql(`SELECT * INTO XLSX("PresMod5.xlsb") FROM ?`, [data]);
/* PresMod5.xlsb will be created */
await alasql(`SELECT * INTO XLSX("PresMod5.xlsx") FROM ?`, [data]);
/* PresMod5.xlsx will be created */
})();
```
### NodeJS Example
:::note
This demo was tested on 2023 February 23 against AlaSQL 3.1.0
:::
1) Create an empty folder for the project:
```bash

@ -11,14 +11,17 @@ This demo assumes familiarity with Lightning Web Components. Salesforce has a
:::caution
Some of the details may differ across releases of Salesforce. This demo is based
on Lightning API version `57.0` and was last tested on 2023 April 09.
Salesforce may change the platform in backwards-incompatible ways, so the demo
may require some adjustments. The official documentation should be consulted.
:::
:::note
This demo was last tested on 2023 April 09 using Lightning API version `57.0`.
:::
## Getting Started
This demo was built on a "Developer Edition" account. At the time of writing, an

@ -160,6 +160,12 @@ function SheetJSEnregistrez() {
## Dropbox App
:::note
This demo was last tested on 2022 February 28.
:::
This demo requires a "Dropbox app":
0) Create a Dropbox app through the Developer tools. For this demo:

File diff suppressed because one or more lines are too long