forked from sheetjs/docs.sheetjs.com
		
	inout
This commit is contained in:
		
							parent
							
								
									9acdfab935
								
							
						
					
					
						commit
						f3b4f8067a
					
				| @ -44,7 +44,9 @@ InDesign | ||||
| IndexedDB | ||||
| JavaScriptCore | ||||
| LocalStorage | ||||
| MacOS | ||||
| NestJS | ||||
| NetSuite | ||||
| NPM | ||||
| Nuxt | ||||
| PhantomJS | ||||
| @ -55,6 +57,7 @@ RequireJS | ||||
| Rollup | ||||
| SessionStorage | ||||
| SQLite | ||||
| SuiteScripts | ||||
| SystemJS | ||||
| VueJS | ||||
| WebKit | ||||
|  | ||||
| @ -45,7 +45,9 @@ Deno scripts must be invoked with `--allow-read` to read from the filesystem. | ||||
| 
 | ||||
| #### Examples | ||||
| 
 | ||||
| Here are a few common scenarios (click on each subtitle to see the code): | ||||
| Here are a few common scenarios (click on each subtitle to see the code). | ||||
| 
 | ||||
| The [demos](../getting-started/demos) cover special deployments in more detail. | ||||
| 
 | ||||
| ### Example: Local File | ||||
| 
 | ||||
