SAP 分析云经验分享:如何“点对点”地批量修改日历事件的上下文

Estimated read time 10 min read

一、介绍 

在数字化转型加速演进、企业对敏捷运营与智能决策需求持续攀升的当下,SAP 分析云凭借其强大的综合能力,正成为企业赋能业务管理与战略决策的核心平台。它集数据可视化、预测分析、规划及协作于一体,不仅帮助企业洞察趋势、优化流程,更为组织打造出一套覆盖全局的智能化运营体系。 

SAP 分析云中,日历功能被广泛用于企业计划事件安排、任务追踪及跨部门协作,但其上下文批量修改能力仍存在明显短板。 

例如,当企业根据标准化模板生成一个规模较大的流程后,如果后续需要针对某一关键维度(如时间、区域等)进行整体性调整,往往只能通过“编辑事件”中的“替换上下文”来实现,但这种方法意味着原有的全部上下文信息会被一并清空,导致企业需耗费人力重新配置所有维度,容易引发管理上的不一致与风险。 

针对这一问题,我开发了基于 SAC 日历 API 脚本的故事应用,专注于实现点对点”的上下文批量修改功能。用户只需输入一个流程的 ID,即可完整展现该流程及其所有子流程、子事件的层级结构,精准锁定需要修改的范围。接着,可根据实际业务需要灵活选择目标模型、待修改的上下文维度,并进一步指定新成员实现对指定维度的批量更新,同时保证其他维度信息原封不动地保留在流程上下文中。

这项能力尤其适用于以下场景: 
• 基于标准模板生成流程后,需对某一单一维度进行快速统一调整。
• 在组织架构或战略方向变更时,对流程的上下文进行局部修订,而无需重新初始化全部配置。

 

二、如何使用“批量修改日历事件上下文”应用 

使用该故事应用前可在该故事页面查看相关故事应用的使用说明。 

1、要执行此操作,您需要具备以下权限 

公共文件的“读”权限 

计划模型的“读”权限 

2、请按照以下步骤获取父日历流程的事件 ID: 

选中事件后,点击右上角的详细信息,在弹出菜单栏的右上角,点击更多,然后点击事件设置 

如果未勾选允许外部 API 访问选项,请勾选该选项。 

然后点击显示详情以查看并复制事件 ID

3将事件 ID 粘贴到文本框中,并点击“Confirm,之后会在下一栏中显示出进程及其子事件的结构。 

4、在下一栏中选择想要修改的范围,并点击“Confirm”。但请注意,并不是所有选中的事件都一定会被修改,这取决于这一事件是否使用到了你之后选择的模型,以及是否包括了你之后选择的维度。 

5、在下一栏中选择一个你想要修改的上下文所引用的模型,并点击“Confirm”。 

6、在下一栏中选择你想要修改的维度,并点击“Confirm”。 

7、在下一栏中,请分别修改维度中的成员,方法如下: 

单击某一维度。 

按如下示意操作。 

8、将所有维度都设置好后,点击“Confirm”。 

9修改完成后,右侧栏会显示日志。 

10、若想要修改其他子事件,请重新从步骤4开始。 

 

三、注意事项 

无法替换数据锁定任务、数据操作任务、多操作任务、输入任务。

 

四、代码实现 

在介绍之前,我们先明确三种概念 

维度(Dimension):模型中的一个特定方面或分类依据。 

成员(Member):在某个维度下的具体实例或分类项。 

筛选器(Filter):由一个维度及其对应的一些成员所构成的组合,用于对数据进行筛选和限定,以便聚焦于特定的分析范围或数据子集。 

接下来将对主要的实现逻辑进行介绍主要逻辑步骤如下: 

1、变量与页面初始化 

在实现该功能之前,需要在故事应用中配置“日历集成”,并完成变量的初始化。以下是部分关键变量的说明:

datasource // 所选中model的datasource对象
eventsIds // 流程及其子项的id
isEventsAllSelected// 是否选中了所有的事件(用于全选按钮)
modelId // 所选中model的id
selectedFilters // 所选择的筛选器;如选择维度A,那么所有事件中与A相关的筛选器都会被添加到这个数组
toBeModifiedEvents // 选中的事件
//以下两个变量用于模拟二维数组,目的是存储每个model id下都有什么dimension id
uniqueModelDimensionId_1 // 这个数组存储model id
uniqueModelDimensionId_2 //这个数组存储dimension id

 在页面初始化中,设置了系统消息提示类型。 

