forked from sheetjs/docs.sheetjs.com
		
	tauri
This commit is contained in:
		
							parent
							
								
									ee071949a3
								
							
						
					
					
						commit
						b36455026b
					
				| @ -43,7 +43,7 @@ For example, with `fetch`: | ||||
| 
 | ||||
| ```js | ||||
| const res = await fetch("https://sheetjs.com/pres.numbers"); | ||||
| const ab = res.arrayBuffer(); // recover data as ArrayBuffer | ||||
| const ab = await res.arrayBuffer(); // recover data as ArrayBuffer | ||||
| 
 | ||||
| const wb = XLSX.read(ab); | ||||
| ``` | ||||
|  | ||||
| @ -82,7 +82,7 @@ running `npm start` again. | ||||
| 
 | ||||
| The library can be installed like any other NodeJS module: | ||||
| 
 | ||||
| ```powershell | ||||
| ```bash | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| ``` | ||||
| 
 | ||||
|  | ||||
| @ -346,3 +346,207 @@ Electron 14+ must use `@electron/remote` instead of `remote`.  An `initialize` | ||||
| call is required to enable DevTools in the window. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| ## Tauri | ||||
| 
 | ||||
| The [NodeJS Module](../getting-started/installation/nodejs) can be imported | ||||
| from frontend code. | ||||
| 
 | ||||
| This demo was tested against Tauri 1.0.5 on 2022 August 13. | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| Tauri currently does not provide NodeJS-esque `fs` wrapper functions.  The raw | ||||
| `@tauri-apps/api` methods used in the examples are not expected to change. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| `http` and `dialog` must be explicitly allowed in `tauri.conf.json`: | ||||
| 
 | ||||
| ```json title="tauri.conf.json" | ||||
|     "allowlist": { | ||||
|       "all": true, | ||||
|       "http": { | ||||
|         "all": true, | ||||
|         "request": true, | ||||
|         "scope": ["https://**"] | ||||
|       }, | ||||
|       "dialog": { | ||||
|         "all": true | ||||
|       } | ||||
| ``` | ||||
| 
 | ||||
| The "Complete Example" creates an app that looks like the screenshot: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| <details><summary><b>Complete Example</b> (click to show)</summary> | ||||
| 
 | ||||
| 0) [Read Tauri "Getting Started" guide and install dependencies.](https://tauri.app/v1/guides/getting-started/prerequisites) | ||||
| 
 | ||||
| 1) Create a new Tauri app: | ||||
| 
 | ||||
| ```bash | ||||
| npm create tauri-app | ||||
| ``` | ||||
| 
 | ||||
| When prompted: | ||||
| 
 | ||||
| - App Name: `SheetJSTauri` | ||||
| - Window Title: `SheetJS + Tauri` | ||||
| - UI recipe: `create-vite` | ||||
| - Add "@tauri-apps/api": `Y` | ||||
| - Vite template: `vue-ts` | ||||
| 
 | ||||
| 2) Enter the directory: | ||||
| 
 | ||||
| ```bash | ||||
| cd SheetJSTauri | ||||
| ``` | ||||
| 
 | ||||
| Open `package.json` with a text editor and add the highlighted lines: | ||||
| 
 | ||||
| ```json title="package.json" | ||||
| { | ||||
|   "name": "SheetJSTauri", | ||||
|   "private": true, | ||||
|   "version": "0.0.0", | ||||
|   "type": "module", | ||||
|   "scripts": { | ||||
|     "dev": "vite", | ||||
|     "build": "vue-tsc --noEmit && vite build", | ||||
|     "preview": "vite preview", | ||||
|     "tauri": "tauri" | ||||
|   }, | ||||
|   "dependencies": { | ||||
| // highlight-next-line | ||||
|     "@tauri-apps/api": "^1.0.2", | ||||
|     "vue": "^3.2.37", | ||||
| // highlight-next-line | ||||
|     "xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
| // highlight-next-line | ||||
|     "@tauri-apps/cli": "^1.0.5", | ||||
|     "@vitejs/plugin-vue": "^3.0.3", | ||||
|     "typescript": "^4.6.4", | ||||
|     "vite": "^3.0.7", | ||||
|     "vue-tsc": "^0.39.5" | ||||
|   } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 3) Install dependencies: | ||||
| 
 | ||||
| ```bash | ||||
| npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| ``` | ||||
| 
 | ||||
| 4) Enable operations by adding the highlighted lines to `tauri.conf.json`: | ||||
| 
 | ||||
| ```json title="src-tauri/tauri.conf.json" | ||||
|   "tauri": { | ||||
|     "allowlist": { | ||||
| // highlight-start | ||||
|       "http": { | ||||
|         "all": true, | ||||
|         "request": true, | ||||
|         "scope": ["https://**"] | ||||
|       }, | ||||
|       "dialog": { | ||||
|         "all": true | ||||
|       }, | ||||
| // highlight-end | ||||
|       "all": true | ||||
|     } | ||||
| ``` | ||||
| 
 | ||||