| @ -63,16 +65,14 @@ var XLSX = require("xlsx"); | ||||
| var workbook = XLSX.readFile("test.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| For Node ESM, the `readFile` helper is not enabled. Instead, `fs.readFileSync` | ||||
| should be used to read the file data as a `Buffer` for use with `XLSX.read`: | ||||
| For Node ESM, `fs` must be loaded manually: | ||||
| 
 | ||||
| ```js | ||||
| import { readFileSync } from "fs"; | ||||
| import { read } from "xlsx/xlsx.mjs"; | ||||
| import * as fs from "fs"; | ||||
| import { readFile, set_fs } from "xlsx/xlsx.mjs"; | ||||
| set_fs(fs); | ||||
| 
 | ||||
| const buf = readFileSync("test.xlsx"); | ||||
| /* buf is a Buffer */ | ||||
| const workbook = read(buf); | ||||
| const workbook = readFile("test.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
| @ -108,17 +108,27 @@ shows a complete example and details the required version-specific settings. | ||||
|   </TabItem> | ||||
|   <TabItem value="reactnative" label="React Native"> | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| React Native does not provide a way to read files from the filesystem.  A | ||||
| separate third-party library must be used. | ||||
| 
 | ||||
| Since React Native internals change between releases, libraries may only work | ||||
| with specific versions of React Native.  Project documentation should be | ||||
| consulted before picking a library. | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| The [`react` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/react) includes a sample React Native app. | ||||
| 
 | ||||
| Since React Native does not provide a way to read files from the filesystem, a | ||||
| third-party library must be used.  The following libraries have been tested: | ||||
| The following libraries have been tested: | ||||
| 
 | ||||
| - [`react-native-file-access`](https://npm.im/react-native-file-access) | ||||
| 
 | ||||
| The `base64` encoding returns strings compatible with the `base64` type: | ||||
| 
 | ||||
| ```js | ||||
| import XLSX from "xlsx"; | ||||
| import * as XLSX from "xlsx"; | ||||
| import { FileSystem } from "react-native-file-access"; | ||||
| 
 | ||||
| const b64 = await FileSystem.readFile(path, "base64"); | ||||
| @ -131,7 +141,7 @@ const workbook = XLSX.read(b64, {type: "base64"}); | ||||
| The `ascii` encoding returns binary strings compatible with the `binary` type: | ||||
| 
 | ||||
| ```js | ||||
| import XLSX from "xlsx"; | ||||
| import * as XLSX from "xlsx"; | ||||
| import { readFile } from "react-native-fs"; | ||||
| 
 | ||||
| const bstr = await readFile(path, "ascii"); | ||||
| @ -293,8 +303,11 @@ The [`server` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/server) | ||||
| 
 | ||||
| ### Example: Remote File | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Fetching a file in the web browser ("Ajax")</b> (click to show)</summary> | ||||
| This example focuses on fetching files ("Ajax" in browser parlance) using APIs | ||||
| like `XMLHttpRequest` and `fetch` as well as third-party libraries. | ||||
| 
 | ||||
| <Tabs> | ||||
|   <TabItem value="browser" label="Browser"> | ||||
| 
 | ||||
| For modern websites targeting Chrome 42+, `fetch` is recommended: | ||||
| 
 | ||||
| @ -334,11 +347,8 @@ The [`xhr` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/xhr/) incl | ||||
| 
 | ||||
| <http://oss.sheetjs.com/sheetjs/ajax.html> shows fallback approaches for IE6+. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Download files in a NodeJS process</b> (click to show)</summary> | ||||
|   </TabItem> | ||||
|   <TabItem value="nodejs" label="NodeJS"> | ||||
| 
 | ||||
| Node 17.5 and 18.0 have native support for fetch: | ||||
| 
 | ||||
| @ -380,10 +390,8 @@ const axios = require("axios"); | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Download files in an Electron app</b> (click to show)</summary> | ||||
|   </TabItem> | ||||
|   <TabItem value="electron" label="Electron"> | ||||
| 
 | ||||
| The `net` module in the main process can make HTTP/HTTPS requests to external | ||||
| resources.  Responses should be manually concatenated using `Buffer.concat`: | ||||
| @ -405,37 +413,39 @@ req.on("response", (res) => { | ||||
| req.end(); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| ### Example: Readable Streams | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Readable Streams in NodeJS</b> (click to show)</summary> | ||||
| :::caution | ||||
| 
 | ||||
| When dealing with Readable Streams, the easiest approach is to buffer the stream | ||||
| and process the whole thing at the end: | ||||
| The recommended approach is to buffer streams in memory and process once all of | ||||
| the data has been collected. A proper streaming parse is technically impossible. | ||||
| 
 | ||||
| ```js | ||||
| var fs = require("fs"); | ||||
| var XLSX = require("xlsx"); | ||||
| <details><summary><b>Technical details</b> (click to show)</summary> | ||||
| 
 | ||||
| function process_RS(stream, cb) { | ||||
|   var buffers = []; | ||||
|   stream.on("data", function(data) { buffers.push(data); }); | ||||
|   stream.on("end", function() { | ||||
|     var buffer = Buffer.concat(buffers); | ||||
|     var workbook = XLSX.read(buffer, {type:"buffer"}); | ||||
| XLSX, XLSB, NUMBERS, and ODS files are ultimately ZIP files that contain binary | ||||
| and XML entries.  The ZIP file format stores the table of contents ("end of | ||||
| central directory" record) at the end of the file, so a proper parse of a ZIP | ||||
| file requires scanning from the end.  Streams do not provide random access into | ||||
| the data, so the only correct approach involves buffering the entire stream. | ||||
| 
 | ||||
|     /* DO SOMETHING WITH workbook IN THE CALLBACK */ | ||||
|     cb(workbook); | ||||
|   }); | ||||
| } | ||||
| ``` | ||||
| XLS, XLR, QPW, and Works 4 for Mac files use the "Compound File Binary Format". | ||||
| It is a container format that can hold multiple "files" and "folders".  It also | ||||
| has a table of contents ("directory sectors") but these can be placed anywhere | ||||
| in the file!  The only correct approach involves buffering enough of the stream | ||||
| to find the full table of contents, but the added complexity has little benefit | ||||
| when testing against real-world files generated by various versions of Excel and | ||||
| other tools. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>ReadableStream in the browser</b> (click to show)</summary> | ||||
| ::: | ||||
| 
 | ||||
| 
 | ||||
| <Tabs> | ||||
|   <TabItem value="browser" label="Browser"> | ||||
| 
 | ||||
| When dealing with `ReadableStream`, the easiest approach is to buffer the stream | ||||
| and process the whole thing at the end: | ||||
| @ -470,7 +480,31 @@ const data = await process_RS(stream); | ||||
| const workbook = XLSX.read(data, {type: 'array'}); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
|   </TabItem> | ||||
|   <TabItem value="nodejs" label="NodeJS"> | ||||
| 
 | ||||
| When dealing with Readable Streams, the easiest approach is to buffer the stream | ||||
| and process the whole thing at the end: | ||||
| 
 | ||||
| ```js | ||||
| var fs = require("fs"); | ||||
| var XLSX = require("xlsx"); | ||||
| 
 | ||||
| function process_RS(stream, cb) { | ||||
|   var buffers = []; | ||||
|   stream.on("data", function(data) { buffers.push(data); }); | ||||
|   stream.on("end", function() { | ||||
|     var buffer = Buffer.concat(buffers); | ||||
|     var workbook = XLSX.read(buffer, {type:"buffer"}); | ||||
| 
 | ||||
|     /* DO SOMETHING WITH workbook IN THE CALLBACK */ | ||||
|     cb(workbook); | ||||
|   }); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| More detailed examples are covered in the [included demos](https://github.com/SheetJS/SheetJS/tree/master/demos/) | ||||
| 
 | ||||
| @ -538,9 +572,9 @@ from a JSON Endpoint and Generate a Workbook" | ||||
| 
 | ||||
| [`x-spreadsheet`](https://github.com/myliang/x-spreadsheet) is an interactive | ||||
| data grid for previewing and modifying structured data in the web browser.  The | ||||
| [`xspreadsheet` demo](https://github.com/sheetjs/sheetjs/tree/master/demos/xspreadsheet) includes a sample script with the | ||||
| `xtos` function for converting from x-spreadsheet data object to a workbook. | ||||
| <https://oss.sheetjs.com/sheetjs/x-spreadsheet> is a live demo. | ||||
| [demo](https://github.com/sheetjs/sheetjs/tree/master/demos/xspreadsheet) | ||||
| includes a sample script with the `xtos` function for converting from | ||||
| x-spreadsheet to a workbook.  Live Demo: <https://oss.sheetjs.com/sheetjs/x-spreadsheet> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Records from a database query (SQL or no-SQL)</b> (click to show)</summary> | ||||
|  | ||||
| @ -4,9 +4,13 @@ sidebar_position: 5 | ||||
| 
 | ||||
| # Data Export | ||||
| 
 | ||||
| import current from '/version.js'; | ||||
| import Tabs from '@theme/Tabs'; | ||||
| import TabItem from '@theme/TabItem'; | ||||
| 
 | ||||
| ## Writing Workbooks | ||||
| 
 | ||||
| #### API | ||||
| ### API | ||||
| 
 | ||||
| _Generate spreadsheet bytes (file) from data_ | ||||
| 
 | ||||
| @ -32,9 +36,8 @@ The `writeFile` method packages the data and attempts to save the new file.  The | ||||
| export file format is determined by the extension of `filename` (`SheetJS.xlsx` | ||||
| signals XLSX export, `SheetJS.xlsb` signals XLSB export, etc). | ||||
| 
 | ||||
| The `writeFile` method uses platform-specific APIs to initiate the file save. In | ||||
| NodeJS, `fs.readFileSync` can create a file.  In the web browser, a download is | ||||
| attempted using the HTML5 `download` attribute, with fallbacks for IE. | ||||
| The second `opts` argument is optional.  ["Writing Options"](../api/write-options) | ||||
| covers the supported properties and behaviors. | ||||
| 
 | ||||
| _Generate and attempt to save an XLSX file_ | ||||
| 
 | ||||
| @ -50,71 +53,26 @@ referencing the other export functions. | ||||
| The second `opts` argument is optional.  ["Writing Options"](../api/write-options) | ||||
| covers the supported properties and behaviors. | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| The `writeFile` and `writeFileXLSX` methods uses platform-specific APIs to save | ||||
| files. The APIs do not generally provide feedback on whether files were created. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| #### Examples | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Local file in a NodeJS server</b> (click to show)</summary> | ||||
| Here are a few common scenarios (click on each subtitle to see the code). | ||||
| 
 | ||||
| `writeFile` uses `fs.writeFileSync` in server environments: | ||||
| The [demos](../getting-started/demos) cover special deployments in more detail. | ||||
| 
 | ||||
| ```js | ||||
| var XLSX = require("xlsx"); | ||||
| ### Example: Local File | ||||
| 
 | ||||
| /* output format determined by filename */ | ||||
| XLSX.writeFile(workbook, "out.xlsb"); | ||||
| ``` | ||||
| `XLSX.writeFile` supports writing local files in platforms like NodeJS. In other | ||||
| platforms like React Native, `XLSX.write` should be called with file data. | ||||
| 
 | ||||
| For Node ESM, the `writeFile` helper is not enabled. Instead, `fs.writeFileSync` | ||||
| should be used to write the file data to a `Buffer` for use with `XLSX.write`: | ||||
| 
 | ||||
| ```js | ||||
| import { writeFileSync } from "fs"; | ||||
| import { write } from "xlsx/xlsx.mjs"; | ||||
| 
 | ||||
| const buf = write(workbook, {type: "buffer", bookType: "xlsb"}); | ||||
| /* buf is a Buffer */ | ||||
| const workbook = writeFileSync("out.xlsb", buf); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Local file in a Deno application</b> (click to show)</summary> | ||||
| 
 | ||||
| `writeFile` uses `Deno.writeFileSync` under the hood: | ||||
| 
 | ||||
| ```js | ||||
| // @deno-types="https://deno.land/x/sheetjs/types/index.d.ts" | ||||
| import * as XLSX from 'https://deno.land/x/sheetjs/xlsx.mjs' | ||||
| 
 | ||||
| XLSX.writeFile(workbook, "test.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| Applications writing files must be invoked with the `--allow-write` flag.  The | ||||
| [`deno` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/deno/) has more examples | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Local file in a PhotoShop or InDesign plugin</b> (click to show)</summary> | ||||
| 
 | ||||
| `writeFile` wraps the `File` logic in Photoshop and other ExtendScript targets. | ||||
| The specified path should be an absolute path: | ||||
| 
 | ||||
| ```js | ||||
| #include "xlsx.extendscript.js" | ||||
| 
 | ||||
| /* output format determined by filename */ | ||||
| XLSX.writeFile(workbook, "out.xlsx"); | ||||
| /* at this point, out.xlsx is a file that you can distribute */ | ||||
| ``` | ||||
| 
 | ||||
| The [`extendscript` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/extendscript/) includes a more complex example. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Download a file in the browser to the user machine</b> (click to show)</summary> | ||||
| <Tabs> | ||||
|   <TabItem value="browser" label="Browser"> | ||||
| 
 | ||||
| `XLSX.writeFile` wraps a few techniques for triggering a file save: | ||||
| 
 | ||||
| @ -132,10 +90,22 @@ XLSX.writeFile(workbook, "out.xlsb"); | ||||
| /* at this point, out.xlsb will have been downloaded */ | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Download a file in legacy browsers</b> (click to show)</summary> | ||||
|   <summary><b>SWF workaround for Windows 95+</b> (click to show)</summary> | ||||
| 
 | ||||
| :::warning | ||||
| 
 | ||||
| Each moving part in this solution has been deprecated years ago: | ||||
| 
 | ||||
| - Adobe stopped supporting Flash Player at the end of 2020 | ||||
| - Microsoft stopped supporting IE8 in 2019 and stopped supporting IE9 in 2020 | ||||
| - `Downloadify` support ended in 2010 and `SWFObject` support ended in 2016 | ||||
| 
 | ||||
| New projects should strongly consider requiring modern browsers.  This info is | ||||
| provided on an "as is" basis and there is no realistic way to provide support | ||||
| given that every related vendor stopped providing support for their software. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| `XLSX.writeFile` techniques work for most modern browsers as well as older IE. | ||||
| For much older browsers, there are workarounds implemented by wrapper libraries. | ||||
| @ -157,28 +127,123 @@ The [`oldie` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/oldie/) | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Browser upload file (ajax)</b> (click to show)</summary> | ||||
|   </TabItem> | ||||
|   <TabItem value="nodejs" label="NodeJS"> | ||||
| 
 | ||||
| A complete example using XHR is [included in the XHR demo](https://github.com/SheetJS/SheetJS/tree/master/demos/xhr/), along | ||||
| with examples for fetch and wrapper libraries.  This example assumes the server | ||||
| can handle Base64-encoded files (see the demo for a basic nodejs server): | ||||
| `writeFile` uses `fs.writeFileSync` under the hood: | ||||
| 
 | ||||
| ```js | ||||
| /* in this example, send a base64 string to the server */ | ||||
| var wopts = { bookType:"xlsx", bookSST:false, type:"base64" }; | ||||
| var XLSX = require("xlsx"); | ||||
| 
 | ||||
| var wbout = XLSX.write(workbook,wopts); | ||||
| 
 | ||||
| var req = new XMLHttpRequest(); | ||||
| req.open("POST", "/upload", true); | ||||
| var formdata = new FormData(); | ||||
| formdata.append("file", "test.xlsx"); // <-- server expects `file` to hold name | ||||
| formdata.append("data", wbout); // <-- `data` holds the base64-encoded data | ||||
| req.send(formdata); | ||||
| /* output format determined by filename */ | ||||
| XLSX.writeFile(workbook, "out.xlsb"); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| For Node ESM, `fs` must be loaded manually: | ||||
| 
 | ||||
| ```js | ||||
| import * as fs from "fs"; | ||||
| import { writeFile, set_fs } from "xlsx/xlsx.mjs"; | ||||
| set_fs(fs); | ||||
| 
 | ||||
| /* output format determined by filename */ | ||||
| writeFile(workbook, "out.xlsb"); | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
|   <TabItem value="deno" label="Deno"> | ||||
| 
 | ||||
| `writeFile` uses `Deno.writeFileSync` under the hood: | ||||
| 
 | ||||
| <pre><code parentName="pre" {...{"className": "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'; | ||||
| 
 | ||||
| XLSX.writeFile(workbook, "test.xlsx");`}</code></pre> | ||||
| 
 | ||||
| Applications writing files must be invoked with the `--allow-write` flag.  The | ||||
| [`deno` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/deno/) has more examples | ||||
| 
 | ||||
|   </TabItem> | ||||
|   <TabItem value="electron" label="Electron"> | ||||
| 
 | ||||
| `writeFile` can be used in the renderer process: | ||||
| 
 | ||||
| ```js | ||||
| /* From the renderer process */ | ||||
| var XLSX = require("xlsx"); | ||||
| 
 | ||||
| XLSX.writeFile(workbook, "out.xlsb"); | ||||
| ``` | ||||
| 
 | ||||
| Electron APIs have changed over time.  The [`electron` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/electron/) | ||||
| shows a complete example and details the required version-specific settings. | ||||
| 
 | ||||
|   </TabItem> | ||||
|   <TabItem value="reactnative" label="React Native"> | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| React Native does not provide a way to write files to the filesystem.  A | ||||
| separate third-party library must be used. | ||||
| 
 | ||||
| Since React Native internals change between releases, libraries may only work | ||||
| with specific versions of React Native.  Project documentation should be | ||||
| consulted before picking a library. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| The [`react` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/react) includes a sample React Native app. | ||||
| 
 | ||||
| The following libraries have been tested: | ||||
| 
 | ||||
| - [`react-native-file-access`](https://npm.im/react-native-file-access) | ||||
| 
 | ||||
| The `base64` encoding returns strings compatible with the `base64` type: | ||||
| 
 | ||||
| ```js | ||||
| import * as XLSX from "xlsx"; | ||||
| import { Dirs, FileSystem } from "react-native-file-access"; | ||||
| const DDP = Dirs.DocumentDir + "/"; | ||||
| 
 | ||||
| const b64 = XLSX.write(workbook, {type:'base64', bookType:"xlsx"}); | ||||
| /* b64 is a base64 string */ | ||||
| await FileSystem.writeFile(DDP + "sheetjs.xlsx", b64, "base64"); | ||||
| ``` | ||||
| 
 | ||||
| - [`react-native-fs`](https://npm.im/react-native-fs) | ||||
| 
 | ||||
| The `ascii` encoding accepts binary strings compatible with the `binary` type: | ||||
| 
 | ||||
| ```js | ||||
| import * as XLSX from "xlsx"; | ||||
| import { writeFile, DocumentDirectoryPath } from "react-native-fs"; | ||||
| const DDP = DocumentDirectoryPath + "/"; | ||||
| 
 | ||||
| const bstr = XLSX.write(workbook, {type:'binary', bookType:"xlsx"}); | ||||
| /* bstr is a binary string */ | ||||
| await writeFile(DDP + "sheetjs.xlsx", bstr, "ascii"); | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
|   <TabItem value="extendscript" label="Photoshop"> | ||||
| 
 | ||||
| `writeFile` wraps the `File` logic in Photoshop and other ExtendScript targets. | ||||
| The specified path should be an absolute path: | ||||
| 
 | ||||
| ```js | ||||
| #include "xlsx.extendscript.js" | ||||
| 
 | ||||
| /* Ask user to select path */ | ||||
| var thisFile = File.saveDialog("Select an output file", "*.xlsx;*.xls"); | ||||
| /* output format determined by filename */ | ||||
| XLSX.writeFile(workbook, thisFile.absoluteURI); | ||||
| ``` | ||||
| 
 | ||||
| The [`extendscript` demo](../getting-started/demos/extendscript) includes a more complex example. | ||||
| 
 | ||||
|   </TabItem> | ||||
|   <TabItem value="headless" label="Headless"> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>PhantomJS (Headless Webkit) File Generation</b> (click to show)</summary> | ||||
| @ -203,55 +268,86 @@ to generate a workbook from HTML tables in a page in "Headless WebKit". | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| 
 | ||||
| The [included demos](https://github.com/SheetJS/SheetJS/tree/master/demos/) cover mobile apps and other special deployments. | ||||
| ### Example: Remote File | ||||
| 
 | ||||
| ### Writing Examples | ||||
| This example focuses on uploading files ("Ajax" in browser parlance) using APIs | ||||
| like `XMLHttpRequest` and `fetch` as well as third-party libraries. | ||||
| 
 | ||||
| - <http://sheetjs.com/demos/table.html> exporting an HTML table | ||||
| - <http://sheetjs.com/demos/writexlsx.html> generates a simple file | ||||
| <Tabs> | ||||
|   <TabItem value="browser" label="Browser"> | ||||
| 
 | ||||
| ### Streaming Write | ||||
| :::caution | ||||
| 
 | ||||
| The streaming write functions are available in the `XLSX.stream` object.  They | ||||
| take the same arguments as the normal write functions but return a NodeJS | ||||
| Readable Stream. | ||||
| Some platforms like Azure and AWS will attempt to parse POST request bodies as | ||||
| UTF-8 strings before user code can see the data.  This will result in corrupt | ||||
| data parsed by the server.  There are some workarounds, but the safest approach | ||||
| is to adjust the server process or Lambda function to accept Base64 strings. | ||||
| 
 | ||||
| - `XLSX.stream.to_csv` is the streaming version of `XLSX.utils.sheet_to_csv`. | ||||
| - `XLSX.stream.to_html` is the streaming version of `XLSX.utils.sheet_to_html`. | ||||
| - `XLSX.stream.to_json` is the streaming version of `XLSX.utils.sheet_to_json`. | ||||
| ::: | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>nodejs convert to CSV and write file</b> (click to show)</summary> | ||||
| A complete example using XHR is [included in the XHR demo](https://github.com/SheetJS/SheetJS/tree/master/demos/xhr/), along | ||||
| with examples for fetch and wrapper libraries.  This example assumes the server | ||||
| can handle Base64-encoded files (see the demo for a basic nodejs server): | ||||
| 
 | ||||
| ```js | ||||
| var output_file_name = "out.csv"; | ||||
| var stream = XLSX.stream.to_csv(worksheet); | ||||
| stream.pipe(fs.createWriteStream(output_file_name)); | ||||
| /* in this example, send a base64 string to the server */ | ||||
| var wbout = XLSX.write(workbook, { bookType: "xlsx", type: "base64" }); | ||||
| 
 | ||||
| /* prepare data for POST */ | ||||
| var formdata = new FormData(); | ||||
| formdata.append("file", "test.xlsx"); // <-- server expects `file` to hold name | ||||
| formdata.append("data", wbout); // <-- `data` holds the base64-encoded data | ||||
| 
 | ||||
| /* perform POST request */ | ||||
| var req = new XMLHttpRequest(); | ||||
| req.open("POST", "/upload", true); | ||||
| req.send(formdata); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>nodejs write JSON stream to screen</b> (click to show)</summary> | ||||
| For servers that do not parse POST request bodies as UTF-8 strings, a `Blob` can | ||||
| be generated from the `array` output: | ||||
| 
 | ||||
| ```js | ||||
| /* to_json returns an object-mode stream */ | ||||
| var stream = XLSX.stream.to_json(worksheet, {raw:true}); | ||||
| /* in this example, send a Blob to the server */ | ||||
| var wbout = XLSX.write(workbook, { bookType: "xlsx", type: "array" }); | ||||
| 
 | ||||
| /* the following stream converts JS objects to text via JSON.stringify */ | ||||
| var conv = new Transform({writableObjectMode:true}); | ||||
| conv._transform = function(obj, e, cb){ cb(null, JSON.stringify(obj) + "\n"); }; | ||||
| /* prepare data for POST */ | ||||
| var blob = new Blob([new Uint8Array(wbout)], {type:"application/octet-stream"}); | ||||
| var formdata = new FormData(); | ||||
| formdata.append("file", blob, "test.xlsx"); | ||||
| 
 | ||||
| stream.pipe(conv); conv.pipe(process.stdout); | ||||
| /* perform POST request */ | ||||
| fetch("/upload", { method: 'POST', body: formdata }); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
|   </TabItem> | ||||
|   <TabItem value="nodejs" label="NodeJS"> | ||||
| 
 | ||||
| <https://github.com/sheetjs/sheetaki> pipes write streams to nodejs response. | ||||
| `XLSX.write` with `type: "buffer"` will generate a NodeJS `Buffer` which can be | ||||
| used with standard NodeJS approaches for uploading data. | ||||
| 
 | ||||
| ### Generating JSON and JS Data | ||||
| Node 17.5 and 18.0 have native support for fetch: | ||||
| 
 | ||||
| ```js | ||||
| const XLSX = require("xlsx"); | ||||
| 
 | ||||
| const buf = XLSX.write(workbook, { bookType: "xlsx", type: "buffer" }); | ||||
| var blob = new Blob([buf], {type:"application/octet-stream"}); | ||||
| var formdata = new FormData(); | ||||
| formdata.append("file", blob, "test.xlsx"); | ||||
| 
 | ||||
| /* perform POST request */ | ||||
| fetch("https://thisis.a.test/upload", { method: 'POST', body: formdata }); | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| ## Generating JSON and JS Data | ||||
| 
 | ||||
| JSON and JS data tend to represent single worksheets. The utility functions in | ||||
| this section work with single worksheets. | ||||
| @ -263,7 +359,7 @@ names and whose values are worksheet objects. | ||||
| 
 | ||||
| The "first worksheet" is stored at `workbook.Sheets[workbook.SheetNames[0]]`. | ||||
| 
 | ||||
| #### API | ||||
| ### API | ||||
| 
 | ||||
| _Create an array of JS objects from a worksheet_ | ||||
| 
 | ||||
| @ -287,14 +383,19 @@ With the `header: 1` option, the function exports an array of arrays of values. | ||||
| 
 | ||||
| #### Examples | ||||
| 
 | ||||
| ### Example: Data Grids | ||||
| 
 | ||||
| <Tabs> | ||||
|   <TabItem value="js" label="Vanilla JS"> | ||||
| 
 | ||||
| [`x-spreadsheet`](https://github.com/myliang/x-spreadsheet) is an interactive | ||||
| data grid for previewing and modifying structured data in the web browser.  The | ||||
| [`xspreadsheet` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/xspreadsheet) includes a sample script with the | ||||
| `stox` function for converting from a workbook to x-spreadsheet data object. | ||||
| <https://oss.sheetjs.com/sheetjs/x-spreadsheet> is a live demo. | ||||
| [demo](https://github.com/SheetJS/SheetJS/tree/master/demos/xspreadsheet) | ||||
| includes a sample script with the `stox` function for converting from | ||||
| a workbook to x-spreadsheet.  Live Demo: <https://oss.sheetjs.com/sheetjs/x-spreadsheet> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Previewing data in a React data grid</b> (click to show)</summary> | ||||
|   </TabItem> | ||||
|   <TabItem value="react" label="React"> | ||||
| 
 | ||||
| [`react-data-grid`](https://adazzle.github.io/react-data-grid) is a data grid | ||||
| built for React.  It uses two properties: `rows` of data objects and `columns` | ||||
| @ -314,7 +415,7 @@ export default function App() { | ||||
|   const [columns, setColumns] = useState([]); | ||||
|   const [rows, setRows] = useState([]); | ||||
|   useEffect(() => {(async () => { | ||||
|     const wb = read(await (await fetch(url)).arrayBuffer(), { WTF: 1 }); | ||||
|     const wb = read(await (await fetch(url)).arrayBuffer()); | ||||
| 
 | ||||
|     /* use sheet_to_json with header: 1 to generate an array of arrays */ | ||||
|     const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { header: 1 }); | ||||
| @ -331,22 +432,23 @@ export default function App() { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Previewing data in a VueJS data grid</b> (click to show)</summary> | ||||
|   </TabItem> | ||||
|   <TabItem value="vue" label="VueJS"> | ||||
| 
 | ||||
| [`vue3-table-lite`](https://linmasahiro.github.io/vue3-table-lite/dist/) is a | ||||
| simple VueJS 3 data table.  It is featured in the | ||||
| [VueJS demo](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/modify/). | ||||
| 
 | ||||
| </details> | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| ### Example: Data Loading | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Populating a database (SQL or no-SQL)</b> (click to show)</summary> | ||||
| 
 | ||||
| The [`database` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/database/) includes examples of working with | ||||
| databases and query results. | ||||
| The [`database` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/database/) | ||||
| includes examples of working with databases and query results. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| @ -390,7 +492,7 @@ The [`array` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/array/) | ||||
| </details> | ||||
| 
 | ||||
| 
 | ||||
| ### Generating HTML Tables | ||||
| ## Generating HTML Tables | ||||
| 
 | ||||
| #### API | ||||
| 
 | ||||
| @ -416,8 +518,10 @@ container.innerHTML = XLSX.utils.sheet_to_html(worksheet); | ||||
| 
 | ||||
| Combining with `fetch`, constructing a site from a workbook is straightforward: | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>Vanilla JS + HTML fetch workbook and generate table previews</b> (click to show)</summary> | ||||
| <Tabs> | ||||
|   <TabItem value="js" label="Vanilla JS"> | ||||
| 
 | ||||
| This example assigns the `innerHTML` of a DIV element: | ||||
| 
 | ||||
| ```html | ||||
| <body> | ||||
| @ -447,15 +551,15 @@ Combining with `fetch`, constructing a site from a workbook is straightforward: | ||||
| </body> | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>React fetch workbook and generate HTML table previews</b> (click to show)</summary> | ||||
|   </TabItem> | ||||
|   <TabItem value="react" label="React"> | ||||
| 
 | ||||
| It is generally recommended to use a React-friendly workflow, but it is possible | ||||
| to generate HTML and use it in React with `dangerouslySetInnerHTML`: | ||||
| 
 | ||||
| ```jsx | ||||
| import * as XLSX from 'xlsx'; | ||||
| 
 | ||||
| function Tabeller(props) { | ||||
|   /* the workbook object is the state */ | ||||
|   const [workbook, setWorkbook] = React.useState(XLSX.utils.book_new()); | ||||
| @ -479,10 +583,8 @@ function Tabeller(props) { | ||||
| 
 | ||||
| The [`react` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/react) includes more React examples. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>VueJS fetch workbook and generate HTML table previews</b> (click to show)</summary> | ||||
|   </TabItem> | ||||
|   <TabItem value="vue" label="VueJS"> | ||||
| 
 | ||||
| It is generally recommended to use a VueJS-friendly workflow, but it is possible | ||||
| to generate HTML and use it in VueJS with the `v-html` directive: | ||||
| @ -515,9 +617,10 @@ const S5SComponent = { | ||||
| 
 | ||||
| The [`vuejs` demo](https://github.com/SheetJS/SheetJS/tree/master/demos/vue) includes more React examples. | ||||
| 
 | ||||
| </details> | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| ### Generating Single-Worksheet Snapshots | ||||
| ## Generating Single-Worksheet Snapshots | ||||
| 
 | ||||
| The `sheet_to_*` functions accept a worksheet object. | ||||
| 
 | ||||
| @ -555,3 +658,42 @@ rendered in the form `cell=formula or value`.  String literals are prefixed with | ||||
| an apostrophe `'`, consistent with Excel's formula bar display. | ||||
| 
 | ||||
| ["Formulae Output"](../api/utilities#formulae-output) describes the function in more detail. | ||||
| 
 | ||||
| ## Streaming Write | ||||
| 
 | ||||
| The streaming write functions are available in the `XLSX.stream` object.  They | ||||
| take the same arguments as the normal write functions but return a NodeJS | ||||
| Readable Stream. | ||||
| 
 | ||||
| - `XLSX.stream.to_csv` is the streaming version of `XLSX.utils.sheet_to_csv`. | ||||
| - `XLSX.stream.to_html` is the streaming version of `XLSX.utils.sheet_to_html`. | ||||
| - `XLSX.stream.to_json` is the streaming version of `XLSX.utils.sheet_to_json`. | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>nodejs convert to CSV and write file</b> (click to show)</summary> | ||||
| 
 | ||||
| ```js | ||||
| var output_file_name = "out.csv"; | ||||
| var stream = XLSX.stream.to_csv(worksheet); | ||||
| stream.pipe(fs.createWriteStream(output_file_name)); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details> | ||||
|   <summary><b>nodejs write JSON stream to screen</b> (click to show)</summary> | ||||
| 
 | ||||
| ```js | ||||
| /* to_json returns an object-mode stream */ | ||||
| var stream = XLSX.stream.to_json(worksheet, {raw:true}); | ||||
| 
 | ||||
| /* the following stream converts JS objects to text via JSON.stringify */ | ||||
| var conv = new Transform({writableObjectMode:true}); | ||||
| conv._transform = function(obj, e, cb){ cb(null, JSON.stringify(obj) + "\n"); }; | ||||
| 
 | ||||
| stream.pipe(conv); conv.pipe(process.stdout); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <https://github.com/sheetjs/sheetaki> pipes write streams to nodejs response. | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| --- | ||||
| sidebar_position: 6 | ||||
| sidebar_position: 4 | ||||
| hide_table_of_contents: true | ||||
| --- | ||||
| 
 | ||||
| @ -1,5 +1,5 @@ | ||||
| --- | ||||
| sidebar_position: 7 | ||||
| sidebar_position: 5 | ||||
| --- | ||||
| 
 | ||||
| # Contributing | ||||
| @ -91,7 +91,7 @@ On Linux: | ||||
| sudo apt-get install mercurial subversion | ||||
| ``` | ||||
| 
 | ||||
| On MacOS, install using [Homebrew](https://brew.sh/): | ||||
| On MacOS, install using [`brew`](https://brew.sh/): | ||||
| 
 | ||||
| ```bash | ||||
| brew install mercurial subversion | ||||
| @ -128,7 +128,7 @@ cd modules; make; cd .. | ||||
| make dist | ||||
| ``` | ||||
| 
 | ||||
| 4) (For deno testing) Install deno: | ||||
| 4) (For Deno testing) Install Deno: | ||||
| 
 | ||||
| ```bash | ||||
| curl -fsSL https://deno.land/install.sh | sh | ||||
| @ -1,5 +1,5 @@ | ||||
| --- | ||||
| sidebar_position: 8 | ||||
| sidebar_position: 7 | ||||
| hide_table_of_contents: true | ||||
| --- | ||||
| 
 | ||||
| @ -1,5 +1,5 @@ | ||||
| --- | ||||
| sidebar_position: 9 | ||||
| sidebar_position: 8 | ||||
| hide_table_of_contents: true | ||||
| --- | ||||
| 
 | ||||
| @ -9,10 +9,9 @@ Some of our original research is documented at <https://oss.sheetjs.com/notes/> | ||||
| 
 | ||||
| The specifications list is non-exhaustive. | ||||
| 
 | ||||
| - ISO/IEC 29500:2012(E) "Information technology — Document description and processing languages — Office Open XML File Formats" | ||||
| - Open Document Format for Office Applications Version 1.2 (29 September 2011) | ||||
| - Worksheet File Format (From Lotus) December 1984 | ||||
| 
 | ||||
|  - Worksheet File Format (From Lotus) December 1984 | ||||
|  - Open Document Format for Office Applications Version 1.2 (29 September 2011) | ||||
|  - ISO/IEC 29500:2012(E) "Information technology — Document description and processing languages — Office Open XML File Formats" | ||||
| 
 | ||||
| ## Open Specifications Promise | ||||
| 
 | ||||
| @ -43,4 +42,10 @@ to sue.  The documentation that falls under the promise are listed below. | ||||
|  - `XLS`: Microsoft Office Excel 97-2007 Binary File Format Specification | ||||
|  - `RTF`: Rich Text Format | ||||
| 
 | ||||
| </details> | ||||
| </details> | ||||
| 
 | ||||
| 
 | ||||
| ## Other Resources | ||||
| 
 | ||||
| - ISBN 1556155212 "Excel Software Development Kit Version 4" | ||||
| - ISBN 1556156324 "Excel Developer's Kit Version 5" | ||||
| @ -61,7 +61,7 @@ document.getElementById("sheetjsexport").addEventListener('click', function() { | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details open><summary><b>Live Example</b> (click to show)</summary> | ||||
| <details open><summary><b>Live Example</b> (click to hide)</summary> | ||||
| 
 | ||||
| ```jsx live | ||||
| /* The live editor requires this function wrapper */ | ||||
| @ -133,7 +133,7 @@ support for CSS styling and rich text. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| <details><summary><b>Live Example</b> (click to hide)</summary> | ||||
| <details><summary><b>Live Example</b> (click to show)</summary> | ||||
| 
 | ||||
| ```jsx live | ||||
| /* The live editor requires this function wrapper */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user