542 lines
19 KiB
Markdown
542 lines
19 KiB
Markdown
|
---
|
||
|
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:
|
||
|
|
||
|
<CodeBlock language="json" value="json">{`\
|
||
|
"requirejs": {
|
||
|
"paths": {
|
||
|
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"
|
||
|
}
|
||
|
}
|
||
|
`}
|
||
|
</CodeBlock>
|
||
|
|
||
|
#### 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:
|
||
|
|
||
|
<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 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:
|
||
|
|
||
|
<table>
|
||
|
<thead><tr><th>Spreadsheet</th><th>Business Object Definition</th></tr></thead>
|
||
|
<tbody><tr><td>
|
||
|
|
||
|
![`pres.xlsx` data](pathname:///pres.png)
|
||
|
|
||
|
</td><td>
|
||
|
|
||
|
```json
|
||
|
{
|
||
|
"items" : [ {
|
||
|
"name": "Pres",
|
||
|
"fields": {
|
||
|
"name": {
|
||
|
"type": "string",
|
||
|
"label": "Name"
|
||
|
},
|
||
|
"index1": {
|
||
|
"type": "number",
|
||
|
"label": "Index"
|
||
|
}
|
||
|
}
|
||
|
}]
|
||
|
}
|
||
|
```
|
||
|
|
||
|
</td></tr></tbody></table>
|
||
|
|
||
|
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;
|
||
|
```
|
||
|
|
||
|
<CodeBlock language="javascript" value="javascript" title="Download workbook, extract data from first worksheet, and update ">{`
|
||
|
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;
|
||
|
});
|
||
|
`}
|
||
|
</CodeBlock>
|
||
|
|
||
|
#### 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.
|
||
|
|
||
|
<CodeBlock language="html" value="html" title="Example View for displaying an array of objects [sheetjs_demo_app/main/main-start]">{`\
|
||
|
<div class="oj-flex">
|
||
|
// highlight-start
|
||
|
<!-- Data source for the table -->
|
||
|
<oj-table scroll-policy="loadMoreOnScroll" class="oj-flex-item oj-sm-12 oj-md-12"
|
||
|
data="[[$variables.presListSDP]]"
|
||
|
columns='[
|
||
|
{"headerText":"Name","field":"name"},
|
||
|
{"headerText":"Index","field":"index1"}
|
||
|
]'>
|
||
|
</oj-table>
|
||
|
// highlight-end
|
||
|
</div>
|
||
|
`}
|
||
|
</CodeBlock>
|
||
|
|
||
|
|
||
|
#### 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;
|
||
|
```
|
||
|
|
||
|
<CodeBlock language="javascript" value="javascript" title="Download workbook, extract data from the first worksheet, and update ">{`
|
||
|
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;
|
||
|
});
|
||
|
`}
|
||
|
</CodeBlock>
|
||
|
|
||
|
:::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`
|
||
|
|
||
|
<CodeBlock language="json" value="json" title="copy paste after line 5">{`\
|
||
|
"requirejs": {
|
||
|
"paths": {
|
||
|
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"
|
||
|
}
|
||
|
}
|
||
|
`}
|
||
|
</CodeBlock>
|
||
|
|
||
|
![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.
|