diff --git a/docz/docs/03-demos/30-cloud/03-oraclecloud.md b/docz/docs/03-demos/30-cloud/03-oraclecloud.md new file mode 100644 index 0000000..b1d315d --- /dev/null +++ b/docz/docs/03-demos/30-cloud/03-oraclecloud.md @@ -0,0 +1,541 @@ +--- +title: Oracle Cloud Services +pagination_prev: demos/local/index +pagination_next: demos/extensions/index +--- + +import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; + +[Oracle Cloud Services](https://www.oracle.com/cloud/) (OCI) is a cloud services +platform which includes traditional virtual machine support, "Serverless +Functions" and cloud storage. + +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. + +This demo demonstrates how to integrate SheetJS with Oracle `Visual Builder Studio (VBS)`[^2] +to build a web application that handles Excel files. You'll learn to create an application +that can import spreadsheet data, store it in `Business Objects`[^1], display it in a table, and +export it back to Excel format. + +:::caution pass + +Oracle Cloud Services iterates quickly and there is no guarantee that the referenced services +will be available in the future. + +::: + +:::note Tested Deployments + +This demo was last tested on 2025-02-04. + +::: + + +## Visual Applications +Oracle Cloud Services offers Visual Builder Studio a browser-based development environment for +creating web applications with drag-and-drop components. + + +## Installation +SheetJS libraries conform to the Oracle Cloud Visual Builder Studio (VBS) ECMAScript[^5] requirements. +SheetJS libraries can be loaded in Oracle VBS site at different points in the app lifecycle. + +#### Configure in app-flow.json + +The `app-flow.json` method is recommended as it aligns better with Visual Builder Studio's +module management system. + +1. Click 📄 `Source` from the left sidebar +2. Open `webApps/sheetjs_demo_app/app-flow.json` +3. Add the following configuration after line 5: + +{`\ +"requirejs": { + "paths": { + "xlsx": "https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js" + } + } +`} + + +#### HTML {#installation-html} + +Oracle Cloud VBS is typically loaded in `SCRIPT` tag in `webApps/sheetjs_demo_app/index.html`. Similarly, +[SheetJS Standalone scripts](/docs/getting-started/installation/standalone) +can be loaded with a `SCRIPT` tag in the same HTML page: + +{`\ + +`} + + +This will expose the `XLSX` global object, which includes the functions listed +in the ["API Reference"](/docs/api/) section of the documentation. + + +## Internal State + +The various SheetJS APIs work with various data shapes. The preferred state +depends on the application. + + +### Business Objects + +`Business Objects`[^1] in Oracle VBS provides a server-side model implementation for persistent data storage. +Think of them as a combination of a data model and database table that handles both data storage and +UI binding. + +#### Business Object Definition + +The example [presidents sheet](https://docs.sheetjs.com/pres.xlsx) has one header row with "Name" and "Index" +columns. In Oracle VBS, we model this as a Business Object with corresponding fields: + + + +
SpreadsheetBusiness Object Definition
+ +![`pres.xlsx` data](pathname:///pres.png) + + + +```json +{ + "items" : [ { + "name": "Pres", + "fields": { + "name": { + "type": "string", + "label": "Name" + }, + "index1": { + "type": "number", + "label": "Index" + } + } + }] +} +``` + +
+ +Here is how the data is represented when queried from the Business Object via REST call: + +```json +{ + "items": [ + { "name": "Bill Clinton", "index1": 42 }, + { "name": "GeorgeW Bush", "index1": 43 }, + { "name": "Barack Obama", "index1": 44 }, + { "name": "Donald Trump", "index1": 45 }, + { "name": "Joseph Biden", "index1": 46 } + ] +} +``` + +#### Updating Business Object + +Starting from a spreadsheet file, the SheetJS [`read`](/docs/api/parse-options) method parses the data into a workbook object. After +selecting a worksheet, [`sheet_to_json`](/docs/api/utilities/array#array-output) generates row objects that can be created as Business Object +records using the auto-generated REST API. + +Here is a sample flow diagram and method for downloading a workbook, generating rows from the first worksheet, and updating a `Business Object`[^1]: + +```mermaid +flowchart LR + xlsx[(Remote\nFile)] + bo1[(Data\nArrayBuffer)] + wb(SheetJS\nWorkbook) + ws(SheetJS\nWorksheet) + json(JSON\nData) + bo2[(Business\nObject)] + + xlsx --> |fetch\n\n| bo1 + bo1 --> |XLSX.read\n\n| wb + wb --> |wb.Sheets\nselect| ws + ws --> |sheet_to_json\n\n| json + json --> |REST API\ncreate| bo2 + linkStyle 1,2,3 color:blue,stroke:blue; +``` + +{` + define(['vb/action/actionChain', 'vb/action/actions', 'xlsx'], (ActionChain, Actions, XLSX) => { + class ButtonActionChain extends ActionChain { + async run(context) { + // fetch XLSX file + const data = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer(); + const wb = XLSX.read(data); + // get the first worksheet + const ws = wb.Sheets[wb.SheetNames[0]]; + // convert to json + const jsonData = XLSX.utils.sheet_to_json(ws); + + // process each row and create business object records + for (const row of jsonData) { + const presData = { + name: row.Name, + index1: Number(row.Index) + }; + + // update business object with new record + await Actions.callRest(context, { + endpoint: 'businessObjects/create_Pres', + body: presData + }); + } + } + } + return ButtonActionChain; + }); +`} + + +#### Rendering Data +In Oracle VBS, the table component `oj-table` supports direct binding to Business Objects for data display. +The view structure defines both the data source binding and column layout: + +The following example uses the `Table`[^4] component to display data. + +{`\ +
+ // highlight-start + + + + // highlight-end +
+`} +
+ + +#### Exporting Data +The export functionality converts Business Object data into an Excel spreadsheet. The process involves retrieving data through +REST API call, transforming it into a format suitable for SheetJS, and generating an XLSX file. Here's the complete flow: + +```mermaid +flowchart LR + bo[(Business\nObject)] + rest(REST API\nCall) + json(JSON\nArray) + ws(SheetJS\nWorksheet) + wb(SheetJS\nWorkbook) + xlsx[(XLSX\nFile)] + + bo --> |getall_Pres\nendpoint| rest + rest --> |transform\nresponse| json + json --> |json_to_sheet\n\n| ws + ws --> |book_new\n\n| wb + wb --> |writeFileXLSX\n\n| xlsx + + linkStyle 2,3,4 color:blue,stroke:blue; +``` + +{` + define(['vb/action/actionChain', 'vb/action/actions', 'xlsx'], (ActionChain, Actions, XLSX) => { + class ButtonActionChain1 extends ActionChain { + async run(context) { + // get pres data + const presDataResponse = await Actions.callRest(context, { + endpoint: 'businessObjects/getall_Pres', + parameters: { + fields: 'name,index1' + } + }); + + // transform to simple array + const simplifiedData = presDataResponse.body.items.map(item => ({ + Name: item.name, + Index: item.index1 + })); + + // generate workbook + const ws = XLSX.utils.json_to_sheet(simplifiedData); + const wb = XLSX.utils.book_new(ws, "Presidents"); + + // export to XLSX which triggers a download + XLSX.writeFileXLSX(wb, "SheetJSOracleVisualBuilderAoO.xlsx"); + } + } + return ButtonActionChain1; + }); +`} + + +:::note pass + +Visual Builder Studio provides a visual development environment and handles the build and +deployment process automatically. + +::: + + +## Importing Data {#importing-data-snippet} +The import functionality enables data transfer from an Excel spreadsheet into your Oracle VBS +application. The process begins by fetching the XLSX file, parsing it using SheetJS, and then +creating corresponding Business Object records. + +```javascript title="" +define([ + 'vb/action/actionChain', + 'vb/action/actions', + 'vb/action/actionUtils', + 'xlsx' +], ( + ActionChain, + Actions, + ActionUtils, + XLSX +) => { + 'use strict'; + + class ButtonActionChain extends ActionChain { + + /** + * @param {Object} context + */ + async run(context) { + const { $page, $flow, $application, $constants, $variables } = context; + + // fetch XLSX file + const url = "https://docs.sheetjs.com/pres.xlsx"; + const data = await (await fetch(url)).arrayBuffer(); + const wb = XLSX.read(data); + + // get the first worksheet + const ws = wb.Sheets[wb.SheetNames[0]]; + + // convert to json + const jsonData = XLSX.utils.sheet_to_json(ws); + + // process each row and create business object records + for (const row of jsonData) { + const presData = { + name: row.Name, + index1: Number(row.Index) + }; + + // create a business object record + await Actions.callRest(context, { + endpoint: 'businessObjects/create_Pres', + body: presData + }); + } + } + } + return ButtonActionChain; +}); +``` + +## Exporting Data {#exporting-data-snippet} +The export functionality allows you to convert Business Object data into Excel spreadsheets. +This process involves retrieving data from the Business Object using REST API calls, transforming +it into a format suitable for SheetJS, and generating an XLSX file. + +```javascript +define([ + 'vb/action/actionChain', + 'vb/action/actions', + 'vb/action/actionUtils', + 'xlsx' +], ( + ActionChain, + Actions, + ActionUtils, + XLSX +) => { + 'use strict'; + + class ButtonActionChain1 extends ActionChain { + + /** + * @param {Object} context + */ + async run(context) { + const { $page, $flow, $application, $constants, $variables } = context; + + // get pres data + const presDataResponse = await Actions.callRest(context, { + endpoint: 'businessObjects/getall_Pres', + parameters: { + fields: 'name,index1' + } + }); + + // transform to simple array + const simplifiedData = presDataResponse.body.items.map(item => ({ + Name: item.name, + Index: item.index1 + })); + + // generate workbook + const ws = XLSX.utils.json_to_sheet(simplifiedData); + const wb = XLSX.utils.book_new(ws, "Presidents"); + + /* export to XLSX */ + XLSX.writeFileXLSX(wb, "SheetJSOracleVisualBuilderAoO.xlsx"); + + } + } + return ButtonActionChain1; +}); +``` + +## Oracle Visual Builder Studio Web Applications Demo + +:::note pass + +At the time of writing, Oracle Cloud offers a 30-day free trial that includes +Visual Builder Studio access. + +::: + +0. If you do not have an account create a new Oracle Cloud free tier account[^3]. + +### Visual Builder Setup + +1. Sign in to the [Oracle Cloud Management Console](https://cloud.oracle.com/) with your created account. + +2. Type "Visual Builder Studio" in the top search box and click Visual Builder Studio (under services). + +![Oracle Cloud search for "Visual Builder Studio"](pathname:///oraclecloud/search_box_visual_builder.png) + +3. Before creating Visual Builder Studio Instances we need to create an instance. Click `Visual Builder` from the left sidebar and click Create an instance. + +![Create Visual Builder Instance](pathname:///oraclecloud/create_vb_instance.png) + +- Give it a name: `sheetjs-demo-vb-instance` +- Select network access: `Default (No access rules.)` +- Nodes: `1` + +4. Now click `Visual Builder Studio` from the left sidebar and click `Create Visual Builder Studio` and give it instance name: `sheetjs-vbs-instance` and click next and set + select compartment to `yourusername (root)`. Lastly, click `Create Visual Builder Studio` (this will take 5-15 minutes to fully setup). + +- Click link name `sheetjs-vbs-instance` + +5. Click `Service Console` create a new project and fill it with the following inputs. + +- Project Details: `sheetjs-demo-project` +- Project Template: `Empty Project` +- Project Properties: `Markdown` +- Click Finish + +6. Select `Project Home` from the left sidebar and create an environment. +- Environment Name: `sheetjs-demo-env` +- Click Create +- Click `Add Instance` + +![Connect instance to environment](pathname:///oraclecloud/env_connect_to_instance.png) + +7. In Environments select the Service Instances tab and search for `Instance URL` if not shown click details to expand Visual Builder `sheetjs-demo-vb-instance` and open `Instance URL` + This will open Visual Builder Studio. + +8. Click `New Application` and set + +- Application Display Name: `sheetjs-vbs-demo` +- Application Template: `Empty Application` +- Click Finish + +9. Create a new Business Object by clicking **Business Object** card in the Welcome tab or from the sidebar as shown + ![Create a new Business Object](pathname:///oraclecloud/create_business_object.png) + +- Name: `Pres` +- Display: `President` + +10. Click `Pres` Business Object and select Fields tab. Then, create a new field by clicking the `+Fields` button and select first drop-down `Field`. + +- Label1: `Name` +- Type1: Click `A` (`String`) + +- Label2: `Index` +- Type2: Click `#` (`Number`) + +![Add two new fields](pathname:///oraclecloud/creating_new_fields_name_index.png) + +11. Click 🖥️ Web Applications from the left sidebar and create a new Web Application by clicking `+Web Application` + You should have the following fields. + +- Application Name: `sheetjs_demo_app` +- Navigation Style: `None` +- Click Create + +12. [Adding SheetJS Module](#installation) to the App Click 📄 `Source` from the left sidebar and paste the following on `webApps/sheetjs_demo_app/app-flow.json` + +{`\ +"requirejs": { + "paths": { + "xlsx": "https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js" + } + } +`} + + +![Adding Sheetjs to the web application](pathname:///oraclecloud/adding_sheetjs_to_app.png) + + +13. Let's create the UI for our application we will be creating a table and two buttons one for import XLSX and one for export XLSX. + +- From the left sidebar click the 🖥️ `Web Applications` and select `main-start` +- Select Page Designer and drag and drop two `Button` components and one `Table` Component to the canvas + +![Darg and drop ui components to canvas](pathname:///oraclecloud/drag_drop_components_to_canvas.png) + +14. Creating our button event handler +- Now select the left button in the canvas and on the right side on `General` tab set ID to `import-xslx` and label to `Import XLSX`. +- Now select the `Events` tab and click `+ Event Listener` drop down button and select `On 'ojAction'` +- Now it should auto-select `Action Chains` if not click from top tab option. +- Switch from `Design` to `Code` from top right + +![Switch from Design to Code in Action Chains for the button](pathname:///oraclecloud/action_chain_select_code.png) + +15. Replace `Action Chains > ButtonActionChain > Code` with the importing data snippet in the + ["Importing Data"](#importing-data-snippet) example code. + +16. Now repeat step 14 for the second button +- Now select the first button in the canvas and on the right side on `General` tab set ID to `export-xslx` and label to `Export XLSX`. +- Now select the `Events` tab and click `+ Event Listener` drop down button and select `On 'ojAction'` +- Now it should auto-select `Action Chains` if not click from top tab option. +- Switch from `Design` to `Code` from top right + +17. Replace `Action Chains > ButtonActionChain1 > Code` with the exporting data snippet in the + ["Exporting Data"](#exporting-data-snippet) example code. + +18. Connect the Business Object `Pres` to the table. +- Now select `Page Designer` and in the canvas select the table component from the right sidebar select `Quick Start` and then `Add Data` +- This opens up a modal on `Choose the source of your data` select `Pres` Business Object and click next. + +![Connecting Business Object Pres to the table](pathname:///oraclecloud/connecting_business_object.png) + +- On Bind Data step 2 from the left sidebar named `Endpoint Structure` check box `name` and `index1` then click next and lastly click finish. + +![Bind columns to field name and index1](pathname:///oraclecloud/bind_columns_to_fields_name_index1.png) + +19. Testing the Application + - a) Launch the Preview: + - Look for the Play (▶️) icon in the top-right corner of the Visual Builder Studio + - Click it to open your application in a new browser tab + - b) Test the Import Function: + - In the preview tab, click the "Import XLSX" button + - Navigate back to Visual Builder Studio + - Select the `Pres` business object + - Click the "Data" tab + - Verify that new records have been created with the president names and index + - Return to your application preview tab + - Refresh the page + - You should now see the table populated with the imported president data + - c) Test the Export Function: + - Click the "Export XLSX" button + - This will trigger an automatic download of a file named "SheetJSOracleVisualBuilderAoO.xlsx" + - Open the downloaded file using a spreadsheet editor. + - Verify that the exported data matches what was displayed in your application's table + +[^1]: See Oracle VBS working with [Business Objects](https://docs.oracle.com/en/cloud/paas/visual-builder/visualbuilder-building-applications/working-business-objects1.html) for more detail. +[^2]: [Oracle Visual Builder Studio](https://docs.oracle.com/en/cloud/paas/visual-builder/) +[^3]: Registering for a free account [on the Oracle Cloud Free Tier](https://www.oracle.com/cloud/free/) requires a valid phone number and a valid credit card. +[^4]: See [Oracle VBS Table Component](https://docs.oracle.com/en/middleware/developer-tools/jet/13/reference-api/oj.ojTable.html) for more details. +[^5]: See ["JavaScript Support in Oracle VBS"](https://docs.oracle.com/en/cloud/paas/visual-builder/visualbuilder-building-applications/work-javascript-editor1.html?utm_source=chatgpt.com) for more details on custom JavaScript functionality and module handling. diff --git a/docz/static/oraclecloud/action_chain_select_code.png b/docz/static/oraclecloud/action_chain_select_code.png new file mode 100644 index 0000000..ba42b96 Binary files /dev/null and b/docz/static/oraclecloud/action_chain_select_code.png differ diff --git a/docz/static/oraclecloud/adding_sheetjs_to_app.png b/docz/static/oraclecloud/adding_sheetjs_to_app.png new file mode 100644 index 0000000..667b149 Binary files /dev/null and b/docz/static/oraclecloud/adding_sheetjs_to_app.png differ diff --git a/docz/static/oraclecloud/bind_columns_to_fields_name_index1.png b/docz/static/oraclecloud/bind_columns_to_fields_name_index1.png new file mode 100644 index 0000000..f94affe Binary files /dev/null and b/docz/static/oraclecloud/bind_columns_to_fields_name_index1.png differ diff --git a/docz/static/oraclecloud/connecting_business_object.png b/docz/static/oraclecloud/connecting_business_object.png new file mode 100644 index 0000000..49ae39e Binary files /dev/null and b/docz/static/oraclecloud/connecting_business_object.png differ diff --git a/docz/static/oraclecloud/create_business_object.png b/docz/static/oraclecloud/create_business_object.png new file mode 100644 index 0000000..e0d54c6 Binary files /dev/null and b/docz/static/oraclecloud/create_business_object.png differ diff --git a/docz/static/oraclecloud/create_vb_instance.png b/docz/static/oraclecloud/create_vb_instance.png new file mode 100644 index 0000000..8abb4bd Binary files /dev/null and b/docz/static/oraclecloud/create_vb_instance.png differ diff --git a/docz/static/oraclecloud/creating_new_fields_name_index.png b/docz/static/oraclecloud/creating_new_fields_name_index.png new file mode 100644 index 0000000..cac2a7d Binary files /dev/null and b/docz/static/oraclecloud/creating_new_fields_name_index.png differ diff --git a/docz/static/oraclecloud/drag_drop_components_to_canvas.png b/docz/static/oraclecloud/drag_drop_components_to_canvas.png new file mode 100644 index 0000000..a189194 Binary files /dev/null and b/docz/static/oraclecloud/drag_drop_components_to_canvas.png differ diff --git a/docz/static/oraclecloud/env_connect_to_instance.png b/docz/static/oraclecloud/env_connect_to_instance.png new file mode 100644 index 0000000..0f5c5ff Binary files /dev/null and b/docz/static/oraclecloud/env_connect_to_instance.png differ diff --git a/docz/static/oraclecloud/launch_instance.png b/docz/static/oraclecloud/launch_instance.png new file mode 100644 index 0000000..9b3b438 Binary files /dev/null and b/docz/static/oraclecloud/launch_instance.png differ diff --git a/docz/static/oraclecloud/search_box_visual_builder.png b/docz/static/oraclecloud/search_box_visual_builder.png new file mode 100644 index 0000000..8556800 Binary files /dev/null and b/docz/static/oraclecloud/search_box_visual_builder.png differ