forked from sheetjs/docs.sheetjs.com
		
	neu
This commit is contained in:
		
							parent
							
								
									aa7cc47197
								
							
						
					
					
						commit
						5f52a9f6b6
					
				| @ -78,7 +78,7 @@ The React `useState` hook can configure the state: | ||||
| ```ts | ||||
| import { useState } from 'react'; | ||||
| 
 | ||||
| /* the component state is an array of presidents */ | ||||
| /* the component state is an array of objects */ | ||||
| const [pres, setPres] = useState([]); | ||||
| ``` | ||||
| 
 | ||||
| @ -88,6 +88,15 @@ const [pres, setPres] = useState([]); | ||||
| ```ts | ||||
| import { useState } from 'react'; | ||||
| 
 | ||||
| /* the component state is an array of objects */ | ||||
| const [pres, setPres] = useState<any[]>([]); | ||||
| ``` | ||||
| 
 | ||||
| When the spreadsheet header row is known ahead of time, row typing is possible: | ||||
| 
 | ||||
| ```ts | ||||
| import { useState } from 'react'; | ||||
| 
 | ||||
| interface President { | ||||
|   Name: string; | ||||
|   Index: number; | ||||
| @ -97,11 +106,13 @@ interface President { | ||||
| const [pres, setPres] = useState<President[]>([]); | ||||
| ``` | ||||
| 
 | ||||
| :::note | ||||
| :::caution pass | ||||
| 
 | ||||
| The types are informative. They do not enforce that worksheets include the named | ||||
| columns. A runtime data validation library should be used to verify the dataset. | ||||
| 
 | ||||
