forked from sheetjs/docs.sheetjs.com
		
	
		
			
	
	
		
			548 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			548 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								title: Sheets in OpenUI5 Sites
							 | 
						||
| 
								 | 
							
								sidebar_label: OpenUI5
							 | 
						||
| 
								 | 
							
								description: Build enterprise-grade applications with OpenUI5. Seamlessly integrate spreadsheets into your app using SheetJS. Bring Excel-powered workflows and data to the modern web.
							 | 
						||
| 
								 | 
							
								pagination_prev: demos/index
							 | 
						||
| 
								 | 
							
								pagination_next: demos/grid/index
							 | 
						||
| 
								 | 
							
								sidebar_position: 10
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import current from '/version.js';
							 | 
						||
| 
								 | 
							
								import Tabs from '@theme/Tabs';
							 | 
						||
| 
								 | 
							
								import TabItem from '@theme/TabItem';
							 | 
						||
| 
								 | 
							
								import CodeBlock from '@theme/CodeBlock';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[OpenUI5](https://openui5.org/) is a JavaScript framework for building enterprise-ready web applications.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
							 | 
						||
| 
								 | 
							
								data from spreadsheets.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This demo uses OpenUI5 and SheetJS to process and generate a spreadsheets. We'll
							 | 
						||
| 
								 | 
							
								explore how to load SheetJS in an OpenUI5 app and handle data binding with the
							 | 
						||
| 
								 | 
							
								Model-View-Controller pattern.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Installation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
							 | 
						||
| 
								 | 
							
								installation with Yarn and other package managers.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The library should be loaded via script tag in your HTML:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<CodeBlock language="html" value="html">
							 | 
						||
| 
								 | 
							
								    {`<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
							 | 
						||
| 
								 | 
							
								</CodeBlock>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This will expose the `XLSX` global object which contains all the necessary methods. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Internal State
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The various SheetJS APIs work with various data shapes. The preferred state
							 | 
						||
| 
								 | 
							
								depends on the application.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### JSON Model
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The OpenUI5 JSON Model provides ideal integration for spreadsheet data, enabling direct UI control binding.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### State
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The example [presidents sheet](https://docs.sheetjs.com/pres.xlsx) has one
							 | 
						||
| 
								 | 
							
								header row with "Name" and "Index" columns. The natural JS representation is an
							 | 
						||
| 
								 | 
							
								object for each row, using the values in the first rows as keys:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<table>
							 | 
						||
| 
								 | 
							
								  <thead><tr><th>Spreadsheet</th><th>State</th></tr></thead>
							 | 
						||
| 
								 | 
							
								  <tbody><tr><td>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								</td><td>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								[
							 | 
						||
| 
								 | 
							
								  { Name: "Bill Clinton", Index: 42 },
							 | 
						||
| 
								 | 
							
								  { Name: "GeorgeW Bush", Index: 43 },
							 | 
						||
| 
								 | 
							
								  { Name: "Barack Obama", Index: 44 },
							 | 
						||
| 
								 | 
							
								  { Name: "Donald Trump", Index: 45 },
							 | 
						||
| 
								 | 
							
								  { Name: "Joseph Biden", Index: 46 }
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								</td></tr></tbody></table>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The OpenUI5 `JSONModel`[^1] is a client-side model implementation that stores data as JSON.
							 | 
						||
| 
								 | 
							
								Here's a basic example of initializing a model, with a more complete implementation shown later:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<Tabs groupId="lang">
							 | 
						||
| 
								 | 
							
								  <TabItem name="JS" value="JavaScript">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								sap.ui.define(["sap/ui/model/json/JSONModel"], function (JSONModel) {
							 | 
						||
| 
								 | 
							
								    const oModel = new JSONModel({ presidents: [] });
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								  </TabItem>
							 | 
						||
| 
								 | 
							
								</Tabs>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Updating State
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The SheetJS [`read`](/docs/api/parse-options) and [`sheet_to_json`](/docs/api/utilities/array#array-output)
							 | 
						||
| 
								 | 
							
								functions simplify state updates. OpenUI5's JSONModel provides powerful two-way data binding
							 | 
						||
| 
								 | 
							
								capabilities.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```mermaid
							 | 
						||
| 
								 | 
							
								flowchart LR
							 | 
						||
| 
								 | 
							
								  url[(Remote\nFile)]
							 | 
						||
| 
								 | 
							
								  ab[(Data\nArrayBuffer)]
							 | 
						||
| 
								 | 
							
								  wb(SheetJS\nWorkbook)
							 | 
						||
| 
								 | 
							
								  ws(SheetJS\nWorksheet)
							 | 
						||
| 
								 | 
							
								  aoo(array of\nobjects)
							 | 
						||
| 
								 | 
							
								  model((JSON\nModel))
							 | 
						||
| 
								 | 
							
								  url --> |fetch\n\n| ab
							 | 
						||
| 
								 | 
							
								  ab --> |read\n\n| wb
							 | 
						||
| 
								 | 
							
								  wb --> |wb.Sheets\nselect sheet| ws
							 | 
						||
| 
								 | 
							
								  ws --> |sheet_to_json\n\n| aoo
							 | 
						||
| 
								 | 
							
								  aoo --> |setProperty\nfrom model| model
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<Tabs groupId="lang">
							 | 
						||
| 
								 | 
							
								  <TabItem name="JS" value="JavaScript">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								_loadExcelFile: async function () {
							 | 
						||
| 
								 | 
							
								  /* Download from https://docs.sheetjs.com/pres.xlsx */
							 | 
						||
| 
								 | 
							
								  const f = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer();
							 | 
						||
| 
								 | 
							
								  // highlight-start
							 | 
						||
| 
								 | 
							
								  /* parse */
							 | 
						||
| 
								 | 
							
								  const wb = XLSX.read(f); // parse the array buffer
							 | 
						||
| 
								 | 
							
								  /* generate array of objects from first worksheet */
							 | 
						||
| 
								 | 
							
								  const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
							 | 
						||
| 
								 | 
							
								  const data = XLSX.utils.sheet_to_json(ws); // generate objects
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* update JSONModel */
							 | 
						||
| 
								 | 
							
								    this.getView().getModel().setProperty("/presidents", data);
							 | 
						||
| 
								 | 
							
								  // highlight-end
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  </TabItem>
							 | 
						||
| 
								 | 
							
								</Tabs>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Rendering Data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In OpenUI5, the `Model-View-Controller`[^2] pattern is used to organize code and separate concerns.
							 | 
						||
| 
								 | 
							
								The view defines the UI structure, the controller handles the logic, and the model manages the data.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```xml title="Example XML for displayin array of objects"
							 | 
						||
| 
								 | 
							
								<mvc:View>
							 | 
						||
| 
								 | 
							
								    <Page>
							 | 
						||
| 
								 | 
							
								        <!-- The Table component binds to the presidents array -->
							 | 
						||
| 
								 | 
							
								        <Table width="300px" items="{/presidents}">
							 | 
						||
| 
								 | 
							
								            <!-- Column definitions specify the table structure -->
							 | 
						||
| 
								 | 
							
								            <columns>
							 | 
						||
| 
								 | 
							
								                <Column>
							 | 
						||
| 
								 | 
							
								                    <header> <Text text="Name" /> </header>
							 | 
						||
| 
								 | 
							
								                </Column>
							 | 
						||
| 
								 | 
							
								                <Column>
							 | 
						||
| 
								 | 
							
								                    <header> <Text text="Value" /> </header>
							 | 
						||
| 
								 | 
							
								                </Column>
							 | 
						||
| 
								 | 
							
								            </columns>
							 | 
						||
| 
								 | 
							
								            <!-- ColumnItem template defines how each row should be rendered -->
							 | 
						||
| 
								 | 
							
								            // highlight-start
							 | 
						||
| 
								 | 
							
								            <items>
							 | 
						||
| 
								 | 
							
								                <ColumnItem>
							 | 
						||
| 
								 | 
							
								                    <cells>
							 | 
						||
| 
								 | 
							
								                        <Text text="{Name}" />
							 | 
						||
| 
								 | 
							
								                        <Text text="{Index}" />
							 | 
						||
| 
								 | 
							
								                    </cells>
							 | 
						||
| 
								 | 
							
								                </ColumnItem>
							 | 
						||
| 
								 | 
							
								            </items>
							 | 
						||
| 
								 | 
							
								            // highlight-end
							 | 
						||
| 
								 | 
							
								        </Table>
							 | 
						||
| 
								 | 
							
								    </Page>
							 | 
						||
| 
								 | 
							
								</mvc:View>
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Exporting Data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The [`writeFile`](/docs/api/write-options) and [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
							 | 
						||
| 
								 | 
							
								functions simplify exporting data. They are typically used in event handlers attached to buttons or other elements.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A button press handler can generate a local file when clicked:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```mermaid
							 | 
						||
| 
								 | 
							
								flowchart LR
							 | 
						||
| 
								 | 
							
								  state((oModel\ngetProperty))
							 | 
						||
| 
								 | 
							
								  ws(SheetJS\nWorksheet)
							 | 
						||
| 
								 | 
							
								  wb(SheetJS\nWorkbook)
							 | 
						||
| 
								 | 
							
								  file[(XLSX\nexport)]
							 | 
						||
| 
								 | 
							
								  state --> |json_to_sheet\n\n| ws
							 | 
						||
| 
								 | 
							
								  ws --> |book_new\nbook_append_sheet| wb
							 | 
						||
| 
								 | 
							
								  wb --> |writeFile\n\n| file
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								/* get model data and export to XLSX */
							 | 
						||
| 
								 | 
							
								 onExport: function() {
							 | 
						||
| 
								 | 
							
								    const data = this.getView().getModel().getProperty("/presidents");
							 | 
						||
| 
								 | 
							
								    /* generate worksheet from model data */
							 | 
						||
| 
								 | 
							
								    // highlight-next-line
							 | 
						||
| 
								 | 
							
								    const ws = XLSX.utils.json_to_sheet(data);
							 | 
						||
| 
								 | 
							
								    /* create workbook and append worksheet */
							 | 
						||
| 
								 | 
							
								    const wb = XLSX.utils.book_new();
							 | 
						||
| 
								 | 
							
								    XLSX.utils.book_append_sheet(wb, ws, "Data");
							 | 
						||
| 
								 | 
							
								    /* export to XLSX */
							 | 
						||
| 
								 | 
							
								    XLSX.writeFileXLSX(wb, "SheetJSOpenUI5AoO.xlsx");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Complete Component
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This complete component example fetches a test file and displays the contents in a table.
							 | 
						||
| 
								 | 
							
								When the export button is clicked, an event handler will export a file:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```xml title="webapp/view/Main.view.xml"
							 | 
						||
| 
								 | 
							
								<mvc:View
							 | 
						||
| 
								 | 
							
								    controllerName="sheetjs.openui5.controller.Main"
							 | 
						||
| 
								 | 
							
								    displayBlock="true"
							 | 
						||
| 
								 | 
							
								    xmlns="sap.m"
							 | 
						||
| 
								 | 
							
								    xmlns:mvc="sap.ui.core.mvc"
							 | 
						||
| 
								 | 
							
								    xmlns:core="sap.ui.core"
							 | 
						||
| 
								 | 
							
								    core:require="{formatter: 'sheetjs/openui5/model/formatter'}">
							 | 
						||
| 
								 | 
							
								    <Page>
							 | 
						||
| 
								 | 
							
								        <VBox width="auto" alignItems="Start">
							 | 
						||
| 
								 | 
							
								            <Table width="300px" items="{/presidents}">
							 | 
						||
| 
								 | 
							
								                <columns>
							 | 
						||
| 
								 | 
							
								                    <Column>
							 | 
						||
| 
								 | 
							
								                        <header>
							 | 
						||
| 
								 | 
							
								                            <Text text="Name" />
							 | 
						||
| 
								 | 
							
								                        </header>
							 | 
						||
| 
								 | 
							
								                    </Column>
							 | 
						||
| 
								 | 
							
								                    <Column>
							 | 
						||
| 
								 | 
							
								                        <header>
							 | 
						||
| 
								 | 
							
								                            <Text text="Value" />
							 | 
						||
| 
								 | 
							
								                        </header>
							 | 
						||
| 
								 | 
							
								                    </Column>
							 | 
						||
| 
								 | 
							
								                </columns>
							 | 
						||
| 
								 | 
							
								                <items>
							 | 
						||
| 
								 | 
							
								                    <ColumnListItem>
							 | 
						||
| 
								 | 
							
								                        <cells>
							 | 
						||
| 
								 | 
							
								                            <Text text="{Name}" />
							 | 
						||
| 
								 | 
							
								                            <Text text="{Index}" />
							 | 
						||
| 
								 | 
							
								                        </cells>
							 | 
						||
| 
								 | 
							
								                    </ColumnListItem>
							 | 
						||
| 
								 | 
							
								                </items>
							 | 
						||
| 
								 | 
							
								            </Table>
							 | 
						||
| 
								 | 
							
								            <Button text="Export XLSX" press=".onExport" />
							 | 
						||
| 
								 | 
							
								        </VBox>
							 | 
						||
| 
								 | 
							
								    </Page>
							 | 
						||
| 
								 | 
							
								</mvc:View>
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="webapp/controller/Main.controller.js"
							 | 
						||
| 
								 | 
							
								sap.ui.define(
							 | 
						||
| 
								 | 
							
								    ["./BaseController", "sap/ui/model/json/JSONModel"],
							 | 
						||
| 
								 | 
							
								    function (BaseController, JSONModel) {
							 | 
						||
| 
								 | 
							
								        "use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return BaseController.extend("com.demo.xlsx.controller.Main", {
							 | 
						||
| 
								 | 
							
								            onInit: function () {
							 | 
						||
| 
								 | 
							
								                /* initialize model */
							 | 
						||
| 
								 | 
							
								                const oModel = new JSONModel({
							 | 
						||
| 
								 | 
							
								                    presidents: [],
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								                this.getView().setModel(oModel);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                /* load data when component is initialized */
							 | 
						||
| 
								 | 
							
								                this._loadExcelFile();
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            _loadExcelFile: async function () {
							 | 
						||
| 
								 | 
							
								                const f = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer();
							 | 
						||
| 
								 | 
							
								                const wb = XLSX.read(f);
							 | 
						||
| 
								 | 
							
								                const ws = wb.Sheets[wb.SheetNames[0]];
							 | 
						||
| 
								 | 
							
								                const data = XLSX.utils.sheet_to_json(ws);
							 | 
						||
| 
								 | 
							
								                this.getView().getModel().setProperty("/presidents", data);
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            onExport: function () {
							 | 
						||
| 
								 | 
							
								                const data = this.getView().getModel().getProperty("/presidents");
							 | 
						||
| 
								 | 
							
								                const ws = XLSX.utils.json_to_sheet(data);
							 | 
						||
| 
								 | 
							
								                const wb = XLSX.utils.book_new();
							 | 
						||
| 
								 | 
							
								                XLSX.utils.book_append_sheet(wb, ws, "Data");
							 | 
						||
| 
								 | 
							
								                XLSX.writeFileXLSX(wb, "SheetJSOpenUI5AoO.xlsx");
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<details open>
							 | 
						||
| 
								 | 
							
								  <summary><b>How to run the example</b> (click to hide)</summary>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::note Tested Deployments
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This demo was tested in the following environments:
							 | 
						||
| 
								 | 
							
								| OpenUI5 | generator-easy-ui5 | Date |
							 | 
						||
| 
								 | 
							
								|:--------|---------|---------|
							 | 
						||
| 
								 | 
							
								| `1.131.1` | `3.8.1`  | 2024-12-24 |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1) Create a new site:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npm i -g generator-easy-ui5
							 | 
						||
| 
								 | 
							
								npx yo easy-ui5 app
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::note Use the provided defaults:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 - Application id: `sheetjs.openui5`
							 | 
						||
| 
								 | 
							
								 - Framework: `OpenUI5`
							 | 
						||
| 
								 | 
							
								 - Version: `1.131.1`
							 | 
						||
| 
								 | 
							
								 - Author: `SheetJS`
							 | 
						||
| 
								 | 
							
								 - Create new directory: `Y`
							 | 
						||
| 
								 | 
							
								 - Initialize git: `N`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								2) Install the dependencies and start server:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								cd sheetjs.openui5
							 | 
						||
| 
								 | 
							
								npm install
							 | 
						||
| 
								 | 
							
								npm start
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								3) Open a web browser and access the displayed URL (`http://localhost:8080`)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								4) Add SheetJS to your project by including this script tag in `webapp/index.html`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<CodeBlock language="html" value="html" title="webapp/index.html">
							 | 
						||
| 
								 | 
							
								    {`<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
							 | 
						||
| 
								 | 
							
								</CodeBlock>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								5) Replace `webapp/view/Main.view.xml` with the complete implementation above.
							 | 
						||
| 
								 | 
							
								6) Replace `webapp/controller/Main.controller.js` with the complete implementation above.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The page will refresh and show a table with an Export button. Click the button and the page will
							 | 
						||
| 
								 | 
							
								attempt to download `SheetJSOpenUI5AoO.xlsx`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								7) Build the site:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npm run build
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The generated site will be placed in the `dist` folder.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								8) Start a local web server:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npm run start:dist
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Access the displayed URL (typically http://localhost:8080) with a web browser and test the page.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When the page loads, the app will fetch https://docs.sheetjs.com/pres.xlsx and
							 | 
						||
| 
								 | 
							
								display the data from the first worksheet in a TABLE. The "Export XLSX" button
							 | 
						||
| 
								 | 
							
								will generate a workbook that can be opened in a spreadsheet editor.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								</details>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### HTML
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The main disadvantage of the Array of Objects approach is the specific nature
							 | 
						||
| 
								 | 
							
								of the columns.  For more general use, passing around an Array of Arrays works.
							 | 
						||
| 
								 | 
							
								However, this does not handle merge cells[^3] well!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The [`sheet_to_html`](/docs/api/utilities/html#html-table-output) function generates HTML that is aware of merges and other worksheet
							 | 
						||
| 
								 | 
							
								features. Using OpenUI5's `core:HTML`[^4] control, we can render this HTML directly. During export, we extract the table element from the
							 | 
						||
| 
								 | 
							
								rendered HTML and use [`table_to_book`](/docs/api/utilities/html#html-table-input) to create a workbook that maintains all the worksheet
							 | 
						||
| 
								 | 
							
								features.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In this example, the component directly renders the HTML table in the model through OpenUI5's `core:HTML`[^4] control. For export, we extract
							 | 
						||
| 
								 | 
							
								the inner table from the rendered HTML using `getElementsByTagName("table")[1]`, then pass it to [`table_to_book`](/docs/api/utilities/html#html-table-input)
							 | 
						||
| 
								 | 
							
								to create a workbook that preserves all features.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```xml title="webapp/view/Main.view.xml"
							 | 
						||
| 
								 | 
							
								<mvc:View
							 | 
						||
| 
								 | 
							
								        controllerName="sheetjs.openui5.controller.Main"
							 | 
						||
| 
								 | 
							
								        displayBlock="true"
							 | 
						||
| 
								 | 
							
								        xmlns="sap.m"
							 | 
						||
| 
								 | 
							
								        xmlns:mvc="sap.ui.core.mvc"
							 | 
						||
| 
								 | 
							
								        xmlns:core="sap.ui.core"
							 | 
						||
| 
								 | 
							
								        xmlns:html="http://www.w3.org/1999/xhtml">
							 | 
						||
| 
								 | 
							
								    <Page>
							 | 
						||
| 
								 | 
							
								        <content>
							 | 
						||
| 
								 | 
							
								            <core:HTML content="{/tableHTML}" />
							 | 
						||
| 
								 | 
							
								            <Button text="Export XLSX" press=".onExport"/>
							 | 
						||
| 
								 | 
							
								        </content>
							 | 
						||
| 
								 | 
							
								    </Page>
							 | 
						||
| 
								 | 
							
								</mvc:View>
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js title="webapp/controller/Main.controller.js"
							 | 
						||
| 
								 | 
							
								sap.ui.define(
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        "sap/ui/core/mvc/Controller",
							 | 
						||
| 
								 | 
							
								        "sap/ui/model/json/JSONModel"
							 | 
						||
| 
								 | 
							
								    ],
							 | 
						||
| 
								 | 
							
								    function (Controller, JSONModel) {
							 | 
						||
| 
								 | 
							
								        "use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return Controller.extend("sheetjs.openui5.controller.Main", {
							 | 
						||
| 
								 | 
							
								            onInit: function () {
							 | 
						||
| 
								 | 
							
								                /* the component state is an HTML string */
							 | 
						||
| 
								 | 
							
								                const oModel = new JSONModel({
							 | 
						||
| 
								 | 
							
								                    tableHTML: "",
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								                this.getView().setModel(oModel);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                /* load data when component is initialized */
							 | 
						||
| 
								 | 
							
								                this._loadExcelFile();
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            _loadExcelFile: async function () {
							 | 
						||
| 
								 | 
							
								                const f = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer();
							 | 
						||
| 
								 | 
							
								                const wb = XLSX.read(f); // parse the array buffer
							 | 
						||
| 
								 | 
							
								                const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
							 | 
						||
| 
								 | 
							
								                const opts = {
							 | 
						||
| 
								 | 
							
								                    header: `<table id="excel-table">`,
							 | 
						||
| 
								 | 
							
								                    footer: `</table>`
							 | 
						||
| 
								 | 
							
								                };
							 | 
						||
| 
								 | 
							
								                const tableHTML = XLSX.utils.sheet_to_html(ws, opts); // generate HTML
							 | 
						||
| 
								 | 
							
								                this.getView().getModel().setProperty("/tableHTML", tableHTML); // update state
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            /* get live table and export the XLSX */
							 | 
						||
| 
								 | 
							
								            onExport: function () {
							 | 
						||
| 
								 | 
							
								                const tableHTML = this.getView().getModel().getProperty("/tableHTML"); // get HTML string from the model
							 | 
						||
| 
								 | 
							
								                const div = document.createElement("div"); // create temporary div to parse HTML
							 | 
						||
| 
								 | 
							
								                div.innerHTML = tableHTML; // insert HTML into div
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                const table = div.getElementsByTagName("table")[1]; // get inner table (bypasses outer wrapper)
							 | 
						||
| 
								 | 
							
								                const wb = XLSX.utils.table_to_book(table); // convert table element to workbook
							 | 
						||
| 
								 | 
							
								                XLSX.writeFileXLSX(wb, "SheetJSOpenUI5HTML.xlsx");
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<details open>
							 | 
						||
| 
								 | 
							
								  <summary><b>How to run the example</b> (click to hide)</summary>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::note Tested Deployments
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This demo was tested in the following environments:
							 | 
						||
| 
								 | 
							
								| OpenUI5 | generator-easy-ui5 | Date |
							 | 
						||
| 
								 | 
							
								|:--------|---------|---------|
							 | 
						||
| 
								 | 
							
								| `1.131.1` | `3.8.1`  | 2024-12-24 |
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1) Create a new site:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npm i -g generator-easy-ui5
							 | 
						||
| 
								 | 
							
								npx yo easy-ui5 app
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::note Use the provided defaults:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- Application id: `sheetjs.openui5`
							 | 
						||
| 
								 | 
							
								- Framework: `OpenUI5`
							 | 
						||
| 
								 | 
							
								- Version: `1.131.1`
							 | 
						||
| 
								 | 
							
								- Author: `SheetJS`
							 | 
						||
| 
								 | 
							
								- Create new directory: `Y`
							 | 
						||
| 
								 | 
							
								- Initialize git: `N`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								2) Install the dependencies and start server:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								cd sheetjs.openui5
							 | 
						||
| 
								 | 
							
								npm install
							 | 
						||
| 
								 | 
							
								npm start
							 | 
						||
| 
								 | 
							
								````
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								3) Open a web browser and access the displayed URL (`http://localhost:8080`)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								4) Add SheetJS to your project by including this script tag in `webapp/index.html`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<CodeBlock language="html" value="html" title="webapp/index.html">
							 | 
						||
| 
								 | 
							
								    {`<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
							 | 
						||
| 
								 | 
							
								</CodeBlock>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								5) Replace `webapp/view/Main.view.xml` with the complete implementation above.
							 | 
						||
| 
								 | 
							
								6) Replace `webapp/controller/Main.controller.js` with the complete implementation above.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The page will refresh and show a table with an Export button. Click the button and the page will
							 | 
						||
| 
								 | 
							
								attempt to download `SheetJSOpenUI5HTML.xlsx`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								7) Build the site:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npm run build
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The generated site will be placed in the `dist` folder.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								8) Start a local web server:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```bash
							 | 
						||
| 
								 | 
							
								npm run start:dist
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Access the displayed URL (typically http://localhost:8080) with a web browser and test the page.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When the page loads, the app will fetch https://docs.sheetjs.com/pres.xlsx and
							 | 
						||
| 
								 | 
							
								display the data from the first worksheet in a TABLE. The "Export XLSX" button
							 | 
						||
| 
								 | 
							
								will generate a workbook that can be opened in a spreadsheet editor.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								</details>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Rows and Columns
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Some data grids and UI components split worksheet state in two parts: an array
							 | 
						||
| 
								 | 
							
								of column attribute objects and an array of row objects.  The former is used to
							 | 
						||
| 
								 | 
							
								generate column headings and for indexing into the row objects.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The safest approach is to use an array of arrays for state and to generate
							 | 
						||
| 
								 | 
							
								column objects that map to A1-Style column headers.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The [React Data Grid demo](/docs/demos/grid/rdg#rows-and-columns-state) uses
							 | 
						||
| 
								 | 
							
								this approach with the following column and row structure:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								/* rows are generated with a simple array of arrays */
							 | 
						||
| 
								 | 
							
								const rows = utils.sheet_to_json(worksheet, { header: 1 });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* column objects are generated based on the worksheet range */
							 | 
						||
| 
								 | 
							
								const range = utils.decode_range(ws["!ref"]||"A1");
							 | 
						||
| 
								 | 
							
								const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({
							 | 
						||
| 
								 | 
							
								  /* for an array of arrays, the keys are "0", "1", "2", ... */
							 | 
						||
| 
								 | 
							
								  key: String(i),
							 | 
						||
| 
								 | 
							
								  /* column labels: encode_col translates 0 -> "A", 1 -> "B", 2 -> "C", ... */
							 | 
						||
| 
								 | 
							
								  name: XLSX.utils.encode_col(i)
							 | 
						||
| 
								 | 
							
								}));
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[^1]: See [`JSONModel`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.model.json.JSONModel.html) in the OpenUI5 documentation.
							 | 
						||
| 
								 | 
							
								[^2]: See OpenUI5's [MVC Documentation](https://sdk.openui5.org/topic/91f233476f4d1014b6dd926db0e91070) for detailed explanation of the pattern implementation.
							 | 
						||
| 
								 | 
							
								[^3]: See ["Merged Cells" in "SheetJS Data Model"](/docs/csf/features/merges) for more details.
							 | 
						||
| 
								 | 
							
								[^4]: See [`core:HTML`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.core.HTML.html) in the OpenUI5 documentation.
							 |