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.
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</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