2校验并获取流程及其子项 

//获取event ID。Get the event ID.
var userInput_processID = InputField_1.getValue();
var processEvent = CalendarIntegration_1.getCalendarEventById(userInput_processID);
//如果获取不到对象,则报错。 If the object cannot be obtained, an error will be reported.
if (processEvent === undefined) {
Application.showMessage(ApplicationMessageType.Warning, “Please enter a correct ID.”);
Application.hideBusyIndicator();
return;
}

使用队列进行广度优先遍历。 

同时使用两个队列,idQueue用于存储event id,spaceQueue用于记录深度,以便后续能更好地显示层次结构 对每个事件获取其对象,并将其属性添加到复选框中。 若这个事件同时是流程,将它的子项加入到队列。 //BFS
var idQueue = ArrayUtils.create(Type.string);
var spaceQueue = ArrayUtils.create(Type.string);
idQueue.push(processEvent.getId());
//spaceQueue以字符的形式标明了目前遍历到第几层。 spaceQueue indicates the current level of traversal in the form of characters.
spaceQueue.push(“”);
while (idQueue.length > 0) {
var currentId = idQueue.shift();
var currentSpace = spaceQueue.shift();
var currentEvent = CalendarIntegration_1.getCalendarEventById(currentId);
if (currentEvent !== undefined) {
CheckboxGroup_1.addItem(currentId, currentSpace + currentEvent.getName());
eventsIds.push(currentId);
if (currentEvent.getType() === CalendarTaskType.Process) {
var currentProcess = cast(Type.CalendarProcess, currentEvent);
var childrenIds = currentProcess.getChildren();
for (var i = 0; i < childrenIds.length; i++) {
idQueue.push(childrenIds[i]);
spaceQueue.push(currentSpace + “-“);
}
}
}
}

3用户选择事件后,获取所有被选中的事件里面互不相同的filter 

获取到选择的事件 对每个选择的事件,遍历其filter,并维护到一个不重复的数组中。 如果数组为空,即找不到任何filter,则报错。 //获取到选择的事件 Obtain the selected events.
toBeModifiedEvents = ArrayUtils.create(Type.CalendarEvent);
var toBeModifiedEventsID = CheckboxGroup_1.getSelectedKeys();
var uniqueFilters = ArrayUtils.create(Type.CalendarContextFilter);

//获取到有几种不同的筛选器 Obtain the unique filters.
for (var i = 0; i < toBeModifiedEventsID.length; i++) {
var event = CalendarIntegration_1.getCalendarEventById(toBeModifiedEventsID[i]);
toBeModifiedEvents.push(event);
// 获取当前事件的筛选器数组 Obtain the array of filters of the current event.
var filters = event.getContextFilters();
if (filters === undefined) {
continue;
}
console.log(filters);
// 遍历每个筛选器 Traverse each filter.
for (var j = 0; j < filters.length; j++) {
var filter = filters[j];
if (!uniqueFilters.includes(filter)) {
uniqueFilters.push(filter);
}
}
}
//如果找不到任何筛选器,则报错。If no filter is found, an error will be reported.
if (uniqueFilters.length === 0) {
Application.showMessage(ApplicationMessageType.Warning, “No context was found.”);
Application.hideBusyIndicator();
return;
}

4、获取每个model Id下的dimension Id,以及model Idmodel name的对应关系 

通过之前维护的不重复filter数组中获取到每个model id下的dimension id。 获取到每个model对应的datasource来得到该model的名称;在这里,我使用了一个hidden table。 var uniqueModelId = ArrayUtils.create(Type.string);
for (var m = 0; m < uniqueFilters.length; m++) {
var modelId_ = uniqueFilters[m].members[0].modelId;
var dimensionId = uniqueFilters[m].members[0].dimensionId;
if (!(uniqueModelDimensionId_1.includes(modelId_) && uniqueModelDimensionId_2.includes(dimensionId))) {
uniqueModelDimensionId_1.push(modelId_);
uniqueModelDimensionId_2.push(dimensionId);
}
if (!uniqueModelId.includes(modelId_)) {
uniqueModelId.push(modelId_);
}
}

var temp1 = ArrayUtils.create(Type.string);
var temp2 = ArrayUtils.create(Type.string);

