forked from sheetjs/docs.sheetjs.com
		
	quasar+cordova
This commit is contained in:
		
							parent
							
								
									b36455026b
								
							
						
					
					
						commit
						847a1c850a
					
				| @ -57,19 +57,19 @@ For existing projects, the easiest approach is to uninstall and reinstall: | ||||
|   <TabItem value="npm" label="npm"> | ||||
| <pre><code parentName="pre" {...{"className": "language-bash"}}>{`\ | ||||
| npm rm --save xlsx | ||||
| npm i --save file:vendor/xlsx-${current}.tgz`} | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| </code></pre> | ||||
|   </TabItem> | ||||
|   <TabItem value="pnpm" label="pnpm"> | ||||
| <pre><code parentName="pre" {...{"className": "language-bash"}}>{`\ | ||||
| pnpm rm xlsx | ||||
| pnpm install file:vendor/xlsx-${current}.tgz`} | ||||
| pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| </code></pre> | ||||
|   </TabItem> | ||||
|   <TabItem value="yarn" label="Yarn" default> | ||||
| <pre><code parentName="pre" {...{"className": "language-bash"}}>{`\ | ||||
| yarn remove xlsx | ||||
| yarn add file:vendor/xlsx-${current}.tgz`} | ||||
| yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| </code></pre> | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
|  | ||||
| @ -167,7 +167,7 @@ and place in the scripts directory.  For CS6 Windows 10 the path is typically | ||||
| 3) File > File Info ... and confirm there is an Author. If not, set to `SheetJS` | ||||
| 
 | ||||
| 4) File > Scripts > write and use the popup to select the Documents folder. | ||||
|    Enter `SheetJSPSTest.xlsx` and hit "Save" | ||||
|    Enter `SheetJSPSTest.xlsx` and press "Save" | ||||
| 
 | ||||
| 4) An alert will confirm that the file was created: | ||||
| 
 | ||||
|  | ||||
| @ -239,7 +239,7 @@ async function extern() { | ||||
| After making the change, save the files.  Close the terminal window and the | ||||
| Excel window (do not save the Excel file).  Re-run `npm start`. | ||||
| 
 | ||||
| Enter the formula `=SHEETJS.EXTERN()` in cell D1 and hit Enter.  Excel should | ||||
| Enter the formula `=SHEETJS.EXTERN()` in cell D1 and press Enter.  Excel should | ||||
| pull in the data and generate a dynamic array: | ||||
| 
 | ||||
|  | ||||
|  | ||||
| @ -132,7 +132,7 @@ selecting the terminal and entering the key sequence `CTRL + C` | ||||
| 3) From the project folder, install the library: | ||||
| 
 | ||||
| ```bash | ||||
| npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| ``` | ||||
| 
 | ||||
| 4) To confirm the library was loaded, change the title to show the version.  The | ||||
| @ -375,3 +375,369 @@ id,name,role | ||||
|  | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## Quasar | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was tested on an Intel Mac on 2022 August 14. Quasar version `2.7.7`. | ||||
| The iOS simulator runs iOS 15.5 on an iPhone SE 3rd generation. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| This demo will focus on VueJS and Cordova with the Quasar Vite starter project. | ||||
| 
 | ||||
| ### Integration Details | ||||
| 
 | ||||
| The complete solution uses `cordova-plugin-file` for file operations.  It can | ||||
| be installed like any other Cordova plugin: | ||||
| 
 | ||||
| ```bash | ||||
| cd src-cordova | ||||
| cordova plugin add cordova-plugin-file | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| #### Reading data | ||||
| 
 | ||||
| The `q-file` component presents an API reminiscent of File Input elements: | ||||
| 
 | ||||
| ```html | ||||
| <q-file label="Load File" filled label-color="orange" @input="updateFile"/> | ||||
| ``` | ||||
| 
 | ||||
| When binding to the `input` element, the callback receives an `Event` object: | ||||
| 
 | ||||
| ```ts | ||||
| import { read } from 'xlsx'; | ||||
| 
 | ||||
