| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | --- | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | title: Storing Sheets with CapacitorJS | 
					
						
							|  |  |  | sidebar_label: CapacitorJS | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  | pagination_prev: demos/static/index | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | pagination_next: demos/desktop/index | 
					
						
							|  |  |  | sidebar_position: 5 | 
					
						
							|  |  |  | sidebar_custom_props: | 
					
						
							|  |  |  |   summary: JS + Web View | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | import current from '/version.js'; | 
					
						
							| 
									
										
										
										
											2023-05-07 13:58:36 +00:00
										 |  |  | import CodeBlock from '@theme/CodeBlock'; | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | [CapacitorJS](https://capacitorjs.com/) is a mobile app runtime for building iOS | 
					
						
							|  |  |  | and Android apps. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing | 
					
						
							|  |  |  | data from spreadsheets. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses CapacitorJS and SheetJS to process data and export spreadsheets. | 
					
						
							|  |  |  | We'll explore how to load SheetJS in an CapacitorJS app and use APIs and plugins | 
					
						
							|  |  |  | to extract data from, and write data to, spreadsheet files on the device. | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | The ["Demo"](#demo) creates an app that looks like the screenshots below: | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | <table><thead><tr> | 
					
						
							|  |  |  |   <th><a href="#demo">iOS</a></th> | 
					
						
							|  |  |  |   <th><a href="#demo">Android</a></th> | 
					
						
							|  |  |  | </tr></thead><tbody><tr><td> | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  |  | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | </td><td> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </td></tr></tbody></table> | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | :::note Tested Deployments | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo was tested in the following environments: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | **Real Devices** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | OS         | Device              | CapacitorJS + FS  | Date       | | 
					
						
							|  |  |  | |:-----------|:--------------------|:------------------|:-----------| | 
					
						
							|  |  |  | | Android 30 | NVIDIA Shield       | `6.0.0` / `6.0.0` | 2024-06-02 | | 
					
						
							|  |  |  | | iOS 15.1   | iPad Pro            | `6.0.0` / `6.0.0` | 2024-06-02 | | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-30 04:29:40 +00:00
										 |  |  | **Simulators** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | OS         | Device              | CapacitorJS + FS  | Dev Platform | Date       | | 
					
						
							|  |  |  | |:-----------|:--------------------|:------------------|:-------------|:-----------| | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | | Android 34 | Pixel 3a            | `6.0.0` / `6.0.0` | `darwin-x64` | 2024-06-02 | | 
					
						
							|  |  |  | | iOS 17.5   | iPhone 15 Pro Max   | `6.0.0` / `6.0.0` | `darwin-x64` | 2024-06-02 | | 
					
						
							|  |  |  | | Android 34 | Pixel 3a            | `6.0.0` / `6.0.0` | `darwin-arm` | 2024-06-02 | | 
					
						
							|  |  |  | | iOS 17.5   | iPhone 15 Pro Max   | `6.0.0` / `6.0.0` | `darwin-arm` | 2024-06-02 | | 
					
						
							| 
									
										
										
										
											2024-05-28 05:20:05 +00:00
										 |  |  | | Android 34 | Pixel 3a            | `6.0.0` / `6.0.0` | `win10-x64`  | 2024-05-28 | | 
					
						
							| 
									
										
										
										
											2024-04-30 04:29:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-14 07:40:38 +00:00
										 |  |  | :::danger Telemetry | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Before starting this demo, manually disable telemetry.  On Linux and MacOS: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx @capacitor/cli telemetry off | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To verify telemetry was disabled: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx @capacitor/cli telemetry | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | ## Integration Details
 | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be | 
					
						
							|  |  |  | imported from any component or script in the app. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses [SvelteJS](/docs/demos/frontend/svelte), but the same principles | 
					
						
							|  |  |  | apply to other frameworks. | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #### Reading data
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | The standard [HTML5 File Input](/docs/demos/local/file#file-api) API works as | 
					
						
							|  |  |  | expected in CapacitorJS. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Apps will typically include an `input type="file"` element. When the element is | 
					
						
							|  |  |  | activated, CapacitorJS will show a file picker. After the user selects a file, | 
					
						
							|  |  |  | the element will receive a `change` event. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following example parses the selected file using the SheetJS `read`[^1] | 
					
						
							|  |  |  | method, generates a HTML table from the first sheet using `sheet_to_html`[^2], | 
					
						
							|  |  |  | and displays the table by setting the `innerHTML` attribute of a `div` element: | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | ```html title="Sample component for data import" | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | <script> | 
					
						
							|  |  |  | import { read, utils } from 'xlsx'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let html = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* show file picker, read file, load table */ | 
					
						
							|  |  |  | async function importFile(evt) { | 
					
						
							|  |  |  |   // highlight-start | 
					
						
							|  |  |  |   const f = evt.target.files[0]; | 
					
						
							|  |  |  |   const wb = read(await f.arrayBuffer()); | 
					
						
							|  |  |  |   // highlight-end | 
					
						
							|  |  |  |   const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet | 
					
						
							|  |  |  |   html = utils.sheet_to_html(ws); // generate HTML and update state | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <main> | 
					
						
							|  |  |  |   <!-- highlight-next-line --> | 
					
						
							|  |  |  |   <input type="file" on:change={importFile}/> | 
					
						
							|  |  |  |   <div bind:this={tbl}>{@html html}</div> | 
					
						
							|  |  |  | </main> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### Writing data
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | Starting from a SheetJS workbook object[^3], the `write` method with the option | 
					
						
							|  |  |  | `type: "base64"`[^4] will generate Base64-encoded files. | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | The `@capacitor/filesystem` plugin can write Base64 strings to the device. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following example uses the SheetJS `table_to_book` method[^5] to create a | 
					
						
							|  |  |  | workbook object from a HTML table. The workbook object is exported to the XLSX | 
					
						
							|  |  |  | format and written to the device. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html title="Sample component for data export" | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | <script> | 
					
						
							|  |  |  | import { Filesystem, Directory } from '@capacitor/filesystem'; | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | import { utils, write } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | let html = ""; | 
					
						
							|  |  |  | let tbl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* get state data and export to XLSX */ | 
					
						
							|  |  |  | async function exportFile() { | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  |   /* generate workbook object from HTML table */ | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  |   const elt = tbl.getElementsByTagName("TABLE")[0]; | 
					
						
							|  |  |  |   const wb = utils.table_to_book(elt); | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  |   // highlight-start | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  |   /* export to XLSX encoded in a Base64 string  */ | 
					
						
							|  |  |  |   const data = write(wb, { bookType: "xlsx", type: "base64" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* attempt to write to the device */ | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  |   await Filesystem.writeFile({ | 
					
						
							|  |  |  |     data, | 
					
						
							|  |  |  |     path: "SheetJSCap.xlsx", | 
					
						
							|  |  |  |     directory: Directory.Documents | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  |   // highlight-end | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <main> | 
					
						
							|  |  |  |   <button on:click={exportFile}>Export XLSX</button> | 
					
						
							|  |  |  |   <div bind:this={tbl}>{@html html}</div> | 
					
						
							|  |  |  | </main> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | :::caution pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `Filesystem.writeFile` cannot overwrite existing files. Production apps should | 
					
						
							|  |  |  | attempt to delete the file before writing: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  |   /* attempt to delete file first */ | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     await Filesystem.deleteFile({ | 
					
						
							|  |  |  |       path: "SheetJSCap.xlsx", | 
					
						
							|  |  |  |       directory: Directory.Documents | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } catch(e) {} | 
					
						
							|  |  |  |   /* attempt to write to the device */ | 
					
						
							|  |  |  |   await Filesystem.writeFile({ | 
					
						
							|  |  |  |     data, | 
					
						
							|  |  |  |     path: "SheetJSCap.xlsx", | 
					
						
							|  |  |  |     directory: Directory.Documents | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | ## Demo
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | The app in this demo will display data in a table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When the app is launched, a [test file](https://docs.sheetjs.com/pres.numbers) | 
					
						
							|  |  |  | will be fetched and processed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When a document is selected with the file picker, it will be processed and the | 
					
						
							|  |  |  | table will refresh to show the contents. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "Export XLSX" will attempt to export the table data to `SheetJSCap.xlsx` in the | 
					
						
							|  |  |  | app Documents folder. An alert will display the location of the file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | ### Base Project
 | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 0) Follow the official "Environment Setup"[^6] instructions to set up Android | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | and iOS targets | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | iOS development is only supported on macOS. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 04:47:04 +00:00
										 |  |  | <details> | 
					
						
							|  |  |  |   <summary><b>Installation Notes</b> (click to show)</summary> | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | CapacitorJS requires Java 17. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 1) Disable telemetry. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx @capacitor/cli telemetry off | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Verify that telemetry is disabled by running | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx @capacitor/cli telemetry | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | (it should print `Telemetry is off`) | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 2) Create a new Svelte project: | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm create vite@latest sheetjs-cap -- --template svelte | 
					
						
							|  |  |  | cd sheetjs-cap | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 3) Install dependencies: | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 13:58:36 +00:00
										 |  |  | <CodeBlock language="bash">{`\ | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz | 
					
						
							|  |  |  | npm i --save @capacitor/core @capacitor/cli @capacitor/filesystem`} | 
					
						
							| 
									
										
										
										
											2023-05-07 13:58:36 +00:00
										 |  |  | </CodeBlock> | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 4) Create CapacitorJS structure: | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx cap init sheetjs-cap com.sheetjs.cap --web-dir=dist | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | npm run build | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-03 06:47:00 +00:00
										 |  |  | :::note pass | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | If prompted to create an Ionic account, type `N` and press <kbd>Enter</kbd>. | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 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 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | ### Android
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | 6) Create Android app | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | npm i --save @capacitor/android | 
					
						
							|  |  |  | npx cap add android | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | 7) Enable file reading and writing in the Android app. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | Add the highlighted lines to `android/app/src/main/AndroidManifest.xml` after | 
					
						
							|  |  |  | the `Permissions` comment: | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```xml title="android/app/src/main/AndroidManifest.xml (add to file)" | 
					
						
							|  |  |  |     <!-- Permissions --> | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | <!-- highlight-start --> | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  |     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | 
					
						
							| 
									
										
										
										
											2023-09-11 04:44:15 +00:00
										 |  |  |     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | <!-- highlight-end --> | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  |     <uses-permission android:name="android.permission.INTERNET" /> | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-28 05:20:05 +00:00
										 |  |  | 8) Run the app in the simulator: | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | ```bash | 
					
						
							|  |  |  | npm run build | 
					
						
							|  |  |  | npx cap sync | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | npx cap run android | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-28 05:20:05 +00:00
										 |  |  | The app should look like the screenshot at the top of the page. | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-28 05:20:05 +00:00
										 |  |  | 9) Test the export functionality. | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-28 05:20:05 +00:00
										 |  |  | Touch "Export XLSX" and the emulator will ask for permission. Tap "Allow" and a | 
					
						
							|  |  |  | popup will be displayed with a path. | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-28 05:20:05 +00:00
										 |  |  | Open the "Files" app in the simulator, tap the `≡` icon and tap "Documents". Tap | 
					
						
							|  |  |  | the "Documents" folder to find `SheetJSCap.xlsx`. | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-28 05:20:05 +00:00
										 |  |  | <details open> | 
					
						
							|  |  |  |   <summary><b>Downloading the generated file</b> (click to hide)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `adb` must be run from the root user: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | adb root | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The file location can be found by searching for `SheetJSCap.xlsx`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | adb exec-out find / -name SheetJSCap.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The first line of the output starting with `/` is the desired path: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```text | 
					
						
							|  |  |  | find: /proc/8533/task/8533/exe: No such file or directory | 
					
						
							|  |  |  | find: /proc/8533/exe: No such file or directory | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  | /data/media/0/Documents/SheetJSCap.xlsx | 
					
						
							|  |  |  | /storage/emulated/0/Documents/SheetJSCap.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `adb pull` can download the file: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | adb pull "/data/media/0/Documents/SheetJSCap.xlsx" SheetJSCap.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `SheetJSCap.xlsx` can be opened with a spreadsheet editor such as Excel. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 10) Test the import functionality. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Create a spreadsheet or find an existing file. Click and drag the file into the | 
					
						
							|  |  |  | Android emulator window. The file will be uploaded to a Downloads folder in the | 
					
						
							|  |  |  | emulator. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Tap on "Choose File" in the app. In the selector, tap `≡` and select "Downloads" | 
					
						
							|  |  |  | to find the uploaded file. After selecting the file, the table will refresh. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | ### iOS
 | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 11) Create iOS app | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | npm i --save @capacitor/ios | 
					
						
							|  |  |  | npx cap add ios | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 12) Enable file sharing and make the documents folder visible in the iOS app. | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | The following lines must be added to `ios/App/App/Info.plist`: | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | ```xml title="ios/App/App/Info.plist (add to file)" | 
					
						
							|  |  |  | <plist version="1.0"> | 
					
						
							|  |  |  | <dict> | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | <!-- highlight-start --> | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  |   <key>UIFileSharingEnabled</key> | 
					
						
							|  |  |  |   <true/> | 
					
						
							|  |  |  |   <key>LSSupportsOpeningDocumentsInPlace</key> | 
					
						
							|  |  |  |   <true/> | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | <!-- highlight-end --> | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  |   <key>CFBundleDevelopmentRegion</key> | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | (The root element of the document is `plist` and it contains one `dict` child) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 13) Run the app in the simulator | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | npm run build | 
					
						
							|  |  |  | npx cap sync | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | npx cap run ios | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | If prompted to select a target device, select "iPhone 15 Pro Max (simulator)". | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | The app should look like the screenshot at the top of the page. | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 14) Test the export functionality. | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | Touch "Export XLSX" and a popup will be displayed. | 
					
						
							| 
									
										
										
										
											2023-04-01 20:13:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | To see the generated file, switch to the "Files" app in the simulator and look | 
					
						
							|  |  |  | for `SheetJSCap.xlsx` in "On My iPhone" > "`sheetjs-cap`" | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | <details open> | 
					
						
							|  |  |  |   <summary><b>Downloading the generated file</b> (click to hide)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The app files are available in the filesystem in `~/Library/Developer`. Open a | 
					
						
							|  |  |  | terminal and run the following command to find the file: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | find ~/Library/Developer -name SheetJSCap.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 15) Test the import functionality. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Create a spreadsheet or find an existing file. Click and drag the file into the | 
					
						
							|  |  |  | iOS simulator window. The simulator will show a picker for saving the file. | 
					
						
							|  |  |  | Select the `sheetjs-cap` folder and tap "Save". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Tap on "Choose File" in the app and "Choose File" in the popup. In the picker, | 
					
						
							|  |  |  | tap "Recents" and select the new file. After selecting the file, the table will refresh. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | ### Android Device
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 16) Connect an Android device using a USB cable. | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | If the device asks to allow USB debugging, tap "Allow". | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 17) Close any Android / iOS emulators. | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 18) Build APK and run on device: | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm run build | 
					
						
							|  |  |  | npx cap sync | 
					
						
							|  |  |  | npx cap run android | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If the Android emulators are closed and an Android device is connected, the last | 
					
						
							|  |  |  | command will build an APK and install on the device. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | :::note pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In some tests, the last command asked for a target device. Select the Android | 
					
						
							|  |  |  | device in the list and press <kbd>Enter</kbd> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | :::caution pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For real devices running API level 29 or below, the following line must be added | 
					
						
							|  |  |  | to the `application` open tag in `android/app/src/main/AndroidManifest.xml`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```xml title="android/app/src/main/AndroidManifest.xml (add highlighted attribute)" | 
					
						
							|  |  |  |     <application | 
					
						
							|  |  |  |         android:allowBackup="true" | 
					
						
							|  |  |  |         android:icon="@mipmap/ic_launcher" | 
					
						
							|  |  |  |         android:label="@string/app_name" | 
					
						
							|  |  |  |         android:roundIcon="@mipmap/ic_launcher_round" | 
					
						
							|  |  |  |         android:supportsRtl="true" | 
					
						
							|  |  |  |         // highlight-next-line | 
					
						
							|  |  |  |         android:requestLegacyExternalStorage="true" | 
					
						
							|  |  |  |         android:theme="@style/AppTheme"> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### iOS Device
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 19) Connect an iOS device using a USB cable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 20) Close any Android / iOS emulators. | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 21) Enable developer code signing certificates. | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | Open `ios/App/App.xcworkspace` in Xcode. Select the "Project Navigator" and | 
					
						
							|  |  |  | select the "App" project. In the main view, select "Signing & Capabilities". | 
					
						
							|  |  |  | Under "Signing", select a team in the dropdown menu. | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | 22) Run on device: | 
					
						
							| 
									
										
										
										
											2023-12-05 03:46:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm run build | 
					
						
							|  |  |  | npx cap sync | 
					
						
							|  |  |  | npx cap run ios | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When prompted to select a target device, select the real device in the list. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-03 03:25:20 +00:00
										 |  |  | [^1]: See [`read` in "Reading Files"](/docs/api/parse-options) | 
					
						
							|  |  |  | [^2]: See [`sheet_to_html` in "Utilities"](/docs/api/utilities/html#html-table-output) | 
					
						
							|  |  |  | [^3]: See ["Workbook Object"](/docs/csf/book) | 
					
						
							|  |  |  | [^4]: See [the "base64" type in "Writing Files"](/docs/api/write-options#input-type) | 
					
						
							|  |  |  | [^5]: See [`table_to_book` in "HTML" Utilities](/docs/api/utilities/html#create-new-sheet) | 
					
						
							|  |  |  | [^6]: See ["Environment Setup"](https://capacitorjs.com/docs/getting-started/environment-setup) in the CapacitorJS documentation. |