| When the file header is not known in advance, `any` should be used. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
|   </TabItem> | ||||
|  | ||||
| @ -212,7 +212,7 @@ require(["dojo/request/xhr", "xlsx"], function(xhr, _XLSX) { | ||||
| </details> | ||||
| 
 | ||||
| The ["Dojo" section in "Bundlers"](/docs/demos/bundler#dojo) includes a complete example | ||||
| mirroring the [official example](/docs/getting-started/example) | ||||
| mirroring the [official export example](/docs/getting-started/example) | ||||
| 
 | ||||
| <details><summary><b>Details</b> (click to show)</summary> | ||||
| 
 | ||||
|  | ||||
| @ -257,9 +257,10 @@ This demo was tested in the following environments: | ||||
| 
 | ||||
| | OS and Version | Arch | Tauri    | Date       | | ||||
| |:---------------|:-----|:---------|:-----------| | ||||
| | macOS 13.4.1   | ARM  | `v1.4.0` | 2023-06-29 | | ||||
| | macOS 13.4.0   | x64  | `v1.4.0` | 2023-06-25 | | ||||
| | Windows 10     | x64  | `v1.2.3` | 2023-03-18 | | ||||
| | Linux (HoloOS) | x64  | `v1.2.3` | 2023-03-18 | | ||||
| | Linux (HoloOS) | x64  | `v1.2.3` |            | | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -294,6 +295,13 @@ If required dependencies are installed, the output will show a checkmark next to | ||||
|     - npm: 9.5.1 | ||||
| ``` | ||||
| 
 | ||||
| :::caution pass | ||||
| 
 | ||||
| When the demo was last tested on ARM64 macOS, the output mentioned `X64`. The | ||||
| build step will correctly detect the platform architecture. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| 1) Create a new Tauri app: | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| --- | ||||
| title: NeutralinoJS | ||||
| sidebar_label: NeutralinoJS | ||||
| description: Build data-intensive desktop apps using NeutralinoJS. Seamlessly integrate spreadsheets into your app using SheetJS. Quickly modernize Excel-powered business processes. | ||||
| pagination_prev: demos/mobile/index | ||||
| pagination_next: demos/data/index | ||||
| sidebar_position: 5 | ||||
| @ -7,15 +9,25 @@ sidebar_custom_props: | ||||
|   summary: Webview + Lightweight Extensions | ||||
| --- | ||||
| 
 | ||||
| # Data Munging in NeutralinoJS | ||||
| 
 | ||||
| import current from '/version.js'; | ||||
| import Tabs from '@theme/Tabs'; | ||||
| import TabItem from '@theme/TabItem'; | ||||
| import CodeBlock from '@theme/CodeBlock'; | ||||
| 
 | ||||
| The [Standalone build](/docs/getting-started/installation/standalone) can be added | ||||
| to the entry `index.html` | ||||
| [NeutralinoJS](https://neutralino.js.org/) is a modern desktop app framework. | ||||
| NeutralinoJS apps pair platform-native browser tools with a static web server. | ||||
| 
 | ||||
| The "Complete Example" creates an app that looks like the screenshot: | ||||
| [SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing | ||||
| data from spreadsheets. | ||||
| 
 | ||||
| This demo uses NeutralinoJS and SheetJS to pull data from a spreadsheet and | ||||
| display the data in the app. We'll explore how to load SheetJS in a NeutralinoJS | ||||
| app and use native features to read and write files. | ||||
| 
 | ||||
| The ["Complete Example"](#complete-example) section covers a complete desktop | ||||
| app to read and write workbooks. The app will look like the screenshots below: | ||||
| 
 | ||||
| <table><thead><tr> | ||||
|   <th><a href="#complete-example">Win10</a></th> | ||||
| @ -37,15 +49,16 @@ The "Complete Example" creates an app that looks like the screenshot: | ||||
| 
 | ||||
| ## Integration Details | ||||
| 
 | ||||
| :::note | ||||
| The [SheetJS Standalone build](/docs/getting-started/installation/standalone) | ||||
| can be added to the entry `index.html` | ||||
| 
 | ||||
| NeutralinoJS currently does not provide the equivalent of NodeJS `fs` module. | ||||
| The raw `Neutralino.filesystem` and `Neutralino.os` methods are used. | ||||
| For code running in the window, native methods must be explicitly enabled in the | ||||
| NeutralinoJS `neutralino.conf.json` settings file[^1]. | ||||
| 
 | ||||
| ::: | ||||
| - `os.*` enables the open and save dialog methods. | ||||
| - `filesystem.*` enables reading and writing file data. | ||||
| 
 | ||||
| The `os` and `filesystem` modules must be enabled in `neutralino.conf.json`. | ||||
| The starter already enables `os` so typically one line must be added: | ||||
| The starter app enables `os.*` so typically one line must be added: | ||||
| 
 | ||||
| ```json title="neutralino.config.json" | ||||
|   "nativeAllowList": [ | ||||
| @ -57,28 +70,33 @@ The starter already enables `os` so typically one line must be added: | ||||
|   ], | ||||
| ``` | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| At the time of writing, `filters` did not work as expected on MacOS.  They have | ||||
| been omitted in the example and commented in the code snippets | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| ### Reading Files | ||||
| 
 | ||||
| There are two steps to reading files: obtaining a path and reading binary data: | ||||
| There are three steps to reading files: | ||||
| 
 | ||||
| 1) Show an open file dialog with `Neutralino.os.showOpenDialog`[^2]. This method | ||||
|    resolves to the selected path. | ||||
| 
 | ||||
| 2) Read raw data from the file with `Neutralino.filesystem.readBinaryFile`[^3]. | ||||
|    This method resolves to a standard `ArrayBuffer`. | ||||
| 
 | ||||
| 3) Parse the data with the SheetJS `read` method[^4]. This method returns a | ||||
|    SheetJS workbook object. | ||||
| 
 | ||||
| The following code example defines a single function `openFile` that performs | ||||
| all three steps and returns a SheetJS workbook object: | ||||
| 
 | ||||
| ```js | ||||
| const filters = [ | ||||
|   {name: "Excel Binary Workbook", extensions: ["xlsb"]}, | ||||
|   {name: "Excel Workbook", extensions: ["xlsx"]}, | ||||
|   {name: "Excel Binary Workbook", extensions: ["xls", "xlsb"]}, | ||||
|   {name: "Excel Workbook", extensions: ["xls", "xlsx"]}, | ||||
| ] | ||||
| 
 | ||||
| async function openFile() { | ||||
|   /* show open file dialog */ | ||||
|   const [filename] = await Neutralino.os.showOpenDialog( | ||||
|     'Open a spreadsheet', | ||||
|     { /* filters, */ multiSelections: false } | ||||
|     { filters, multiSelections: false } | ||||
|   ); | ||||
| 
 | ||||
|   /* read data into an ArrayBuffer */ | ||||
| @ -90,23 +108,56 @@ async function openFile() { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| This method can be called from a button click or other event. | ||||
| At this point, standard SheetJS utility functions[^5] can extract data from the | ||||
| workbook object. The demo includes a button that calls `sheet_to_html`[^6] to | ||||
| generate an HTML TABLE and add to the DOM: | ||||
| 
 | ||||
| ```js | ||||
| const open_button_callback = async() => { | ||||
|   const wb = await openFile(); | ||||
| 
 | ||||
|   /* get the first worksheet */ | ||||
|   // highlight-start | ||||
|   const ws = wb.Sheets[wb.SheetNames[0]]; | ||||
|   // highlight-end | ||||
| 
 | ||||
|   /* get data from the first worksheet */ | ||||
|   // highlight-start | ||||
|   const html = XLSX.utils.sheet_to_html(ws); | ||||
|   // highlight-end | ||||
| 
 | ||||
|   /* display table */ | ||||
|   document.getElementById('info').innerHTML = html; | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| ### Writing Files | ||||
| 
 | ||||
| There are two steps to writing files: obtaining a path and writing binary data: | ||||
| There are three steps to reading files: | ||||
| 
 | ||||
| 1) Show a file dialog with `Neutralino.os.showSaveDialog`[^7]. This method | ||||
|    resolves to the selected path. | ||||
| 
 | ||||
| 2) Write the data with the SheetJS `write` method[^8]. The output book type can | ||||
|    be inferred from the selected file path. Using the `buffer` output type[^9], | ||||
|    the method returns a `Uint8Array` object that plays nice with NeutralinoJS. | ||||
| 
 | ||||
| 2) Write to file with `Neutralino.filesystem.writeBinaryFile`[^10]. | ||||
| 
 | ||||
| The following code example defines a single function `saveFile` that performs | ||||
| all three steps starting from a SheetJS workbook object: | ||||
| 
 | ||||
| ```js | ||||
| const filters = [ | ||||
|   {name: "Excel Binary Workbook", extensions: ["xlsb"]}, | ||||
|   {name: "Excel Workbook", extensions: ["xlsx"]}, | ||||
|   {name: "Excel Binary Workbook", extensions: ["xls", "xlsb"]}, | ||||
|   {name: "Excel Workbook", extensions: ["xls", "xlsx"]}, | ||||
| ] | ||||
| 
 | ||||
| async function saveFile(wb) { | ||||
|   /* show save file dialog */ | ||||
|   const filename = await Neutralino.os.showSaveDialog( | ||||
|     'Save to file', | ||||
|     { /* filters */ } | ||||
|     { filters } | ||||
|   ); | ||||
| 
 | ||||
|   /* Generate workbook */ | ||||
| @ -118,11 +169,35 @@ async function saveFile(wb) { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| The demo includes a button that calls `table_to_book`[^11] to generate a | ||||
| workbook object from the HTML table: | ||||
| 
 | ||||
| ```js | ||||
| const save_button_callback = async() => { | ||||
|   /* get the table */ | ||||
|   const tbl = document.getElementById('info').querySelector('table'); | ||||
| 
 | ||||
|   /* generate workbook from the table */ | ||||
|   // highlight-start | ||||
|   const wb = XLSX.utils.table_to_book(tbl); | ||||
|   // highlight-end | ||||
| 
 | ||||
|   await saveFile(wb); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ## Complete Example | ||||
| 
 | ||||
| :::note | ||||
| :::note pass | ||||
| 
 | ||||
| This demo was tested on 2023 March 19 with "binaries" `4.7.0` and "client" `3.6.0` | ||||
| This demo was tested in the following environments: | ||||
| 
 | ||||
| | OS and Version | Arch | Server    | Client   | Date       | | ||||
| |:---------------|:-----|:----------|:---------|:-----------| | ||||
| | macOS 13.4.1   | x64  | `v4.10.0` | `v3.8.2` | 2023-06-28 | | ||||
| | macOS 13.4.1   | ARM  | `v4.10.0` | `v3.8.2` | 2023-06-28 | | ||||
| | Windows 10     | x64  | `v4.7.0`  | `v3.6.0` | 2023-03-19 | | ||||
| | Linux (HoloOS) | x64  | `v4.7.0`  | `v3.6.0` |            | | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -137,13 +212,13 @@ cd sheetjs-neu | ||||
| ``` | ||||
| 
 | ||||
| 2) Download [Standalone build](/docs/getting-started/installation/standalone) | ||||
| and place in `resources/js/main.js`: | ||||
| and place in the `resources/js/` folder: | ||||
| 
 | ||||
| <CodeBlock language="bash">{`\ | ||||
| curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`} | ||||
| </CodeBlock> | ||||
| 
 | ||||
| 3) Add the highlighted line to `neutralino.conf.json` in `nativeAllowList`: | ||||
| 3) Add the highlighted line to `neutralino.config.json` in `nativeAllowList`: | ||||
| 
 | ||||
| ```json title="neutralino.config.json" | ||||
|   "nativeAllowList": [ | ||||
| @ -158,9 +233,16 @@ curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-${current} | ||||
| 
 | ||||
| 4) Set up skeleton app and print version info: | ||||
| 
 | ||||
| - Edit `resources/index.html` and replace the `<body>` with the code below: | ||||
| - Replace the contents of `resources/index.html` with the following code: | ||||
| 
 | ||||
| ```html title="resources/index.html" | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
|   <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <title>SheetJS + NeutralinoJS</title> | ||||
|     <link rel="stylesheet" href="styles.css"> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div id="neutralinoapp"> | ||||
|       <h1>SheetJS × NeutralinoJS</h1> | ||||
| @ -173,6 +255,7 @@ curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-${current} | ||||
|     <script src="js/xlsx.full.min.js"></script> | ||||
|     <script src="js/main.js"></script> | ||||
|   </body> | ||||
| </html> | ||||
| ``` | ||||
| 
 | ||||
| - Append the following code to `resources/styles.css` to center the table: | ||||
| @ -190,6 +273,8 @@ table { | ||||
| - Print the version number in the `showInfo` method of `resources/js/main.js`: | ||||
| 
 | ||||
| ```js title="resources/js/main.js" | ||||
| function showInfo() { | ||||
|     document.getElementById('info').innerHTML = ` | ||||
|         ${NL_APPID} is running on port ${NL_PORT}  inside ${NL_OS} | ||||
|         <br/><br/> | ||||
|         <span>server: v${NL_VERSION} . client: v${NL_CVERSION}</span> | ||||
| @ -198,6 +283,7 @@ table { | ||||
|         <span>SheetJS version ${XLSX.version}</span> | ||||
| // highlight-end | ||||
|         `; | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 5) Run the app: | ||||
| @ -206,11 +292,11 @@ table { | ||||
| npx @neutralinojs/neu run | ||||
| ``` | ||||
| 
 | ||||
| You should see `SheetJS Version ` followed by the library version number. | ||||
| <p>The app should print <code>SheetJS Version {current}</code></p> | ||||
| 
 | ||||
| 6) Add the following code to the bottom of `resources/js/main.js`: | ||||
| 
 | ||||
| ```js | ||||
| ```js title="resources/js/main.js" | ||||
| (async() => { | ||||
|   const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer(); | ||||
|   const wb = XLSX.read(ab); | ||||
| @ -219,13 +305,13 @@ You should see `SheetJS Version ` followed by the library version number. | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| Save the source file, close the app and re-run the command from step 5. | ||||
| Save the source file, close the app and re-run with `npx @neutralinojs/neu run` | ||||
| 
 | ||||
| When the app loads, a table should show in the main screen. | ||||
| 
 | ||||
| 7) Add `importFile` and `exportFile` to the bottom of `resources/js/main.js`: | ||||
| 
 | ||||
| ```js | ||||
| ```js title="resources/js/main.js" | ||||
| async function importData() { | ||||
|   /* show open dialog */ | ||||
|   const [filename] = await Neutralino.os.showOpenDialog('Open a spreadsheet'); | ||||
| @ -240,7 +326,7 @@ async function importData() { | ||||
| } | ||||
| 
 | ||||
| async function exportData() { | ||||
|     /* show save dialog */ | ||||
|   /* show save dialog */ | ||||
|   const filename = await Neutralino.os.showSaveDialog('Save to file'); | ||||
| 
 | ||||
|   /* make workbook */ | ||||
| @ -254,15 +340,36 @@ async function exportData() { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Save the source file, close the app and re-run the command from step 5. | ||||
| Save the source file, close the app and re-run with `npx @neutralinojs/neu run` | ||||
| 
 | ||||
| When the app loads, click the "Import File" button and select a spreadsheet to | ||||
| see the contents.  Click "Export File" and enter `SheetJSNeu.xlsx` to write. | ||||
| see the contents. | ||||
| 
 | ||||
| Click "Export File" and enter `SheetJSNeu.xlsx` to write a new file. | ||||
| 
 | ||||
| :::caution pass | ||||
| 
 | ||||
| When saving the file, the actual file extension must be included. Attempting to | ||||
| save as `SheetJSNeu` will not automatically add the `.xlsx` extension! | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 8) Build production apps: | ||||
| 
 | ||||
| ```bash | ||||
| npx @neutralinojs/neu run | ||||
| npx @neutralinojs/neu build | ||||
| ``` | ||||
| 
 | ||||
| Platform-specific programs will be created in the `dist` folder. | ||||
| 
 | ||||
| [^1]: See [`nativeAllowList`](https://neutralino.js.org/docs/configuration/neutralino.config.json#nativeallowlist-string) in the NeutralinoJS documentation | ||||
| [^2]: See [`os.showOpenDialog`](https://neutralino.js.org/docs/api/os#osshowopendialogtitle-options) in the NeutralinoJS documentation | ||||
| [^3]: See [`filesystem.readBinaryFile`](https://neutralino.js.org/docs/api/filesystem/#filesystemreadbinaryfilefilename) in the NeutralinoJS documentation | ||||
| [^4]: See [`read` in "Reading Files"](/docs/api/parse-options) | ||||
| [^5]: See ["Utility Functions"](/docs/api/utilities/) | ||||
| [^6]: See ["HTML Table Output" in "Utility Functions"](/docs/api/utilities/html#html-table-output) | ||||
| [^7]: See [`os.showSaveDialog`](https://neutralino.js.org/docs/api/os#osshowsavedialogtitle-options) in the NeutralinoJS documentation | ||||
| [^8]: See [`write` in "Writing Files"](/docs/api/write-options) | ||||
| [^9]: See ["Supported Output Formats"](/docs/api/write-options#supported-output-formats) | ||||
| [^10]: See [`filesystem.writeBinaryFile`](https://neutralino.js.org/docs/api/filesystem/#filesystemwritebinaryfilefilename-data) in the NeutralinoJS documentation | ||||
| [^11]: See ["HTML Table Input" in "Utility Functions"](/docs/api/utilities/html#html-table-input) | ||||
|  | ||||
| @ -16,7 +16,7 @@ PouchDB is a pure JS database with built-in synchronization features. | ||||
| `Database#allDocs` is the standard approach for bulk data export. The generated | ||||
| row objects have additional `_id` and `_rev` keys that should be removed. | ||||
| 
 | ||||
| Nested objects must be flattened. The ["Tutorial"](/docs/getting-started/example) | ||||
| Nested objects must be flattened. The ["Export Tutorial"](/docs/getting-started/example) | ||||
| includes an example of constructing a simple array. | ||||
| 
 | ||||
| ```js | ||||
|  | ||||
| @ -735,8 +735,8 @@ the function and the optional `opts` argument in more detail. | ||||
| 
 | ||||
| #### Examples | ||||
| 
 | ||||
| ["Complete Example"](/docs/getting-started/example) contains a detailed example | ||||
| "Get Data from a JSON Endpoint and Generate a Workbook" | ||||
| ["Export Tutorial"](/docs/getting-started/example) contains a detailed | ||||
| example of fetching data from a JSON Endpoint and generating a workbook. | ||||
| 
 | ||||
| [`x-spreadsheet`](/docs/demos/grid/xs) is an interactive data grid for | ||||
| previewing and modifying structured data in the web browser. | ||||
|  | ||||
| @ -60,7 +60,7 @@ of date or time.  Instead, dates and times are stored as offsets from an epoch. | ||||
| The magic behind date interpretations is hidden in functions or number formats. | ||||
| 
 | ||||
| SheetJS attempts to create a friendly JS date experience while also exposing | ||||
| options to use the traditional date codes | ||||
| options to use the traditional date codes. | ||||
| 
 | ||||
| :::tip pass | ||||
| 
 | ||||
| @ -104,7 +104,7 @@ function SheetJSNow() { | ||||
| ## How Spreadsheets Understand Time | ||||
| 
 | ||||
| Excel stores dates as numbers.  When displaying dates, the format code should | ||||
| include special date and time tokens like `yyyyy` for long year. `EDATE` and | ||||
| include special date and time tokens like `yyyy` for long year. `EDATE` and | ||||
| other date functions operate on and return date numbers. | ||||
| 
 | ||||
| For date formats like `yyyy-mm-dd`, the integer part represents the number of | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/data/mf221.xlw
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/data/mf221.xlw
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 107 KiB | 
		Loading…
	
		Reference in New Issue
	
	Block a user