WeRun Consulting

In this Groovy scripting tutorial, we’ll explore how to use gridBuilder functions in Oracle EPM Cloud

Back to Home

Groovy DataGrid Builders Cheatsheet for Oracle EPM Cloud

Published: November 10, 2024 | By WeRun Consulting

In Oracle EPM Cloud, Groovy scripting offers robust tools to interact with data grids—virtual representations of cube data. This cheatsheet dives into DataGridDefinitionBuilder, DataGridBuilder, and FlexibleDataGridDefinitionBuilder, providing detailed explanations and unique examples. Building on our getEval tutorial, these builders let you read, write, and filter data with precision.

DataGridDefinitionBuilder: Fetching Forecast Data

The DataGridDefinitionBuilder constructs a read-only grid definition for retrieving data from an Essbase cube. Per Oracle’s Groovy API, it’s a programmatic equivalent to a Smart View retrieve, requiring a Point of View (POV), rows, and columns. Key methods include:

The resulting DataGrid object provides iterators like dataCellIterator() to access cell data and metadata.

Fetch Regional Forecast Variances
Retrieve forecast vs. actual variances for specific regions to analyze prediction accuracy.
Cube cube = operation.application.getCube("Forecast")
DataGridDefinitionBuilder builder = cube.dataGridDefinitionBuilder()
builder.addPov(['Year', 'Scenario', 'Version'], [['FY24'], ['Forecast', 'Actual'], ['Final']])
builder.addColumn(['Measure'], [['Variance']])
builder.addRow(['Region'], [['North', 'South']])
DataGrid grid = cube.loadGrid(builder.build(), false)
grid.dataCellIterator().each { cell ->
    println "Region: ${cell.getMemberName('Region')}, Variance: ${cell.data}"
}
grid.close()
                
Logic: The POV locks Year to FY24, Scenario to Forecast and Actual, and Version to Final, creating a 2x1 grid (2 rows: North, South; 1 column: Variance). false in loadGrid skips member expansion for speed.
Tip: Use getMemberName(dim) to extract specific dimension members from a cell.
Use Case: Compare forecast accuracy across regions for reporting.

DataGridBuilder: Distributing Expenses

The DataGridBuilder creates a writable grid to push data into a cube, akin to a Smart View submit. It’s instantiated with a date format (e.g., "MM/DD/YYYY") for timestamped operations. Key methods include:

It’s designed for precision updates, with Status providing feedback on save success.

Distribute Quarterly Expenses
Allocate a quarterly expense budget across months using custom weights.
Cube cube = operation.application.getCube("Expenses")
DataGridBuilder builder = cube.dataGridBuilder("MM/DD/YYYY")
builder.addPov('FY24', 'Plan', 'USD', 'Working')
builder.addColumn('Apr', 'May', 'Jun')
def weights = [0.3, 0.3, 0.4] // 30%, 30%, 40%
def totalExpense = 15000
def expenseData = weights.collect { it * totalExpense }
builder.addRow(['Travel'], expenseData)
DataGridBuilder.Status status = new DataGridBuilder.Status()
builder.build(status).withCloseable { grid ->
    println "Cells saved: ${status.numAcceptedCells}"
    cube.saveGrid(grid)
}
                
Logic: POV fixes the intersection (FY24, Plan, USD, Working). Columns are Q2 months, and expenseData calculates 4500, 4500, 6000 based on weights. Status confirms 3 cells saved.
Tip: Use weights.collect to dynamically compute values; check status.numRejectedCells if saves fail.
Use Case: Allocate travel expenses across Q2 for budgeting.

FlexibleDataGridDefinitionBuilder: Targeted Revenue Analysis

The FlexibleDataGridDefinitionBuilder extends DataGridDefinitionBuilder with dynamic dimension handling and exclusion capabilities. It simplifies complex queries by inferring dimensions from members. Key methods include:

It’s ideal for grids with variable or filtered data needs.

Analyze Active Customer Revenue
Fetch revenue data for active customers, excluding dormant GENERATION ones.
Cube cube = operation.application.getCube("Revenue")
def builder = cube.flexibleDataGridDefinitionBuilder()
builder.setPov('FY24', 'Actual', 'USD', 'Final')
builder.setColumnDimensions('Customer')
builder.addColumn('ILvl0Descendants("AllCustomers")')
builder.setRowDimensions('Account')
builder.addRow('NetRevenue').setExclude('[Customer].[DormantCustomers]')
cube.loadGrid(builder.build(), false).withCloseable { grid ->
    grid.dataCellIterator().each { cell ->
        println "Customer: ${cell.getMemberName('Customer')}, Revenue: ${cell.data}"
    }
}
                
Logic: POV sets a static intersection. Columns use ILvl0Descendants to fetch all base-level customers, while setExclude skips "DormantCustomers". Row is fixed to NetRevenue.
Tip: Use Essbase functions like ILvl0Descendants for dynamic member sets; verify exclusions exist in the hierarchy.
Use Case: Report revenue for active customers only.

Key Differences

- DataGridDefinitionBuilder: Structured reads with explicit dimension-member pairs, best for static grids.
- DataGridBuilder: Write operations with direct member inputs, suited for data submission.
- FlexibleDataGridDefinitionBuilder: Dynamic reads with inferred dimensions and exclusions, ideal for complex queries.

Tips and Tricks

Resource Management
Always close grids to prevent memory leaks, per Oracle’s best practices.
cube.loadGrid(builder.build(), false).withCloseable { grid ->
    // Process grid here
}
                
Logic: withCloseable auto-closes the grid after use, avoiding resource exhaustion.
Debugging Saves
Use Status to diagnose write issues, as recommended by Oracle.
if (status.numRejectedCells > 0) {
    println "Rejected: ${status.numRejectedCells}, Reason: ${status.rejectedCells}"
}
                
Logic: numRejectedCells counts failed saves; rejectedCells (if logged) details why (e.g., locked intersections).

Disclaimer

This blog reflects my personal insights, written independently of my employer or Oracle. EPM Cloud features evolve, so verify with Oracle’s official documentation for the latest details.

Comments