forked from sheetjs/docs.sheetjs.com
		
	nits
This commit is contained in:
		
							parent
							
								
									a6a981226f
								
							
						
					
					
						commit
						22720fd7a6
					
				| @ -202,7 +202,7 @@ many additional features including massive data streaming, sorting and styling. | ||||
| 
 | ||||
| ### Tabulator | ||||
| 
 | ||||
| [Tabulator](http://tabulator.info/docs/5.3/download#xlsx) includes deep support | ||||
| [Tabulator](https://tabulator.info/docs/5.4/download#xlsx) includes deep support | ||||
| through a special Export button.  It handles the SheetJS operations internally. | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -100,7 +100,8 @@ In the following example, the script: | ||||
| 
 | ||||
| - generates a workbook object in the Web Worker | ||||
| - generates a XLSB file using `XLSX.write` in the Web Worker | ||||
| - sends the file (`Uint8Array`) to the main browser context | ||||
| - generates an object URL in the Web Worker | ||||
| - sends the object URL to the main browser context | ||||
| - performs a download action in the main browser context | ||||
| 
 | ||||
| ```jsx live | ||||
| @ -124,11 +125,14 @@ SheetJS,in,Web,Workers | ||||
| 1,2,3,4\`; | ||||
|     const wb = XLSX.read(csv, { type: "string" }); | ||||
| 
 | ||||
|     /* Write XLSB data */ | ||||
|     /* Write XLSB data (Uint8Array) */ | ||||
|     const u8 = XLSX.write(wb, { bookType: "xlsb", type: "buffer" }); | ||||
| 
 | ||||
|     /* Generate URL */ | ||||
|     const url = URL.createObjectURL(new Blob([u8])); | ||||
| 
 | ||||
|     /* Reply with result */ | ||||
|     postMessage({data: u8}); | ||||
|     postMessage({ url }); | ||||
|   } catch(e) { | ||||
|     /* Pass the error message back */ | ||||
|     postMessage({error: String(e.message || e).bold() }); | ||||
| @ -142,7 +146,7 @@ SheetJS,in,Web,Workers | ||||
|         /* this mantra is the standard HTML5 download attribute technique */ | ||||
|         const a = document.createElement("a"); | ||||
|         a.download = "SheetJSWriteFileWorker.xlsb"; | ||||
|         a.href = URL.createObjectURL(new Blob([e.data.data])); | ||||
|         a.href = e.data.url; | ||||
|         document.body.appendChild(a); | ||||
|         a.click(); | ||||
|         document.body.removeChild(a); | ||||
| @ -176,10 +180,10 @@ In the following example, the script: | ||||
| ```jsx live | ||||
| function SheetJSDragDropWorker() { | ||||
|   const [html, setHTML] = React.useState(""); | ||||
|   /* suppress default behavior for dragover and drop */ | ||||
|   /* suppress default behavior for drag and drop */ | ||||
|   function suppress(e) { e.stopPropagation(); e.preventDefault(); } | ||||
|   return ( <> | ||||
|     <div onDragOver={suppress} onDrop={(e) => { | ||||
|     <div onDragOver={suppress} onDragEnter={suppress} onDrop={(e) => { | ||||
|       suppress(e); | ||||
| 
 | ||||
|       /* this mantra embeds the worker source in the function */ | ||||
| @ -188,7 +192,7 @@ function SheetJSDragDropWorker() { | ||||
| importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"); | ||||
| 
 | ||||
| /* this callback will run once the main context sends a message */ | ||||
| self.addEventListener('message', async(e) => { | ||||
| self.addEventListener('message', (e) => { | ||||
|   try { | ||||
|     /* Read file data */ | ||||
|     const ab = new FileReaderSync().readAsArrayBuffer(e.data.file); | ||||
|  | ||||
| @ -2,10 +2,11 @@ | ||||
| title: Local File Access | ||||
| --- | ||||
| 
 | ||||
| Reading and writing files require native support.  `readFile` and `writeFile` | ||||
| include support for some approaches but do not support every API.  When an API | ||||
| is not supported by `readFile` or `writeFile`, the underlying `read` and | ||||
| `write` methods can be used. | ||||
| Reading and writing files require native platform support.  `XLSX.readFile` and | ||||
| `XLSX.writeFile` include support for some APIs. | ||||
| 
 | ||||
| For other APIs, user code can pass data to `XLSX.read` or use data generated by | ||||
| `XLSX.write` directly.  Both methods work with a number of common storage types. | ||||
| 
 | ||||
| This demo looks at various web APIs.  More specific approaches for deployments | ||||
| like mobile apps are covered in their respective demos. | ||||
| @ -35,20 +36,63 @@ Modern browser APIs typically use typed arrays or `Blob` or `File` structures. | ||||
| 
 | ||||
| _Reading Binary Data_ | ||||
| 
 | ||||
| Given a `Blob` or `File`, the underlying data cannot be read synchronously! | ||||
| `XLSX.read` supports `Uint8Array` and `ArrayBuffer` data.  For `Blob` or `File` | ||||
| objects, the underlying data must be pulled into an `ArrayBuffer`. | ||||
| 
 | ||||
| The callback-based approach uses a `FileReader`: | ||||
| 
 | ||||
| ```js | ||||
| const reader = new FileReader(); | ||||
| reader.onload = function(e) { | ||||
|   /* e.target.result is an ArrayBuffer */ | ||||
|   const wb = XLSX.read(e.target.result); | ||||
|   console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]])); | ||||
| // usage: file_to_wb(file, function(wb) { /* wb is a workbook object */ }); | ||||
| function file_to_wb(file, callback) { | ||||
|   var reader = new FileReader(); | ||||
|   reader.onload = function(e) { | ||||
|     /* e.target.result is an ArrayBuffer */ | ||||
|     callback(XLSX.read(e.target.result)); | ||||
|   }; | ||||
|   reader.readAsArrayBuffer(file); | ||||
| } | ||||
| reader.readAsArrayBuffer(file); | ||||
| ``` | ||||
| 
 | ||||
| <details><summary><b>FileReaderSync in Web Workers</b> (click to show)</summary> | ||||
| 
 | ||||
| `FileReaderSync` is only available in Web Workers: | ||||
| 
 | ||||
| ```js | ||||
| // assuming main thread called worker.postMessage({ file: file_object }) | ||||
| self.addEventListener('message', (e) => { | ||||
|   /* get file object from message */ | ||||
|   var file = e.data.file; | ||||
|   /* Read file data */ | ||||
|   const ab = new FileReaderSync().readAsArrayBuffer(file); | ||||
|   /* Parse file */ | ||||
|   const wb = XLSX.read(ab); | ||||
|   /* DO SOMETHING WITH wb HERE */ | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| ["User-Submitted File" example](./worker#user-submitted-file) has a live demo. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details><summary><b>IE10 Binary Strings</b> (click to show)</summary> | ||||
| 
 | ||||
| In IE10, binary strings are more performant than `ArrayBuffer`. `XLSX.read` | ||||
| supports binary strings with `type: "binary"`: | ||||
| 
 | ||||
| ```js | ||||
| // usage: file_bs_to_wb(file, function(wb) { /* wb is a workbook object */ }); | ||||
| function file_bs_to_wb(file, callback) { | ||||
|   var reader = new FileReader(); | ||||
|   reader.onload = function(e) { | ||||
|     /* e.target.result is a binary string */ | ||||
|     callback(XLSX.read(e.target.result, { type: "binary" })); | ||||
|   }; | ||||
|   reader.readAsBinaryString(file); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| The Promise-based approach uses `Blob#arrayBuffer`: | ||||
| 
 | ||||
| ```js | ||||
| @ -60,8 +104,9 @@ async function blob_to_wb(blob) { | ||||
| 
 | ||||
| _Writing Binary Data_ | ||||
| 
 | ||||
| `XLSX.write` can generate `Uint8Array` results by passing `type: "buffer"`.  A | ||||
| `Blob` can be created by using the constructor: | ||||
| `XLSX.write` can generate `Uint8Array` results by passing `type: "buffer"`. | ||||
| 
 | ||||
| A `Blob` can be created by using the constructor: | ||||
| 
 | ||||
| ```js | ||||
| const u8 = XLSX.write(workbook, { type: "buffer", bookType: "xlsx" }); | ||||
| @ -78,6 +123,17 @@ _Writing Files_ | ||||
| XLSX.writeFile(wb, "SheetJS.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| :::caution Web Workers | ||||
| 
 | ||||
| `XLSX.writeFile` requires DOM access and will not work in a Web Worker! | ||||
| 
 | ||||
| The workaround is to generate the file data from the Worker (using `XLSX.write`) | ||||
| and send the data back to the main context for the actual download action. | ||||
| 
 | ||||
| ["Creating a Local File" includes a live demo](./worker#creating-a-local-file). | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| ## File API | ||||
| 
 | ||||
| _Reading Files_ | ||||
| @ -93,7 +149,7 @@ async function handleFileAsync(e) { | ||||
|   /* data is an ArrayBuffer */ | ||||
|   const workbook = XLSX.read(data); | ||||
|   /* do something with the workbook here */ | ||||
|   console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])) | ||||
|   console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])); | ||||
| } | ||||
| input_dom_element.addEventListener("change", handleFileAsync, false); | ||||
| ``` | ||||
| @ -105,8 +161,12 @@ _Reading Files_ | ||||
| The `dataTransfer` property of the `drop` event holds a list of files: | ||||
| 
 | ||||
| ```js | ||||
| /* suppress default behavior for drag and drop events */ | ||||
| function suppress(e) { e.stopPropagation(); e.preventDefault(); } | ||||
| 
 | ||||
| /* handle data from drop event */ | ||||
| async function handleDropAsync(e) { | ||||
|   e.stopPropagation(); e.preventDefault(); | ||||
|   suppress(e); | ||||
|   /* get first file */ | ||||
|   const f = e.dataTransfer.files[0]; | ||||
|   /* get raw data */ | ||||
| @ -114,9 +174,12 @@ async function handleDropAsync(e) { | ||||
|   /* data is an ArrayBuffer */ | ||||
|   const wb = XLSX.read(data); | ||||
|   /* do something with the workbook here */ | ||||
|   console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])) | ||||
|   console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])); | ||||
| } | ||||
| 
 | ||||
| drop_dom_element.addEventListener("drop", handleDropAsync, false); | ||||
| drop_dom_element.addEventListener("dragover", suppress, false); | ||||
| drop_dom_element.addEventListener("dragenter", suppress, false); | ||||
| ``` | ||||
| 
 | ||||
| ## File System Access API | ||||
| @ -128,6 +191,45 @@ the feature in version 86.  Safari did not support File System Access API. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| <details><summary><b>Live Example</b> (click to show) </summary> | ||||
| 
 | ||||
| This live example reads a file then tries to save as XLSX. | ||||
| 
 | ||||
| ```jsx live | ||||
| function SheetJSRoundTripFileSystemAPI() { return ( <button onClick={async () => { | ||||
|   /* Show picker and get data */ | ||||
|   const [rFile] = await window.showOpenFilePicker({ | ||||
|     types: [{ | ||||
|       description: 'Spreadsheets', | ||||
|       accept: { 'application/vnd.ms-excel': ['.xlsx', '.xls', '.xlsb', /*...*/] } | ||||
|     }], | ||||
|     excludeAcceptAllOption: true, | ||||
|     multiple: false | ||||
|   }); | ||||
|   const ab = await (await rFile.getFile()).arrayBuffer(); | ||||
| 
 | ||||
|   /* parse */ | ||||
|   const wb = XLSX.read(ab); | ||||
| 
 | ||||
|   /* Show picker and get handle to file */ | ||||
|   const wFile = await window.showSaveFilePicker({ | ||||
|     suggestedName: "SheetJSRT.xlsx", | ||||
|     types: [ { description: 'XLSX', accept: { 'application/vnd.ms-excel': ['.xlsx'] } } ] | ||||
|   }); | ||||
|   const wstream = await wFile.createWritable(); | ||||
| 
 | ||||
|   /* write */ | ||||
|   const buf = XLSX.write(wb, { bookType: "xlsx", type: "buffer" }); | ||||
|   wstream.write(buf); | ||||
| 
 | ||||
|   /* close stream to commit file */ | ||||
|   wstream.close(); | ||||
| 
 | ||||
| }}>Click to read then save as XLSX</button> ) } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| _Reading Files_ | ||||
| 
 | ||||
| `window.showOpenFilePicker` shows a file picker and resolves to an array of | ||||
| @ -182,47 +284,6 @@ wstream.write(XLSX.write(wb, { bookType: ext, type: "buffer" })) | ||||
| wstream.close(); | ||||
| ``` | ||||
| 
 | ||||
| ### Demo | ||||
| 
 | ||||
| <details><summary><b>Live Example</b> (click to show) </summary> | ||||
| 
 | ||||
| This live example reads a file then tries to save as XLSX. | ||||
| 
 | ||||
| ```jsx live | ||||
| function SheetJSRoundTripFileSystemAPI() { return ( <button onClick={async () => { | ||||
|   /* Show picker and get data */ | ||||
|   const [rFile] = await window.showOpenFilePicker({ | ||||
|     types: [{ | ||||
|       description: 'Spreadsheets', | ||||
|       accept: { 'application/vnd.ms-excel': ['.xlsx', '.xls', '.xlsb', /*...*/] } | ||||
|     }], | ||||
|     excludeAcceptAllOption: true, | ||||
|     multiple: false | ||||
|   }); | ||||
|   const ab = await (await rFile.getFile()).arrayBuffer(); | ||||
| 
 | ||||
|   /* parse */ | ||||
|   const wb = XLSX.read(ab); | ||||
| 
 | ||||
|   /* Show picker and get handle to file */ | ||||
|   const wFile = await window.showSaveFilePicker({ | ||||
|     suggestedName: "SheetJSRT.xlsx", | ||||
|     types: [ { description: 'XLSX', accept: { 'application/vnd.ms-excel': ['.xlsx'] } } ] | ||||
|   }); | ||||
|   const wstream = await wFile.createWritable(); | ||||
| 
 | ||||
|   /* write */ | ||||
|   const buf = XLSX.write(wb, { bookType: "xlsx", type: "buffer" }); | ||||
|   wstream.write(buf); | ||||
| 
 | ||||
|   /* close stream to commit file */ | ||||
|   wstream.close(); | ||||
| 
 | ||||
| }}>Click to read then save as XLSX</button> ) } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## File and Directory Entries API | ||||
| 
 | ||||
| :::caution Deprecated | ||||
| @ -263,7 +324,8 @@ Internet Explorer offered proprietary APIs that were not adopted by Chromium. | ||||
| 
 | ||||
| _Writing Files_ | ||||
| 
 | ||||
| IE10 and IE11 support `navigator.msSaveBlob`. `writeFile` will use the method. | ||||
| IE10 and IE11 support `navigator.msSaveBlob`. `XLSX.writeFile` will use this | ||||
| method if it is available. | ||||
| 
 | ||||
| #### VBScript | ||||
| 
 | ||||
| @ -304,8 +366,8 @@ import { readFile, writeFile, set_fs } from 'xlsx'; | ||||
| import * as fs from 'fs'; | ||||
| set_fs(fs); | ||||
| 
 | ||||
| var wb = XLSX.readFile("sheetjs.numbers"); | ||||
| XLSX.writeFile(wb, "sheetjs.xlsx"); | ||||
| var wb = readFile("sheetjs.numbers"); | ||||
| writeFile(wb, "sheetjs.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| ### ExtendScript | ||||
| @ -322,8 +384,7 @@ XLSX.writeFile(wb, "sheetjs.csv"); | ||||
| 
 | ||||
| ### Deno | ||||
| 
 | ||||
| `Deno.readFileSync` and `Deno.writeFileSync` are supported by `readFile` and | ||||
| `writeFile` out of the box: | ||||
| `readFile` uses `Deno.readFileSync` and `writeFile` uses `Deno.writeFileSync`: | ||||
| 
 | ||||
| ```js | ||||
| // @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" | ||||
| @ -333,11 +394,11 @@ const wb = XLSX.readFile("sheetjs.numbers"); | ||||
| XLSX.writeFile(wb, "sheetjs.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| :::note | ||||
| :::caution Deno entitlements | ||||
| 
 | ||||
| Any script using `XLSX.readFile` requires the `--allow-read` permission. | ||||
| Any Deno script using `XLSX.readFile` requires the `--allow-read` entitlement. | ||||
| 
 | ||||
| Any script using `XLSX.writeFile` requires the `--allow-write` permission. | ||||
| Any Deno script using `XLSX.writeFile` requires the `--allow-write` entitlement. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -346,12 +407,12 @@ Any script using `XLSX.writeFile` requires the `--allow-write` permission. | ||||
| Bun requires the `fs` module: | ||||
| 
 | ||||
| ```js | ||||
| import * as XLSX from 'xlsx'; | ||||
| import { readFile, writeFile, set_fs } from 'xlsx'; | ||||
| import * as fs from 'fs'; | ||||
| XLSX.set_fs(fs); | ||||
| set_fs(fs); | ||||
| 
 | ||||
| var wb = XLSX.readFile("sheetjs.numbers"); | ||||
| XLSX.writeFile(wb, "sheetjs.xlsx"); | ||||
| var wb = readFile("sheetjs.numbers"); | ||||
| writeFile(wb, "sheetjs.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| ### Apps | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user