When a context requiring a Groovy script will typically use a short (often, one-line) script, we emphasize that fact by calling it an expression, however technically the terms script and expression are interchangeable. Anywhere you can provide a one-line expression is also a valid context for providing a multi-line script if the need arises. Whether you provide a short expression or a multi-line script, the syntax and features at your disposal are the same.
You need only pay attention that your code returns a value of the appropriate type for the context in which you use it. Any Groovy script that returns a String will be considered as returning an Essbase calc script which will be executed against Essbase. Avoid using Strings as the final value of the last statement unless it is a calc script that you wish to execute after the Groovy script launches successfully.
/*RTPS: {Driver} {DriverValue}*/
"""FIX("No Scenario", "No Version", "No Entity", "No Year", "BegBalance", "Local") $rtps.Driver = $rtps.DriverValue; ENDFIX;"""
/*RTPS: {Employee} {NewParent}*/
rtps.Employee.member.dimension.saveMember(["Member" : rtps.Employee.member.name, "Parent" : rtps.NewParent.member.name] as Map<String, Object>)
/*RTPS: {Employee} {NewName}*/
rtps.Employee.member.dimension.saveMember(["Member" : rtps.Employee.member.name, "New Name" : rtps.NewName.enteredValue] as Map<String, Object>)
/*RTPS: {Employee} {NewName} {NewParent}*/
rtps.Employee.member.dimension.saveMember(["Member" : rtps.Employee.member.name, "New Name" : rtps.NewName.enteredValue, "Parent" : rtps.NewParent.member.name] as Map<String, Object>)
/*RTPS: {EmployeeName} {EmployeePhone} {EmployeeEmail} {Scenario} {Year} {Period} {Entity} {Version}*/
def mbUs = messageBundle(["validation.invalidemail":"Email address is invalid: {0}", "validation.invalidphone":"Phone number is invalid: {0}",
"validation.memberexists":"The member you have specified already exists and cannot be created: {0}.", "validation.invalidnamelength":"Employee name must be 5 to 40 characters: {0}"])
def mbl = messageBundleLoader(["en" : mbUs]);
// Validate the Rtp values
Dimension employeeDim = operation.application.getDimension("Employee")
Member parentEmployee = employeeDim.getMember("Total Employees")
if(parentEmployee.hasChild(rtps.EmployeeName))
throwVetoException(mbl, "validation.memberexists", rtps.EmployeeName)
validateRtp(rtps.EmployeeName, {(5..40).contains(it.enteredValue.size()) }, mbl, "validation.invalidnamelength", rtps.EmployeeName);
validateRtp(rtps.EmployeeEmail, /^.+@.+/, mbl, "validation.invalidemail", rtps.EmployeeEmail.enteredValue);
validateRtp(rtps.EmployeePhone, /^(?:\+?1[- ]?)?\(?([0-9]{3})\)?[- ]?([0-9]{3})[- ]?([0-9]{4})$/, mbl, "validation.invalidphone", rtps.EmployeePhone);
Map newEmployee = parentEmployee.newChildAsMap(rtps.EmployeeName)
// Save the new employee as a dynamic child member always
Member employee = employeeDim.saveMember(newEmployee, DynamicChildStrategy.ALWAYS_DYNAMIC)
// Generate the calc script to save employee email and phone property values
"""SET CREATENONMISSINGBLK ON;
FIX(${fixValues(rtps.Scenario, rtps.Year, rtps.Period, rtps.Entity, rtps.Version, employee)}, "Local", "HSP_InputValue")
"Employee Phone" = $rtps.EmployeePhone;
"Employee Email" = $rtps.EmployeeEmail;
ENDFIX;"""
class GradeData {
Integer Grade
DataGrid.DataCell minSalary
DataGrid.DataCell maxSalary
DataGrid.DataCell minBonus
DataGrid.DataCell maxBonus
public String toString() {
return "minSalary: ${minSalary?.formattedValue}, maxSalary: ${maxSalary?.formattedValue}, minBonus: ${minBonus?.formattedValue}, maxBonus: ${maxBonus?.formattedValue}"
}
}
// Create a resource bundle loader containing localized messages needed by this rule.
def mbUs = messageBundle( ["validation.missingmember.grade":"No Grades found on the Grid."] )
def mbl = messageBundleLoader(["en" : mbUs]);
Cube driverCube = operation.application.getCube("Plan1")
DataGridDefinitionBuilder builder = driverCube.dataGridDefinitionBuilder()
builder.setPov(['Years', 'Scenario', 'Currency', 'Period', 'Version', 'Entity'], [['FY16'], ['Current'], ['Local'], ['BegBalance'], ['BU Version_1'], ['No Entity']])
builder.addColumn(['Account'], [ ['Min Salary', 'Max Salary', 'Min Bonus', 'Max Bonus'] ])
builder.addRow(['Grades'], [ ['ILvl0Descendants("Grades")'] ])
DataGridDefinition gridDefinition = builder.build()
// Load the data grid from the driver cube
DataGrid dataGrid = driverCube.loadGrid(gridDefinition, false)
// Create a map of grade data (Min/Max Salary and Bonus) by grade name from the data grid.
def gradeDataMap = new HashMap()
StringBuilder scriptBldr = StringBuilder.newInstance()
if(dataGrid) {
println("dataGrid is not null")
GridIterator itr = dataGrid.dataCellIterator('Min Salary')
itr.each {
def gradeData = new GradeData()
gradeData.minSalary = it
gradeData.maxSalary = it.crossDimCell('Max Salary')
gradeData.minBonus = it.crossDimCell('Min Bonus')
gradeData.maxBonus = it.crossDimCell('Max Bonus')
gradeDataMap[(it.getMemberName('Grades'))] = gradeData
println(it.getMemberName('Grades') + ": " + gradeData)
}
}
DataGrid grid = operation.grid
// Construct an iterator that iterates over all data cells containing the Grade member.
GridIterator itr = grid.dataCellIterator('Grade')
// Throw a veto exception if the grid has at least one cell but does not contain any cells containing the Grade member.
if(!grid.empty && !itr.hasNext()) {
// Found 0 cells with Grade
throwVetoException(mbl, "validation.missingmember.grade");
}
// Validate the values in the grid being saved against the values in gradeDataMap.
itr.each {
GradeData gradeData = gradeDataMap[it.DataAsSmartListMemberName]
if(gradeData == null) {
println("Unable to locate grade data for grade: ${it.DataAsSmartListMemberName}, with data value: ${it.formattedValue}" )
} else {
println(it.getMemberName('Employee') + ": " + gradeData.toString())
DataCell salary = it.crossDimCell('Salary')
if(salary == null)
println("Unable to locate Salary")
else if(salary.data < gradeData.minSalary.data || salary.data > gradeData.maxSalary.data) {
salary.addValidationError(0xFF0000, "Salary is outside of the allowed range.")
}
DataCell bonus = it.crossDimCell('Bonus')
if(bonus == null) {
println("Unable to locate Bonus")
} else if(bonus.data < gradeData.minBonus.data || bonus.data > gradeData.maxBonus.data) {
bonus.addValidationError(0xFF0000, "Bonus is outside of the allowed range.")
}
}
}