for (var n = 0; n < uniqueModelId.length; n++) {
var modelId__ = uniqueModelId[n];
Table_1.setModel(modelId__);
datasource = Table_1.getDataSource();
temp1.push(modelId__);
temp2.push(datasource.getInfo().modelName);
}

for (var o = 0; o < temp1.length; o++) {
RadioButtonGroup_1.addItem(temp1[o], temp2[o]);
}

5、用户选择某个model后,获取dimension iddescription的对应关系 

Calendar APIdimension iddatasourcedimension id进行匹配,获取到每个dimensiondescription modelId = RadioButtonGroup_1.getSelectedKey();
datasource = Table_1.getDataSource();
var dimensions = datasource.getDimensions();
var descriptions = ArrayUtils.create(Type.string);
for (var h = 0; h < uniqueModelDimensionId_1.length; h++) {
if (uniqueModelDimensionId_1[h] === modelId) {
for (var j = 0; j < dimensions.length; j++) {
if (dimensions[j].id === uniqueModelDimensionId_2[h]) {
descriptions.push(dimensions[j].description);
break;
}
}
console.log(“error, dimension id dismatch”);
} else {
descriptions.push(“1”); //占位
}
}

for (var i = 0; i < uniqueModelDimensionId_1.length; i++) {
if (uniqueModelDimensionId_1[i] === modelId) {
CheckboxGroup_2.addItem(uniqueModelDimensionId_2[i], uniqueModelDimensionId_2[i] + ” ” + descriptions[i]);
}
}

6用户选择dimension后,通过已选择的dimension id获取到具体需要修改哪些filter 

var selectedDimensions = CheckboxGroup_2.getSelectedKeys();
selectedFilters = ArrayUtils.create(Type.CalendarContextFilter);
for (var k = 0; k < toBeModifiedEvents.length; k++) {
var filters = toBeModifiedEvents[k].getContextFilters();
for (var m = 0; m < filters.length; m++) {
if (selectedDimensions.includes(filters[m].members[0].dimensionId) && filters[m].members[0].modelId === modelId && !selectedFilters.includes(filters[m])){
selectedFilters.push(filters[m]);
}
}
}

7、将具体需要修改filter添加到datasource中,以便能够在filter line中显示 

Version维度会默认作为datasourcefilter,为了避免这一情况,预先将Version加入到Table的列中。 var dimensions = datasource.getDimensions();
for (var s = 0; s < dimensions.length; s++) {
if (dimensions[s] == “Version”) {
Table_1.addDimensionToColumns(“Version”);
break;
}
}

for (var o = 0; o < selectedDimensions.length; o++) {
for (var u = 0; u < selectedFilters.length; u++) {
if (selectedFilters[u].members[0].dimensionId === selectedDimensions[o]) {
datasource.setDimensionFilter(selectedDimensions[o], selectedFilters[u].members);
}
}
}

8、删除旧的filter并添加新的filter 

