Groovy scripting in Oracle Cloud EPM Planning is not just a scripting tool—it's a superpower. With the ability to manipulate forms, validate data, execute calculations, and orchestrate workflows dynamically, Groovy turns your Planning environment into a living, breathing application.
Whether you’re validating input, enforcing business rules, or orchestrating complex data flows, Groovy scripting provides flexibility and control that traditional Planning business rules can only dream of.
Understanding the Multidimensional Mindset
Before jumping into the code, it's critical to understand the Essbase multidimensional model behind the curtain. In EPM:
-
A cube (also called a database) holds data structured by dimensions like
Account
,Entity
,Period
,Year
,Scenario
, andVersion
. -
Each dimension is a tree of members. Data is stored at leaf members (Level 0), and upper-level members aggregate this data.
-
Shared members, alias tables, sparse vs. dense configurations, and alternate hierarchies all play a role in optimizing performance and usability.
Knowing your data structure is as essential as knowing your script.
Groovy API Basics
Your entry points in every script are the EpmScript
methods and the operation
object. Here are the most essential patterns:
Accessing the Grid
Use this to validate or transform form data:
/* RTPS: */
if (!operation.hasGrid()) {
throwVetoException("No grid available to process!")
}
Grid grid = operation.grid
grid.dataCellIterator().each { DataCell cell ->
cell.bgColor = 0xFFFF00 // Highlight all cells yellow (because why not?)
}
Retrieving Data from the Cube
When you need data that's not on the form, use a FlexibleDataGridDefinitionBuilder
.
/* RTPS: */
Cube cube = operation.application.getCube("FinPln")
cube.flexibleDataGridDefinitionBuilder()
.with {
setPov(['Actual', 'Final', 'Entity1', 'FY25'])
addColumn(['Jan', 'Feb', 'Mar'])
addRow(['Salary'])
build()
}
.with { gridDef ->
cube.loadGrid(gridDef, false).withCloseable { grid ->
grid.dataCellIterator().each { DataCell cell ->
println("${cell.getMemberNames()} = ${cell.data}")
}
}
}
Writing Data
Use DataGridBuilder
to save values programmatically:
/* RTPS: */
Cube cube = operation.application.getCube("FinPln")
DataGridBuilder builder = cube.dataGridBuilder("05/31/2025")
builder.addPov("Plan", "Working", "Entity1", "FY25")
builder.addColumn("Jan", "Feb", "Mar")
builder.addRow(["Salary"], [10000, 12000, 13000])
DataGridBuilder.Status status = new DataGridBuilder.Status()
builder.build(status).withCloseable { grid ->
cube.saveGrid(grid)
println "Accepted: ${status.numAcceptedCells}, Rejected: ${status.numRejectedCells}"
}
Validations
Groovy is also a superhero for data validation. Here's how you veto a cell based on a rule:
/* RTPS: */
if (!operation.hasGrid()) {
throwVetoException("Expected form data not found.")
}
operation.grid.dataCellIterator().findAll { it.account == "Salary" }.each { DataCell cell ->
if (cell.data > 50000) {
cell.addValidationError(0xFFFF00, "Salary exceeds allowed maximum.")
}
}
- Always check
operation.hasGrid()
before callingoperation.grid
.
-
Use
withCloseable
blocks for all cube grid operations. -
Prefer
findAll()
to filter collections before iteration. -
Always explicitly declare types (
Cube
,Grid
, etc.). -
Never return anything from a script unless it’s a string of valid Essbase calc commands.
No comments:
Post a Comment