| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: Electron | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | pagination_prev: demos/mobile/index | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  | pagination_next: demos/data/index | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | sidebar_position: 1 | 
					
						
							|  |  |  | sidebar_custom_props: | 
					
						
							|  |  |  |   summary: Embedded NodeJS + Chromium | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import Tabs from '@theme/Tabs'; | 
					
						
							|  |  |  | import TabItem from '@theme/TabItem'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported | 
					
						
							|  |  |  | from the main or the renderer thread. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | The "Complete Example" creates an app that looks like the screenshots below: | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | <table><thead><tr> | 
					
						
							| 
									
										
										
										
											2023-02-21 01:04:05 +00:00
										 |  |  |   <th><a href="#complete-example">Win10</a></th> | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  |   <th><a href="#complete-example">macOS</a></th> | 
					
						
							|  |  |  |   <th><a href="#complete-example">Linux</a></th> | 
					
						
							|  |  |  | </tr></thead><tbody><tr><td> | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-21 01:04:05 +00:00
										 |  |  |  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </td><td> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  |  | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | </td><td> | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  |  | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | </td></tr></tbody></table> | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | ## Integration Details
 | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | Electron presents a `fs` module.  The `require('xlsx')` call loads the CommonJS | 
					
						
							|  |  |  | module, so `XLSX.readFile` and `XLSX.writeFile` work in the renderer thread. | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### Reading Files
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Electron offers 3 different ways to read files, two of which use Web APIs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **File Input Element** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | File input elements automatically map to standard Web APIs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For example, assuming a file input element on the page: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html | 
					
						
							|  |  |  | <input type="file" name="xlfile" id="xlf" /> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The event handler would process the event as if it were a web event: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | async function handleFile(e) { | 
					
						
							|  |  |  |   const file = e.target.files[0]; | 
					
						
							|  |  |  |   const data = await file.arrayBuffer(); | 
					
						
							|  |  |  |   /* data is an ArrayBuffer */ | 
					
						
							|  |  |  |   const workbook = XLSX.read(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* DO SOMETHING WITH workbook HERE */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | document.getElementById("xlf").addEventListener("change", handleFile, false); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **Drag and Drop** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The [drag and drop snippet](/docs/solutions/input#example-user-submissions) | 
					
						
							|  |  |  | applies to DIV elements on the page. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For example, assuming a DIV on the page: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html | 
					
						
							|  |  |  | <div id="drop">Drop a spreadsheet file here to see sheet data</div> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The event handler would process the event as if it were a web event: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | async function handleDrop(e) { | 
					
						
							|  |  |  |   e.stopPropagation(); | 
					
						
							|  |  |  |   e.preventDefault(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const file = e.dataTransfer.files[0]; | 
					
						
							|  |  |  |   const data = await file.arrayBuffer(); | 
					
						
							|  |  |  |   /* data is an ArrayBuffer */ | 
					
						
							|  |  |  |   const workbook = XLSX.read(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* DO SOMETHING WITH workbook HERE */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | document.getElementById("drop").addEventListener("drop", handleDrop, false); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **Electron API** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [`XLSX.readFile`](/docs/api/parse-options) reads workbooks from the file system. | 
					
						
							|  |  |  | `showOpenDialog` shows a Save As dialog and returns the selected file name. | 
					
						
							|  |  |  | Unlike the Web APIs, the `showOpenDialog` flow can be initiated by app code: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* from the renderer thread */ | 
					
						
							|  |  |  | const electron = require('@electron/remote'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* this function will show the open dialog and try to parse the workbook */ | 
					
						
							|  |  |  | async function importFile() { | 
					
						
							|  |  |  |   /* show Save As dialog */ | 
					
						
							|  |  |  |   const result = await electron.dialog.showOpenDialog({ | 
					
						
							|  |  |  |     title: 'Select a file', | 
					
						
							|  |  |  |     filters: [{ | 
					
						
							|  |  |  |       name: "Spreadsheets", | 
					
						
							|  |  |  |       extensions: ["xlsx", "xls", "xlsb", /* ... other formats ... */] | 
					
						
							|  |  |  |     }] | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   /* result.filePaths is an array of selected files */ | 
					
						
							|  |  |  |   if(result.filePaths.length == 0) throw new Error("No file was selected!"); | 
					
						
							|  |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   return XLSX.readFile(result.filePaths[0]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 03:59:48 +00:00
										 |  |  | :::note pass | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | In older versions of Electron, `showOpenDialog` returned the path directly: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var dialog = require('electron').remote.dialog; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function importFile(workbook) { | 
					
						
							|  |  |  |   var result = dialog.showOpenDialog({ properties: ['openFile'] }); | 
					
						
							|  |  |  |   return XLSX.readFile(result[0]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-12 08:15:17 +00:00
										 |  |  | ### Writing Files
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [`XLSX.writeFile`](/docs/api/write-options) writes workbooks to the file system. | 
					
						
							|  |  |  | `showSaveDialog` shows a Save As dialog and returns the selected file name: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* from the renderer thread */ | 
					
						
							|  |  |  | const electron = require('@electron/remote'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* this function will show the save dialog and try to write the workbook */ | 
					
						
							|  |  |  | async function exportFile(workbook) { | 
					
						
							|  |  |  |   /* show Save As dialog */ | 
					
						
							|  |  |  |   const result = await electron.dialog.showSaveDialog({ | 
					
						
							|  |  |  |     title: 'Save file as', | 
					
						
							|  |  |  |     filters: [{ | 
					
						
							|  |  |  |       name: "Spreadsheets", | 
					
						
							|  |  |  |       extensions: ["xlsx", "xls", "xlsb", /* ... other formats ... */] | 
					
						
							|  |  |  |     }] | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   /* write file */ | 
					
						
							|  |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   XLSX.writeFile(workbook, result.filePath); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 03:59:48 +00:00
										 |  |  | :::note pass | 
					
						
							| 
									
										
										
										
											2023-02-12 08:15:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | In older versions of Electron, `showSaveDialog` returned the path directly: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var dialog = require('electron').remote.dialog; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function exportFile(workbook) { | 
					
						
							|  |  |  |   var result = dialog.showSaveDialog(); | 
					
						
							|  |  |  |   XLSX.writeFile(workbook, result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | ## Complete Example
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | This demo was tested in the following environments: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | OS and Version | Arch | Electron | Date       | | 
					
						
							|  |  |  | |:---------------|:-----|:---------|:-----------| | 
					
						
							|  |  |  | | macOS 13.5.1   | x64  | `26.1.0` | 2023-09-03 | | 
					
						
							| 
									
										
										
										
											2023-09-25 07:30:54 +00:00
										 |  |  | | macOS 13.5.1   | ARM  | `26.1.0` | 2023-09-03 | | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | | Windows 10     | x64  | `26.1.0` | 2023-09-03 | | 
					
						
							| 
									
										
										
										
											2023-09-25 07:30:54 +00:00
										 |  |  | | Windows 10     | ARM  | `26.1.0` | 2023-09-24 | | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | | Linux (HoloOS) | x64  | `26.1.0` | 2023-09-03 | | 
					
						
							|  |  |  | | Linux (Debian) | ARM  | `26.1.0` | 2023-09-03 | | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo includes a drag-and-drop box as well as a file input box, mirroring | 
					
						
							|  |  |  | the [SheetJS Data Preview Live Demo](https://oss.sheetjs.com/sheetjs/) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The core data in this demo is an editable HTML table.  The readers build up the | 
					
						
							|  |  |  | table using `sheet_to_html` (with `editable:true` option) and the writers scrape | 
					
						
							|  |  |  | the table using `table_to_book`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The demo project is wired for `electron-forge` to build the standalone binary. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Download the demo files: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - [`package.json`](pathname:///electron/package.json) : project structure | 
					
						
							|  |  |  | - [`main.js`](pathname:///electron/main.js) : main process script | 
					
						
							|  |  |  | - [`index.html`](pathname:///electron/index.html) : window page | 
					
						
							|  |  |  | - [`index.js`](pathname:///electron/index.js) : script loaded in render context | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 03:59:48 +00:00
										 |  |  | :::caution pass | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Right-click each link and select "Save Link As...".  Left-clicking a link will | 
					
						
							|  |  |  | try to load the page in your browser.  The goal is to save the file contents. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | These instructions can be run in a terminal window: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | mkdir sheetjs-electron | 
					
						
							|  |  |  | cd sheetjs-electron | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/electron/package.json | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/electron/main.js | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/electron/index.html | 
					
						
							|  |  |  | curl -LO https://docs.sheetjs.com/electron/index.js | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | 2) Install dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm install | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 3) To verify the app works, run in the test environment: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx -y electron . | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | The app will show. | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 4) To build a standalone app, run the builder: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm run make | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | This will create a package in the `out\make` folder. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | On Linux, the packaging step may require additional dependencies[^1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-25 07:30:54 +00:00
										 |  |  | :::info pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When the demo was last tested on Windows ARM, the generated binary targeted x64. | 
					
						
							|  |  |  | The program will run on ARM64 Windows. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | **Testing** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 5) Download [the test file `pres.numbers`](https://sheetjs.com/pres.numbers) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 6) Re-launch the application in the test environment: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx -y electron . | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Electron API_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 7) Click "Click here to select a file from your computer". With the file picker, | 
					
						
							|  |  |  | navigate to the Downloads folder and select `pres.numbers`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The application should show data in a table. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 8) Click "Export Data!" and click "Save" in the popup. By default, it will try | 
					
						
							|  |  |  | to write to `Untitled.xls` in the Downloads folder. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The app will show a popup once the data is exported. Open the file in a | 
					
						
							|  |  |  | spreadsheet editor and compare the data to the table shown in the application. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Drag and Drop_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 9) Close the application, end the terminal process and re-launch (see step 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 10) Open the Downloads folder in a file explorer or finder window. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 11) Click and drag the `pres.numbers` file from the Downloads folder to the | 
					
						
							|  |  |  | bordered "Drop a spreadsheet file" box. The file data should be displayed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _File Input Element_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 12) Close the application, end the terminal process and re-launch (see step 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 13) Click "Choose File". With the file picker, navigate to the Downloads folder | 
					
						
							|  |  |  | and select `pres.numbers`. | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Electron Breaking Changes
 | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The first version of this demo used Electron 1.7.5.  The current demo includes | 
					
						
							| 
									
										
										
										
											2023-02-09 08:33:59 +00:00
										 |  |  | the required changes for Electron 23.0.0. | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | There are no Electron-specific workarounds in the library, but Electron broke | 
					
						
							|  |  |  | backwards compatibility multiple times.  A summary of changes is noted below. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-24 03:59:48 +00:00
										 |  |  | :::caution pass | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Electron 6.x changed the `dialog` API. Methods like `showSaveDialog` originally | 
					
						
							|  |  |  | returned an array of strings, but now returns a `Promise`.  This change was not | 
					
						
							|  |  |  | documented. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Electron 9.0.0 and later require the preference `nodeIntegration: true` in order | 
					
						
							|  |  |  | to `require('xlsx')` in the renderer process. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Electron 12.0.0 and later also require `worldSafeExecuteJavascript: true` and | 
					
						
							|  |  |  | `contextIsolation: true`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Electron 14+ must use `@electron/remote` instead of `remote`.  An `initialize` | 
					
						
							|  |  |  | call is required to enable Developer Tools in the window. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							| 
									
										
										
										
											2023-09-05 18:04:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | [^1]: See ["Makers"](https://www.electronforge.io/config/makers) in the Electron Forge documentation. |