首先,对之前存储的需要修改的filter数组进行去重处理 删除旧的filter 构造新的Context Filter 加入新的filter 添加日志 var dimensions = datasource.getDimensions();
var selectedFiltersNoRepeat = ArrayUtils.create(Type.CalendarContextFilter);
for (var v = 0; v < selectedFilters.length; v++) {
if (!selectedFiltersNoRepeat.includes(selectedFilters[v])) {
selectedFiltersNoRepeat.push(selectedFilters[v]);
}
}
//selectedFilters 去重 Remove duplicates from selected filters.
for (var q = 0; q < selectedFiltersNoRepeat.length; q++) {
//selectedFilter是目前需要修改的筛选器 selectedFilter is the filter that currently needs to be modified.
var selectedFilter = selectedFiltersNoRepeat[q];
//复制一份变量,避免出现意外情况 Make a copy of the variable to avoid unexpected situations
var modifiedFilter = selectedFilter;
var dimensionId = modifiedFilter.members[0].dimensionId;
var newMemberInfo = ArrayUtils.create(Type.MemberInfo);
//构造一个原有members的字符串,以供日志使用 Construct a string of the original members for logging purposes.
var oldMembers = “”;
for (var r = 0; r < modifiedFilter.members.length; r++) {
oldMembers = oldMembers + ” ” + modifiedFilter.members[r].description;
}
//从datasource中获取到用户已经在filter line中修改好的filter Obtain the filter that the user has already modified in the filter line from the datasource.
var unspecifiedFilterValues = datasource.getDimensionFilters(dimensionId);

//删除旧的筛选器。remove old filter
var recordModifiedEvents = ArrayUtils.create(Type.integer);
for (var j = 0; j < toBeModifiedEvents.length; j++) {
if (toBeModifiedEvents[j].removeContextFilter(selectedFilter)) {
recordModifiedEvents.push(j);

}
}

//构建新的member info Construct the new member info.
for (var m = 0; m < unspecifiedFilterValues.length; m++) {
if (unspecifiedFilterValues[m].type == “Single”) {
var filterValue = cast(Type.SingleFilterValue, unspecifiedFilterValues[m]);
var thisMemberInfo = datasource.getMember(dimensionId, filterValue.value);
newMemberInfo.push(thisMemberInfo);
}
if (unspecifiedFilterValues[m].type == “Multiple”) {
var multipleFilterValue = cast(Type.MultipleFilterValue, unspecifiedFilterValues[m]);
var tempValues = multipleFilterValue.values;
for (var u = 0; u < tempValues.length; u++) {
var thisMemberInfo2 = datasource.getMember(dimensionId, tempValues[u]);
newMemberInfo.push(thisMemberInfo2);
}
}
}

//替换掉原来的member info Replace the original member info.
modifiedFilter.members = newMemberInfo;

//构造一个新members的字符串,以供日志使用 Construct a new string of members for logging purposes.
var newMembers = “”;
for (var e = 0; e < modifiedFilter.members.length; e++) {
newMembers = newMembers + ” ” + modifiedFilter.members[e].description;
}

//增加新的filter,并添加日志 Add a new filter and log the action.
for (var k = 0; k < recordModifiedEvents.length; k++) {
toBeModifiedEvents[recordModifiedEvents[k]].addContextFilter(modifiedFilter);
ListBox_1.addItem(toBeModifiedEvents[recordModifiedEvents[k]].getName()+” [“+modifiedFilter.members[0].dimensionId + “] ” + oldMembers + ” ->” + newMembers);
}
}

 

五、总结 

本文主要分享了我开发“批量修改日历事件上下文”故事应用的经验。如果您也遇到了类似的问题,希望可以给您启发。 

 

