| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | --- | 
					
						
							| 
									
										
										
										
											2022-08-24 23:48:22 +00:00
										 |  |  | pagination_prev: getting-started/index | 
					
						
							| 
									
										
										
										
											2022-08-13 22:01:26 +00:00
										 |  |  | sidebar_position: 2 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | import current from '/version.js'; | 
					
						
							|  |  |  | import Tabs from '@theme/Tabs'; | 
					
						
							|  |  |  | import TabItem from '@theme/TabItem'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-13 22:01:26 +00:00
										 |  |  | # Tutorial | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | SheetJS presents a simple JS interface that works with "Array of Arrays" and | 
					
						
							|  |  |  | "Array of JS Objects".  The API functions are building blocks that should be | 
					
						
							|  |  |  | combined with other JS APIs to solve problems. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The discussion focuses on the problem solving mindset.  API details are covered | 
					
						
							|  |  |  | in other parts of the documentation. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-01 20:19:13 +00:00
										 |  |  | The goal of this example is to generate a XLSX workbook of US President names | 
					
						
							| 
									
										
										
										
											2023-01-23 05:37:44 +00:00
										 |  |  | and birthdays.  [Click here](#live-demo) to jump to the live demo. The sequence | 
					
						
							|  |  |  | diagram below shows the process: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```mermaid | 
					
						
							|  |  |  | sequenceDiagram | 
					
						
							|  |  |  |   actor U as User | 
					
						
							|  |  |  |   participant P as Page | 
					
						
							|  |  |  |   participant A as API | 
					
						
							|  |  |  |   U->>P: click button | 
					
						
							|  |  |  |   P->>A: fetch data | 
					
						
							|  |  |  |   A->>P: raw data | 
					
						
							|  |  |  |   Note over P: process data | 
					
						
							|  |  |  |   Note over P: make workbook | 
					
						
							|  |  |  |   Note over P: setup download | 
					
						
							|  |  |  |   P->>U: download workbook | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Acquire Data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Raw Data | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 00:39:07 +00:00
										 |  |  | [The raw data is available in JSON form](https://theunitedstates.io/congress-legislators/executive.json). | 
					
						
							| 
									
										
										
										
											2022-08-21 19:43:30 +00:00
										 |  |  | For convenience, it has been [mirrored here](https://sheetjs.com/data/executive.json) | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-08 05:43:21 +00:00
										 |  |  | Acquiring the data is straightforward with `fetch`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							|  |  |  | const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The raw data is an Array of objects. This is the data for John Adams: | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   "id": { /* (data omitted) */ }, | 
					
						
							|  |  |  |   "name": { | 
					
						
							|  |  |  |     "first": "John",          // <-- first name | 
					
						
							|  |  |  |     "last": "Adams"           // <-- last name | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   "bio": { | 
					
						
							|  |  |  |     "birthday": "1735-10-19", // <-- birthday | 
					
						
							|  |  |  |     "gender": "M" | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   "terms": [ | 
					
						
							|  |  |  |     { "type": "viceprez", /* (other fields omitted) */ }, | 
					
						
							|  |  |  |     { "type": "viceprez", /* (other fields omitted) */ }, | 
					
						
							|  |  |  |     { "type": "prez", /* (other fields omitted) */ } | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Filtering for Presidents | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The dataset includes Aaron Burr, a Vice President who was never President! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `Array#filter` creates a new array with the desired rows.  A President served | 
					
						
							|  |  |  | at least one term with `type` set to `"prez"`.  To test if a particular row has | 
					
						
							|  |  |  | at least one `"prez"` term, `Array#some` is another native JS function.  The | 
					
						
							|  |  |  | complete filter would be: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  | ### Sorting by First Term | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The dataset is sorted in chronological order by the first presidential or vice | 
					
						
							|  |  |  | presidential term.  The Vice President and President in a given term are sorted | 
					
						
							|  |  |  | alphabetically. Joe Biden and Barack Obama were Vice President and President | 
					
						
							|  |  |  | respectively in 2009. Since "Biden" is lexicographically before "Obama", Biden's | 
					
						
							|  |  |  | data point appears first. The goal is to sort the presidents in order of their | 
					
						
							|  |  |  | presidential term. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The first step is adding the first presidential term start date to the dataset. | 
					
						
							|  |  |  | `Array#find` will find the first value in an array that matches a criterion. | 
					
						
							|  |  |  | The following code looks at each president and creates a `"start"` property that | 
					
						
							|  |  |  | represents the start of the first presidential term. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `Array#sort` will sort the array. Since the `start` properties are strings, the | 
					
						
							|  |  |  | recommended approach is to use `String#localeCompare` to compare strings: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | ### Reshaping the Array | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For this example, the name will be the first name combined with the last name | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | (`row.name.first + " " + row.name.last`) and the birthday will be available at | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | `row.bio.birthday`.  Using `Array#map`, the dataset can be massaged in one call: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const rows = prez.map(row => ({ | 
					
						
							|  |  |  |   name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |   birthday: row.bio.birthday | 
					
						
							|  |  |  | })); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The result is an array of "simple" objects with no nesting: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | [ | 
					
						
							|  |  |  |   { name: "George Washington", birthday: "1732-02-22" }, | 
					
						
							|  |  |  |   { name: "John Adams", birthday: "1735-10-19" }, | 
					
						
							|  |  |  |   // ... one row per President | 
					
						
							|  |  |  | ] | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Create a Workbook | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | With the cleaned dataset, `XLSX.utils.json_to_sheet` generates a worksheet: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `XLSX.utils.book_new` creates a new workbook and `XLSX.utils.book_append_sheet` | 
					
						
							|  |  |  | appends a worksheet to the workbook. The new worksheet will be called "Dates": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  | XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Clean up Workbook | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The data is in the workbook and can be exported. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 05:45:37 +00:00
										 |  |  |  | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | There are multiple opportunities for improvement: the headers can be renamed and | 
					
						
							|  |  |  | the column widths can be adjusted.  [SheetJS Pro](https://sheetjs.com/pro) offers | 
					
						
							|  |  |  | additional styling options like cell styling and frozen rows. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Changing Header Names</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | By default, `json_to_sheet` creates a worksheet with a header row. In this case, | 
					
						
							|  |  |  | the headers come from the JS object keys: "name" and "birthday". | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-23 03:20:02 +00:00
										 |  |  | The headers are in cells `A1` and `B1`.  `XLSX.utils.sheet_add_aoa` can write | 
					
						
							|  |  |  | text values to the existing worksheet starting at cell `A1`: | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Changing Column Widths</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Some of the names are longer than the default column width.  Column widths are | 
					
						
							|  |  |  | set by setting the `"!cols"` worksheet property. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following line sets the width of column A to approximately 10 characters: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | worksheet["!cols"] = [ { wch: 10 } ]; // set column A width to 10 characters | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | One `Array#reduce` call over `rows` can calculate the maximum width: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  | worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Export a File | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `XLSX.writeFile` creates a spreadsheet file and tries to write it to the system. | 
					
						
							|  |  |  | In the browser, it will try to prompt the user to download the file.  In NodeJS, | 
					
						
							|  |  |  | it will write to the local directory. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-26 10:49:14 +00:00
										 |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `XLSX.writeFileXLSX` only writes XLSX files and is recommended when the export | 
					
						
							|  |  |  | will always be in the `.xlsx` format. `writeFileXLSX` is more amenable to tree | 
					
						
							|  |  |  | shaking.  This example uses `XLSX.writeFile` since `writeFileXLSX` does not | 
					
						
							|  |  |  | support other common export formats like `.xls` or `.xlsb` or `.csv`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-11 04:46:01 +00:00
										 |  |  | `compression: true` enables ZIP compression for XLSX and other formats. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-26 10:49:14 +00:00
										 |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2022-10-11 04:46:01 +00:00
										 |  |  | XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 05:45:37 +00:00
										 |  |  |  | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Live Demo | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-08 05:43:21 +00:00
										 |  |  | This demo runs in the web browser!  Click "Click to Generate File!" and the | 
					
						
							|  |  |  | browser should generate a XLSX file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | ```jsx live | 
					
						
							|  |  |  | function Presidents() { return ( <button onClick={async () => { | 
					
						
							|  |  |  |   /* fetch JSON data and parse */ | 
					
						
							| 
									
										
										
										
											2022-08-21 19:43:30 +00:00
										 |  |  |   const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* filter for the Presidents */ | 
					
						
							|  |  |  |   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  |   /* sort by first presidential term */ | 
					
						
							|  |  |  |   prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  |   prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   /* flatten objects */ | 
					
						
							|  |  |  |   const rows = prez.map(row => ({ | 
					
						
							|  |  |  |     name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |     birthday: row.bio.birthday | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate worksheet and workbook */ | 
					
						
							|  |  |  |   const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  |   const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  |   XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* fix headers */ | 
					
						
							|  |  |  |   XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculate column width */ | 
					
						
							|  |  |  |   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  |   worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-01 20:19:13 +00:00
										 |  |  |   /* create an XLSX file and try to save to Presidents.xlsx */ | 
					
						
							| 
									
										
										
										
											2022-10-11 04:46:01 +00:00
										 |  |  |   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | }}><b>Click to Generate file!</b></button> ); } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Run the Demo Locally | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <Tabs> | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   <TabItem value="browser" label="Web Browser"> | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Save the following script to `snippet.html` and open the page.  The page must be | 
					
						
							|  |  |  | hosted (no `file:///` access). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <https://sheetjs.com/pres.html> is a hosted version of the page. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html | 
					
						
							|  |  |  | <body> | 
					
						
							|  |  |  | <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script> | 
					
						
							|  |  |  | <script> | 
					
						
							|  |  |  | (async() => { | 
					
						
							|  |  |  |   /* fetch JSON data and parse */ | 
					
						
							| 
									
										
										
										
											2022-08-21 19:43:30 +00:00
										 |  |  |   const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* filter for the Presidents */ | 
					
						
							|  |  |  |   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  |   /* sort by first presidential term */ | 
					
						
							|  |  |  |   prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  |   prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   /* flatten objects */ | 
					
						
							|  |  |  |   const rows = prez.map(row => ({ | 
					
						
							|  |  |  |     name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |     birthday: row.bio.birthday | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate worksheet and workbook */ | 
					
						
							|  |  |  |   const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  |   const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  |   XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* fix headers */ | 
					
						
							|  |  |  |   XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculate column width */ | 
					
						
							|  |  |  |   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  |   worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-01 20:19:13 +00:00
										 |  |  |   /* create an XLSX file and try to save to Presidents.xlsx */ | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | })(); | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | <body> | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   </TabItem> | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   <TabItem value="nodejs" label="Command-Line (NodeJS)"> | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Install the dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2022-08-07 07:48:40 +00:00
										 |  |  | npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Save the following script to `snippet.js` and run `node snippet.js`: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  | ```js title="snippet.js" | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | const XLSX = require("xlsx"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | (async() => { | 
					
						
							|  |  |  |   /* fetch JSON data and parse */ | 
					
						
							| 
									
										
										
										
											2022-08-21 19:43:30 +00:00
										 |  |  |   const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* filter for the Presidents */ | 
					
						
							|  |  |  |   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  |   /* sort by first presidential term */ | 
					
						
							|  |  |  |   prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  |   prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   /* flatten objects */ | 
					
						
							|  |  |  |   const rows = prez.map(row => ({ | 
					
						
							|  |  |  |     name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |     birthday: row.bio.birthday | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate worksheet and workbook */ | 
					
						
							|  |  |  |   const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  |   const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  |   XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* fix headers */ | 
					
						
							|  |  |  |   XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculate column width */ | 
					
						
							|  |  |  |   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  |   worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-01 20:19:13 +00:00
										 |  |  |   /* create an XLSX file and try to save to Presidents.xlsx */ | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | })(); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | :::caution | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | Native `fetch` support was added in NodeJS 18.  For older versions of NodeJS, | 
					
						
							|  |  |  | the script will throw an error `fetch is not defined`.  A third-party library | 
					
						
							|  |  |  | like `axios` presents a similar API for fetching data: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Example using axios</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Install the dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-27 09:12:19 +00:00
										 |  |  | <pre><code parentName="pre" {...{"className": "language-bash"}}>{`\ | 
					
						
							|  |  |  | npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz axios`} | 
					
						
							|  |  |  | </code></pre> | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The differences in the script are highlighted below. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  | ```js title="snippet.js" | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | const XLSX = require("xlsx"); | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  | const axios = require("axios"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | (async() => { | 
					
						
							|  |  |  |   /* fetch JSON data and parse */ | 
					
						
							| 
									
										
										
										
											2022-08-21 19:43:30 +00:00
										 |  |  |   const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   const raw_data = (await axios(url, {responseType: "json"})).data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* filter for the Presidents */ | 
					
						
							|  |  |  |   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  |   /* sort by first presidential term */ | 
					
						
							|  |  |  |   prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  |   prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   /* flatten objects */ | 
					
						
							|  |  |  |   const rows = prez.map(row => ({ | 
					
						
							|  |  |  |     name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |     birthday: row.bio.birthday | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate worksheet and workbook */ | 
					
						
							|  |  |  |   const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  |   const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  |   XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* fix headers */ | 
					
						
							|  |  |  |   XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculate column width */ | 
					
						
							|  |  |  |   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  |   worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-01 20:19:13 +00:00
										 |  |  |   /* create an XLSX file and try to save to Presidents.xlsx */ | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | })(); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Other Server-Side Platforms</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <Tabs> | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  |   <TabItem value="deno" label="Deno"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Save the following script to `snippet.ts` and run with | 
					
						
							|  |  |  | `deno run --allow-net --allow-write snippet.ts`: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  | ```js title="snippet.ts" | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | // @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" | 
					
						
							|  |  |  | import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* fetch JSON data and parse */ | 
					
						
							| 
									
										
										
										
											2022-08-21 19:43:30 +00:00
										 |  |  | const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* filter for the Presidents */ | 
					
						
							|  |  |  | const prez = raw_data.filter((row: any) => row.terms.some((term: any) => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  | /* sort by first presidential term */ | 
					
						
							|  |  |  | prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  | prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | /* flatten objects */ | 
					
						
							|  |  |  | const rows = prez.map((row: any) => ({ | 
					
						
							|  |  |  |   name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |   birthday: row.bio.birthday | 
					
						
							|  |  |  | })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* generate worksheet and workbook */ | 
					
						
							|  |  |  | const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  | const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  | XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* fix headers */ | 
					
						
							|  |  |  | XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* calculate column width */ | 
					
						
							|  |  |  | const max_width = rows.reduce((w: number, r: any) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  | worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-01 20:19:13 +00:00
										 |  |  | /* create an XLSX file and try to save to Presidents.xlsx */ | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  |   <TabItem value="bun" label="Bun"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Download <https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs> to `xlsx.mjs` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Save the following script to `snippet.js` and run with `bun snippet.js`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js title="snippet.js" | 
					
						
							|  |  |  | import * as XLSX from './xlsx.mjs'; | 
					
						
							|  |  |  | import * as fs from 'fs'; | 
					
						
							|  |  |  | XLSX.set_fs(fs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* fetch JSON data and parse */ | 
					
						
							| 
									
										
										
										
											2022-08-21 19:43:30 +00:00
										 |  |  | const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  | const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* filter for the Presidents */ | 
					
						
							|  |  |  | const prez = raw_data.filter((row) => row.terms.some((term) => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  | /* sort by first presidential term */ | 
					
						
							|  |  |  | prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  | prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  | /* flatten objects */ | 
					
						
							|  |  |  | const rows = prez.map((row) => ({ | 
					
						
							|  |  |  |   name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |   birthday: row.bio.birthday | 
					
						
							|  |  |  | })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* generate worksheet and workbook */ | 
					
						
							|  |  |  | const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  | const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  | XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* fix headers */ | 
					
						
							|  |  |  | XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* calculate column width */ | 
					
						
							|  |  |  | const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  | worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* create an XLSX file and try to save to Presidents.xlsx */ | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   <TabItem value="desktop" label="Desktop App"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Save the following script to `snippet.html`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html title="snippet.html" | 
					
						
							|  |  |  | <body> | 
					
						
							|  |  |  | <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script> | 
					
						
							|  |  |  | <script> | 
					
						
							|  |  |  | (async() => { | 
					
						
							|  |  |  |   /* fetch JSON data and parse */ | 
					
						
							|  |  |  |   const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							|  |  |  |   const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* filter for the Presidents */ | 
					
						
							|  |  |  |   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  |   /* sort by first presidential term */ | 
					
						
							|  |  |  |   prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  |   prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   /* flatten objects */ | 
					
						
							|  |  |  |   const rows = prez.map(row => ({ | 
					
						
							|  |  |  |     name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |     birthday: row.bio.birthday | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate worksheet and workbook */ | 
					
						
							|  |  |  |   const worksheet = XLSX.utils.json_to_sheet(rows); | 
					
						
							|  |  |  |   const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  |   XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* fix headers */ | 
					
						
							|  |  |  |   XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculate column width */ | 
					
						
							|  |  |  |   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  |   worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* create an XLSX file and try to save to Presidents.xlsx */ | 
					
						
							|  |  |  |   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | 
					
						
							|  |  |  | })(); | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | <body> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Save the following to `package.json`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```json title="package.json" | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   "name": "sheetjs-nwjs", | 
					
						
							|  |  |  |   "author": "sheetjs", | 
					
						
							|  |  |  |   "version": "0.0.0", | 
					
						
							|  |  |  |   "main": "snippet.html", | 
					
						
							|  |  |  |   "dependencies": { | 
					
						
							|  |  |  |     "nw": "~0.66.0", | 
					
						
							|  |  |  |     "xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz" | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2022-07-10 22:17:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  | Install dependencies and run: | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm i | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  | npx nw . | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  | The app will show a save dialog. After selecting a path, it will write the file. | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="mobile" label="Mobile App"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note Initial Setup | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Follow the [Environment Setup](https://reactnative.dev/docs/environment-setup) | 
					
						
							|  |  |  | of the React Native documentation before testing the demo. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Create a new project by running the following commands in the Terminal: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  | npx react-native@0.70.6 init SheetJSPres --version="0.70.6" | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | cd SheetJSPres | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz react-native-blob-util@0.17.1 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Save the following to `App.js` in the project: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js title="App.js" | 
					
						
							|  |  |  | import React from 'react'; | 
					
						
							|  |  |  | import { Alert, Button, SafeAreaView, Text, View } from 'react-native'; | 
					
						
							|  |  |  | import { utils, version, write } from 'xlsx'; | 
					
						
							|  |  |  | import RNFetchBlob from 'react-native-blob-util'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const make_workbook = async() => { | 
					
						
							|  |  |  |   /* fetch JSON data and parse */ | 
					
						
							|  |  |  |   const url = "https://sheetjs.com/data/executive.json"; | 
					
						
							|  |  |  |   const raw_data = await (await fetch(url)).json(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* filter for the Presidents */ | 
					
						
							|  |  |  |   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 08:14:34 +00:00
										 |  |  |   /* sort by first presidential term */ | 
					
						
							|  |  |  |   prez.forEach(prez => prez.start = prez.terms.find(term => term.type === "prez").start); | 
					
						
							|  |  |  |   prez.sort((l,r) => l.start.localeCompare(r.start)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   /* flatten objects */ | 
					
						
							|  |  |  |   const rows = prez.map(row => ({ | 
					
						
							|  |  |  |     name: row.name.first + " " + row.name.last, | 
					
						
							|  |  |  |     birthday: row.bio.birthday | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate worksheet and workbook */ | 
					
						
							|  |  |  |   const worksheet = utils.json_to_sheet(rows); | 
					
						
							|  |  |  |   const workbook = utils.book_new(); | 
					
						
							|  |  |  |   utils.book_append_sheet(workbook, worksheet, "Dates"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* fix headers */ | 
					
						
							|  |  |  |   utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculate column width */ | 
					
						
							|  |  |  |   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | 
					
						
							|  |  |  |   worksheet["!cols"] = [ { wch: max_width } ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* React Native does not support `writeFile`. This is a low-level write ! */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* write workbook to buffer */ | 
					
						
							|  |  |  |   const buf = write(workbook, {type:'buffer', bookType:"xlsx"}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* write buffer to file */ | 
					
						
							|  |  |  |   const filename = RNFetchBlob.fs.dirs.DocumentDir + "/Presidents.xlsx"; | 
					
						
							|  |  |  |   await RNFetchBlob.fs.writeFile(filename, Array.from(buf), 'ascii'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-23 05:37:44 +00:00
										 |  |  |   return filename; | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const App = () => ( <SafeAreaView><View style={{ marginTop: 32, padding: 24 }}> | 
					
						
							|  |  |  |   <Text style={{ fontSize: 24, fontWeight: 'bold' }}>SheetJS {version} Export Demo</Text> | 
					
						
							|  |  |  |   <Button title='Press to Export' onPress={async() => { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       const filename = await make_workbook(); | 
					
						
							|  |  |  |       Alert.alert("Export Finished", `Exported to ${filename}`); | 
					
						
							|  |  |  |     } catch(err) { | 
					
						
							|  |  |  |       Alert.alert("Export Error", `Error ${err.message||err}`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }}/> | 
					
						
							|  |  |  | </View></SafeAreaView> ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default App; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-25 08:25:06 +00:00
										 |  |  | <Tabs> | 
					
						
							|  |  |  |   <TabItem value="asim" label="Android"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The Android demo has been tested in Windows 10 and in macOS. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Test the app in the Android simulator: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm run android | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | After clicking "Press to Export", the app will show an alert with the location | 
					
						
							|  |  |  | to the generated file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In the Android simulator, pulling the file requires additional steps.  This | 
					
						
							|  |  |  | command will pull a Base64-encoded string from the simulator: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | adb exec-out run-as com.sheetjspres base64 files/Presidents.xlsx > pres.b64 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Decoding the file requires an OS-specific command: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <Tabs> | 
					
						
							|  |  |  |   <TabItem value="windows" label="Windows"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```powershell | 
					
						
							|  |  |  | certutil -decode .\pres.b64 .\Presidents.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="macos" label="macOS"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | base64 -D pres.b64 > Presidents.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This command generates `Presidents.xlsx` which can be opened. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note Device Testing | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For testing on a real device, Android 10+ requires an additional step to access | 
					
						
							|  |  |  | the generated file. Add highlighted lines to `App.js`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx title="App.js" | 
					
						
							|  |  |  |   /* write buffer to file */ | 
					
						
							|  |  |  |   const filename = RNFetchBlob.fs.dirs.DocumentDir + "/Presidents.xlsx"; | 
					
						
							|  |  |  |   await RNFetchBlob.fs.writeFile(filename, Array.from(buf), 'ascii'); | 
					
						
							|  |  |  | // highlight-start | 
					
						
							|  |  |  |   await RNFetchBlob.MediaCollection.copyToMediaStore({ | 
					
						
							|  |  |  |     parentFolder: "", | 
					
						
							|  |  |  |     mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", | 
					
						
							|  |  |  |     name: "Presidents.xlsx" | 
					
						
							|  |  |  |   }, "Download", filename); | 
					
						
							|  |  |  | // highlight-end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return filename; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `Presidents.xlsx` will be copied to the `Downloads` folder. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="ios" label="iOS"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::caution | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo runs in iOS and requires a Macintosh computer with Xcode installed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The native component must be linked: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | cd ios; pod install; cd .. | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | Test the app in the iOS simulator: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm run ios | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | After clicking "Press to Export", the app will show an alert with the location | 
					
						
							|  |  |  | to the generated file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-25 08:25:06 +00:00
										 |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   </TabItem> | 
					
						
							| 
									
										
										
										
											2022-05-16 03:26:04 +00:00
										 |  |  | </Tabs> |