| // assuming `todos` is a standard VueJS `ref` | ||||
| async function updateFile(v) { try { | ||||
|   // `v.target.files[0]` is the desired file object | ||||
|   const files = (v.target as HTMLInputElement).files; | ||||
|   if(!files || files.length == 0) return; | ||||
| 
 | ||||
|   // read first file | ||||
|   const wb = read(await files[0].arrayBuffer()); | ||||
| 
 | ||||
|   // get data of first worksheet as an array of objects | ||||
|   const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); | ||||
| 
 | ||||
|   // update state | ||||
|   todos.value = data.map(row => ({id: row.Index, content: row.Name})); | ||||
| 
 | ||||
| } catch(e) { console.log(e); } } | ||||
| ``` | ||||
| 
 | ||||
| #### Writing data | ||||
| 
 | ||||
| The API is shaped like the File and Directory Entries API.  For clarity, since | ||||
| the code is a "pyramid of doom", the error handlers are omitted: | ||||
| 
 | ||||
| ```ts | ||||
| import { write } from 'xlsx'; | ||||
| 
 | ||||
| // on iOS and android, `XLSX.write` with type "buffer" returns a `Uint8Array` | ||||
| const u8: Uint8Array = write(wb, {bookType: "xlsx", type: "buffer"}); | ||||
| // Request filesystem access for persistent storage | ||||
| window.requestFileSystem(window.PERSISTENT, 0, function(fs) { | ||||
|   // Request a handle to "SheetJSQuasar.xlsx", making a new file if necessary | ||||
|   fs.root.getFile("SheetJSQuasar.xlsx", {create: true}, entry => { | ||||
|     // Request a FileWriter for writing data | ||||
|     entry.createWriter(writer => { | ||||
|       // The FileWriter API needs an actual Blob | ||||
|       const data = new Blob([u8], {type: "application/vnd.ms-excel"}); | ||||
|       // This callback is called if the write is successful | ||||
|       writer.onwriteend = () => { | ||||
|         // TODO: show a dialog | ||||
|       }; | ||||
|       // writer.onerror will be invoked if there is an error in writing | ||||
| 
 | ||||
|       // write the data | ||||
|       writer.write(data); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| ### Demo | ||||
| 
 | ||||
| The demo builds off of the Vite example.  Familiarity with VueJS and TypeScript | ||||
| is assumed. | ||||
| 
 | ||||
| <details open><summary><b>Complete Example</b> (click to show)</summary> | ||||
| 
 | ||||
| 0) Ensure all of the dependencies are installed.  Install the CLI globally: | ||||
| 
 | ||||
| ```bash | ||||
| npm i -g @quasar/cli cordova | ||||
| ``` | ||||
| 
 | ||||
| (you may need to run `sudo npm i -g` if there are permission issues) | ||||
| 
 | ||||
| 1) Create a new app: | ||||
| 
 | ||||
| ```bash | ||||
| npm init quasar | ||||
| ``` | ||||
| 
 | ||||
| When prompted: | ||||
| 
 | ||||
| - "What would you like to build?": `App with Quasar CLI` | ||||
| - "Project folder": `SheetJSQuasar` | ||||
| - "Pick Quasar version": `Quasar v2 (Vue 3 | latest and greatest)` | ||||
| - "Pick script type": `Typescript` | ||||
| - "Pick Quasar App CLI variant": `Quasar App CLI with Vite` | ||||
| - "Package name": (just press enter, it will use the default `sheetjsquasar` | ||||
| - "Project product name": `SheetJSQuasar` | ||||
| - "Project description": `SheetJS + Quasar` | ||||
| - "Author": (just press enter, 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 | ||||
| - "Install project dependencies": `No` | ||||
| 
 | ||||
| 2) Install dependencies: | ||||
| 
 | ||||
| ```bash | ||||
| cd SheetJSQuasar | ||||
| npm i | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| ``` | ||||
| 
 | ||||
| 3) Set up Cordova: | ||||
| 
 | ||||
| ```bash | ||||
| quasar mode add cordova | ||||
| ``` | ||||
| 
 | ||||
| When prompted, enter the app id `org.sheetjs.quasar`. | ||||
| 
 | ||||
| It will create a new `src-cordova` folder. Continue in that folder: | ||||
| 
 | ||||
| ```bash | ||||
| cd src-cordova | ||||
| cordova platform add ios | ||||
| cordova plugin add cordova-plugin-wkwebview-engine | ||||
| cordova plugin add cordova-plugin-file | ||||
| ``` | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| If there is an error `Could not load API for iOS project`, it needs to be reset: | ||||
| 
 | ||||
| ```bash | ||||
| cordova platform rm ios | ||||
| cordova platform add ios | ||||
| cordova plugin add cordova-plugin-file | ||||
| ``` | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| Return to the project directory: | ||||
| 
 | ||||
| ```bash | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| 4) Start the dev server: | ||||
| 
 | ||||
| ```bash | ||||
| quasar dev -m ios | ||||
| ``` | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| If the app is blank, delete the app and close the simulator, then restart dev | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| 
 | ||||
| 5) Add the Dialog plugin to `quasar.config.js`: | ||||
| 
 | ||||
| ```js title="quasar.config.js" | ||||
|       // Quasar plugins | ||||
|       // highlight-next-line | ||||
|       plugins: ['Dialog'] | ||||
| ``` | ||||
| 
 | ||||
| 6) In the template section of `src/pages/IndexPage.vue`, add a Save button and | ||||
|    a Load file picker component at the bottom of the page: | ||||
| 
 | ||||
| ```html title="src/pages/IndexPage.vue" | ||||
|     <!-- highlight-start --> | ||||
|     <q-btn-group> | ||||
|       <q-file label="Load File" filled label-color="orange" @input="updateFile"/> | ||||
|       <q-btn label="Save File" @click="saveFile" /> | ||||
|     </q-btn-group> | ||||
|     <!-- highlight-end --> | ||||
|   </q-page> | ||||
| </template> | ||||
| ``` | ||||
| 
 | ||||
| This uses two functions that should be added to the component script: | ||||
| 
 | ||||
| ```ts title="src/pages/IndexPage.vue" | ||||
|     const meta = ref<Meta>({ | ||||
|       totalCount: 1200 | ||||
|     }); | ||||
| // highlight-start | ||||
|     function saveFile() { | ||||
|     } | ||||
|     async function updateFile(v) { | ||||
|     } | ||||
|     return { todos, meta, saveFile, updateFile }; | ||||
| // highlight-end | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| The app should now show two buttons at the bottom: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| If the app is blank or not refreshing, delete the app and close the simulator, | ||||
| then restart the dev process. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 7) Wire up the `updateFile` function: | ||||
| 
 | ||||
| ```ts title="src/pages/IndexPage.vue" | ||||
| import { defineComponent, ref } from 'vue'; | ||||
| // highlight-start | ||||
| import { read, write, utils } from 'xlsx'; | ||||
| import { useQuasar } from 'quasar'; | ||||
| // highlight-end | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| // ... | ||||
| // highlight-start | ||||
|     const $q = useQuasar(); | ||||
|     function dialogerr(e) { $q.dialog({title: "Error!", message: e.message || String(e)}); } | ||||
| // highlight-end | ||||
|     function saveFile() { | ||||
|     } | ||||
|     async function updateFile(v) { | ||||
| // highlight-start | ||||
|       try { | ||||
|         const files = (v.target as HTMLInputElement).files; | ||||
|         if(!files || files.length == 0) return; | ||||
| 
 | ||||
|         const wb = read(await files[0].arrayBuffer()); | ||||
| 
 | ||||
|         const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); | ||||
|         todos.value = data.map(row => ({id: row.Index, content: row.Name})); | ||||
|       } catch(e) { dialogerr(e); } | ||||
| // highlight-end | ||||
|     } | ||||
| ``` | ||||
| 
 | ||||
| To test that reading works: | ||||
| 
 | ||||
| - Download <https://sheetjs.com/pres.numbers> | ||||
| - In the simulator, click the Home icon to return to the home screen | ||||
| - Click on the "Files" icon | ||||
| - Click and drag `pres.numbers` from a Finder window into the simulator. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| - Make sure "On My iPhone" is highlighted and select "Save" | ||||
| - Click the Home icon again then select the SheetJSQuasar app | ||||
| - Click the "Load" button, then select "Choose File" and select `pres`: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| Once selected, the screen should refresh with new contents: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| 8) Wire up the `saveFile` function: | ||||
| 
 | ||||
| ```js | ||||
|     function saveFile() { | ||||
| // highlight-start | ||||
|       /* generate workbook from state */ | ||||
|       const ws = utils.json_to_sheet(todos.value); | ||||
|       const wb = utils.book_new(); | ||||
|       utils.book_append_sheet(wb, ws, "SheetJSQuasar"); | ||||
|       const u8: Uint8Array = write(wb, {bookType: "xlsx", type: "buffer"}); | ||||
| 
 | ||||
|       /* save to file */ | ||||
|       window.requestFileSystem(window.PERSISTENT, 0, function(fs) { | ||||
|         try { | ||||
|           fs.root.getFile("SheetJSQuasar.xlsx", {create: true}, entry => { | ||||
|             const msg = `File stored at ${$q.cordova.file.documentsDirectory} ${entry.fullPath}`; | ||||
|             entry.createWriter(writer => { | ||||
|               try { | ||||
|                 const data = new Blob([u8], {type: "application/vnd.ms-excel"}); | ||||
|                 writer.onwriteend = () => { | ||||
|                   try { | ||||
|                     $q.dialog({title: "Success!", message: msg}); | ||||
|                   } catch(e) { dialogerr(e); } | ||||
|                 }; | ||||
|                 writer.onerror = dialogerr; | ||||
|                 writer.write(data); | ||||
|               } catch(e) { dialogerr(e); } | ||||
|             }, dialogerr); | ||||
|           }, dialogerr); | ||||
|         } catch(e) { dialogerr(e) } | ||||
|       }, dialogerr); | ||||
| // highlight-end | ||||
|     } | ||||
| ``` | ||||
| 
 | ||||
| The page should revert to the old contents. | ||||
| 
 | ||||
| To test that writing works: | ||||
| 
 | ||||
| - Click "Save File".  You will see a popup with a location: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| - Find the file and verify the contents are correct.  Run in a new terminal: | ||||
| 
 | ||||
| ```bash | ||||
| find ~/Library/Developer/CoreSimulator -name SheetJSQuasar.xlsx | | ||||
|   while read x; do echo "$x"; npx xlsx-cli "$x"; done | ||||
| ``` | ||||
| 
 | ||||
| Since the contents reverted, you should see | ||||
| 
 | ||||
| ``` | ||||
| SheetJSQuasar | ||||
| id,content | ||||
| 1,ct1 | ||||
| 2,ct2 | ||||
| 3,ct3 | ||||
| 4,ct4 | ||||
| 5,ct5 | ||||
| ``` | ||||
| 
 | ||||
| - Use "Load File" to select `pres.numbers` again.  Wait for the app to refresh. | ||||
| 
 | ||||
| - Click "Save File", then re-run the command: | ||||
| 
 | ||||
| ```bash | ||||
| find ~/Library/Developer/CoreSimulator -name SheetJSQuasar.xlsx | | ||||
|   while read x; do echo "$x"; npx xlsx-cli "$x"; done | ||||
| ``` | ||||
| 
 | ||||
| The contents from `pres.numbers` should show up now, with a new header row: | ||||
| 
 | ||||
| ``` | ||||
| SheetJSQuasar | ||||
| id,content | ||||
| 42,Bill Clinton | ||||
| 43,GeorgeW Bush | ||||
| 44,Barack Obama | ||||
| 45,Donald Trump | ||||
| 46,Joseph Biden | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
|  | ||||
| @ -115,17 +115,17 @@ npx create-nuxt-app SheetJSNuxt | ||||
| 
 | ||||
| When prompted, enter the following options: | ||||
| 
 | ||||
| - `Project name`: hit Enter (use default SheetJSNuxt) | ||||
| - `Programming language`: hit Down Arrow (`TypeScript` selected) and hit Enter | ||||
| - `Package manager`: select `Npm` and hit Enter | ||||
| - `UI framework`: select `None` and hit Enter | ||||
| - `Nuxt.js modules`: scroll to `Content`, select with Space, then hit Enter | ||||
| - `Linting tools`: hit Enter (do not select any Linting tools) | ||||
| - `Testing framework`: select `None` and hit Enter | ||||
| - `Rendering mode`: select `Universal (SSR / SSG)` and hit Enter | ||||
| - `Deployment target`: select `Static (Static/Jamstack hosting)` and hit Enter | ||||
| - `Development tools`: hit Enter (do not select any Development tools) | ||||
| - `What is your GitHub username?`: hit Enter | ||||
| - `Project name`: press Enter (use default SheetJSNuxt) | ||||
| - `Programming language`: press Down Arrow (`TypeScript` selected) then Enter | ||||
| - `Package manager`: select `Npm` and press Enter | ||||
| - `UI framework`: select `None` and press Enter | ||||
| - `Nuxt.js modules`: scroll to `Content`, select with Space, then press Enter | ||||
| - `Linting tools`: press Enter (do not select any Linting tools) | ||||
| - `Testing framework`: select `None` and press Enter | ||||
| - `Rendering mode`: select `Universal (SSR / SSG)` and press Enter | ||||
| - `Deployment target`: select `Static (Static/Jamstack hosting)` and press Enter | ||||
| - `Development tools`: press Enter (do not select any Development tools) | ||||
| - `What is your GitHub username?`: press Enter | ||||
| - `Version control system`: select `None` | ||||
| 
 | ||||
| The project will be configured and modules will be installed. | ||||
| @ -179,7 +179,7 @@ export default { | ||||
| ``` | ||||
| 
 | ||||
| The browser should refresh to show the contents of the spreadsheet.  If it does | ||||
| not, hit Refresh manually or open a new browser window. | ||||
| not, click Refresh manually or open a new browser window. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| @ -198,7 +198,7 @@ The page should automatically refresh with the new content: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| 7) Stop the dev server (hit `CTRL+C` in the terminal window) and run | ||||
| 7) Stop the dev server (press `CTRL+C` in the terminal window) and run | ||||
| 
 | ||||
| ```bash | ||||
| npm run generate | ||||
|  | ||||
| @ -22,7 +22,7 @@ The demo projects include small runnable examples and short explainers. | ||||
| - [`Angular 2+ and Ionic`](https://github.com/SheetJS/SheetJS/tree/master/demos/angular2/) | ||||
| - [`Knockout`](./legacy#knockout) | ||||
| - [`React, React Native and NextJS`](https://github.com/SheetJS/SheetJS/tree/master/demos/react/) | ||||
| - [`VueJS, WeeX, and NuxtJS`](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/) | ||||
| - [`VueJS`](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/) | ||||
| 
 | ||||
| ### Front-End UI Components | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/mobile/quasar4.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/mobile/quasar4.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 60 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/mobile/quasar6.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/mobile/quasar6.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 10 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/mobile/quasar7a.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/mobile/quasar7a.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 43 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/mobile/quasar7b.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/mobile/quasar7b.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 38 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/mobile/quasar7c.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/mobile/quasar7c.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 79 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/mobile/quasar8.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/mobile/quasar8.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 22 KiB | 
		Loading…
	
		Reference in New Issue
	
	Block a user