​ 一、介绍  在数字化转型加速演进、企业对敏捷运营与智能决策需求持续攀升的当下,SAP 分析云凭借其强大的综合能力,正成为企业赋能业务管理与战略决策的核心平台。它集数据可视化、预测分析、规划及协作于一体,不仅帮助企业洞察趋势、优化流程,更为组织打造出一套覆盖全局的智能化运营体系。 在 SAP 分析云中,日历功能被广泛用于企业计划、事件安排、任务追踪及跨部门协作,但其上下文批量修改能力仍存在明显短板。 例如,当企业根据标准化模板生成一个规模较大的流程后,如果后续需要针对某一关键维度(如时间、区域等)进行整体性调整,往往只能通过“编辑事件”中的“替换上下文”来实现,但这种方法意味着原有的全部上下文信息会被一并清空,导致企业需耗费人力重新配置所有维度,容易引发管理上的不一致与风险。 针对这一问题,我开发了基于 SAC 日历 API 脚本的故事应用,专注于实现“点对点”的上下文批量修改功能。用户只需输入一个流程的 ID,即可完整展现该流程及其所有子流程、子事件的层级结构,精准锁定需要修改的范围。接着,可根据实际业务需要灵活选择目标模型、待修改的上下文维度,并进一步指定新成员,实现对指定维度的批量更新,同时保证其他维度信息原封不动地保留在流程上下文中。这项能力尤其适用于以下场景: • 基于标准模板生成流程后,需对某一单一维度进行快速统一调整。• 在组织架构或战略方向变更时,对流程的上下文进行局部修订,而无需重新初始化全部配置。 二、如何使用“批量修改日历事件上下文”应用 使用该故事应用前可在该故事页面查看相关故事应用的使用说明。  1、要执行此操作,您需要具备以下权限 公共文件的“读”权限 计划模型的“读”权限 2、请按照以下步骤获取父日历流程的事件 ID:  选中事件后,点击右上角的“详细信息”,在弹出菜单栏的右上角,点击“更多”,然后点击“事件设置” 如果未勾选“允许外部 API 访问”选项,请勾选该选项。  然后点击“显示详情”以查看并复制事件 ID。3、将事件 ID 粘贴到文本框中,并点击“Confirm”,之后会在下一栏中显示出进程及其子事件的结构。 4、在下一栏中选择想要修改的范围,并点击“Confirm”。但请注意,并不是所有选中的事件都一定会被修改,这取决于这一事件是否使用到了你之后选择的模型,以及是否包括了你之后选择的维度。 5、在下一栏中选择一个你想要修改的上下文所引用的模型,并点击“Confirm”。 6、在下一栏中选择你想要修改的维度,并点击“Confirm”。 7、在下一栏中,请分别修改维度中的成员,方法如下: 单击某一维度。 按如下示意操作。 8、将所有维度都设置好后,点击“Confirm”。 9、在修改完成后,右侧栏会显示日志。 10、若想要修改其他子事件,请重新从步骤4开始。  三、注意事项  无法替换数据锁定任务、数据操作任务、多操作任务、输入任务。 四、代码实现 在介绍之前,我们先明确三种概念。 维度(Dimension):模型中的一个特定方面或分类依据。 成员(Member):在某个维度下的具体实例或分类项。 筛选器(Filter):由一个维度及其对应的一些成员所构成的组合,用于对数据进行筛选和限定,以便聚焦于特定的分析范围或数据子集。 接下来将对主要的实现逻辑进行介绍,主要逻辑步骤如下: 1、变量与页面初始化 在实现该功能之前,需要在故事应用中配置“日历集成”,并完成变量的初始化。以下是部分关键变量的说明:datasource // 所选中model的datasource对象
eventsIds // 流程及其子项的id
isEventsAllSelected// 是否选中了所有的事件(用于全选按钮)
modelId // 所选中model的id
selectedFilters // 所选择的筛选器;如选择维度A,那么所有事件中与A相关的筛选器都会被添加到这个数组
toBeModifiedEvents // 选中的事件
//以下两个变量用于模拟二维数组,目的是存储每个model id下都有什么dimension id
uniqueModelDimensionId_1 // 这个数组存储model id
uniqueModelDimensionId_2 //这个数组存储dimension id  在页面初始化中,设置了系统消息提示类型。 2、校验并获取流程及其子项 //获取event ID。Get the event ID.
var userInput_processID = InputField_1.getValue();
var processEvent = CalendarIntegration_1.getCalendarEventById(userInput_processID);
//如果获取不到对象,则报错。 If the object cannot be obtained, an error will be reported.
if (processEvent === undefined) {
Application.showMessage(ApplicationMessageType.Warning, “Please enter a correct ID.”);
Application.hideBusyIndicator();
return;
} 使用队列进行广度优先遍历。 同时使用两个队列,idQueue用于存储event id,spaceQueue用于记录深度,以便后续能更好地显示层次结构 对每个事件获取其对象,并将其属性添加到复选框中。 若这个事件同时是流程,将它的子项加入到队列。 //BFS
var idQueue = ArrayUtils.create(Type.string);
var spaceQueue = ArrayUtils.create(Type.string);
idQueue.push(processEvent.getId());
//spaceQueue以字符的形式标明了目前遍历到第几层。 spaceQueue indicates the current level of traversal in the form of characters.
spaceQueue.push(“”);
while (idQueue.length > 0) {
var currentId = idQueue.shift();
var currentSpace = spaceQueue.shift();
var currentEvent = CalendarIntegration_1.getCalendarEventById(currentId);
if (currentEvent !== undefined) {
CheckboxGroup_1.addItem(currentId, currentSpace + currentEvent.getName());
eventsIds.push(currentId);
if (currentEvent.getType() === CalendarTaskType.Process) {
var currentProcess = cast(Type.CalendarProcess, currentEvent);
var childrenIds = currentProcess.getChildren();
for (var i = 0; i < childrenIds.length; i++) {
idQueue.push(childrenIds[i]);
spaceQueue.push(currentSpace + “-“);
}
}
}
} 3、用户选择事件后,获取所有被选中的事件里面互不相同的filter 获取到选择的事件 对每个选择的事件,遍历其filter,并维护到一个不重复的数组中。 如果数组为空,即找不到任何filter,则报错。 //获取到选择的事件 Obtain the selected events.
toBeModifiedEvents = ArrayUtils.create(Type.CalendarEvent);
var toBeModifiedEventsID = CheckboxGroup_1.getSelectedKeys();
var uniqueFilters = ArrayUtils.create(Type.CalendarContextFilter);

//获取到有几种不同的筛选器 Obtain the unique filters.
for (var i = 0; i < toBeModifiedEventsID.length; i++) {
var event = CalendarIntegration_1.getCalendarEventById(toBeModifiedEventsID[i]);
toBeModifiedEvents.push(event);
// 获取当前事件的筛选器数组 Obtain the array of filters of the current event.
var filters = event.getContextFilters();
if (filters === undefined) {
continue;
}
console.log(filters);
// 遍历每个筛选器 Traverse each filter.
for (var j = 0; j < filters.length; j++) {
var filter = filters[j];
if (!uniqueFilters.includes(filter)) {
uniqueFilters.push(filter);
}
}
}
//如果找不到任何筛选器,则报错。If no filter is found, an error will be reported.
if (uniqueFilters.length === 0) {
Application.showMessage(ApplicationMessageType.Warning, “No context was found.”);
Application.hideBusyIndicator();
return;
} 4、获取每个model Id下的dimension Id,以及model Id与model name的对应关系 通过之前维护的不重复filter数组中获取到每个model id下的dimension id。 获取到每个model对应的datasource来得到该model的名称;在这里,我使用了一个hidden table。 var uniqueModelId = ArrayUtils.create(Type.string);
for (var m = 0; m < uniqueFilters.length; m++) {
var modelId_ = uniqueFilters[m].members[0].modelId;
var dimensionId = uniqueFilters[m].members[0].dimensionId;
if (!(uniqueModelDimensionId_1.includes(modelId_) && uniqueModelDimensionId_2.includes(dimensionId))) {
uniqueModelDimensionId_1.push(modelId_);
uniqueModelDimensionId_2.push(dimensionId);
}
if (!uniqueModelId.includes(modelId_)) {
uniqueModelId.push(modelId_);
}
}

var temp1 = ArrayUtils.create(Type.string);
var temp2 = ArrayUtils.create(Type.string);

for (var n = 0; n < uniqueModelId.length; n++) {
var modelId__ = uniqueModelId[n];
Table_1.setModel(modelId__);
datasource = Table_1.getDataSource();
temp1.push(modelId__);
temp2.push(datasource.getInfo().modelName);
}

for (var o = 0; o < temp1.length; o++) {
RadioButtonGroup_1.addItem(temp1[o], temp2[o]);
} 5、用户选择某个model后,获取dimension id与description的对应关系 将Calendar API的dimension id与datasource的dimension id进行匹配,获取到每个dimension的description modelId = RadioButtonGroup_1.getSelectedKey();
datasource = Table_1.getDataSource();
var dimensions = datasource.getDimensions();
var descriptions = ArrayUtils.create(Type.string);
for (var h = 0; h < uniqueModelDimensionId_1.length; h++) {
if (uniqueModelDimensionId_1[h] === modelId) {
for (var j = 0; j < dimensions.length; j++) {
if (dimensions[j].id === uniqueModelDimensionId_2[h]) {
descriptions.push(dimensions[j].description);
break;
}
}
console.log(“error, dimension id dismatch”);
} else {
descriptions.push(“1”); //占位
}
}

for (var i = 0; i < uniqueModelDimensionId_1.length; i++) {
if (uniqueModelDimensionId_1[i] === modelId) {
CheckboxGroup_2.addItem(uniqueModelDimensionId_2[i], uniqueModelDimensionId_2[i] + ” ” + descriptions[i]);
}
} 6、用户选择dimension后,通过已选择的dimension id来获取到具体需要修改哪些filter var selectedDimensions = CheckboxGroup_2.getSelectedKeys();
selectedFilters = ArrayUtils.create(Type.CalendarContextFilter);
for (var k = 0; k < toBeModifiedEvents.length; k++) {
var filters = toBeModifiedEvents[k].getContextFilters();
for (var m = 0; m < filters.length; m++) {
if (selectedDimensions.includes(filters[m].members[0].dimensionId) && filters[m].members[0].modelId === modelId && !selectedFilters.includes(filters[m])){
selectedFilters.push(filters[m]);
}
}
} 7、将具体需要修改的filter添加到datasource中,以便能够在filter line中显示 Version维度会默认作为datasource的filter,为了避免这一情况,预先将Version加入到Table的列中。 var dimensions = datasource.getDimensions();
for (var s = 0; s < dimensions.length; s++) {
if (dimensions[s] == “Version”) {
Table_1.addDimensionToColumns(“Version”);
break;
}
}

