| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | --- | 
					
						
							| 
									
										
										
										
											2022-08-26 19:21:53 +00:00
										 |  |  | title: Data Grids and Tables | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  | pagination_prev: demos/frontend/index | 
					
						
							|  |  |  | pagination_next: demos/net/index | 
					
						
							| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Various JavaScript UI components provide a more interactive editing experience. | 
					
						
							|  |  |  | Most are able to interchange with arrays of arrays or arrays of data objects. | 
					
						
							|  |  |  | This demo focuses on a few open source data grids. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [SheetJS Pro](https://sheetjs.com/pro) offers additional features like styling | 
					
						
							|  |  |  | and images. The UI tools typically support many of these advanced features. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To eliminate any confusion, the live examples linked from this page demonstrate | 
					
						
							|  |  |  | SheetJS Community Edition data interchange. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Managed Lifecycle
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Many UI components tend to manage the entire lifecycle, providing methods to | 
					
						
							|  |  |  | import and export data. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `sheet_to_json` utility function generates arrays of objects, which is | 
					
						
							|  |  |  | suitable for a number of libraries.  When more advanced shapes are needed, | 
					
						
							| 
									
										
										
										
											2022-08-25 08:22:28 +00:00
										 |  |  | it is easier to process an array of arrays. | 
					
						
							| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 08:41:34 +00:00
										 |  |  | ### x-spreadsheet
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  | With a familiar UI, `x-spreadsheet` is an excellent choice for a modern editor. | 
					
						
							| 
									
										
										
										
											2022-08-18 08:41:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | [Click here for a live integration demo.](pathname:///xspreadsheet/) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 06:25:57 +00:00
										 |  |  | **[The exposition has been moved to a separate page.](/docs/demos/grid/xs)** | 
					
						
							| 
									
										
										
										
											2022-08-18 08:41:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 06:25:57 +00:00
										 |  |  | ### Canvas Datagrid
 | 
					
						
							| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 06:25:57 +00:00
										 |  |  | After extensive testing, `canvas-datagrid` stood out as a high-performance grid | 
					
						
							|  |  |  | with a straightforward API. | 
					
						
							| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | [Click here for a live integration demo.](pathname:///cdg/index.html) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 06:25:57 +00:00
										 |  |  | **[The exposition has been moved to a separate page.](/docs/demos/grid/cdg)** | 
					
						
							| 
									
										
										
										
											2022-08-24 23:48:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### Tabulator
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-19 21:12:12 +00:00
										 |  |  | [Tabulator](https://tabulator.info/docs/5.4/download#xlsx) includes deep support | 
					
						
							| 
									
										
										
										
											2022-08-25 08:22:28 +00:00
										 |  |  | through a special Export button.  It handles the SheetJS operations internally. | 
					
						
							| 
									
										
										
										
											2022-08-24 23:48:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | ### Angular UI Grid
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::warning | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This UI Grid is for AngularJS, not the modern Angular.  New projects should not | 
					
						
							|  |  |  | use AngularJS.  This demo is included for legacy applications. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-09 00:20:50 +00:00
										 |  |  | The [AngularJS demo](/docs/demos/frontend/angularjs) covers more general strategies. | 
					
						
							| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [Click here for a live integration demo.](pathname:///angularjs/ui-grid.html) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Notes</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The library does not provide any way to modify the import button, so the demo | 
					
						
							| 
									
										
										
										
											2022-08-25 08:22:28 +00:00
										 |  |  | includes a simple directive for a File Input HTML element.  It also includes a | 
					
						
							| 
									
										
										
										
											2022-08-01 05:34:23 +00:00
										 |  |  | sample service for export which adds an item to the export menu. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The demo `SheetJSImportDirective` follows the prescription from the README for | 
					
						
							|  |  |  | File input controls using `readAsArrayBuffer`, converting to a suitable | 
					
						
							|  |  |  | representation and updating the scope. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `SheetJSExportService` exposes export functions for `XLSB` and `XLSX`.  Other | 
					
						
							|  |  |  | file formats can be exported by changing the `bookType` variable.  It grabs | 
					
						
							|  |  |  | values from the grid, builds an array of arrays, generates a workbook and forces | 
					
						
							|  |  |  | a download.  By setting the `filename` and `sheetname` options in the `ui-grid` | 
					
						
							|  |  |  | options, the output can be controlled. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Framework Lifecycle
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For modern frameworks like React, data grids tend to follow the framework state | 
					
						
							|  |  |  | and idioms.  The same `sheet_to_json` and `json_to_sheet` / `aoa_to_sheet` | 
					
						
							|  |  |  | methods are used, but they pull from a shared state object that can be mutated | 
					
						
							|  |  |  | with other buttons and components on the page. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### React Data Grid
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 08:50:07 +00:00
										 |  |  | **[The exposition has been moved to a separate page.](/docs/demos/grid/rdg)** | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-07 09:24:49 +00:00
										 |  |  | ### Glide Data Grid
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-07 08:30:20 +00:00
										 |  |  | **[The exposition has been moved to a separate page.](/docs/demos/grid/gdg)** | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | ### Material UI Data Grid
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Material UI Data Grid and React Data Grid share many state patterns and idioms. | 
					
						
							| 
									
										
										
										
											2023-04-19 08:50:07 +00:00
										 |  |  | Differences from ["React Data Grid"](/docs/demos/grid/rdg) will be highlighted. | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | [A complete example is included below.](#muidg-demo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::warning | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Despite presenting an editable UI, Material UI Data Grid version `5.17.0` does | 
					
						
							|  |  |  | not update the state when values are changed. The demo uses the React Data Grid | 
					
						
							|  |  |  | editable structure in the hopes that a future version does support state. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Until the issues are resolved, "React Data Grid" is an excellent choice. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **Rows and Columns State** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The analogue of `Column` is `GridColDef`.  The simple structure looks like: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  | import { DataGrid, GridColDef } from "@mui/x-data-grid"; | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default function App() { | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  |   const [rows, setRows] = useState([]); | 
					
						
							|  |  |  |   const [columns, setColumns] = useState([]); | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  |   return ( <DataGrid columns={columns} rows={rows} onRowsChange={setRows} /> ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The most generic data representation is an array of arrays. To sate the grid, | 
					
						
							|  |  |  | columns must be objects whose `field` property is the index converted to string: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```ts | 
					
						
							|  |  |  | import { WorkSheet, utils } from 'xlsx'; | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  | import { GridColDef } from "@mui/x-data-grid"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Row = any[]; | 
					
						
							|  |  |  | type RowCol = { rows: Row[]; columns: GridColDef[]; }; | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | function ws_to_muidg(ws: WorkSheet): RowCol { | 
					
						
							|  |  |  |   /* create an array of arrays */ | 
					
						
							|  |  |  |   const rows = utils.sheet_to_json(ws, { header: 1 }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* create column array */ | 
					
						
							|  |  |  |   const range = utils.decode_range(ws["!ref"]||"A1"); | 
					
						
							|  |  |  |   const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({ | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  |     // highlight-start | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  |     field: String(i), // MUIDG will access row["0"], row["1"], etc | 
					
						
							|  |  |  |     headerName: utils.encode_col(i), // the column labels will be A, B, etc | 
					
						
							|  |  |  |     editable: true // enable cell editing | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  |     // highlight-end | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  |   })); | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  |   return { rows, columns }; // these can be fed to setRows / setColumns | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | In the other direction, a worksheet can be generated with `aoa_to_sheet`: | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | :::caution | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | `x-data-grid` does not properly preserve row array objects, so the row arrays | 
					
						
							|  |  |  | must be re-created.  The snippet defines a `arrayify` function. | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | ::: | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | ```ts | 
					
						
							|  |  |  | import { WorkSheet, utils } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | type Row = any[]; | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | // highlight-start | 
					
						
							|  |  |  | function arrayify(rows: any[]): Row[] { | 
					
						
							|  |  |  |   return rows.map(row => { | 
					
						
							|  |  |  |     var length = Object.keys(row).length; | 
					
						
							|  |  |  |     for(; length > 0; --length) if(row[length-1] != null) break; | 
					
						
							|  |  |  |     return Array.from({length, ...row}); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | // highlight-end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function muidg_to_ws(rows: Row[]): WorkSheet { | 
					
						
							|  |  |  |   return utils.aoa_to_sheet(arrayify(rows)); | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | <!-- spellchecker-disable --> | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | #### MUIDG Demo
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <!-- spellchecker-enable --> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Complete Example</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 0) [Follow the React Data Grid demo](#rdg-demo) and generate the sample app. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Install dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz @mui/x-data-grid @emotion/react @emotion/styled | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2) Download [`App.tsx`](pathname:///muidg/App.tsx) and replace `src/App.tsx`. | 
					
						
							| 
									
										
										
										
											2022-08-17 07:10:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | 3) run `npm start`.  When you load the page in the browser, it will attempt to | 
					
						
							|  |  |  |    fetch <https://sheetjs.com/pres.numbers> and load the data. | 
					
						
							| 
									
										
										
										
											2022-08-18 08:41:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-25 08:22:28 +00:00
										 |  |  | <!-- spellchecker-disable --> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 08:41:34 +00:00
										 |  |  | ### vue3-table-lite
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-25 08:22:28 +00:00
										 |  |  | <!-- spellchecker-enable --> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-24 08:50:42 +00:00
										 |  |  | **[The exposition has been moved to a separate page.](/docs/demos/grid/vtl)** | 
					
						
							| 
									
										
										
										
											2022-08-18 08:41:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | ## Standard HTML Tables
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Many UI components present styled HTML tables.  Data can be extracted from the | 
					
						
							|  |  |  | tables given a reference to the underlying TABLE element: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | function export_html_table(table) { | 
					
						
							|  |  |  |   const wb = XLSX.utils.table_to_book(table); | 
					
						
							|  |  |  |   XLSX.writeFile(wb, "HTMLTable.xlsx"); | 
					
						
							|  |  |  | } // yes, it's that easy! | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::info | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SheetJS CE is focused on data preservation and will extract values from tables. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [SheetJS Pro](https://sheetjs.com/pro) offers styling support when reading from | 
					
						
							|  |  |  | TABLE elements and when writing to XLSX and other spreadsheet formats. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Fixed Tables
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When the page has a raw HTML table, the easiest solution is to attach an `id`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html | 
					
						
							|  |  |  | <table id="xport"><tr><td>SheetJS</td></tr></table> | 
					
						
							|  |  |  | <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script> | 
					
						
							|  |  |  | <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script> | 
					
						
							|  |  |  | <script> | 
					
						
							|  |  |  | /* as long as this script appears after the table, it will be visible */ | 
					
						
							|  |  |  | var tbl = document.getElementById("xport"); | 
					
						
							|  |  |  | const wb = XLSX.utils.table_to_book(tbl); | 
					
						
							|  |  |  | XLSX.writeFile(wb, "HTMLTable.xlsx"); | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When programmatically constructing the table in the browser, retain a reference: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var tbl = document.createElement("TABLE"); | 
					
						
							|  |  |  | tbl.insertRow(0).insertCell(0).innerHTML = "SheetJS"; | 
					
						
							|  |  |  | document.body.appendChild(tbl); | 
					
						
							|  |  |  | const wb = XLSX.utils.table_to_book(tbl); | 
					
						
							|  |  |  | XLSX.writeFile(wb, "HTMLFlicker.xlsx"); | 
					
						
							|  |  |  | document.body.removeChild(tbl); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### React
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The typical solution is to attach a Ref to the table element.  The `current` | 
					
						
							|  |  |  | property will be a live reference which plays nice with `table_to_book`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  | import { useRef } from "react"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default function ReactTable() { | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  |   const tbl = useRef(null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( <> | 
					
						
							|  |  |  |     <button onClick={() => { | 
					
						
							|  |  |  |       // highlight-next-line | 
					
						
							|  |  |  |       const wb = XLSX.utils.table_to_book(tbl.current); | 
					
						
							|  |  |  |       XLSX.writeFile(wb, "ReactTable.xlsx"); | 
					
						
							|  |  |  |     }}>Export</button> | 
					
						
							|  |  |  |     // highlight-next-line | 
					
						
							|  |  |  |     <table ref={tbl}> | 
					
						
							|  |  |  |     {/* ... TR and TD/TH elements ... */} | 
					
						
							|  |  |  |     </table> | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |   </> ); | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Material UI Table
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `Table` component abstracts the `<table>` element in HTML. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```tsx | 
					
						
							|  |  |  | import TableContainer from '@mui/material/TableContainer'; | 
					
						
							|  |  |  | import Table from '@mui/material/Table'; | 
					
						
							|  |  |  | // ... | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  | import { useRef } from "react"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ... | 
					
						
							|  |  |  | export default function BasicTable() { | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  |   const tbl = useRef<HTMLTableElement>(null); | 
					
						
							| 
									
										
										
										
											2023-02-28 11:40:44 +00:00
										 |  |  |   return ( <> | 
					
						
							| 
									
										
										
										
											2022-09-03 10:02:45 +00:00
										 |  |  |     <button onClick={() => { | 
					
						
							|  |  |  |       const wb = utils.table_to_book(tbl.current); | 
					
						
							|  |  |  |       writeFileXLSX(wb, "SheetJSMaterialUI.xlsx"); | 
					
						
							|  |  |  |     }}>Export</button> | 
					
						
							|  |  |  |     <TableContainer {...}> | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  |       <Table {...} ref={tbl}> | 
					
						
							|  |  |  |       {/* ... material ui table machinations ... */} | 
					
						
							|  |  |  |       </Table> | 
					
						
							|  |  |  |     </TableContainer> | 
					
						
							|  |  |  |   <>); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details><summary><b>Complete Example</b> (click to show)</summary> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Create a new TypeScript `create-react-app` app: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npx create-react-app sheetjs-mui --template typescript | 
					
						
							|  |  |  | cd sheetjs-mui | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2) Install dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz @mui/material | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3) Replace `src/App.tsx` with the following code. This is based on the official | 
					
						
							|  |  |  | Material UI Table example.  Differences are highlighted. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```tsx title="src/App.tsx" | 
					
						
							|  |  |  | // highlight-start | 
					
						
							|  |  |  | import React, { useEffect, useState, useRef, ChangeEvent } from "react"; | 
					
						
							|  |  |  | import { utils, writeFileXLSX } from 'xlsx'; | 
					
						
							|  |  |  | // highlight-end | 
					
						
							|  |  |  | import Table from '@mui/material/Table'; | 
					
						
							|  |  |  | import TableBody from '@mui/material/TableBody'; | 
					
						
							|  |  |  | import TableCell from '@mui/material/TableCell'; | 
					
						
							|  |  |  | import TableContainer from '@mui/material/TableContainer'; | 
					
						
							|  |  |  | import TableHead from '@mui/material/TableHead'; | 
					
						
							|  |  |  | import TableRow from '@mui/material/TableRow'; | 
					
						
							|  |  |  | import Paper from '@mui/material/Paper'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function createData( | 
					
						
							|  |  |  |   name: string, | 
					
						
							|  |  |  |   calories: number, | 
					
						
							|  |  |  |   fat: number, | 
					
						
							|  |  |  |   carbs: number, | 
					
						
							|  |  |  |   protein: number, | 
					
						
							|  |  |  | ) { | 
					
						
							|  |  |  |   return { name, calories, fat, carbs, protein }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const rows = [ | 
					
						
							|  |  |  |   createData('Frozen yoghurt', 159, 6.0, 24, 4.0), | 
					
						
							|  |  |  |   createData('Ice cream sandwich', 237, 9.0, 37, 4.3), | 
					
						
							|  |  |  |   createData('Eclair', 262, 16.0, 24, 6.0), | 
					
						
							|  |  |  |   createData('Cupcake', 305, 3.7, 67, 4.3), | 
					
						
							|  |  |  |   createData('Gingerbread', 356, 16.0, 49, 3.9), | 
					
						
							|  |  |  | ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default function BasicTable() { | 
					
						
							|  |  |  |   // highlight-start | 
					
						
							|  |  |  |   const tbl = useRef<HTMLTableElement>(null); | 
					
						
							|  |  |  |   return ( <> | 
					
						
							|  |  |  |     <button onClick={() => { | 
					
						
							|  |  |  |       const wb = utils.table_to_book(tbl.current); | 
					
						
							|  |  |  |       writeFileXLSX(wb, "SheetJSMaterialUI.xlsx"); | 
					
						
							|  |  |  |     }}>Export</button> | 
					
						
							|  |  |  |     // highlight-end | 
					
						
							|  |  |  |     <TableContainer component={Paper}> | 
					
						
							|  |  |  |       // highlight-next-line | 
					
						
							|  |  |  |       <Table sx={{ minWidth: 650 }} aria-label="simple table" ref={tbl}> | 
					
						
							|  |  |  |         <TableHead> | 
					
						
							|  |  |  |           <TableRow> | 
					
						
							|  |  |  |             <TableCell>Dessert (100g serving)</TableCell> | 
					
						
							|  |  |  |             <TableCell align="right">Calories</TableCell> | 
					
						
							|  |  |  |             <TableCell align="right">Fat (g)</TableCell> | 
					
						
							|  |  |  |             <TableCell align="right">Carbs (g)</TableCell> | 
					
						
							|  |  |  |             <TableCell align="right">Protein (g)</TableCell> | 
					
						
							|  |  |  |           </TableRow> | 
					
						
							|  |  |  |         </TableHead> | 
					
						
							|  |  |  |         <TableBody> | 
					
						
							|  |  |  |           {rows.map((row) => ( | 
					
						
							|  |  |  |             <TableRow | 
					
						
							|  |  |  |               key={row.name} | 
					
						
							|  |  |  |               sx={{ '&:last-child td, &:last-child th': { border: 0 } }} | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               <TableCell component="th" scope="row"> | 
					
						
							|  |  |  |                 {row.name} | 
					
						
							|  |  |  |               </TableCell> | 
					
						
							|  |  |  |               <TableCell align="right">{row.calories}</TableCell> | 
					
						
							|  |  |  |               <TableCell align="right">{row.fat}</TableCell> | 
					
						
							|  |  |  |               <TableCell align="right">{row.carbs}</TableCell> | 
					
						
							|  |  |  |               <TableCell align="right">{row.protein}</TableCell> | 
					
						
							|  |  |  |             </TableRow> | 
					
						
							|  |  |  |           ))} | 
					
						
							|  |  |  |         </TableBody> | 
					
						
							|  |  |  |       </Table> | 
					
						
							|  |  |  |     </TableContainer> | 
					
						
							|  |  |  |     // highlight-next-line | 
					
						
							|  |  |  |   </> ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 4) run `npm start`.  Click the "Export" button and inspect the generated file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> |