salesforce sluggishness
This commit is contained in:
parent
3d661faddb
commit
d6f964ca26
@ -50,14 +50,13 @@ reading and writing many spreadsheet formats.
|
||||
`xlsx.mini.min.js` is a slimmer build that omits the following features:
|
||||
|
||||
- CSV and SYLK encodings (directly affecting users outside of the United States)
|
||||
- XLSB / XLS / Lotus 1-2-3 / SpreadsheetML 2003 / Numbers file formats
|
||||
- XLSB / XLS / Lotus 1-2-3 / SpreadsheetML 2003 / Apple Numbers file formats
|
||||
- [Stream utility functions](/docs/api/stream)
|
||||
|
||||
<details>
|
||||
<summary><b>How to integrate the mini build</b> (click to show)</summary>
|
||||
|
||||
Replace references to `xlsx.full.min.js` with `xlsx.mini.min.js`. Starting from
|
||||
scratch, a single script tag should be added at the top of the HTML page:
|
||||
A single script tag should be added at the top of the HTML page:
|
||||
|
||||
<CodeBlock language="html">{`\
|
||||
<!-- use xlsx.mini.min.js from version ${current} -->
|
||||
@ -76,7 +75,7 @@ strongly recommended. Vendoring decouples websites from SheetJS infrastructure.
|
||||
|
||||
2) Move the script to a `public` folder with other scripts.
|
||||
|
||||
3) Reference the local script from HTML pages:
|
||||
3) Reference the vendored script from HTML pages:
|
||||
|
||||
```html
|
||||
<script src="/public/xlsx.full.min.js"></script>
|
||||
@ -132,9 +131,9 @@ that do not exfiltrate data.
|
||||
|
||||
:::
|
||||
|
||||
The type checker integrated in VSCodium and VSCode do not currently provide type
|
||||
hints when using the standalone build. Using the JSDoc `@type` directive coupled
|
||||
with type imports, VSCodium will recognize the types:
|
||||
The type checker integrated in VSCodium and VSCode does not currently provide
|
||||
type hints when using the standalone build. Using the JSDoc `@type` directive
|
||||
coupled with type imports, VSCodium will recognize the types:
|
||||
|
||||
![VSCodium types](pathname:///files/standalone-types.png)
|
||||
|
||||
@ -183,7 +182,7 @@ JSDoc types using the `@import` directive are not supported in `<script>` tags.
|
||||
|
||||
## ECMAScript Module Imports
|
||||
|
||||
:::caution pass
|
||||
:::info pass
|
||||
|
||||
This section refers to imports in HTML pages using `<script type="module">`.
|
||||
|
||||
|
@ -281,7 +281,8 @@ import { utils, writeFileXLSX } from "xlsx";
|
||||
export { utils, writeFileXLSX };
|
||||
```
|
||||
|
||||
A dynamic import of the wrapper script will only load the requested features:
|
||||
Bundlers will typically optimize the script and only add the requested features.
|
||||
A dynamic import of the wrapper will load the optimized wrapper script:
|
||||
|
||||
```js
|
||||
async function export_data() {
|
||||
|
@ -33,31 +33,31 @@ SheetJS Loader to answer questions based on data from a XLS workbook.
|
||||
|
||||
This demo was tested in the following configurations:
|
||||
|
||||
| Date | Platform |
|
||||
|:-----------|:--------------------------------------------------------------|
|
||||
| 2024-08-31 | NVIDIA RTX 4090 (24 GB VRAM) + i9-10910 (128 GB RAM) |
|
||||
| 2024-08-09 | NVIDIA RTX 4080 SUPER (16 GB VRAM) + i9-10910 (128 GB RAM) |
|
||||
| 2024-09-21 | AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) |
|
||||
| 2024-07-15 | Apple M2 Max 12-Core CPU + 30-Core GPU (32 GB unified memory) |
|
||||
| Platform | Architecture | Date |
|
||||
|:--------------------------------------------------------------|:-------------|:-----------|
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + i9-10910 (128 GB RAM) | `win10-x64` | 2024-08-31 |
|
||||
| NVIDIA RTX 4080 SUPER (16 GB VRAM) + i9-10910 (128 GB RAM) | `win10-x64` | 2024-08-09 |
|
||||
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2024-09-21 |
|
||||
| AMD RX 6800 XT (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2024-10-07 |
|
||||
| Apple M2 Max 12-Core CPU + 30-Core GPU (32 GB unified memory) | `darwin-arm` | 2024-07-15 |
|
||||
|
||||
SheetJS users have verified this demo in other configurations:
|
||||
|
||||
<details>
|
||||
<summary><b>Other tested configurations</b> (click to show)</summary>
|
||||
|
||||
| Demo | Platform |
|
||||
|:------------|:-------------------------------------------------------------|
|
||||
| LangChainJS | NVIDIA RTX 4070 Ti (12 GB VRAM) + Ryzen 7 5800x (64 GB RAM) |
|
||||
| LangChainJS | NVIDIA RTX 4060 (8 GB VRAM) + Ryzen 7 5700g (32 GB RAM) |
|
||||
| LangChainJS | NVIDIA RTX 3090 (24 GB VRAM) + Ryzen 9 3900XT (128 GB RAM) |
|
||||
| LangChainJS | NVIDIA RTX 3080 (12 GB VRAM) + Ryzen 7 5800X (32 GB RAM) |
|
||||
| LangChainJS | NVIDIA RTX 3070 (8 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) |
|
||||
| LangChainJS | NVIDIA RTX 3060 (12 GB VRAM) + i5-11400 (32 GB RAM) |
|
||||
| LangChainJS | NVIDIA RTX 2080 (12 GB VRAM) + i7-9700K (16 GB RAM) |
|
||||
| LangChainJS | NVIDIA RTX 2060 (6 GB VRAM) + Ryzen 5 3600 (32 GB RAM) |
|
||||
| LangChainJS | NVIDIA GTX 1080 (8 GB VRAM) + Ryzen 7 5800x (64 GB RAM) |
|
||||
| LangChainJS | NVIDIA GTX 1070 (8 GB VRAM) + Ryzen 7 7700x (32 GB RAM) |
|
||||
| LangChainJS | AMD RX 6800 XT (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) |
|
||||
| Platform | Architecture | Demo |
|
||||
|:-------------------------------------------------------------|:-------------|:------------|
|
||||
| NVIDIA RTX 4070 Ti (12 GB VRAM) + Ryzen 7 5800x (64 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 4060 (8 GB VRAM) + Ryzen 7 5700g (32 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 3090 (24 GB VRAM) + Ryzen 9 3900XT (128 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 3080 (12 GB VRAM) + Ryzen 7 5800X (32 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 3070 (8 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | LangChainJS |
|
||||
| NVIDIA RTX 3060 (12 GB VRAM) + i5-11400 (32 GB RAM) | `win10-x64` | LangChainJS |
|
||||
| NVIDIA RTX 2080 (12 GB VRAM) + i7-9700K (16 GB RAM) | `win10-x64` | LangChainJS |
|
||||
| NVIDIA RTX 2060 (6 GB VRAM) + Ryzen 5 3600 (32 GB RAM) | `win10-x64` | LangChainJS |
|
||||
| NVIDIA GTX 1080 (8 GB VRAM) + Ryzen 7 5800x (64 GB RAM) | `win10-x64` | LangChainJS |
|
||||
| NVIDIA GTX 1070 (8 GB VRAM) + Ryzen 7 7700x (32 GB RAM) | `win11-x64` | LangChainJS |
|
||||
|
||||
</details>
|
||||
|
||||
@ -66,11 +66,10 @@ Special thanks to:
|
||||
- [Rasmus Tengstedt](https://tengstedt.dev/)
|
||||
- [Triston Armstrong](https://tristonarmstrong.com/)
|
||||
- [Ben Halverson](https://benhalverson.dev/)
|
||||
- [Navid Nami](https://github.com/CaseoJKL)
|
||||
- [Navid Nami](https://navidnami.com/)
|
||||
- [Benjamin Gregg](https://bgregg.dev/)
|
||||
- [`@Smor`](https://smor.dev/)
|
||||
- [`@timbr`](https://timbr.dev/)
|
||||
- [`@n3bs`](https://github.com/0xn3bs)
|
||||
- [Andreas Karydopoulos](https://smor.dev/)
|
||||
- [Tim Brugman](https://timbrugman.com/)
|
||||
|
||||
:::
|
||||
|
||||
|
@ -641,5 +641,5 @@ embedded in the final site and the data is parsed when the page is loaded.
|
||||
[^6]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^7]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^8]: See [the "base64" type in "Reading Files"](/docs/api/parse-options#input-type)
|
||||
[^9]: See [`examples/sheetjs-vite`](https://git.sheetjs.com/examples/sheetjs-vite/) on the SheetJS git server.
|
||||
[^9]: See [`examples/sheetjs-vite`](https://git.sheetjs.com/examples/sheetjs-vite/) on the SheetJS Git server.
|
||||
[^10]: See ["Server-Side Rendering"](https://vitejs.dev/guide/ssr.html) in the ViteJS documentation.
|
@ -94,7 +94,7 @@ NextJS use legacy versions of ReactJS that do not support function components
|
||||
and other idioms.
|
||||
|
||||
[`examples/reactjs-legacy`](https://git.sheetjs.com/examples/reactjs-legacy) on
|
||||
the SheetJS git server includes code samples for legacy NextJS versions.
|
||||
the SheetJS Git server includes code samples for legacy NextJS versions.
|
||||
|
||||
:::
|
||||
|
||||
|
@ -200,7 +200,7 @@ When prompted:
|
||||
- "Package name": (press <kbd>Enter</kbd>, it will use the default `sheetjsquasar`)
|
||||
- "Project product name": `SheetJSQuasar`
|
||||
- "Project description": `SheetJS + Quasar`
|
||||
- "Author": (press <kbd>Enter</kbd>, it will use your git config settings)
|
||||
- "Author": (press <kbd>Enter</kbd>, it will use your Git config settings)
|
||||
- "Pick a Vue component style": `Composition API`
|
||||
- "Pick your CSS preprocessor": `None`
|
||||
- "Check the features needed for your project": Deselect everything (scroll down to each selected item and press <kbd>Space</kbd>)
|
||||
|
@ -29,14 +29,14 @@ may require some adjustments. The official documentation should be consulted.
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2024 May 05 using Lightning API version `59.0`.
|
||||
This demo was last tested on 2024 October 06 using Lightning API version `61.0`.
|
||||
|
||||
:::
|
||||
|
||||
:::danger Telemetry
|
||||
|
||||
The Salesforce developer tools embed telemetry. It can be disabled by setting
|
||||
the environment variable `SF_DISABLE_TELEMETRY` to `true` or by running
|
||||
the environment variable `SF_DISABLE_TELEMETRY` to `true` or running a command:
|
||||
|
||||
```bash
|
||||
npx @salesforce/cli config set disable-telemetry=true --global
|
||||
@ -59,6 +59,38 @@ Due to Salesforce name restrictions, the script must be renamed to `sheetjs.js`.
|
||||
|
||||
:::
|
||||
|
||||
:::caution Lightning Web Security Performance Degradation
|
||||
|
||||
There are known performance regressions with the new Lightning Web Security.
|
||||
SheetJS users have reported that sub-second exports using the older Lightning
|
||||
Locker Service will take over 20 seconds using the new system.
|
||||
|
||||
**This is a bug in Salesforce Lightning Web Security!**
|
||||
|
||||
Until Salesforce fixes the bug, it is strongly recommended to disable the broken
|
||||
"Lightning Web Security" and use the battle-tested "Lightning Locker Service":
|
||||
|
||||
0) Switch to the Salesforce Classic view.
|
||||
|
||||
If a profile icon appears in the top-right corner of the Salesforce page, click
|
||||
on the icon and select "Switch to Salesforce Classic" in the popover menu:
|
||||
|
||||
![Switch to Salesforce Classic](pathname:///salesforce/l2c.png)
|
||||
|
||||
1) Click the "Setup" link in the right side of the top bar.
|
||||
|
||||
2) In the "Quick Find" box, type "Session" and select "Session Settings".
|
||||
|
||||
3) Scroll down to "Lightning Web Security" and uncheck the box next to
|
||||
|
||||
> Use Lightning Web Security for Lightning web components and Aura components
|
||||
|
||||
![Disable Lightning Web Security](pathname:///salesforce/lws.png)
|
||||
|
||||
4) Scroll down to the bottom of the page and click "Save".
|
||||
|
||||
:::
|
||||
|
||||
### Loading SheetJS
|
||||
|
||||
Assuming the script was renamed to `sheetjs.js`, the name of the resource will
|
||||
@ -68,7 +100,7 @@ library. The script will define the variable `XLSX`[^2]
|
||||
It is recommended to load the library in a callback. For example, the following
|
||||
`@api` method loads the library and exports sample data to a spreadsheet file:
|
||||
|
||||
```js
|
||||
```js title="Sample LWC component to export a sample dataset"
|
||||
import { LightningElement, api } from 'lwc';
|
||||
import { loadScript } from 'lightning/platformResourceLoader';
|
||||
// highlight-next-line
|
||||
@ -76,20 +108,21 @@ import sheetjs from '@salesforce/resourceUrl/sheetjs';
|
||||
|
||||
export default class SheetComponent extends LightningElement {
|
||||
@api async download() {
|
||||
// highlight-next-line
|
||||
await loadScript(this, sheetjs); // load the library
|
||||
// At this point, the library is accessible with the `XLSX` variable
|
||||
|
||||
// Create worksheet
|
||||
/* Create worksheet */
|
||||
var ws = XLSX.utils.aoa_to_sheet([
|
||||
[ "S", "h", "e", "e", "t", "J"," S" ],
|
||||
[ 5 , 4 , 3 , 3 , 7 , 9 , 5 ]
|
||||
]);
|
||||
|
||||
// Create workbook and add worksheet
|
||||
/* Create workbook and add worksheet */
|
||||
var wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "Data");
|
||||
|
||||
// Export Data
|
||||
/* Export data and attempt to download a XLSX workbook */
|
||||
XLSX.writeFile(wb, "SheetForceExport.xlsx");
|
||||
}
|
||||
}
|
||||
@ -109,7 +142,7 @@ name of the LWC list view (`listViewApiName` property)
|
||||
|
||||
The following snippet receives data from the "All Accounts" list view:
|
||||
|
||||
```js
|
||||
```js title="Pulling Account data using the LWC Wire Service (sketch)"
|
||||
import { LightningElement, wire } from 'lwc';
|
||||
import { getListUi } from 'lightning/uiListApi';
|
||||
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
|
||||
@ -131,18 +164,29 @@ export default class SheetComponent extends LightningElement {
|
||||
|
||||
#### Array of Arrays
|
||||
|
||||
SheetJS most reliably translates "arrays of arrays", a nested array which
|
||||
directly maps to individual cell addresses. For example:
|
||||
SheetJS most reliably translates "arrays of arrays"[^5], a nested array which
|
||||
directly maps to individual cell addresses.
|
||||
|
||||
```js
|
||||
var data = [
|
||||
["Name", "Phone"], // row 1
|
||||
["Foo Bar", "(555) 555-5555"], // row 2
|
||||
["Baz Qux", "(555) 555-5556"] // row 3
|
||||
For example, using the Accounts list, each row represents one account. Each
|
||||
column represents the account name, phone number, or another field.
|
||||
|
||||
```js title="Sample Array of Arrays based on Account info"
|
||||
var aoa = [
|
||||
["Name", "Phone"], // row 1 -- column titles
|
||||
["Mike Jones", "(281) 330-8004"], // row 2 -- first data row
|
||||
["Jenny Sheets", "(201) 867-5309"] // row 3 -- second data row
|
||||
];
|
||||
```
|
||||
|
||||
The APIs typically return nested objects, so the array must be constructed.
|
||||
The APIs typically return nested objects, so the array of arrays must be
|
||||
manually constructed by iterating over the data.
|
||||
|
||||
:::tip pass
|
||||
|
||||
The ["Export Tutorial"](/docs/getting-started/examples/export) covers JavaScript
|
||||
array methods and transformation in more detail.
|
||||
|
||||
:::
|
||||
|
||||
<details>
|
||||
<summary><b>Salesforce Representation</b> (click to show)</summary>
|
||||
@ -150,7 +194,7 @@ The APIs typically return nested objects, so the array must be constructed.
|
||||
The `data` parameter in the callback has a deep structure. Typically one would
|
||||
set a property in the component and display data in a template:
|
||||
|
||||
```js
|
||||
```js title="Storing records in LWC Component state (sketch)"
|
||||
// ...
|
||||
// declare records variable in the component
|
||||
records;
|
||||
@ -169,7 +213,7 @@ set a property in the component and display data in a template:
|
||||
|
||||
The template itself would iterate across the records:
|
||||
|
||||
```html
|
||||
```html title="Generating HTML Tables in a LWC Template"
|
||||
<template>
|
||||
<template if:true={records}>
|
||||
<table>
|
||||
@ -189,8 +233,8 @@ The template itself would iterate across the records:
|
||||
|
||||
A suitable SheetJS array of arrays can be constructed by mapping across records:
|
||||
|
||||
```js
|
||||
var headers = [ "Name", "Phone" ];
|
||||
```js title="Constructing an array of arrays from Salesforce data (snippet)"
|
||||
var headers = [ "Name", "Phone" ]; // First row of the spreadsheet
|
||||
var aoa = [headers].concat(data.records.records.map(record => [
|
||||
record.fields.Name.value, // Name field
|
||||
record.fields.Phone.value, // Phone field
|
||||
@ -228,11 +272,11 @@ export default class SheetComponent extends LightningElement {
|
||||
|
||||
#### Exporting Data
|
||||
|
||||
This is readily exported to a spreadsheet in a callback function. Starting from
|
||||
the array of arrays, the SheetJS `aoa_to_sheet` method[^5] generates a SheetJS
|
||||
sheet object[^6]. A workbook object[^7] is created with `book_new`[^8] and the
|
||||
sheet is added with `book_append_sheet`[^9]. Finally, the SheetJS `writeFile`
|
||||
method creates a XLSX file and initiates a download[^10].
|
||||
Data is readily exported to a spreadsheet in a callback function. Starting from
|
||||
the array of arrays, the SheetJS `aoa_to_sheet` method[^6] generates a SheetJS
|
||||
sheet object[^7]. A workbook object[^8] is created with `book_new`[^9] and the
|
||||
sheet is added with `book_append_sheet`[^10]. Finally, the SheetJS `writeFile`
|
||||
method creates a XLSX file and initiates a download[^11].
|
||||
|
||||
```js
|
||||
@api async download() {
|
||||
@ -283,7 +327,7 @@ npx @salesforce/cli --version
|
||||
When the demo was last tested, the command printed
|
||||
|
||||
```
|
||||
@salesforce/cli/2.39.6 darwin-x64 node-v22.0.0
|
||||
@salesforce/cli/2.60.13 darwin-arm64 node-v20.18.0
|
||||
```
|
||||
|
||||
:::
|
||||
@ -332,7 +376,7 @@ with the following XML:
|
||||
```xml title="force-app\main\default\lwc\sheetComponent\sheetComponent.js-meta.xml (replace highlighted lines)"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>59.0</apiVersion>
|
||||
<apiVersion>61.0</apiVersion>
|
||||
<!-- highlight-start -->
|
||||
<isExposed>true</isExposed>
|
||||
<masterLabel>SheetForce</masterLabel>
|
||||
@ -515,12 +559,14 @@ mv xlsx.full.min.js force-app/main/default/staticresources/sheetjs.js
|
||||
</StaticResource>
|
||||
```
|
||||
|
||||
18) Deploy the project again. Replace `SF@USER.NAME` with the unique Username:
|
||||
18) Deploy the project again with the same command from step 9:
|
||||
|
||||
```bash
|
||||
npx @salesforce/cli project deploy start -d force-app -o SF@USER.NAME
|
||||
```
|
||||
|
||||
Replace `SF@USER.NAME` with the unique Username.
|
||||
|
||||
19) Look for the static resource:
|
||||
|
||||
<Tabs groupId="sfview">
|
||||
@ -580,7 +626,7 @@ This component exposes a `version` property based on the SheetJS version.
|
||||
21) Replace `force-app/main/default/lwc/sheetComponent/sheetComponent.html` with
|
||||
the following template:
|
||||
|
||||
```html title="force-app/main/default/lwc/sheetComponent/sheetComponent.html"
|
||||
```html title="force-app/main/default/lwc/sheetComponent/sheetComponent.html (replace line)"
|
||||
<template>
|
||||
<!-- highlight-next-line -->
|
||||
<b>SheetForce {version}</b>
|
||||
@ -589,12 +635,14 @@ the following template:
|
||||
|
||||
This template references the `version` property.
|
||||
|
||||
22) Deploy the project again. Replace `SF@USER.NAME` with the unique Username:
|
||||
22) Deploy the project again with the same command from step 9:
|
||||
|
||||
```bash
|
||||
npx @salesforce/cli project deploy start -d force-app -o SF@USER.NAME
|
||||
```
|
||||
|
||||
Replace `SF@USER.NAME` with the unique Username.
|
||||
|
||||
23) Reload the "SheetJS Demo" page. The page should display the SheetJS version:
|
||||
|
||||
![Version number](pathname:///salesforce/version.png)
|
||||
@ -610,7 +658,7 @@ original "SheetForce demo" text after refreshing, close and reopen the demo app.
|
||||
|
||||
24) Add a button to `sheetComponent.html` that will call a `download` callback:
|
||||
|
||||
```html title="force-app/main/default/lwc/sheetComponent/sheetComponent.html"
|
||||
```html title="force-app/main/default/lwc/sheetComponent/sheetComponent.html (replace page)"
|
||||
<template>
|
||||
<!-- if the `aoa` property is set, show a button -->
|
||||
<template if:true={aoa}>
|
||||
@ -623,7 +671,7 @@ original "SheetForce demo" text after refreshing, close and reopen the demo app.
|
||||
|
||||
25) Replace `sheetComponent.js` with the following:
|
||||
|
||||
```js title="force-app/main/default/lwc/sheetComponent/sheetComponent.js"
|
||||
```js title="force-app/main/default/lwc/sheetComponent/sheetComponent.js (replace script)"
|
||||
import { LightningElement, wire, api } from 'lwc';
|
||||
import { loadScript } from 'lightning/platformResourceLoader';
|
||||
import { getListUi } from 'lightning/uiListApi';
|
||||
@ -658,12 +706,14 @@ export default class SheetComponent extends LightningElement {
|
||||
}
|
||||
```
|
||||
|
||||
26) Deploy the project again. Replace `SF@USER.NAME` with the unique Username:
|
||||
26) Deploy the project again with the same command from step 9:
|
||||
|
||||
```bash
|
||||
npx @salesforce/cli project deploy start -d force-app -o SF@USER.NAME
|
||||
```
|
||||
|
||||
Replace `SF@USER.NAME` with the unique Username.
|
||||
|
||||
27) Reload the "SheetJS Demo" page. The page should include a button for export:
|
||||
|
||||
![SF Export Button](pathname:///salesforce/export.png)
|
||||
@ -685,9 +735,10 @@ cell styling, automatic column width calculations, and frozen rows.
|
||||
[^2]: The `XLSX` variable is the main global for the SheetJS library. It exposes methods as described in ["API Reference"](/docs/api/)
|
||||
[^3]: See ["Understand the Wire Service"](https://developer.salesforce.com/docs/platform/lwc/guide/data-wire-service-about.html) in the Salesforce LWC documentation.
|
||||
[^4]: See [`getListUI`](https://developer.salesforce.com/docs/platform/lwc/guide/reference-get-list-ui.html) in the Salesforce LWC documentation.
|
||||
[^5]: See [`aoa_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-arrays-input)
|
||||
[^6]: See ["Sheet Objects"](/docs/csf/sheet)
|
||||
[^7]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^8]: See [`book_new` in "Utilities"](/docs/api/utilities/wb)
|
||||
[^9]: See [`book_append_sheet` in "Utilities"](/docs/api/utilities/wb)
|
||||
[^10]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^5]: See ["Array of Arrays" in "Utilities"](/docs/api/utilities/array#array-of-arrays) for more details.
|
||||
[^6]: See [`aoa_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-arrays-input)
|
||||
[^7]: See ["Sheet Objects"](/docs/csf/sheet)
|
||||
[^8]: See ["Workbook Object"](/docs/csf/book)
|
||||
[^9]: See [`book_new` in "Utilities"](/docs/api/utilities/wb)
|
||||
[^10]: See [`book_append_sheet` in "Utilities"](/docs/api/utilities/wb)
|
||||
[^11]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
@ -32,10 +32,11 @@ flowchart LR
|
||||
data[[Stata\nVariables]]
|
||||
ofile --> |Stata Extension\nSheetJS + Duktape| nfile
|
||||
nfile --> |Stata command\nimport excel|data
|
||||
linkStyle 0 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
The demo will read [a Numbers workbook](https://docs.sheetjs.com/pres.numbers) and
|
||||
generate variables for each column. A sample Stata session is shown below:
|
||||
The demo will read [a NUMBERS workbook](https://docs.sheetjs.com/pres.numbers)
|
||||
and generate variables for each column. A sample Stata session is shown below:
|
||||
|
||||
![Stata commands](pathname:///stata/commands.png)
|
||||
|
||||
@ -71,25 +72,6 @@ Stata can understand.
|
||||
|
||||
## Integration Details
|
||||
|
||||
The current recommendation involves a native plugin that reads arbitrary files
|
||||
and generates clean XLSX files that Stata can import.
|
||||
|
||||
The extension function ultimately pairs the SheetJS `read`[^2] and `write`[^3]
|
||||
methods to read data from the old file and write a new file:
|
||||
|
||||
```js
|
||||
var wb = XLSX.read(original_file_data, {type: "buffer"});
|
||||
var new_file_data = XLSX.write(wb, {type: "array", bookType: "xlsx"});
|
||||
```
|
||||
|
||||
The extension function `cleanfile` will take one or two arguments:
|
||||
|
||||
`plugin call cleanfile, "pres.numbers"` will generate `sheetjs.tmp.xlsx` from
|
||||
the first argument (`"pres.numbers"`) and print instructions to load the file.
|
||||
|
||||
`plugin call cleanfile, "pres.numbers" verbose` will additionally print CSV
|
||||
contents of each worksheet in the workbook.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
ofile{{File\nName}}
|
||||
@ -107,8 +89,34 @@ flowchart LR
|
||||
wb --> |SheetJS\n`write`| njbuf
|
||||
njbuf --> |Duktape\nBuffer Ops| nbuf
|
||||
nbuf --> |C\nWrite File| nfile
|
||||
linkStyle 2,3 color:blue,stroke:blue;
|
||||
```
|
||||
|
||||
The current recommendation involves a native plugin that reads arbitrary files
|
||||
and generates clean XLSX files that Stata can import.
|
||||
|
||||
The extension function ultimately pairs the SheetJS `read`[^2] and `write`[^3]
|
||||
methods to read data from the old file and write a new file:
|
||||
|
||||
```js title="Code executed by Duktape within the Stata extension (snippet)"
|
||||
/* `original_file_data` is a sideloaded Duktape `Buffer` */
|
||||
|
||||
// highlight-start
|
||||
var wb = XLSX.read(original_file_data, {type: "buffer"});
|
||||
var new_file_data = XLSX.write(wb, {type: "array", bookType: "xlsx"});
|
||||
// highlight-end
|
||||
|
||||
/* `new_file_data` will be pulled into the extension and saved */
|
||||
```
|
||||
|
||||
The extension function `cleanfile` will take one or two arguments:
|
||||
|
||||
`plugin call cleanfile, "pres.numbers"` will generate `sheetjs.tmp.xlsx` from
|
||||
the first argument (`"pres.numbers"`) and print instructions to load the file.
|
||||
|
||||
`plugin call cleanfile, "pres.numbers" verbose` will additionally print CSV
|
||||
contents of each worksheet in the workbook.
|
||||
|
||||
### C Extensions
|
||||
|
||||
Stata C extensions are shared libraries or DLLs that use special Stata methods
|
||||
@ -125,7 +133,7 @@ STDLL stata_call(int argc, char *argv[]);
|
||||
|
||||
For example, `argc` is 2 and `argv` has two C strings in the following command:
|
||||
|
||||
```stata
|
||||
```stata title="Sample plugin invocation with arguments"
|
||||
plugin call cleanfile, "pres.numbers" verbose
|
||||
* arguments start
|
||||
* argv[0] ^^^^^^^^^^^^
|
||||
@ -470,7 +478,7 @@ The `codebook` command will display details.
|
||||
<details>
|
||||
<summary><b>Expected Output</b> (click to show)</summary>
|
||||
|
||||
```
|
||||
```text title="Expected output for 80-column terminal windows"
|
||||
-------------------------------------------------------------------------------
|
||||
Name Name
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -20,7 +20,7 @@ applied to text fragments within the cell content. This mirrors HTML semantics.
|
||||
| XLS (BIFF8) | ✔ | ✔ | Cell Link |
|
||||
| XLML | ✔ | ✔ | Cell Link |
|
||||
| ODS / FODS / UOS | ✔ | | Span Link |
|
||||
| HTML | ✔ | ✕ | Span Link |
|
||||
| HTML | ✔ | | Span Link |
|
||||
| NUMBERS | ✔ | ✕ | Span Link |
|
||||
|
||||
X (✕) marks features that are not supported by the file formats. For example,
|
||||
|
@ -284,6 +284,29 @@ The common algorithm produces unexpected results for "Up to one digit":
|
||||
|
||||
:::
|
||||
|
||||
:::caution Quattro Pro Inconsistencies
|
||||
|
||||
The default fractional formats use powers of 10 for the maximum denominator.
|
||||
10 is a valid denominator for Quattro Pro "Denominators <= 10" but is not
|
||||
valid for Excel "Up to one digit" format or SheetJS `?/?` number format.
|
||||
|
||||
Quattro Pro supports arbitrary denominator limits through custom number formats.
|
||||
The equivalent Quattro Pro number formats for SheetJS formats are listed below:
|
||||
|
||||
| SheetJS Format | Excel Description | Quattro Pro Format |
|
||||
|:---------------|:---------------------|:-------------------|
|
||||
| `?/?` | "Up to one digit" | `?//M9` |
|
||||
| `??/??` | "Up to two digits" | `?//M99` |
|
||||
| `???/???` | "Up to three digits" | `?//M999` |
|
||||
| `????/????` | (custom format) | `?//M9999` |
|
||||
| `?????/?????` | (custom format) | (unsupported) |
|
||||
|
||||
The Quattro Pro formats are specified through the `?//M` "numeric code".
|
||||
|
||||
**Quattro Pro does not support fractions with denominator > 64000 !**
|
||||
|
||||
:::
|
||||
|
||||
## Miscellany
|
||||
|
||||
The default formats are listed in ECMA-376 18.8.30:
|
||||
|
@ -78,8 +78,8 @@ Spreadsheet applications commonly display file properties in separate windows:
|
||||
|
||||
:::note pass
|
||||
|
||||
When this demo was last tested, Apple Numbers (14.2, build 7041.0.109) did not
|
||||
support file properties in the XLSX import and export codecs.
|
||||
When this demo was last tested, Apple Numbers 14.2 did not support file
|
||||
properties in the XLSX import and export codecs.
|
||||
|
||||
:::
|
||||
|
||||
|
@ -8,7 +8,7 @@ SheetJS supports reading and writing a number of spreadsheet file formats.
|
||||
|
||||
| Format | Read | Write |
|
||||
|:-------------------------------------------------------------|:-----:|:-----:|
|
||||
| **Excel Worksheet/Workbook Formats** |:-----:|:-----:|
|
||||
| **Excel Worksheet/Workbook Formats** | | |
|
||||
| Excel 2007+ XML Formats (XLSX/XLSM) | ✔ | ✔ |
|
||||
| Excel 2007+ Binary Format (XLSB BIFF12) | ✔ | ✔ |
|
||||
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | ✔ | ✔ |
|
||||
@ -17,13 +17,13 @@ SheetJS supports reading and writing a number of spreadsheet file formats.
|
||||
| Excel 4.0 (XLS/XLW BIFF4) | ✔ | ✔ |
|
||||
| Excel 3.0 (XLS BIFF3) | ✔ | ✔ |
|
||||
| Excel 2.0/2.1 / Multiplan 4.x DOS (XLS BIFF2) | ✔ | ✔ |
|
||||
| **Excel Supported Text Formats** |:-----:|:-----:|
|
||||
| **Excel Supported Text Formats** | | |
|
||||
| Delimiter-Separated Values (CSV/TXT) | ✔ | ✔ |
|
||||
| Data Interchange Format (DIF) | ✔ | ✔ |
|
||||
| Symbolic Link (SYLK/SLK) | ✔ | ✔ |
|
||||
| Lotus Formatted Text (PRN) | ✔ | ✔ |
|
||||
| UTF-16 Unicode Text (TXT) | ✔ | ✔ |
|
||||
| **Other Workbook/Worksheet Formats** |:-----:|:-----:|
|
||||
| **Other Workbook/Worksheet Formats** | | |
|
||||
| Numbers 3.0+ / iWork 2013+ Spreadsheet (NUMBERS) | ✔ | ✔ |
|
||||
| WPS 电子表格 (ET) | ✔ | |
|
||||
| OpenDocument Spreadsheet (ODS) | ✔ | ✔ |
|
||||
@ -35,7 +35,7 @@ SheetJS supports reading and writing a number of spreadsheet file formats.
|
||||
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | ✔ | |
|
||||
| Works 1.x-3.x DOS / 2.x-5.x Windows Spreadsheet (WKS) | ✔ | |
|
||||
| Works 6.x-9.x Spreadsheet (XLR) | ✔ | |
|
||||
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
|
||||
| **Other Common Spreadsheet Output Formats** | | |
|
||||
| HTML Tables | ✔ | ✔ |
|
||||
| Rich Text Format tables (RTF) | ✔ | ✔ |
|
||||
| Ethercalc Record Format (ETH) | ✔ | ✔ |
|
||||
@ -46,6 +46,17 @@ SheetJS supports reading and writing a number of spreadsheet file formats.
|
||||
|
||||
Features not supported by a given file format will not be written.
|
||||
|
||||
## Supporting Libraries
|
||||
|
||||
Related libraries support other structured data formats:
|
||||
|
||||
| Format | Read | Write |
|
||||
|:-------------------------------------------------------------|:-----:|:-----:|
|
||||
| [Stata dataset (DTA)](/docs/constellation/dta) | ✔ | |
|
||||
|
||||
As these formats are not supported in traditional spreadsheet software, they are
|
||||
not integrated in SheetJS CE directly.
|
||||
|
||||
## Worksheet Range Limits
|
||||
|
||||
Formats with range limits will be silently truncated. For example, the Lotus WKS
|
||||
@ -55,7 +66,7 @@ format has a limit of 2048 rows, so data after the 2048th row will not be saved.
|
||||
|:------------------------------------------|:-----------|---------:|---------:|
|
||||
| Excel 2007+ XML Formats (XLSX/XLSM) |`XFD1048576`| 16384 | 1048576 |
|
||||
| Excel 2007+ Binary Format (XLSB BIFF12) |`XFD1048576`| 16384 | 1048576 |
|
||||
| Numbers 13.1 (NUMBERS) |`ALL1000000`| 1000 | 1000000 |
|
||||
| Numbers 14.2 (NUMBERS) |`ALL1000000`| 1000 | 1000000 |
|
||||
| Quattro Pro 9+ (QPW) |`IV1000000 `| 256 | 1000000 |
|
||||
| Excel 97-2004 (XLS BIFF8) |`IV65536 `| 256 | 65536 |
|
||||
| Excel 5.0/95 (XLS BIFF5) |`IV16384 `| 256 | 16384 |
|
||||
@ -191,7 +202,7 @@ XLR also includes a `WksSSWorkBook` stream similar to Lotus FM3/FMT files.
|
||||
|
||||
iWork 2013 (Numbers 3.0 / Pages 5.0 / Keynote 6.0) switched from a proprietary
|
||||
XML-based format to the current file format based on the iWork Archive (IWA).
|
||||
This format has been used up through the current release (Numbers 13.1) as well
|
||||
This format has been used up through the current release (Numbers 14.2) as well
|
||||
as the iCloud.com web interface to Numbers.
|
||||
|
||||
The parser focuses on extracting raw data from tables. Numbers technically
|
||||
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
title: SSF Number Formatter
|
||||
hide_table_of_contents: true
|
||||
pagination_next: constellation/frac/index
|
||||
---
|
||||
|
||||
<head>
|
||||
@ -21,7 +22,7 @@ and `sheet_to_json`[^4].
|
||||
|
||||
The library is also available for standalone use on the SheetJS CDN[^5].
|
||||
|
||||
Source code and project documentation are hosted on the SheetJS git server at
|
||||
Source code and project documentation are hosted on the SheetJS Git server at
|
||||
https://git.sheetjs.com/sheetjs/sheetjs/src/branch/master/packages/ssf
|
||||
|
||||
## Live Demo
|
||||
|
4
docz/docs/12-constellation/02-frac/_category_.json
Normal file
4
docz/docs/12-constellation/02-frac/_category_.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Rational Approximation",
|
||||
"position": 2
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Rational Approximation
|
||||
hide_table_of_contents: true
|
||||
pagination_prev: constellation/ssf
|
||||
pagination_next: constellation/crc32
|
||||
---
|
||||
|
||||
<head>
|
||||
@ -13,23 +14,24 @@ powering "Fraction with up to 1 digit" and related number formats.
|
||||
|
||||
The library is also available for standalone use on the SheetJS CDN[^1].
|
||||
|
||||
Source code and project documentation are hosted on the SheetJS git server at
|
||||
Source code and project documentation are hosted on the SheetJS Git server at
|
||||
https://git.sheetjs.com/sheetjs/frac
|
||||
|
||||
## Live Demo
|
||||
|
||||
The formatted text is calculated from the specified number format and value.
|
||||
Formatted texts are calculated from the value and maximum denominators.
|
||||
|
||||
Please [report an issue](https://git.sheetjs.com/sheetjs/frac/issues) if a
|
||||
particular format is not supported.
|
||||
particular result does not align with expectations.
|
||||
|
||||
```jsx live
|
||||
function SheetJSFrac() {
|
||||
const [val, setVal] = React.useState(0.6994);
|
||||
const [val, setVal] = React.useState(0.699450515);
|
||||
const [text, setText] = React.useState("");
|
||||
|
||||
if(typeof frac == "undefined") return ( <b>ERROR: Reload this page</b> );
|
||||
|
||||
const fmt = arr => `${(""+arr[1]).padStart(3)} / ${(""+arr[2]).padEnd(3)}`;
|
||||
const fmt = arr => `${(""+arr[1]).padStart(5)} / ${(""+arr[2]).padEnd(5)}`;
|
||||
React.useEffect(() => {
|
||||
if(typeof frac == "undefined") return setText("ERROR: Reload this page!");
|
||||
let v = +val;
|
||||
@ -38,26 +40,22 @@ function SheetJSFrac() {
|
||||
fmt(frac(val, 9)); setText("");
|
||||
} catch(e) { setText("ERROR: " + (e && e.message || e)); }
|
||||
}, [val]);
|
||||
|
||||
const n = { textAlign:"right" };
|
||||
const g = { backgroundColor:"#C6EFCE", color:"#006100", whiteSpace:"pre-wrap" };
|
||||
const b = { backgroundColor:"#FFC7CE", color:"#9C0006" };
|
||||
|
||||
return ( <table>
|
||||
<tr><td><b>Number Value</b></td><td colspan="2">
|
||||
<tr><td><b>Number Value</b></td><td colspan="4">
|
||||
<input type="text" value={val} onChange={e => setVal(e.target.value)}/>
|
||||
</td></tr>
|
||||
<tr><td></td><th>Mediant</th><th>Cont</th></tr>
|
||||
<tr><td><b>Up to 1 Digit</b></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac(val,9))}</code></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac.cont(val,9))}</code></td>
|
||||
</tr>
|
||||
<tr><td><b>Up to 2 Digits</b></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac(val,99))}</code></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac.cont(val,99))}</code></td>
|
||||
</tr>
|
||||
<tr><td><b>Up to 3 Digits</b></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac(val,999))}</code></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac.cont(val,999))}</code></td>
|
||||
</tr>
|
||||
<tr><td></td><th>Max Denom</th><th>Mediant</th><th>Continued Frac</th></tr>
|
||||
{[1,2,3,4,5].map(d => ( <tr>
|
||||
<td><b>Up to {d} Digit{d == 1 ? "" : "s"}</b></td>
|
||||
<td style={n}><code>{10**d - 1}</code></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac(val,10**d-1))}</code></td>
|
||||
<td><code style={text?b:g}>{text||fmt(frac.cont(val,10**d-1))}</code></td>
|
||||
</tr> ))}
|
||||
</table> );
|
||||
}
|
||||
```
|
||||
@ -73,12 +71,25 @@ The "Mediant" algorithm (`frac` in the browser; the default export in NodeJS)
|
||||
calculates the exact solution.
|
||||
|
||||
The "Continued Fractions" algorithm (`frac.cont` in the browser; the `cont`
|
||||
field in the NodeJS export) calculates an approximate solution. Excel uses this
|
||||
approach since the mediant algorithm has exponential worst-case performance.
|
||||
field in the NodeJS export) calculates an approximate solution but has better
|
||||
worst-case runtime performance.
|
||||
|
||||
:::caution LibreOffice bugs
|
||||
Spreadsheet software use these algorithms to render number formats including
|
||||
`?/?` and `??/??`. The algorithm choices are summarized in the following table:
|
||||
|
||||
There are known rounding bugs in LibreOffice[^2] which result in inaccurate
|
||||
| Spreadsheet Software | Algorithm |
|
||||
|:-----------------------------------|:--------------------|
|
||||
| [SheetJS](/docs/constellation/ssf) | Continued Fractions |
|
||||
| Apple Numbers | Mediant Algorithm |
|
||||
| Google Sheets | Mediant Algorithm |
|
||||
| Lotus 1-2-3 | (unsupported) |
|
||||
| Microsoft Excel | Continued Fractions |
|
||||
| Quattro Pro | Continued Fractions |
|
||||
| WPS 电子表格 | Mediant Algorithm |
|
||||
|
||||
:::danger LibreOffice bugs
|
||||
|
||||
There are known rounding errors in LibreOffice[^2] which result in inaccurate
|
||||
fraction calculations.
|
||||
|
||||
The LibreOffice developers believe these numerical errors are desirable:
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
title: CRC32 Checksum
|
||||
hide_table_of_contents: true
|
||||
pagination_prev: constellation/frac/index
|
||||
---
|
||||
|
||||
<head>
|
||||
@ -13,7 +14,7 @@ ODS, NUMBERS, and other formats.
|
||||
|
||||
The library is also available for standalone use on the SheetJS CDN[^1].
|
||||
|
||||
Source code and project documentation are hosted on the SheetJS git server at
|
||||
Source code and project documentation are hosted on the SheetJS Git server at
|
||||
https://git.sheetjs.com/sheetjs/js-crc32
|
||||
|
||||
#### Live Demos
|
||||
|
@ -31,5 +31,5 @@ bunx -p xlsx@https://cdn.sheetjs.com/xlsx-cli/xlsx-cli-1.1.4.tgz --help
|
||||
|
||||
## Source Code
|
||||
|
||||
Source code and project documentation are hosted on the SheetJS git server at
|
||||
Source code and project documentation are hosted on the SheetJS Git server at
|
||||
https://git.sheetjs.com/sheetjs/sheetjs/src/branch/master/packages/xlsx-cli
|
||||
|
@ -22,7 +22,7 @@ analysis. Many legacy datasets are only available in Stata DTA data files.
|
||||
The SheetJS DTA codec enables websites and automated data pipelines to integrate
|
||||
data from DTA files.
|
||||
|
||||
Source code and project documentation are hosted on the SheetJS git server at
|
||||
Source code and project documentation are hosted on the SheetJS Git server at
|
||||
https://git.sheetjs.com/sheetjs/sheetjs/src/branch/master/packages/dta
|
||||
|
||||
:::caution DTA support is considered experimental.
|
||||
|
@ -272,7 +272,7 @@ This demo processes https://docs.sheetjs.com/pres.numbers
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function Numbers2HTML(props) {
|
||||
function NUMBERS2HTML(props) {
|
||||
const [__html, setHTML] = React.useState("");
|
||||
|
||||
/* Fetch and update HTML */
|
||||
|
BIN
docz/static/salesforce/l2c.png
Normal file
BIN
docz/static/salesforce/l2c.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
docz/static/salesforce/lws.png
Normal file
BIN
docz/static/salesforce/lws.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 23 KiB |
Loading…
Reference in New Issue
Block a user