OpenUI5 Demo

This commit is contained in:
SheetJS 2025-01-26 11:46:11 -05:00
parent f48835d420
commit 8c95521682
9 changed files with 379 additions and 291 deletions

@ -125,47 +125,13 @@ define(['N/file', 'sheetjs'], function(file, XLSX) {
## SAP UI5
After downloading the script, it can be uploaded to the UI5 project and loaded
in the `sap.ui.define` call:
OpenUI5 and SAPUI5 installation instructions are covered in the dedicated
["OpenUI5 / SAPUI5" demo](/docs/demos/frontend/openui5#installation).
```js
sap.ui.define([
/* ... other libraries ... */
"path/to/xlsx.full.min"
], function(/* ... variables for the other libraries ... */, XLSX) {
// use XLSX here
});
```
SheetJS standalone scripts can be loaded in two ways:
:::caution pass
In some deployments, the function argument was `undefined`.
The standalone scripts add `window.XLSX`, so it is recommended to use `_XLSX`
in the function arguments and access the library with `XLSX` in the callback:
```js
sap.ui.define([
/* ... other libraries ... */
"path/to/xlsx.full.min"
], function(
/* ... variables for the other libraries ... */,
_XLSX // !! NOTE: this is not XLSX! A different variable name must be used
) {
// highlight-next-line
alert(XLSX.version); // use XLSX in the callback
});
```
:::
:::danger pass
**Copy and pasting code does not work** for SheetJS scripts as they contain
Unicode characters that may be mangled. The standalone script should be
downloaded and manually uploaded to the project.
:::
- [`sap.ui.define`](/docs/demos/frontend/openui5#installation-define)
- [HTML SCRIPT tag](/docs/demos/frontend/openui5#installation-html)
## RequireJS

@ -39,6 +39,7 @@ This demo was tested in the following configurations:
| NVIDIA RTX 4080 SUPER (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-01-12 |
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-01-12 |
| AMD RX 6800 XT (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-01-12 |
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (24 GB RAM) | `win11-x64` | 2025-01-24 |
| Apple M2 Max 12-Core CPU + 30-Core GPU (32 GB unified memory) | `darwin-arm` | 2024-11-04 |
SheetJS users have verified this demo in other configurations:
@ -718,25 +719,13 @@ export default class LoadOfSheet extends BufferLoader {
The demo performs the query "Which rows have over 40 miles per gallon?" against
a [sample cars dataset](pathname:///cd.xls) and displays the results.
:::note pass
SheetJS team members have tested this demo on Windows 10 and Windows 11 using
PowerShell and Ollama for Windows.
SheetJS team members have tested this demo on Windows 11 using Windows Subsystem
for Linux.
In addition, SheetJS users have also tested this demo on bare metal Linux.
:::
:::caution pass
This demo was tested using the ChatQA-1.5 model[^9] in Ollama.
The tested model used up to 9.2GB VRAM. It is strongly recommended to run the
demo on a newer Apple Silicon Mac or a PC with an Nvidia GPU with at least 12GB
VRAM. SheetJS users have tested the demo on systems with as little as 6GB VRAM.
The tested model used up to 10GB VRAM. It is strongly recommended to run the
demo on a GPU with at least 12GB VRAM or a newer Apple Silicon Mac with at least
32GB unified memory.
:::
@ -752,6 +741,71 @@ within WSL, Ollama should also be installed within WSL.
:::
:::danger pass
Intel ARC GPUs require the Intel Extension for PyTorch (IPEX) and a special
version of Ollama that ships with the associated LLM Library (IPEX-LLM).
<details>
<summary><b>ARC Instructions</b> (click to show)</summary>
These instructions are based on the official Intel recommendations.
A) If Ollama for Windows was installed, close the program by right-clicking on
the tray icon and selecting "Quit Ollama".
B) Install Miniforge3[^10], selecting "Just Me" when prompted.
C) Launch a normal Command Prompt and create a Conda environment:
```bash
cd %USERPROFILE%\Documents
mkdir ollama-intel
cd ollama-intel
set PATH=%PATH%;%USERPROFILE%\miniforge3\condabin
conda create -n llm-cpp python=3.11
```
D) Activate the environment in the session and install dependencies:
```bash
conda activate llm-cpp
pip install --pre --upgrade ipex-llm[cpp]
```
Close the window after the installation.
E) Launch a new Administrator Command Prompt and set up Ollama:
```bash
cd %USERPROFILE%\Documents\ollama-intel
set PATH=%PATH%;%USERPROFILE%\miniforge3\condabin
conda activate llm-cpp
init-ollama.bat
```
Close the window.
F) Launch a normal Command Prompt window and run Ollama:
```bash
cd %USERPROFILE%\Documents\ollama-intel
set PATH=%PATH%;%USERPROFILE%\miniforge3\condabin
conda activate llm-cpp
set OLLAMA_NUM_GPU=999
set no_proxy=localhost,127.0.0.1
set ZES_ENABLE_SYSMAN=1
set SYCL_CACHE_PERSISTENT=1
set SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1
ollama serve
```
This window should be kept open throughout the demo.
</details>
:::
After installing dependencies, start a new terminal session.
1) Create a new project:
@ -840,6 +894,27 @@ curl.exe -LO https://docs.sheetjs.com/cd.xls
ollama pull llama3-chatqa:8b-v1.5-q8_0
```
<details>
<summary><b>Additional steps for Intel GPUs</b> (click to show)</summary>
A different embedding model must be used on Intel GPUs:
A) Install the `nomic-embed-text:latest` model through Ollama:
```bash
ollama pull nomic-embed-text:latest
```
B) Edit `query.mjs` to use the embedding model:
```js title="query.mjs (edit highlighted line)"
const model = new ChatOllama({ baseUrl: "http://127.0.0.1:11434", model: modelName });
// highlight-next-line
const embeddings = new OllamaEmbeddings({ baseUrl: "http://127.0.0.1:11434", model: "nomic-embed-text:latest"});
```
</details>
7) Run the demo script
```bash
@ -899,3 +974,4 @@ charts, tables, and other features.
[^7]: See ["Workbook Object"](/docs/csf/book)
[^8]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
[^9]: See [the official ChatQA website](https://chatqa-project.github.io/) for the ChatQA paper and other model details.
[^10]: Select ["Windows" `x86_64`](https://conda-forge.org/download/) in the Installation page.

@ -34,6 +34,38 @@ includes a complete example starting from the OpenUI5 "Worklist App Tutorial".
SheetJS libraries conform to the UI5 ECMAScript requirements[^1]. SheetJS
libraries can be loaded in a UI5 site at different points in the app lifecycle.
#### UI5 Module {#installation-define}
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
comply with AMD `define` semantics. They support `sap.ui.define` out of the box.
If the SheetJS Standalone script is saved to `webapp/xlsx.full.min.js`, the base
script `webapp/index.js` can load the `./xlsx.full.min` dependency:
```js title="webapp/index.js (loading the SheetJS dependency)"
sap.ui.define([
// highlight-next-line
"./xlsx.full.min", // relative path to script, without the file extension
/* ... other libraries ... */
], function (
// highlight-next-line
_XLSX // !! NOTE: this is not XLSX! A different variable name must be used
/* ... variables for the other libraries ... */,
) {
// highlight-next-line
alert(XLSX.version); // use XLSX in the callback
});
```
:::info pass
In some deployments, the function argument was `undefined`.
The standalone scripts add `window.XLSX`, so it is recommended to use `_XLSX`
in the function arguments and access the library with `XLSX` in the callback.
:::
#### HTML {#installation-html}
UI5 is typically loaded in a `SCRIPT` tag in `webapp/index.html`. Similarly,
@ -72,38 +104,6 @@ in the ["API Reference"](/docs/api/) section of the documentation.
:::
#### UI5 Module {#installation-define}
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
comply with AMD `define` semantics. They support `sap.ui.define` out of the box.
If the SheetJS Standalone script is saved to `webapp/xlsx.full.min.js`, the base
script `webapp/index.js` can load the `./xlsx.full.min` dependency:
```js title="webapp/index.js (loading the SheetJS dependency)"
sap.ui.define([
// highlight-next-line
"./xlsx.full.min", // relative path to script, without the file extension
/* ... other libraries ... */
], function (
// highlight-next-line
_XLSX // !! NOTE: this is not XLSX! A different variable name must be used
/* ... variables for the other libraries ... */,
) {
// highlight-next-line
alert(XLSX.version); // use XLSX in the callback
});
```
:::info pass
In some deployments, the function argument was `undefined`.
The standalone scripts add `window.XLSX`, so it is recommended to use `_XLSX`
in the function arguments and access the library with `XLSX` in the callback.
:::
## Internal State
The various SheetJS APIs work with various data shapes. The preferred state
@ -158,7 +158,7 @@ sap.ui.define(["sap/ui/model/json/JSONModel"], function (JSONModel) {
#### Updating State {#json-update}
Starting from a spreadsheet file, the SheetJS [`read`](/docs/api/parse-options)
method parses the data into a SheetJS workbook object[^6]. After selecting a
method parses the data into a SheetJS workbook object[^3]. After selecting a
worksheet, the [`sheet_to_json`](/docs/api/utilities/array#array-output) method
generates row objects that can be assigned to the model.
@ -201,10 +201,12 @@ _loadExcelFile: async function () {
#### Rendering Data {#json-render}
In UI5, the "Model-View-Controller"[^3] pattern is used to organize code and
In UI5, the "Model-View-Controller"[^4] 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.
The following example uses the `Table` component[^5] to display data.
```xml title="Example View XML for displaying an array of objects"
<mvc:View>
<Page>
@ -234,37 +236,56 @@ logic, and the model manages the data.
#### Exporting Data {#json-export}
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.
The `getProperty` method[^6] of the `JSONModel` pulls data from the UI5 model.
If an array of objects was pushed with `setProperty`, the `getProperty` method
will return an array of objects.
A button press handler can generate a local file when clicked:
The SheetJS [`json_to_sheet`](/docs/api/utilities/array#array-of-objects-input)
function will create a SheetJS worksheet object[^7] from the data in the array.
The [`book_new`](/docs/api/utilities/wb) method will create a SheetJS workbook
object that includes the new worksheet. [`writeFile`](/docs/api/write-options)
will attempt to generate a file and initiate a download.
```mermaid
flowchart LR
state((oModel\ngetProperty))
state((State\nJSONModel))
aoo[(Array of\nObjects)]
ws(SheetJS\nWorksheet)
wb(SheetJS\nWorkbook)
wb(((SheetJS\nWorkbook)))
file[(XLSX\nexport)]
state --> |json_to_sheet\n\n| ws
ws --> |book_new\nbook_append_sheet| wb
state --> |getProperty\n\n| aoo
aoo --> |json_to_sheet\n\n| ws
ws --> |book_new\n\n| wb
wb --> |writeFile\n\n| file
linkStyle 1,2,3 color:blue,stroke:blue;
```
```js
Here is a sample method for exporting data from the UI5 `JSONModel` to XLSX:
```js title="Fetch data from JSONModel and export to XLSX"
/* 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");
}
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(ws, "Data");
/* export to XLSX */
XLSX.writeFileXLSX(wb, "SheetJSOpenUI5AoO.xlsx");
}
```
This method can be bound to the `press` event of a `sap.m.Button` control:
```xml title="Example View XML for exporting an array of objects to a workbook"
<mvc:View>
<Page>
<!-- The `onExport` method is bound to the `press` event -->
<Button text="Export Data" press=".onExport" />
</Page>
</mvc:View>
```
#### Complete Component
@ -272,79 +293,66 @@ This complete component example fetches a test file and displays the contents in
When the export button is clicked, an event handler will export a file:
##### View Implementation {#view-implementation}
```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 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="Index" /></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>
```
##### Controller Implementation {#controller-implementation}
```js title="webapp/controller/Main.controller.js"
sap.ui.define(
["./BaseController", "sap/ui/model/json/JSONModel"],
function (BaseController, JSONModel) {
"use strict";
["./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);
return BaseController.extend("com.demo.xlsx.controller.Main", {
onInit: function () {
/* initialize model */
const oModel = new JSONModel({ presidents: [] });
this.getView().setModel(oModel);
/* load data */
this._loadExcelFile();
},
/* load data when component is initialized */
this._loadExcelFile();
},
_loadExcelFile: async function () {
/* fetch and parse file */
const f = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer();
const wb = XLSX.read(f);
/* extract data from first worksheet */
const ws = wb.Sheets[wb.SheetNames[0]];
const data = XLSX.utils.sheet_to_json(ws);
/* update state model */
this.getView().getModel().setProperty("/presidents", data);
},
_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");
},
});
}
onExport: function () {
/* fetch data from model */
const data = this.getView().getModel().getProperty("/presidents");
/* generate workbook */
const ws = XLSX.utils.json_to_sheet(data);
const wb = XLSX.utils.book_new(ws, "Data");
/* export to XLSX */
XLSX.writeFileXLSX(wb, "SheetJSOpenUI5AoO.xlsx");
},
});
}
);
```
@ -354,9 +362,10 @@ sap.ui.define(
:::note Tested Deployments
This demo was tested in the following environments:
| OpenUI5 | generator-easy-ui5 | Date |
|:--------|---------|---------|
| `1.131.1` | `3.8.1` | 2025-01-07 |
| OpenUI5 | Date |
|:----------|------------|
| `1.132.1` | 2025-01-24 |
:::
@ -367,17 +376,16 @@ npm i --global generator-easy-ui5
npx yo easy-ui5 app
```
:::note Use the provided defaults:
When prompted, enter the following options:
- Application id: `sheetjs.openui5`
- Framework: `OpenUI5`
- Version: `1.131.1`
- Author: `SheetJS`
- Create new directory: `Y`
- Initialize git: `N`
:::
- `Enter your application id (namespace)?`: Type `sheetjs.openui5` and press <kbd>Enter</kbd>
- `Which framework do you want to use?`: Press <kbd>Enter</kbd> (`OpenUI5` should be the default)
- `Which framework version do you want to use?`: Type `1.132.1` and press <kbd>Enter</kbd>
- `Who is the author of the application?`: Press <kbd>Enter</kbd> (use the default author)
- `Would you like to create a new directory for the application?`: Type `Y` and press <kbd>Enter</kbd>
- `Would you like to initialize a local git repository for the application?`: Type `N` and press <kbd>Enter</kbd>
![Expected output](pathname:///ui5/easy-ui5.png)
2) Install the dependencies and start server:
@ -387,35 +395,57 @@ npm install
npm start
```
3) Open a web browser and access the displayed URL (`http://localhost:8080`)
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`:
In the file listing, click `index.html` to launch the app.
<CodeBlock language="html" value="html" title="webapp/index.html">
{`<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
4) Add the SheetJS Standalone script to `webapp/index.html` after the `title` tag:
<CodeBlock language="html" value="html" title="webapp/index.html (add highlighted lines)">{`\
<title>UI5 Application: sheetjs.openui5</title>
<!-- highlight-next-line -->
<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](#view-implementation).
6) Replace `webapp/controller/Main.controller.js` with the complete [implementation above](#controller-implementation).
5) Replace `webapp/view/Main.view.xml` with the `Main.view.xml` snippet in the
["View Implementation" section](#view-implementation).
The page will refresh and show a table with an Export button. Click the button and the page will
attempt to download `SheetJSOpenUI5AoO.xlsx`.
6) Replace `webapp/controller/Main.controller.js` with the `Main.controller.js`
example in the ["Controller Implementation" section](#controller-implementation).
7) Build the site:
7) Switch back to the browser window.
The page will refresh and show a table with an Export button.
Click the button and the page will attempt to download `SheetJSOpenUI5AoO.xlsx`.
This file can be inspected with a spreadsheet editor.
8) Build the site:
```bash
npm run build
npm run build:opt
```
The generated site will be placed in the `dist` folder.
8) Start a local web server:
:::caution pass
SAP recommends `npm run build`. This does not generate a proper standalone site!
Sites built with `npm run build` must be served with `npm run start:dist`.
This demo uses the `build:opt` target to ensure that a proper static site is
generated. The `dist` folder in this demo can be posted
:::
9) Start a local web server:
```bash
npm run start:dist
npx http-server dist
```
Access the displayed URL (typically http://localhost:8080) with a web browser and test the page.
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
@ -426,82 +456,73 @@ will generate a workbook that can be opened in a spreadsheet editor.
### 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[^4] well!
of the columns. For more general use, passing around an Array of Arrays works.
However, this does not handle merge cells[^8] 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`[^5] 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.
The [`sheet_to_html`](/docs/api/utilities/html#html-table-output) function
generates HTML that is aware of merges and other worksheet features.
In this example, the component directly renders the HTML table in the model through OpenUI5's `core:HTML`[^5] 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.
To render the HTML string from the model, the property from the model should be
bound to the `content` property of a UI5 `core:HTML`[^9] control.
On export, the [`table_to_book`](/docs/api/utilities/html#html-table-input)
method creates a SheetJS workbook object from the rendered HTML table.
##### View Implementation {#view-implementation-html}
```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 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 id="tbl" content="{/tableHTML}" />
<Button text="Export XLSX" press=".onExport"/>
</content>
</Page>
</mvc:View>
```
##### Controller Implementation {#controller-implementation-html}
```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";
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);
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 */
this._loadExcelFile();
},
/* load data when component is initialized */
this._loadExcelFile();
},
_loadExcelFile: async function () {
/* fetch and parse file */
const f = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer();
const wb = XLSX.read(f);
/* generate HTML table from first worksheet */
const ws = wb.Sheets[wb.SheetNames[0]];
const opts = { header: `<table>`, footer: `</table>` };
const tableHTML = XLSX.utils.sheet_to_html(ws, opts);
/* update state model */
this.getView().getModel().setProperty("/tableHTML", tableHTML);
},
_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
},
onExport: function () {
/* Get reference to the `TABLE` element in the model */
const table = this.getView().byId("tbl").getDomRef();
/* 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
/* Generate workbook */
const wb = XLSX.utils.table_to_book(table);
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");
},
});
}
/* Export to XLSX */
XLSX.writeFileXLSX(wb, "SheetJSOpenUI5HTML.xlsx");
},
});
}
);
```
@ -511,9 +532,10 @@ sap.ui.define(
:::note Tested Deployments
This demo was tested in the following environments:
| OpenUI5 | generator-easy-ui5 | Date |
|:--------|---------|---------|
| `1.131.1` | `3.8.1` | 2025-01-07 |
| OpenUI5 | Date |
|:----------|------------|
| `1.132.1` | 2025-01-24 |
:::
@ -524,17 +546,16 @@ npm i --global generator-easy-ui5
npx yo easy-ui5 app
```
:::note Use the provided defaults:
When prompted, enter the following options:
- Application id: `sheetjs.openui5`
- Framework: `OpenUI5`
- Version: `1.131.1`
- Author: `SheetJS`
- Create new directory: `Y`
- Initialize git: `N`
:::
- `Enter your application id (namespace)?`: Type `sheetjs.openui5` and press <kbd>Enter</kbd>
- `Which framework do you want to use?`: Press <kbd>Enter</kbd> (`OpenUI5` should be the default)
- `Which framework version do you want to use?`: Type `1.132.1` and press <kbd>Enter</kbd>
- `Who is the author of the application?`: Press <kbd>Enter</kbd> (use the default author)
- `Would you like to create a new directory for the application?`: Type `Y` and press <kbd>Enter</kbd>
- `Would you like to initialize a local git repository for the application?`: Type `N` and press <kbd>Enter</kbd>
![Expected output](pathname:///ui5/easy-ui5.png)
2) Install the dependencies and start server:
@ -546,33 +567,55 @@ 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`:
In the file listing, click `index.html` to launch the app.
<CodeBlock language="html" value="html" title="webapp/index.html">
{`<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>`}
4) Add the SheetJS Standalone script to `webapp/index.html` after the `title` tag:
<CodeBlock language="html" value="html" title="webapp/index.html (add highlighted lines)">{`\
<title>UI5 Application: sheetjs.openui5</title>
<!-- highlight-next-line -->
<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](#view-implementation-html).
6) Replace `webapp/controller/Main.controller.js` with the complete [implementation above](#controller-implementation-html).
5) Replace `webapp/view/Main.view.xml` with the `Main.view.xml` snippet in the
["View Implementation" section](#view-implementation-html).
The page will refresh and show a table with an Export button. Click the button and the page will
attempt to download `SheetJSOpenUI5HTML.xlsx`.
6) Replace `webapp/controller/Main.controller.js` with the `Main.controller.js`
example in ["Controller Implementation"](#controller-implementation-html).
7) Build the site:
7) Switch back to the browser window.
The page will refresh and show a table with an Export button.
Click the button and the page will attempt to download `SheetJSOpenUI5HTML.xlsx`.
This file can be inspected with a spreadsheet editor.
8) Build the site:
```bash
npm run build
npm run build:opt
```
The generated site will be placed in the `dist` folder.
8) Start a local web server:
:::caution pass
SAP recommends `npm run build`. This does not generate a proper standalone site!
Sites built with `npm run build` must be served with `npm run start:dist`.
This demo uses the `build:opt` target to ensure that a proper static site is
generated. The `dist` folder in this demo can be posted
:::
9) Start a local web server:
```bash
npm run start:dist
npx http-server dist
```
Access the displayed URL (typically http://localhost:8080) with a web browser and test the page.
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
@ -583,7 +626,10 @@ will generate a workbook that can be opened in a spreadsheet editor.
[^1]: See ["ECMAScript Support"](https://sdk.openui5.org/topic/0cb44d7a147640a0890cefa5fd7c7f8e.html#loio0cb44d7a147640a0890cefa5fd7c7f8e/section_UI5Mod) for more details about OpenUI5 compatibility.
[^2]: See [`JSONModel`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.model.json.JSONModel.html) in the OpenUI5 documentation.
[^3]: See OpenUI5's [MVC Documentation](https://sdk.openui5.org/topic/91f233476f4d1014b6dd926db0e91070) for detailed explanation of the pattern implementation.
[^4]: See ["Merged Cells" in "SheetJS Data Model"](/docs/csf/features/merges) for more details.
[^5]: See [`core:HTML`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.core.HTML.html) in the OpenUI5 documentation.
[^6]: See ["SheetJS Data Model"](/docs/csf/)
[^3]: See ["SheetJS Data Model"](/docs/csf/)
[^4]: See [OpenUI5's MVC Documentation](https://sdk.openui5.org/topic/91f233476f4d1014b6dd926db0e91070) for detailed explanation of the pattern implementation.
[^5]: See ["List, List Item, and Table"](https://sdk.openui5.org/topic/295e44b2d0144318bcb7bdd56bfa5189) in the OpenUI5 documentation.
[^6]: See [`getProperty` of class `sap.ui.model.json.JSONModel`](https://sdk.openui5.org/api/sap.ui.model.json.JSONModel#methods/getProperty) in the OpenUI5 documentation.
[^7]: See ["Worksheet Object" in "SheetJS Data Model"](/docs/csf/sheet) for more details.
[^8]: See ["Merged Cells" in "SheetJS Data Model"](/docs/csf/features/merges) for more details.
[^9]: See [`core:HTML`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.core.HTML.html) in the OpenUI5 documentation.

@ -33,7 +33,7 @@ will be available in the future.
:::note Tested Deployments
This demo was last tested on 2024 June 13.
This demo was last tested on 2024-06-13.
:::

@ -35,7 +35,7 @@ will be available in the future.
:::note Tested Deployments
This demo was last tested on 2024 June 12.
This demo was last tested on 2024-06-12.
:::

@ -495,7 +495,7 @@ At this point `wb` is a SheetJS workbook object[^10].
:::note Tested Deployments
This demo was last tested on 2024 June 08 using `googleapis` version `140.0.0`.
This demo was last tested on 2024-06-08 using `googleapis` version `140.0.0`.
The demo uses Sheets v4 and Drive v3 APIs.
:::

@ -206,8 +206,8 @@ const wb = XLSX.readFile("SheetJSAirtableTest.xlsb");
:::note Tested Deployments
This demo was last tested on 2024 May 04. At the time, free accounts included
limited API access.
This demo was last tested on 2024-05-04. In the most recent test, free accounts
included limited API access.
:::

@ -266,7 +266,7 @@ function SheetJSEnregistrez() {
:::note Tested Deployments
This demo was last tested on 2024 May 27.
This demo was last tested on 2024-05-27.
:::

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB