| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: Local File Access | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  | pagination_prev: demos/data/index | 
					
						
							|  |  |  | pagination_next: demos/cloud/index | 
					
						
							|  |  |  | sidebar_custom_props: | 
					
						
							|  |  |  |   summary: Reading and writing files using various platform APIs | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-29 11:21:37 +00:00
										 |  |  | import current from '/version.js'; | 
					
						
							|  |  |  | import CodeBlock from '@theme/CodeBlock'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | 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. | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | This demo looks at various web APIs.  More specific approaches for deployments | 
					
						
							|  |  |  | like mobile apps are covered in their respective demos. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | :::note pass | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Some snippets are also available in the "Common Use Cases" section: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 05:45:37 +00:00
										 |  |  | - [Data Import](/docs/solutions/input) | 
					
						
							|  |  |  | - [Data Export](/docs/solutions/output) | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ## Web Browsers
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::warning pass | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Not all web APIs are supported in all browsers.  For example, Firefox does not | 
					
						
							|  |  |  | support the "File System Access API". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Even when a browser technically supports a web API, it may be disabled in the | 
					
						
							|  |  |  | client browser. Some APIs do not give any feedback. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ### Binary Data
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Modern browser APIs typically use typed arrays or `Blob` or `File` structures. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Reading Binary Data_ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | `XLSX.read` supports `Uint8Array` and `ArrayBuffer` data.  For `Blob` or `File` | 
					
						
							|  |  |  | objects, the underlying data must be pulled into an `ArrayBuffer`. | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The callback-based approach uses a `FileReader`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | // 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); | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | <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 */ | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-29 11:21:37 +00:00
										 |  |  | ["User-Submitted File" example](/docs/demos/bigdata/worker#user-submitted-file) | 
					
						
							|  |  |  | includes a live demo. | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>IE10 Binary Strings</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 00:58:49 +00:00
										 |  |  | `XLSX.read` supports binary strings with `type: "binary"`: | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```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> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | The Promise-based approach uses `Blob#arrayBuffer`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | // usage: const wb = await blob_to_wb(blob); | 
					
						
							|  |  |  | async function blob_to_wb(blob) { | 
					
						
							|  |  |  |   return XLSX.read(await blob.arrayBuffer()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Writing Binary Data_ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | `XLSX.write` can generate `Uint8Array` results by passing `type: "buffer"`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A `Blob` can be created by using the constructor: | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const u8 = XLSX.write(workbook, { type: "buffer", bookType: "xlsx" }); | 
					
						
							|  |  |  | const blob = new Blob([u8], { type: "application/vnd.ms-excel" }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ### HTML5 Download Attribute
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | _Writing Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `writeFile` will attempt a download in the browser using the attribute. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | XLSX.writeFile(wb, "SheetJS.xlsx"); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 10:01:12 +00:00
										 |  |  | <details><summary><b>Implementation Details</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Under the hood, it creates a special URL and clicks a link. The library method | 
					
						
							|  |  |  | includes a few workarounds for legacy browsers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `XLSX.writeFile(wb, "SheetJS.xlsx");` is roughly equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* write data -- note that writeFile infers bookType from filename */ | 
					
						
							|  |  |  | const u8 = XLSX.write(wb, { bookType: "xlsx", type: "buffer" }); | 
					
						
							|  |  |  | /* create Blob */ | 
					
						
							|  |  |  | const blob = new Blob([u8]); | 
					
						
							|  |  |  | /* create object URL */ | 
					
						
							| 
									
										
										
										
											2023-06-23 20:24:44 +00:00
										 |  |  | const url = URL.createObjectURL(blob); | 
					
						
							| 
									
										
										
										
											2023-06-06 10:01:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* create `A` DOM element */ | 
					
						
							|  |  |  | const a = document.createElement("a"); | 
					
						
							|  |  |  | /* set export file name */ | 
					
						
							|  |  |  | a.download = "SheetJS.xlsx"; | 
					
						
							|  |  |  | /* wire up the object URL to the DOM element */ | 
					
						
							|  |  |  | a.href = url; | 
					
						
							|  |  |  | /* add to the page */ | 
					
						
							|  |  |  | document.body.appendChild(a); | 
					
						
							|  |  |  | /* click the link */ | 
					
						
							|  |  |  | a.click(); | 
					
						
							|  |  |  | /* remove the element from the page */ | 
					
						
							|  |  |  | document.body.removeChild(a); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | :::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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-29 11:21:37 +00:00
										 |  |  | ["Creating a Local File"](/docs/demos/bigdata/worker#creating-a-local-file) | 
					
						
							|  |  |  | includes a live demo. | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ### File API
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | _Reading Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In the `change` event of `<input type="file">`, `target` hold a list of files: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | async function handleFileAsync(e) { | 
					
						
							|  |  |  |   /* get first file */ | 
					
						
							|  |  |  |   const file = e.target.files[0]; | 
					
						
							|  |  |  |   /* get raw data */ | 
					
						
							|  |  |  |   const data = await file.arrayBuffer(); | 
					
						
							|  |  |  |   /* data is an ArrayBuffer */ | 
					
						
							|  |  |  |   const workbook = XLSX.read(data); | 
					
						
							|  |  |  |   /* do something with the workbook here */ | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  |   console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])); | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | input_dom_element.addEventListener("change", handleFileAsync, false); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ### HTML Drag and Drop API
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | _Reading Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `dataTransfer` property of the `drop` event holds a list of files: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | /* suppress default behavior for drag and drop events */ | 
					
						
							|  |  |  | function suppress(e) { e.stopPropagation(); e.preventDefault(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* handle data from drop event */ | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | async function handleDropAsync(e) { | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  |   suppress(e); | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  |   /* get first file */ | 
					
						
							|  |  |  |   const f = e.dataTransfer.files[0]; | 
					
						
							|  |  |  |   /* get raw data */ | 
					
						
							|  |  |  |   const data = await f.arrayBuffer(); | 
					
						
							|  |  |  |   /* data is an ArrayBuffer */ | 
					
						
							|  |  |  |   const wb = XLSX.read(data); | 
					
						
							|  |  |  |   /* do something with the workbook here */ | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  |   console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])); | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | drop_dom_element.addEventListener("drop", handleDropAsync, false); | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | drop_dom_element.addEventListener("dragover", suppress, false); | 
					
						
							|  |  |  | drop_dom_element.addEventListener("dragenter", suppress, false); | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ### File System Access API
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 10:00:35 +00:00
										 |  |  | :::caution Limited Browser Support | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | At the time of writing, browser support was fairly limited.  Chrome introduced | 
					
						
							|  |  |  | the feature in version 86.  Safari did not support File System Access API. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | <details><summary><b>Live Example</b> (click to show) </summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This live example reads a file then tries to save as XLSX. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | function SheetJSRoundTripFileSystemAPI() { return window.showSaveFilePicker ? ( | 
					
						
							|  |  |  | <button onClick={async () => { | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  |   /* 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(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | }}>Click to read then save as XLSX</button> | 
					
						
							|  |  |  |   ) : ( <b>This browser does not support File System Access API</b> ); } | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | _Reading Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `window.showOpenFilePicker` shows a file picker and resolves to an array of | 
					
						
							|  |  |  | file handles. When `multiple: false` is set, the array has one element. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `getFile` method resolves to a `File` object whose data can be read with | 
					
						
							|  |  |  | the `arrayBuffer` method: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* Show picker and get data */ | 
					
						
							|  |  |  | const [hFile] = await window.showOpenFilePicker({ | 
					
						
							|  |  |  |   types: [{ | 
					
						
							|  |  |  |     description: 'Spreadsheets', | 
					
						
							|  |  |  |     accept: { 'application/vnd.ms-excel': ['.xlsx', '.xls', '.xlsb', /*...*/] } | 
					
						
							|  |  |  |   }], | 
					
						
							|  |  |  |   excludeAcceptAllOption: true, | 
					
						
							|  |  |  |   multiple: false | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | const ab = await (await hFile.getFile()).arrayBuffer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* parse */ | 
					
						
							|  |  |  | const wb = XLSX.read(ab); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* do something with the workbook */ | 
					
						
							|  |  |  | console.log(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Writing Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `window.showSaveFilePicker` shows a file picker and resolves to a file handle. | 
					
						
							|  |  |  | The `createWritable` method resolves to a `FileSystemWritableFileStream`, which | 
					
						
							|  |  |  | readily accepts `Uint8Array` data from `XLSX.write`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | /* Show picker and get handle to file */ | 
					
						
							|  |  |  | const hFile = await window.showSaveFilePicker({ | 
					
						
							|  |  |  |   suggestedName: "SheetJS.xlsx", | 
					
						
							|  |  |  |   types: [ | 
					
						
							|  |  |  |     { description: 'Excel 2007+ (XLSX)', accept: { 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'] } }, | 
					
						
							|  |  |  |     { description: 'Excel 97-2004 (XLS)', accept: { 'application/vnd.ms-excel': ['.xls'] } }, | 
					
						
							|  |  |  |     { description: 'Excel 2007+ Binary (XLSB)', accept: { 'application/vnd.ms-excel.sheet.binary.macroEnabled.12': ['.xlsb'] } }, | 
					
						
							|  |  |  |     /* note that each MIME type must be unique! */ | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | const wstream = await hFile.createWritable(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* get extension */ | 
					
						
							|  |  |  | const ext = hFile.name.slice(hFile.name.lastIndexOf(".")+1) | 
					
						
							|  |  |  | /* write */ | 
					
						
							|  |  |  | wstream.write(XLSX.write(wb, { bookType: ext, type: "buffer" })) | 
					
						
							|  |  |  | /* close stream to commit file */ | 
					
						
							|  |  |  | wstream.close(); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ### File and Directory Entries API
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 10:00:35 +00:00
										 |  |  | :::caution Deprecated | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In the web browser, the File and Directory Entries API has been deprecated and | 
					
						
							|  |  |  | is not recommended for new applications. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `cordova-plugin-file` still uses the API patterns. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | _Writing Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | // Request File System Access | 
					
						
							|  |  |  | window.requestFileSystem(window.PERSISTENT, 0, (fs) => { | 
					
						
							|  |  |  |   // Request a handle to "SheetJS.xlsx", making a new file if necessary | 
					
						
							|  |  |  |   fs.root.getFile("SheetJS.xlsx", {create: true}, entry => { | 
					
						
							|  |  |  |     // Request a FileWriter for writing data | 
					
						
							|  |  |  |     entry.createWriter(writer => { | 
					
						
							|  |  |  |       // The FileWriter API needs an actual Blob | 
					
						
							|  |  |  |       const u8 = XLSX.write(wb, { type: "buffer", bookType: "xlsx" }); | 
					
						
							|  |  |  |       const data = new Blob([u8], { type: "application/vnd.ms-excel" }); | 
					
						
							|  |  |  |       // `onwriteend` is called on success, `onerror` called on error | 
					
						
							|  |  |  |       writer.onwriteend = () => {}; writer.onerror = () => {}; | 
					
						
							|  |  |  |       // write the data | 
					
						
							|  |  |  |       writer.write(data); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 03:44:38 +00:00
										 |  |  | ### Internet Explorer
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Internet Explorer offered proprietary APIs that were not adopted by Chromium. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### Blob API
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Writing Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | IE10 and IE11 support `navigator.msSaveBlob`. `XLSX.writeFile` will use this | 
					
						
							|  |  |  | method if it is available. | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #### VBScript
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Reading and Writing Files_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Internet Explorer 6-9 with VBScript support `Scripting.FileSystemObject`.  This | 
					
						
							|  |  |  | is not supported in modern browsers. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This approach is implemented in the library `readFile` and `writeFile` methods. | 
					
						
							|  |  |  | It requires the shim script to be loaded before the main library script: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html | 
					
						
							|  |  |  | <!-- load the shim script first --> | 
					
						
							|  |  |  | <script src="shim.min.js"></script> | 
					
						
							|  |  |  | <!-- then load the main script --> | 
					
						
							|  |  |  | <script src="xlsx.full.min.js"></script> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Other Platforms
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### NodeJS
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `fs.readFileSync` and `fs.writeFileSync` allow for reading and writing files. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When using `require`, these are supported in `readFile` and `writeFile`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var XLSX = require("xlsx"); | 
					
						
							|  |  |  | var wb = XLSX.readFile("sheetjs.numbers"); | 
					
						
							|  |  |  | XLSX.writeFile(wb, "sheetjs.xls"); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 05:45:37 +00:00
										 |  |  | [Installation](/docs/getting-started/installation/nodejs) has a special note for | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | use with NodeJS ECMAScript Modules: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { readFile, writeFile, set_fs } from 'xlsx'; | 
					
						
							|  |  |  | import * as fs from 'fs'; | 
					
						
							|  |  |  | set_fs(fs); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | var wb = readFile("sheetjs.numbers"); | 
					
						
							|  |  |  | writeFile(wb, "sheetjs.xlsx"); | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 10:01:12 +00:00
										 |  |  | <details><summary><b>Implementation Details</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **`XLSX.readFile(filepath)`** is equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _CommonJS_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var fs = require("fs"); | 
					
						
							|  |  |  | var buf = fs.readFileSync(filepath); | 
					
						
							|  |  |  | var wb = XLSX.read(buf); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _ECMAScript Modules_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { read } from "xlsx"; | 
					
						
							|  |  |  | import { readFileSync } from "fs"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var buf = readFileSync(filepath); | 
					
						
							|  |  |  | var wb = read(buf); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **`XLSX.writeFile(wb, filepath)`** is equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _CommonJS_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var fs = require("fs"), path = require("path"); | 
					
						
							|  |  |  | var buf = XLSX.write(wb, { bookType: path.extname(filepath).slice(1), type: "buffer" }); | 
					
						
							|  |  |  | fs.writeFileSync(filepath, buf); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _ECMAScript Modules_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { write } from "xlsx"; | 
					
						
							|  |  |  | import { writeFileSync } from "fs"; | 
					
						
							|  |  |  | import { extname } from "path"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var buf = write(wb, { bookType: extname(filepath).slice(1), type: "buffer" }); | 
					
						
							|  |  |  | writeFileSync(filepath, buf); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-30 22:12:52 +00:00
										 |  |  | ### ExtendScript
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In Photoshop and other Adobe apps, `readFile` and `writeFile` use the `File` | 
					
						
							|  |  |  | object under the hood: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | #include "xlsx.extendscript.js"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var wb = XLSX.readFile("sheetjs.xlsx"); | 
					
						
							|  |  |  | XLSX.writeFile(wb, "sheetjs.csv"); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 10:01:12 +00:00
										 |  |  | The [ExtendScript demo](/docs/demos/extensions/extendscript) covers the "Common | 
					
						
							|  |  |  | Extensibility Platform" (CEP) and "Unified Extensibility Platform" (UXP) details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Chrome Extensions
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In Manifest v2 Chrome extensions, `writeFile` calls `chrome.downloads.download`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This approach uses `URL.createObjectURL`, an API that is not supported in a | 
					
						
							|  |  |  | Manifest v3 Background Service Worker. For small exports, raw Base64 URLs can be | 
					
						
							|  |  |  | generated and downloaded. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The [Chromium demo](/docs/demos/extensions/chromium) covers the details. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | ### Deno
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | `readFile` uses `Deno.readFileSync` and `writeFile` uses `Deno.writeFileSync`: | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-29 11:21:37 +00:00
										 |  |  | <CodeBlock language="ts">{`\ | 
					
						
							|  |  |  | // @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" | 
					
						
							|  |  |  | import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs'; | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | const wb: XLSX.WorkBook = XLSX.readFile("sheetjs.numbers"); | 
					
						
							|  |  |  | XLSX.writeFile(wb, "sheetjs.xlsx");`} | 
					
						
							|  |  |  | </CodeBlock> | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | :::caution Deno entitlements | 
					
						
							| 
									
										
										
										
											2022-09-02 05:52:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | Any Deno script using `XLSX.readFile` requires the `--allow-read` entitlement. | 
					
						
							| 
									
										
										
										
											2022-09-02 05:52:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | Any Deno script using `XLSX.writeFile` requires the `--allow-write` entitlement. | 
					
						
							| 
									
										
										
										
											2022-09-02 05:52:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 10:01:12 +00:00
										 |  |  | <details><summary><b>Implementation Details</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **`XLSX.readFile(filepath)`** is equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _ECMAScript Modules_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <CodeBlock language="ts">{`\ | 
					
						
							|  |  |  | // @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" | 
					
						
							|  |  |  | import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs'; | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | const u8: Uint8Array = Deno.readFileSync(filepath); | 
					
						
							|  |  |  | const wb: XLSX.WorkBook = XLSX.read(u8);`} | 
					
						
							|  |  |  | </CodeBlock> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **`XLSX.writeFile(wb, filepath)`** is equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _ECMAScript Modules_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <CodeBlock language="ts">{`\ | 
					
						
							|  |  |  | // @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" | 
					
						
							|  |  |  | import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs'; | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | const u8 = XLSX.write(wb, { bookType: filepath.slice(filepath.lastIndexOf(".")+1), type: "buffer" }); | 
					
						
							|  |  |  | Deno.writeFileSync(filepath, u8);`} | 
					
						
							|  |  |  | </CodeBlock> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-26 19:21:53 +00:00
										 |  |  | ### Bun
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Bun requires the `fs` module: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | import { readFile, writeFile, set_fs } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2022-08-26 19:21:53 +00:00
										 |  |  | import * as fs from 'fs'; | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | set_fs(fs); | 
					
						
							| 
									
										
										
										
											2022-08-26 19:21:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | var wb = readFile("sheetjs.numbers"); | 
					
						
							|  |  |  | writeFile(wb, "sheetjs.xlsx"); | 
					
						
							| 
									
										
										
										
											2022-08-26 19:21:53 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 10:01:12 +00:00
										 |  |  | The implementation is identical to [NodeJS ECMAScript Modules](#nodejs). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | ### Apps
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Desktop and mobile apps have their own specific APIs covered in separate demos: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 05:45:37 +00:00
										 |  |  | - [Electron and other desktop apps](/docs/demos/desktop) | 
					
						
							|  |  |  | - [React Native and other mobile apps](/docs/demos/mobile) |