for (var o = 0; o < selectedDimensions.length; o++) {
for (var u = 0; u < selectedFilters.length; u++) {
if (selectedFilters[u].members[0].dimensionId === selectedDimensions[o]) {
datasource.setDimensionFilter(selectedDimensions[o], selectedFilters[u].members);
}
}
} 8、删除旧的filter并添加新的filter 首先,对之前存储的需要修改的filter数组进行去重处理 删除旧的filter 构造新的Context Filter 加入新的filter 添加日志 var dimensions = datasource.getDimensions();
var selectedFiltersNoRepeat = ArrayUtils.create(Type.CalendarContextFilter);
for (var v = 0; v < selectedFilters.length; v++) {
if (!selectedFiltersNoRepeat.includes(selectedFilters[v])) {
selectedFiltersNoRepeat.push(selectedFilters[v]);
}
}
//selectedFilters 去重 Remove duplicates from selected filters.
for (var q = 0; q < selectedFiltersNoRepeat.length; q++) {
//selectedFilter是目前需要修改的筛选器 selectedFilter is the filter that currently needs to be modified.
var selectedFilter = selectedFiltersNoRepeat[q];
//复制一份变量,避免出现意外情况 Make a copy of the variable to avoid unexpected situations
var modifiedFilter = selectedFilter;
var dimensionId = modifiedFilter.members[0].dimensionId;
var newMemberInfo = ArrayUtils.create(Type.MemberInfo);
//构造一个原有members的字符串,以供日志使用 Construct a string of the original members for logging purposes.
var oldMembers = “”;
for (var r = 0; r < modifiedFilter.members.length; r++) {
oldMembers = oldMembers + ” ” + modifiedFilter.members[r].description;
}
//从datasource中获取到用户已经在filter line中修改好的filter Obtain the filter that the user has already modified in the filter line from the datasource.
var unspecifiedFilterValues = datasource.getDimensionFilters(dimensionId);

//删除旧的筛选器。remove old filter
var recordModifiedEvents = ArrayUtils.create(Type.integer);
for (var j = 0; j < toBeModifiedEvents.length; j++) {
if (toBeModifiedEvents[j].removeContextFilter(selectedFilter)) {
recordModifiedEvents.push(j);

}
}

//构建新的member info Construct the new member info.
for (var m = 0; m < unspecifiedFilterValues.length; m++) {
if (unspecifiedFilterValues[m].type == “Single”) {
var filterValue = cast(Type.SingleFilterValue, unspecifiedFilterValues[m]);
var thisMemberInfo = datasource.getMember(dimensionId, filterValue.value);
newMemberInfo.push(thisMemberInfo);
}
if (unspecifiedFilterValues[m].type == “Multiple”) {
var multipleFilterValue = cast(Type.MultipleFilterValue, unspecifiedFilterValues[m]);
var tempValues = multipleFilterValue.values;
for (var u = 0; u < tempValues.length; u++) {
var thisMemberInfo2 = datasource.getMember(dimensionId, tempValues[u]);
newMemberInfo.push(thisMemberInfo2);
}
}
}

//替换掉原来的member info Replace the original member info.
modifiedFilter.members = newMemberInfo;

//构造一个新members的字符串,以供日志使用 Construct a new string of members for logging purposes.
var newMembers = “”;
for (var e = 0; e < modifiedFilter.members.length; e++) {
newMembers = newMembers + ” ” + modifiedFilter.members[e].description;
}

//增加新的filter,并添加日志 Add a new filter and log the action.
for (var k = 0; k < recordModifiedEvents.length; k++) {
toBeModifiedEvents[recordModifiedEvents[k]].addContextFilter(modifiedFilter);
ListBox_1.addItem(toBeModifiedEvents[recordModifiedEvents[k]].getName()+” [“+modifiedFilter.members[0].dimensionId + “] ” + oldMembers + ” ->” + newMembers);
}
}  五、总结 本文主要分享了我开发“批量修改日历事件上下文”故事应用的经验。如果您也遇到了类似的问题,希望可以给您启发。    Read More Technology Blog Posts by SAP articles 

#SAP

#SAPTechnologyblog

You May Also Like

More From Author