| In the same file, look for the `"identifier"` key and replace the value with `com.sheetjs.tauri`: | ||||
| 
 | ||||
| ```json title="src-tauri/tauri.conf.json" | ||||
|         "icons/icon.ico" | ||||
|       ], | ||||
|       // highlight-next-line | ||||
|       "identifier": "com.sheetjs.tauri", | ||||
|       "longDescription": "", | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| 5) Download [`App.vue`](pathname:///tauri/App.vue) and replace `src/App.vue` | ||||
|    with the downloaded script. | ||||
| 
 | ||||
| 6) Build the app with | ||||
| 
 | ||||
| ```bash | ||||
| npm run tauri build | ||||
| ``` | ||||
| 
 | ||||
| At the end, it will print the path to the generated program. Run the program! | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### Reading Files | ||||
| 
 | ||||
| There are two steps to reading files: obtaining a path and reading binary data: | ||||
| 
 | ||||
| ```js | ||||
| import { read } from 'xlsx'; | ||||
| import { open } from '@tauri-apps/api/dialog'; | ||||
| import { readBinaryFile } from '@tauri-apps/api/fs'; | ||||
| 
 | ||||
| const filters = [ | ||||
|   {name: "Excel Binary Workbook", extensions: ["xlsb"]}, | ||||
|   {name: "Excel Workbook", extensions: ["xlsx"]}, | ||||
|   {name: "Excel 97-2004 Workbook", extensions: ["xls"]}, | ||||
|   // ... other desired formats ... | ||||
| ]; | ||||
| 
 | ||||
