| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: Local Storage API | 
					
						
							|  |  |  | pagination_prev: demos/grid | 
					
						
							|  |  |  | pagination_next: demos/worker | 
					
						
							|  |  |  | sidebar_custom_props: | 
					
						
							|  |  |  |   type: web | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The Storage API, encompassing `localStorage` and `sessionStorage`, describes | 
					
						
							|  |  |  | simple key-value stores that only support string values and keys. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  | This demo covers two common use patterns: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - "Row Objects" shows a simple convention for loading and storing row objects | 
					
						
							|  |  |  | - "Simple Strings" discusses how to persist and recover a raw Storage | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Row Objects
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Consider the following array of objects of data: | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  | [ | 
					
						
							|  |  |  |   { Name: "Barack Obama", Index: 44 }, | 
					
						
							|  |  |  |   { Name: "Donald Trump", Index: 45 }, | 
					
						
							|  |  |  |   { Name: "Joseph Biden", Index: 46 } | 
					
						
							|  |  |  | ] | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  | Storage API expects values to be strings. The simplest approach is to stringify | 
					
						
							|  |  |  | row objects using `JSON.stringify` and store using the row index as a key: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | Key | Value                                | | 
					
						
							|  |  |  | |:---:|:-------------------------------------| | 
					
						
							|  |  |  | |  0  | `{"Name":"Barack Obama","Index":44}` | | 
					
						
							|  |  |  | |  1  | `{"Name":"Donald Trump","Index":45}` | | 
					
						
							|  |  |  | |  2  | `{"Name":"Joseph Biden","Index":46}` | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### Importing Data
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Starting from a worksheet, `XLSX.utils.sheet_to_json` generates an array of row | 
					
						
							|  |  |  | objects.  `localStorage.setItem` will store data in Local Storage: | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  | function sheet_to_localStorage(worksheet) { | 
					
						
							|  |  |  |   const aoo = XLSX.utils.sheet_to_json(worksheet); | 
					
						
							|  |  |  |   for(let i = 0; i < aoo.length; ++i) { | 
					
						
							|  |  |  |     localStorage.setItem(i, JSON.stringify(aoo[i])); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  | #### Exporting Data
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `localStorage.length` returns the total number of entries. A simple `for` loop | 
					
						
							|  |  |  | can cover the keys (integers from `0` to `localStorage.length - 1` inclusive) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `localStorage.getItem` will load the stringified data from the Local Storage. A | 
					
						
							|  |  |  | new array of objects can be constructed by using `JSON.parse` and pushing to an | 
					
						
							|  |  |  | array.  `XLSX.utils.json_to_sheet` can create a new worksheet from that array: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | function localStorage_to_sheet() { | 
					
						
							|  |  |  |   const aoo = []; | 
					
						
							|  |  |  |   for(let i = 0; i < localStorage.length; ++i) { | 
					
						
							|  |  |  |     aoo.push(JSON.parse(localStorage.getItem(i))); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return XLSX.utils.json_to_sheet(aoo); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Live Demo
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo was last tested on 2023 February 26. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This example will fetch <https://sheetjs.com/pres.numbers>, fill `localStorage` | 
					
						
							|  |  |  | with rows, then generate a worksheet from the rows and write to a new file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | After saving the exported file, the Local Storage can be inspected in the | 
					
						
							|  |  |  | "Local Storage" section of the "Application" Tab of Developer Tools: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | :::caution | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This example is for illustration purposes. If array of objects is available, it | 
					
						
							|  |  |  | is strongly recommended to convert that array to a worksheet directly. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJStorage() { | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  |   const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers"); | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  |   const set_url = React.useCallback((evt) => setUrl(evt.target.value)); | 
					
						
							|  |  |  |   const [out, setOut] = React.useState(""); | 
					
						
							|  |  |  |   const xport = React.useCallback(async() => { | 
					
						
							|  |  |  |     // get first worksheet data as array of objects | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  |     const wb = XLSX.read(await (await fetch(url)).arrayBuffer()); | 
					
						
							|  |  |  |     const aoo = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // reset and populate localStorage | 
					
						
							|  |  |  |     localStorage.clear(); | 
					
						
							|  |  |  |     for(var i = 0; i < aoo.length; ++i) localStorage.setItem(i, JSON.stringify(aoo[i])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // create new array of objects from localStorage | 
					
						
							|  |  |  |     const new_aoo = []; | 
					
						
							|  |  |  |     for(var i = 0; i < localStorage.length; ++i) { | 
					
						
							|  |  |  |       const row = JSON.parse(localStorage.getItem(i)); | 
					
						
							|  |  |  |       new_aoo.push(row); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setOut(`Number of rows in LocalStorage: ${localStorage.length}`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // create and export workbook | 
					
						
							|  |  |  |     const new_ws = XLSX.utils.json_to_sheet(new_aoo); | 
					
						
							|  |  |  |     const new_wb = XLSX.utils.book_new(); | 
					
						
							|  |  |  |     XLSX.utils.book_append_sheet(new_wb, new_ws, "Sheet1"); | 
					
						
							|  |  |  |     XLSX.writeFile(new_wb, "SheetJStorage.xlsx"); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  |   return ( <> | 
					
						
							|  |  |  |     {out && (<><a href={url}>{url}</a><pre>{out}</pre></>)} | 
					
						
							| 
									
										
										
										
											2023-02-24 07:46:48 +00:00
										 |  |  |     <b>URL: </b><input type="text" value={url} onChange={set_url} size="50"/> | 
					
						
							|  |  |  |     <br/><button onClick={xport}><b>Fetch!</b></button> | 
					
						
							|  |  |  |   </> ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-02-26 11:38:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Simple Strings
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The ["Row Objects" approach](#row-objects) is strongly recommended when trying | 
					
						
							|  |  |  | to store or recover arrays of row objects. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When the goal is to save an existing Storage, the general representation is an | 
					
						
							|  |  |  | array of pairs.  Consider the following data in Local Storage: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | Key | Value     | | 
					
						
							|  |  |  | |:---:|:----------| | 
					
						
							|  |  |  | | "b" | "Logical" | | 
					
						
							|  |  |  | | "n" | "Numeric" | | 
					
						
							|  |  |  | | "s" | "Textual"  | | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The natural representation is an array of arrays: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | [ | 
					
						
							|  |  |  |   [ "b", "Logical" ], | 
					
						
							|  |  |  |   [ "n", "Numeric" ], | 
					
						
							|  |  |  |   [ "s", "Textual" ] | 
					
						
							|  |  |  | ] | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### Exporting Storage
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In modern browsers, `Object.entries` will generate an array of key/value pairs. | 
					
						
							|  |  |  | `XLSX.utils.aoa_to_sheet` will interpret that array as a worksheet with 2 cols: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | function localStorage_to_ws() { | 
					
						
							|  |  |  |   const aoa = Object.entries(localStorage); | 
					
						
							|  |  |  |   return XLSX.utils.aoa_to_sheet(aoa); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### Importing Storage
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In the other direction, the worksheet is assumed to store keys in column A and | 
					
						
							|  |  |  | values in column B.  `XLSX.utils.sheet_to_json` with the `header: 1` option | 
					
						
							|  |  |  | will generate key/value pairs that can be assigned to a storage: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | function ws_to_localStorage(ws) { | 
					
						
							|  |  |  |   const aoa = XLSX.utils.sheet_to_json(ws, { header: 1 }); | 
					
						
							|  |  |  |   aoa.forEach(([key, val]) => localStorage.setItem(key, val)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` |