diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/docs.sheetjs.com.iml b/.idea/docs.sheetjs.com.iml
new file mode 100644
index 0000000..24643cc
--- /dev/null
+++ b/.idea/docs.sheetjs.com.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/git_toolbox_blame.xml b/.idea/git_toolbox_blame.xml
new file mode 100644
index 0000000..7dc1249
--- /dev/null
+++ b/.idea/git_toolbox_blame.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..7156fee
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docz/docs/03-demos/02-frontend/10-openui5.md b/docz/docs/03-demos/02-frontend/10-openui5.md
new file mode 100644
index 0000000..322687c
--- /dev/null
+++ b/docz/docs/03-demos/02-frontend/10-openui5.md
@@ -0,0 +1,548 @@
+---
+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:
+
+
+ {``}
+
+
+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:
+
+
+
+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:
+
+
+
+
+```js
+sap.ui.define(["sap/ui/model/json/JSONModel"], function (JSONModel) {
+ const oModel = new JSONModel({ presidents: [] });
+});
+```
+
+
+
+
+#### 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
+```
+
+
+
+
+```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
+}
+```
+
+
+
+
+
+#### 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"
+
+
+
+
+
+
+```
+
+
+#### 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"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```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");
+ },
+ });
+ }
+);
+```
+
+
+ How to run the example (click to hide)
+
+:::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`:
+
+
+ {``}
+
+
+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.
+
+
+
+### 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"
+
+
+
+
+
+
+
+
+```
+
+```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: `
`,
+ footer: `
`
+ };
+ 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");
+ },
+ });
+ }
+);
+```
+
+
+ How to run the example (click to hide)
+
+:::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`:
+
+
+ {``}
+
+
+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.
+
+
+
+### 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)
+}));
+```
+
+![Column labels for headers](pathname:///react/cols.png)
+
+
+
+[^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.
\ No newline at end of file