forked from sheetjs/docs.sheetjs.com
dndemo
This commit is contained in:
parent
af187640fa
commit
4f548c4646
@ -7,15 +7,23 @@ sidebar_custom_props:
|
||||
summary: JS + Web View
|
||||
---
|
||||
|
||||
## CapacitorJS
|
||||
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
|
||||
from the main entrypoint or any script in the project.
|
||||
|
||||
:::note
|
||||
The "Complete Example" creates an app that looks like the screenshots below:
|
||||
|
||||
This demo was tested on an Intel Mac on 2022 August 26 with Svelte.
|
||||
<table><thead><tr>
|
||||
<th><a href="#demo">iOS</a></th>
|
||||
<th><a href="#demo">Android</a></th>
|
||||
</tr></thead><tbody><tr><td>
|
||||
|
||||
The iOS simulator runs iOS 15.5 on an iPhone 13 Pro Max.
|
||||
![iOS screenshot](pathname:///cap/ios.png)
|
||||
|
||||
:::
|
||||
</td><td>
|
||||
|
||||
![Android screenshot](pathname:///cap/and.png)
|
||||
|
||||
</td></tr></tbody></table>
|
||||
|
||||
:::warning Telemetry
|
||||
|
||||
@ -33,7 +41,7 @@ npx @capacitor/cli telemetry
|
||||
|
||||
:::
|
||||
|
||||
### Integration Details
|
||||
## Integration Details
|
||||
|
||||
This example uses Svelte, but the same principles apply to other frameworks.
|
||||
|
||||
@ -100,93 +108,150 @@ async function exportFile() {
|
||||
</main>
|
||||
```
|
||||
|
||||
### Demo
|
||||
## Demo
|
||||
|
||||
<details><summary><b>Complete Example</b> (click to show)</summary>
|
||||
:::note
|
||||
|
||||
0) Disable telemetry as noted in the warning.
|
||||
This demo was tested on an Intel Mac on 2023 April 01 with Capacitor 4.7.3 and
|
||||
`@capacitor/filesystem` 4.1.4
|
||||
|
||||
Follow the [React Native demo](#demo) to ensure iOS and Android sims are ready.
|
||||
The iOS simulator runs iOS 16.2 on an iPhone 14 Pro Max.
|
||||
|
||||
The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
|
||||
|
||||
1) Create a new Svelte project:
|
||||
:::
|
||||
|
||||
### Base Project
|
||||
|
||||
1) Disable telemetry.
|
||||
|
||||
```bash
|
||||
npx @capacitor/cli telemetry off
|
||||
```
|
||||
|
||||
Verify that telemetry is disabled by running
|
||||
|
||||
```bash
|
||||
npx @capacitor/cli telemetry
|
||||
```
|
||||
|
||||
(it should print `Telemetry is off`)
|
||||
|
||||
2) Create a new Svelte project:
|
||||
|
||||
```bash
|
||||
npm create vite@latest sheetjs-cap -- --template svelte
|
||||
cd sheetjs-cap
|
||||
```
|
||||
|
||||
2) Install dependencies:
|
||||
3) Install dependencies:
|
||||
|
||||
```bash
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
|
||||
npm i --save @capacitor/core @capacitor/cli @capacitor/ios @capacitor/filesystem
|
||||
npm i --save @capacitor/core @capacitor/cli @capacitor/filesystem
|
||||
```
|
||||
|
||||
3) Create CapacitorJS structure:
|
||||
4) Create CapacitorJS structure:
|
||||
|
||||
```bash
|
||||
npx cap init sheetjs-cap com.sheetjs.cap --web-dir=dist
|
||||
npm run build
|
||||
```
|
||||
|
||||
5) Download [`src/App.svelte`](pathname:///cap/App.svelte) and replace:
|
||||
|
||||
```bash
|
||||
curl -o src/App.svelte -L https://docs.sheetjs.com/cap/App.svelte
|
||||
```
|
||||
|
||||
### iOS
|
||||
|
||||
6) Follow the [React Native demo](/docs/demos/mobile/reactnative#demo) to
|
||||
ensure the iOS simulator is ready.
|
||||
|
||||
7) Create iOS app
|
||||
|
||||
```bash
|
||||
npm i --save @capacitor/ios
|
||||
npx cap add ios
|
||||
```
|
||||
|
||||
4) Replace the contents of `src/App.svelte` with the following:
|
||||
8) Enable file sharing and make the documents folder visible in the iOS app.
|
||||
The following lines must be added to `ios/App/App/Info.plist`:
|
||||
|
||||
```html title="src/App.svelte"
|
||||
<script>
|
||||
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
|
||||
import { onMount } from 'svelte';
|
||||
import { read, utils, version, writeXLSX } from 'xlsx';
|
||||
|
||||
let html = "";
|
||||
let tbl;
|
||||
|
||||
/* Fetch and update the state once */
|
||||
onMount(async() => {
|
||||
const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
|
||||
const wb = read(f); // parse the array buffer
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
html = utils.sheet_to_html(ws); // generate HTML and update state
|
||||
});
|
||||
|
||||
/* get state data and export to XLSX */
|
||||
async function exportFile() {
|
||||
const elt = tbl.getElementsByTagName("TABLE")[0];
|
||||
const wb = utils.table_to_book(elt);
|
||||
/* generate Base64 string for Capacitor */
|
||||
const data = writeXLSX(wb, { type: "base64" });
|
||||
/* write */
|
||||
await Filesystem.writeFile({
|
||||
path: "SheetJSCap.xlsx",
|
||||
data,
|
||||
directory: Directory.Documents
|
||||
});
|
||||
}
|
||||
|
||||
/* show file picker, read file, load table */
|
||||
async function importFile(evt) {
|
||||
const f = evt.target.files[0];
|
||||
const wb = read(await f.arrayBuffer());
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
html = utils.sheet_to_html(ws); // generate HTML and update state
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h3>SheetJS × CapacitorJS { version }</h3>
|
||||
<input type="file" on:change={importFile}/>
|
||||
<button on:click={exportFile}>Export XLSX</button>
|
||||
<div bind:this={tbl}>{@html html}</div>
|
||||
</main>
|
||||
```xml title="ios/App/App/Info.plist"
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- highlight-start -->
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<!-- highlight-end -->
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
```
|
||||
|
||||
5) Test the app:
|
||||
(The root element of the document is `plist` and it contains one `dict` child)
|
||||
|
||||
9) Run the app in the simulator
|
||||
|
||||
```bash
|
||||
npm run build; npx cap sync; npx cap run ios
|
||||
npm run build
|
||||
npx cap sync
|
||||
npx cap run ios
|
||||
```
|
||||
|
||||
There are 3 steps: build the Svelte app, sync with CapacitorJS, and run sim.
|
||||
This sequence must be run every time to ensure changes are propagated.
|
||||
10) Test the app
|
||||
|
||||
</details>
|
||||
Open the app and observe that presidents are listed in the table.
|
||||
|
||||
Touch "Export XLSX" and a popup will be displayed.
|
||||
|
||||
To see the generated file, switch to the "Files" app in the simulator and look
|
||||
for `SheetJSCap.xlsx` in "On My iPhone" > "`sheetjs-cap`"
|
||||
|
||||
### Android
|
||||
|
||||
11) Follow the [React Native demo](/docs/demos/mobile/reactnative#demo) to
|
||||
ensure the Android simulator is ready.
|
||||
|
||||
12) Create Android app
|
||||
|
||||
```bash
|
||||
npm i --save @capacitor/android
|
||||
npx cap add android
|
||||
```
|
||||
|
||||
13) Enable file reading and writing in the Android app.
|
||||
The following lines must be added to `android/app/src/main/AndroidManifest.xml`
|
||||
after the `Permissions` comment:
|
||||
|
||||
```xml title="android/app/src/main/AndroidManifest.xml"
|
||||
<!-- Permissions -->
|
||||
|
||||
<!-- highlight-start -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<!-- highlight-end -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
```
|
||||
|
||||
14) Run the app in the simulator
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npx cap sync
|
||||
npx cap run android
|
||||
```
|
||||
|
||||
15) Test the app
|
||||
|
||||
Open the app and observe that presidents are listed in the table.
|
||||
|
||||
Touch "Export XLSX" and the emulator will ask for permission:
|
||||
|
||||
Tap "Allow" and a popup will be displayed with a path.
|
||||
|
||||
To see the generated file, switch to the "Files" app in the simulator, tap the
|
||||
`≡` icon and tap "Documents". Tap "Documents" folder to find `SheetJSCap.xlsx`.
|
||||
|
@ -59,7 +59,7 @@ Writers will process the `Props` key of the options object:
|
||||
|
||||
```js
|
||||
/* force the Author to be "SheetJS" */
|
||||
XLSX.write(wb, {Props:{Author:"SheetJS"}});
|
||||
XLSX.write(wb, { Props: { Author: "SheetJS" } });
|
||||
```
|
||||
|
||||
## Workbook-Level Attributes
|
||||
@ -92,6 +92,63 @@ Excel allows two sheet-scoped defined names to share the same name. However, a
|
||||
sheet-scoped name cannot collide with a workbook-scope name. Workbook writers
|
||||
may not enforce this constraint.
|
||||
|
||||
The following snippet creates a worksheet-level defined name `"Global"` and a
|
||||
local defined name `"Local"` with distinct values for first and second sheets:
|
||||
|
||||
```js
|
||||
/* ensure the workbook structure exists */
|
||||
if(!wb.Workbook) wb.Workbook = {};
|
||||
if(!wb.Workbook.Names) wb.Workbook.Names = [];
|
||||
|
||||
/* "Global" workbook-level -> Sheet1 A1:A2 */
|
||||
wb.Workbook.Names.push({ Name: "Global", Ref: "Sheet1!$A$1:$A$2" });
|
||||
|
||||
/* "Local" scoped to the first worksheet -> Sheet1 B1:B2 */
|
||||
wb.Workbook.Names.push({ Name: "Local", Ref: "Sheet1!$B$1:$B$2", Sheet: 0 });
|
||||
|
||||
/* "Local" scoped to the second worksheet -> Sheet1 C1:C2 */
|
||||
wb.Workbook.Names.push({ Name: "Local", Ref: "Sheet1!$C$1:$C$2", Sheet: 1 });
|
||||
```
|
||||
|
||||
<details><summary><b>Live Example</b> (click to show)</summary>
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function DefinedNameExport() { return ( <button onClick={() => {
|
||||
/* Create empty workbook */
|
||||
var wb = XLSX.utils.book_new();
|
||||
|
||||
/* Create worksheet Sheet1 */
|
||||
var ws1 = XLSX.utils.aoa_to_sheet([[1,2,3],[4,5,6],["Global",0],["Local",0]]);
|
||||
XLSX.utils.book_append_sheet(wb, ws1, "Sheet1");
|
||||
|
||||
/* Create worksheet Sheet2 */
|
||||
var ws2 = XLSX.utils.aoa_to_sheet([["Global",0],["Local",0]]);
|
||||
XLSX.utils.book_append_sheet(wb, ws2, "Sheet2");
|
||||
|
||||
/* Create defined names */
|
||||
if(!wb.Workbook) wb.Workbook = {};
|
||||
if(!wb.Workbook.Names) wb.Workbook.Names = [];
|
||||
/* "Global" workbook-level -> Sheet1 A1:A2 */
|
||||
wb.Workbook.Names.push({ Name: "Global", Ref: "Sheet1!$A$1:$A$2" });
|
||||
/* "Local" scoped to the first worksheet -> Sheet1 B1:B2 */
|
||||
wb.Workbook.Names.push({ Name: "Local", Sheet: 0, Ref: "Sheet1!$B$1:$B$2" });
|
||||
/* "Local" scoped to the second worksheet -> Sheet1 C1:C2 */
|
||||
wb.Workbook.Names.push({ Name: "Local", Sheet: 1, Ref: "Sheet1!$C$1:$C$2" });
|
||||
|
||||
/* Create formulae */
|
||||
ws1["B3"].f = "SUM(Global)"; // Sheet1 B3 =SUM(Global) 1 + 4 = 5
|
||||
ws1["B4"].f = "SUM(Local)"; // Sheet1 B4 =SUM(Local) 2 + 5 = 7
|
||||
ws2["B1"].f = "SUM(Global)"; // Sheet2 B1 =SUM(Global) 1 + 4 = 5
|
||||
ws2["B2"].f = "SUM(Local)"; // Sheet2 B2 =SUM(Local) 3 + 6 = 9
|
||||
|
||||
/* Export to file (start a download) */
|
||||
XLSX.writeFile(wb, "SheetJSDNExport.xlsx");
|
||||
}}><b>Export XLSX!</b></button> ); }
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Workbook Views
|
||||
|
||||
`wb.Workbook.Views` is an array of workbook view objects which have the keys:
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"label": "Spreadsheet Features",
|
||||
"collapsed": false,
|
||||
"position": 7
|
||||
}
|
||||
|
46
docz/static/cap/App.svelte
Normal file
46
docz/static/cap/App.svelte
Normal file
@ -0,0 +1,46 @@
|
||||
<script>
|
||||
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
|
||||
import { onMount } from 'svelte';
|
||||
import { read, utils, version, writeXLSX } from 'xlsx';
|
||||
|
||||
let html = "";
|
||||
let tbl;
|
||||
|
||||
/* Fetch and update the state once */
|
||||
onMount(async() => {
|
||||
const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
|
||||
const wb = read(f); // parse the array buffer
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
html = utils.sheet_to_html(ws); // generate HTML and update state
|
||||
});
|
||||
|
||||
/* get state data and export to XLSX */
|
||||
async function exportFile() {
|
||||
const elt = tbl.getElementsByTagName("TABLE")[0];
|
||||
const wb = utils.table_to_book(elt);
|
||||
/* generate Base64 string for Capacitor */
|
||||
const data = writeXLSX(wb, { type: "base64" });
|
||||
/* write */
|
||||
await Filesystem.writeFile({
|
||||
path: "SheetJSCap.xlsx",
|
||||
data,
|
||||
directory: Directory.Documents
|
||||
});
|
||||
alert(`Exported to ${Directory.Documents}/SheetJSCap.xlsx`);
|
||||
}
|
||||
|
||||
/* show file picker, read file, load table */
|
||||
async function importFile(evt) {
|
||||
const f = evt.target.files[0];
|
||||
const wb = read(await f.arrayBuffer());
|
||||
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
||||
html = utils.sheet_to_html(ws); // generate HTML and update state
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h3>SheetJS × CapacitorJS { version }</h3>
|
||||
<input type="file" on:change={importFile}/>
|
||||
<button on:click={exportFile}>Export XLSX</button>
|
||||
<div bind:this={tbl}>{@html html}</div>
|
||||
</main>
|
BIN
docz/static/cap/and.png
Normal file
BIN
docz/static/cap/and.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 KiB |
BIN
docz/static/cap/ios.png
Normal file
BIN
docz/static/cap/ios.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
Loading…
Reference in New Issue
Block a user