| async function openFile() { | ||||
|   /* show open file dialog */ | ||||
|   const selected = await open({ | ||||
|     title: "Open Spreadsheet", | ||||
|     multiple: false, | ||||
|     directory: false, | ||||
|     filters | ||||
|   }); | ||||
| 
 | ||||
|   /* read data into a Uint8Array */ | ||||
|   const d = await readBinaryFile(selected); | ||||
| 
 | ||||
|   /* parse with SheetJS */ | ||||
|   const wb = read(d); | ||||
|   return wb; | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ### Writing Files | ||||
| 
 | ||||
| There are two steps to writing files: obtaining a path and writing binary data: | ||||
| 
 | ||||
| ```js | ||||
| import { read } from 'xlsx'; | ||||
| import { save } from '@tauri-apps/api/dialog'; | ||||
| import { writeBinaryFile } from '@tauri-apps/api/fs'; | ||||
| 
 | ||||
| const filters = [ | ||||
|   {name: "Excel Binary Workbook", extensions: ["xlsb"]}, | ||||
|   {name: "Excel Workbook", extensions: ["xlsx"]}, | ||||
|   {name: "Excel 97-2004 Workbook", extensions: ["xls"]}, | ||||
|   // ... other desired formats ... | ||||
| ]; | ||||
| 
 | ||||
| async function saveFile() { | ||||
|   /* show save file dialog */ | ||||
|   const selected = await save({ | ||||
|     title: "Save to Spreadsheet", | ||||
|     filters | ||||
|   }); | ||||
| 
 | ||||
|   /* Generate workbook */ | ||||
|   const bookType = selected.slice(selected.lastIndexOf(".") + 1); | ||||
|   const d = write(wb, {type: "buffer", bookType}); | ||||
| 
 | ||||
|   /* save data to file */ | ||||
|   await writeBinaryFile(selected, d); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| @ -40,6 +40,7 @@ The demo projects include small runnable examples and short explainers. | ||||
| - [`Content Management and Static Sites`](./content) | ||||
| - [`Electron`](./desktop#electron) | ||||
| - [`NW.js`](./desktop#nwjs) | ||||
| - [`Tauri`](./desktop#tauri) | ||||
| - [`Chrome / Chromium Extension`](./chromium) | ||||
| - [`Google Sheets API`](./gsheet) | ||||
| - [`ExtendScript for Adobe Apps`](./extendscript) | ||||
|  | ||||
							
								
								
									
										106
									
								
								docz/static/tauri/App.vue
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										106
									
								
								docz/static/tauri/App.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| <script setup lang="ts"> | ||||
| import { ref, shallowRef, onMounted } from 'vue' | ||||
| import { read, write, utils, version, WorkBook } from 'xlsx'; | ||||
| import { DialogFilter, message, open, save } from '@tauri-apps/api/dialog'; | ||||
| import { fetch, ResponseType } from '@tauri-apps/api/http'; | ||||
| import { readBinaryFile, writeBinaryFile } from '@tauri-apps/api/fs'; | ||||
| 
 | ||||
| const ver = ref(version); | ||||
| const data = shallowRef<any[][]>([[]]) | ||||
| const origin = ref(""); | ||||
| 
 | ||||
| const update = (wb: WorkBook) => { | ||||
|   const ws = wb.Sheets[wb.SheetNames[0]]; | ||||
|   data.value = utils.sheet_to_json<any[]>(ws, { header: 1}) | ||||
| }; | ||||
| 
 | ||||
| /* Download from https://sheetjs.com/pres.numbers */ | ||||
| onMounted(async() => { | ||||
| try { | ||||
|   origin.value = "https://sheetjs.com/pres.numbers"; | ||||
|   const response = await fetch<Uint8Array>("https://sheetjs.com/pres.numbers", { method: "GET", responseType: ResponseType.Binary }); | ||||
|   const wb = read(new Uint8Array(response.data)); | ||||
|   update(wb); | ||||
| } catch(e) { await message((e as Error).message || (e as string), { title: "Fetch Error", type: "error"}); } | ||||
| }); | ||||
| 
 | ||||
| const filters: DialogFilter[] = [ | ||||
|   {name: "Excel Binary Workbook", extensions: ["xlsb"]}, | ||||
|   {name: "Excel Workbook", extensions: ["xlsx"]}, | ||||
|   {name: "Excel 97-2004 Workbook", extensions: ["xls"]}, | ||||
|   {name: "Excel 2003 XML Spreadsheet", extensions: ["xml"]}, | ||||
|   {name: "Symbolic Link", extensions: ["slk"]}, | ||||
|   {name: "Flat OpenDocument Spreadsheet", extensions: ["fods"]}, | ||||
|   {name: "OpenDocument Spreadsheet", extensions: ["fods"]}, | ||||
|   // ... | ||||
| ]; | ||||
| 
 | ||||
| /* Load from File */ | ||||
| const openFile = async() => { | ||||
| try { | ||||
|   const selected = await open({ | ||||
|     title: "Open Spreadsheet", | ||||
|     multiple: false, | ||||
|     directory: false, | ||||
|     filters | ||||
|   }) as string; | ||||
|   const d = await readBinaryFile(selected); | ||||
|   const wb = read(d); | ||||
|   update(wb); | ||||
|   origin.value = selected; | ||||
| } catch(e) { await message((e as Error).message || (e as string), { title: "Load Error", type: "error"}); } | ||||
| }; | ||||
| 
 | ||||
| /* Save to File */ | ||||
| const saveFile = async() => { | ||||
| try { | ||||
|   const selected = await save({ | ||||
|     title: "Save to Spreadsheet", | ||||
|     filters | ||||
|   }); | ||||
|   const ws = utils.aoa_to_sheet(data.value); | ||||
|   const wb = utils.book_new(); | ||||
|   utils.book_append_sheet(wb, ws, "SheetJSTauri"); | ||||
|   const d = write(wb, {type: "buffer", bookType: selected.slice(selected.lastIndexOf(".") + 1) as any}) as Uint8Array; | ||||
|   await writeBinaryFile(selected, d); | ||||
|   await message(`File saved to ${selected}`); | ||||
| } catch(e) { await message((e as Error).message || (e as string), { title: "Save Error", type: "error"}); } | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <div> | ||||
|     <h1><a href="https://sheetjs.com" target="_blank"> | ||||
|       <img src="https://sheetjs.com/sketch128.png" class="logo" alt="SheetJS" /> | ||||
|     SheetJS × Tauri {{ ver }}</a></h1> | ||||
| 
 | ||||
|     <button type="button" @click="openFile()">Load Data</button> or | ||||
|     <button type="button" @click="saveFile()">Save Data</button> | ||||
|     <p><b>Data from {{ origin }}</b></p> | ||||
|     <table class="center"><tbody> | ||||
|     <tr v-for="(row, index) in data" v-bind:key="index"> | ||||
|       <td v-for="(cell, col) in row" v-bind:key="col"> | ||||
|         {{ cell }} | ||||
|       </td> | ||||
|     </tr> | ||||
|     </tbody></table> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <style scoped> | ||||
| .logo { | ||||
|   height: 64px; width: 64px; | ||||
|   vertical-align: text-top; | ||||
|   will-change: filter; | ||||
| } | ||||
| .logo:hover { | ||||
|   filter: drop-shadow(0 0 2em #646cffaa); | ||||
| } | ||||
| .logo.vue:hover { | ||||
|   filter: drop-shadow(0 0 2em #42b883aa); | ||||
| } | ||||
| table.center { | ||||
|   margin-left: auto; | ||||
|   margin-right: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/tauri/macos.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/tauri/macos.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 212 KiB | 
		Loading…
	
		Reference in New Issue
	
	Block a user