简介
本教程介绍了如何实施 Groovy 脚本,该脚本根据存储在驱动程序多维数据集中的允许范围验证数据输入。
背景信息
在此示例中,您将创建一个脚本,当用户从数据输入表单保存对员工薪金和奖金的更新时运行该脚本。该脚本将员工薪资级别数据(最低/最高允许薪资和最低/最高允许奖金)从动因多维数据集加载到内存中的临时网格中,然后根据允许的范围验证输入的薪资和奖金值。
先决条件
Cloud EPM 实操教程可能需要您将快照导入 Cloud EPM Enterprise Service 实例。在导入教程快照之前,必须请求另一个 Cloud EPM Enterprise Service 实例或删除当前应用程序和业务流程。教程快照不会通过现有应用程序或业务流程导入,也不会自动替换或恢复您当前使用的应用程序或业务流程。
在开始本教程之前,您必须:
- 具有服务管理员对 Cloud EPM Enterprise Service 实例的访问权限。
- 将此快照上载并导入到 Planning 实例中。如果您以前上载了其他 Groovy 教程的快照,则可以继续使用相同的快照。
注意:
如果导入快照时遇到迁移错误,请重新运行迁移(不包括 HSS-Shared Services 组件),以及核心组件中的“安全性”和“用户首选项”对象。有关上载和导入快照的更多信息,请参阅 Administering Migration for Oracle Enterprise Performance Management Cloud 文档。提示:
本教程所需的脚本作为每个部分中的文本文件链接。创建脚本
- 打开 Calculation Manager,并在 Plan1 多维数据集中创建名为 Groovy Validate Employee Data 的规则。
- 在规则编辑器中,将设计器选项更改为编辑脚本,并将脚本类型设置为 Groovy 脚本。
- 复制此脚本并将其粘贴到编辑器中。
- 在工具栏上,单击
(保存)以保存脚本,然后单击
(验证和部署)以验证和部署脚本。出现提示时,单击 OK 。关闭 Calculation Manager。


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 lookupCube = operation.application.getCube("Plan1")
DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder()
builder.addPov(['Years', 'Scenario', 'Currency', 'Period', 'Version', 'Entity'], [['FY16'], ['Current'], ['USD'], ['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 lookup cube
DataGrid dataGrid = lookupCube.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()
if(dataGrid) {
println("dataGrid is not null")
dataGrid.dataCellIterator('Min Salary').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.")
}
}
}
说明脚本逻辑
在本节中,我们将描述脚本逻辑,一次一个部分。
-
创建一个类。
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}"
}
}
创建一个类 GradeData,以存储驱动程序多维数据集中的员工薪资级别数据(允许的最低/最高薪金和允许的最低/最高奖金)。
toString()方法返回GradeData对象的字符串表示形式。该方法使用 Groovy 提供的空安全运算符 (?.)。如果问号前面的变量为空,则该变量不会继续并返回NULL。例如,如果minSalary为空,则{minSalary?.formattedValue}的求值结果为NULL值,而不是引发NullPointerException异常。 - 创建捆绑包加载程序。
- 从 DataGridDefinition 对象定义的区域的查找多维数据集加载数据网格。
- 从数据网格中按薪资级别名称创建薪资级别数据(最低/最高薪资和奖金)映射。
def gradeDataMap = new HashMap<String, GradeData>()
if(dataGrid) {
println("dataGrid is not null")
dataGrid.dataCellIterator('Min Salary').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)
}
}
按薪资级别名称创建名为 gradeDataMap的薪资级别数据(最低/最高薪金和奖金)的映射。
使用每个薪资级别的薪资级别数据填充 gradeDataMap映射。薪资级别是关键字,使用“最低/最高薪金”和“奖金”填充的 GradeData 对象是值。 - 构建迭代器,以迭代当前输入网格中包含成绩成员的所有数据单元格。
- 抛出否决权例外。
- 验证网格值。
// 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 lookupCube = operation.application.getCube("Plan1")
DataGridDefinitionBuilder builder = lookupCube.dataGridDefinitionBuilder()
builder.addPov(['Years', 'Scenario', 'Currency', 'Period', 'Version', 'Entity'], [['FY16'], ['Current'], ['USD'], ['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()
![]()
创建包含此规则所需的本地化消息的资源包加载程序。
获取驱动程序/查找多维数据集。
获取多维数据集的 DataGridDefinitionBuilder。通过添加 POV 成员、列成员和行,使用构建器构建从中加载数据的区域。
构建 DataGridDefinition 对象。
DataGrid dataGrid = lookupCube.loadGrid(gridDefinition, false)
DataGrid grid = operation.grid
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.")
}
}
}
根据 gradeDataMap 中的值验证要保存的输入网格中的值。输入网格中的薪资级别是智能列表类型的科目,该列表源自查找多维数据集中定义的薪资级别层次结构。调用 it.DataAsSmartListMemberName 将获取从中派生当前单元的智能列表值的成员的名称,该值随后可以用作映射中的键来获取薪资级别数据。
将调暗到“薪金”单元格中,并根据薪资级别数据中允许的薪金验证薪金。
交叉调暗到“奖金”单元格中,并根据薪资级别数据中允许的奖金验证奖金。如果薪金或奖金不在允许的限制范围内,请将单元格的背景颜色设置为红色,并通过调用 addValidationError() API 在单元上添加验证错误。错误消息将设置为单元格的工具提示,并且还会显示在网格验证消息中。此外,如果此规则在保存后运行,系统将否决保存操作。
测试脚本
- 在表单管理器中,编辑 ManageEmployees 表单,并将要运行的 Groovy 验证员工数据规则关联到加载后和保存前(您可能需要先从多维数据集列表中选择 Plan1)。
- 保存表单并关闭“Form Manager(表单管理器)”窗口。
- 打开员工仪表盘。为员工 1 添加奖金 1000 ,将员工 2 的薪金增加到 65000 。在表单工具栏上,单击
(Save)。
- 在“错误消息”对话框中,单击确定。
- 将鼠标悬停在红色单元格上,以将详细的错误消息视为工具提示。


- 关闭仪表板并打开“Jobs(作业)”控制台。
- 单击 Groovy Validate Employee Data 可显示职务详细信息。单击已完成状态可查看从查找多维数据集加载的薪资级别数据以及每个员工薪资级别的薪资级别数据。





相关链接
更多学习资源
通过 docs.oracle.com/learn 浏览其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 Oracle University 查看可用的培训资源。
有关产品文档,请访问 Oracle 帮助中心。