The “onAfterDataEntryProcess” event in SAP Analytics Cloud Optimized Story

Estimated read time 15 min read

I am happy to share that our new table event, “onAfterDataEntryProcess()” , will be available with QRC1 2025 release in SAP Analytics Cloud!

What is “onDataAfterEntryProcess” event?

The “onAfterDataEntryProcess” event is an event associated with Table Widget in Optimized Story.

This event is triggered after user enters the data on the table and the data changes are processed in the backend. Data changes on the table widget can occur through any of fluid data entry, mass data entry, single data entry, copy and paste, distribution via the planning panel, or the “submitData” script function.

From the parameters of this event, you can get the context of changed table cells, as well as the value of cells before and after the change.

 

Use-cases for onAfterDataEntryProcess

The “onAfterDataEntryProcess” event offers the full flexibility to further process the data after the data changes have been made in the table widget, and to this end, here are some scenarios where “onAfterDataEntryProcess” event can be useful:

If you prefer not to run a data action for the entire model, and instead wish to run the data action only on changed data to optimize the time or resource consumption. In this case you can utilize the event to gather the scope of the changed data. Subsequently, when you click a button or navigate to a different page, the scope of the changed data can be passed to a data action via data action parameters. This approach helps to reduce the scope of data action calculation, thereby enhancing its performance and resource consumption.Where execution of calculations (incl. data actions) is required to occur seamlessly after you enter data on the table. This ensures that the impact of the data changes is reflected almost in real-time.  However, direct referencing of data actions within the ‘onAfterDataEntryProcess” should be done judiciously given the potential impact on the system (see the section on Best Practices). In scenarios where specific constraints for data correctness exist. In this scenario you can validate the correctness of the data in the “onAfterDataEntryProcess” event.

You are not restricted to the above use-cases. You have full flexibility to achieve the more use-cases whenever you expect to execute certain logic following data entry.

 

Details of onAfterDataEntryProcess()

onAfterDataEntryProcess (cells: IChangedCell[], effectiveContext: SelectionContext): void

The “cells” array consists of the changed table cells. This array can have multiple changed cells from various actions, including fluid data entry, mass data entry, copy and paste, distribution via the planning panel, or the “submitData” script function.  Additionally, the “cells” array may contain one single changed cell through single data entry.

Each changed cell in the array contains a new value, an old value, and the cell context. The cell context includes all the dimension members associated with the cell in both the row and column axes.

“effectiveContext” is a JSON object that contains the context of all the changed cells.

 

Example: In your table, Account is listed in the column axis and Product is listed in the row axis. You have made the following changes: the value in the 1st cell has been changed from 123 to 456, the value in the 2nd cell has been deleted(previously 789), and a new value of 123 has been added to the 3rd cell.

cells: [{  // the 1st changed cell

    oldValue: 123,

    newValue: 456, // change 123 to 456

    context: {

      Account: “[Account].[parentId].&[700000]”,

      Product: “[Product].[parentId].&[PRD0005]”,

    }

}, { // the 2nd changed cell

    oldValue: 789,

    newValue: null,  // delete 789

    context: {

      Account: “[Account].[parentId].&[530005]”,

      Product: “[Product].[parentId].&[PRD0006]”,

    }

}, {// the 3rd changed cell

    oldValue: null,

    newValue: 123,  // create new value 123

    context: {

      Account: “[Account].[parentId].&[700001]”, 

      Product: “[Product].[parentId].&[PRD0007]”,

    }

}

]

 

effectiveContext: { // the context of the changed cells

  Account: [“[Account].[parentId].&[700000]”, “[Account].[parentId].&[530005]”, “[Account].[parentId].&[700001]”],
  Product:[“[Product].[parentId].&[PRD0005]”, “[Product].[parentId].&[PRD0006]”, “[Product].[parentId].&[PRD0007]”],
}

 

Please note that “Measure” is technically a special structure. Therefore, in the cell context, the measure is listed as CustomDimension1. For instance, when measure “Amount” is listed in either row or column axis in the table widget in the example above, the cell context is as follow:

    context: {

      Account: “[Account].[parentId].&[700001]”,

      Product: “[Product].[parentId].&[PRD0007]”,

      CustomDimension1: “Amount”,

    }

 

Examples

Example 1: Data action execution only on changed cells. 

To optimize the time and resource consumption, you prefer not to run a data action for the entire model, and instead wish to run the data action only on changed data.

As a story developer, you can write scripts for the “onAfterDataEntryProcess” event to gather the scope of the changed data. Subsequently, you can write scripts for a button click event or a page navigation event to pass the scope of the changed data to a data action via data action parameters.

Prerequisites

You’ve created a story and added the following widgets:A table Table_1, which uses a planning modelA script variable ChangedData, whose data type is an Array of StringA button Button_1A data action technical object DataAction_1, who uses a data action with “Region” parameter 

In the edit mode, you’d like to write scripts to gather the regions whose data has been changed, and execute a data action to calculate on the changed data.

1. Enter the following script for the table’s “onAfterDataEntryProcess” event to gather the regions whose data has been changed.

 

for (var i=0;i<effectiveContext[“Regions”].length; i++){
ChangedData.push(effectiveContext[“Regions”][i]);

};

 

2. Enter the following script for the button’s “onClick” event to execute a data action to calculate on the changed data via parameter. 

 

DataAction_1.setParameterValue(“Region”, { type: DataActionParameterValueType.Member,members:ChangedData});

var result =DataAction_1.execute();

 

This approach helps to reduce the scope of data action calculation, thereby enhancing its performance.

 

Example 2: Validate data correctness.

As a planning analyst, you may want to ensure that data entry for certain cells meets predefined conditions.   Assume for example that we have a constrain that the requested budget should not exceed the originally allocated amount by more than 20%. If this validation is not met, we want to issue a warning to the user.

Prerequisites

You’ve created a story and added the following widgets:A table Table_1, which uses a planning model

In the edit mode, you’d like to write scripts to validate the entered data after data proceed.

Enter the following script for the table’s “onAfterDataEntryProcess” event.

 

var allocatedBudget = 100; // this example uses a fixed allocated budget. You can also read the allocated budget from another version in your case.

For (var i=0;i<cells.length; i++){
if (ConvertUtils.stringToNumber(cells[i].newValue) > allocatedBudget * 1.2){
Application.showMessage(ApplicationMessageType.Warning, “It is not allowed to exceed the originally allocated amount by more than 20%.”)}
}

 

You use newValue from event parameters to validate the constraint.

In the view mode, if you change the value exceeding this constraint, a warning message will appear.

 

Best Practices

As the “onAfterDataEntryProcess” is associated with table widget, there are some best practices to optimize the functionality of this script in coherent with standard table workflow.

Where data action execution is required as part of the calculation workflow, it is recommended to accumulate all data changes via the “onAfterDataEntryProcess” event, and then run data action for all changed in a single execution (e.g. by clicking a button or navigating to another page within story).Calling data actions directly within the “onAfterDataEntryProcess” event is recommended in selective scenarios, for example, a large amount of data is entered in a single end-user action (e.g., Mass Data Entry), and where corresponding data action execution is known to be quick.  Note, data changes through mass data entry are proceed after user clicks “Process Data” button.Where data actions are executed directly in the “onAfterDataEntryProcess” event, it is important that the data action being called does not change data in current table where the event itself is being called. Changing data in the current table through this event might cause a looped refresh, leading to unexpected refresh behavior in the table widget.  The “onAfterDataEntryProcess” execution blocks table UI actions in Single Data Entry (and Mass Data Entry) mode. Consequently, when Single Data Entry mode is enabled, it is not recommended to include heavy scripts in the event call so as to avoid the long wait times for the end-user.  To prevent an endless loop, avoid using the “submitData” script in the “onAfterDataEntryProcess” event. This is because the “submitData” script triggers this event, which in turn executes the “submitData” script again, creating an endless cycle.Page filters / story filters are not included in the “onAfterDataEntryProcess” event. The filter values can be retrieved from filter script functions. For more information about filters script functions, please refer to the following link:https://help.sap.com/doc/1639cb9ccaa54b2592224df577abe822/2024.25/en-US/index.html#InputControlhttps://help.sap.com/docs/SAP_ANALYTICS_CLOUD/18850a0e13944f53aa8a8b7c094ea29e/5bb384ea6b6342129bfa3823a2d859a7.html 

​ I am happy to share that our new table event, “onAfterDataEntryProcess()” , will be available with QRC1 2025 release in SAP Analytics Cloud!What is “onDataAfterEntryProcess” event?The “onAfterDataEntryProcess” event is an event associated with Table Widget in Optimized Story.This event is triggered after user enters the data on the table and the data changes are processed in the backend. Data changes on the table widget can occur through any of fluid data entry, mass data entry, single data entry, copy and paste, distribution via the planning panel, or the “submitData” script function.From the parameters of this event, you can get the context of changed table cells, as well as the value of cells before and after the change. Use-cases for onAfterDataEntryProcessThe “onAfterDataEntryProcess” event offers the full flexibility to further process the data after the data changes have been made in the table widget, and to this end, here are some scenarios where “onAfterDataEntryProcess” event can be useful:If you prefer not to run a data action for the entire model, and instead wish to run the data action only on changed data to optimize the time or resource consumption. In this case you can utilize the event to gather the scope of the changed data. Subsequently, when you click a button or navigate to a different page, the scope of the changed data can be passed to a data action via data action parameters. This approach helps to reduce the scope of data action calculation, thereby enhancing its performance and resource consumption.Where execution of calculations (incl. data actions) is required to occur seamlessly after you enter data on the table. This ensures that the impact of the data changes is reflected almost in real-time.  However, direct referencing of data actions within the ‘onAfterDataEntryProcess” should be done judiciously given the potential impact on the system (see the section on Best Practices). In scenarios where specific constraints for data correctness exist. In this scenario you can validate the correctness of the data in the “onAfterDataEntryProcess” event.You are not restricted to the above use-cases. You have full flexibility to achieve the more use-cases whenever you expect to execute certain logic following data entry. Details of onAfterDataEntryProcess()onAfterDataEntryProcess (cells: IChangedCell[], effectiveContext: SelectionContext): voidThe “cells” array consists of the changed table cells. This array can have multiple changed cells from various actions, including fluid data entry, mass data entry, copy and paste, distribution via the planning panel, or the “submitData” script function.  Additionally, the “cells” array may contain one single changed cell through single data entry.Each changed cell in the array contains a new value, an old value, and the cell context. The cell context includes all the dimension members associated with the cell in both the row and column axes.“effectiveContext” is a JSON object that contains the context of all the changed cells. Example: In your table, Account is listed in the column axis and Product is listed in the row axis. You have made the following changes: the value in the 1st cell has been changed from 123 to 456, the value in the 2nd cell has been deleted(previously 789), and a new value of 123 has been added to the 3rd cell.cells: [{  // the 1st changed cell    oldValue: 123,    newValue: 456, // change 123 to 456    context: {      Account: “[Account].[parentId].&[700000]”,      Product: “[Product].[parentId].&[PRD0005]”,    }}, { // the 2nd changed cell    oldValue: 789,    newValue: null,  // delete 789    context: {      Account: “[Account].[parentId].&[530005]”,      Product: “[Product].[parentId].&[PRD0006]”,    }}, {// the 3rd changed cell    oldValue: null,    newValue: 123,  // create new value 123    context: {      Account: “[Account].[parentId].&[700001]”,       Product: “[Product].[parentId].&[PRD0007]”,    }}] effectiveContext: { // the context of the changed cells  Account: [“[Account].[parentId].&[700000]”, “[Account].[parentId].&[530005]”, “[Account].[parentId].&[700001]”],  Product:[“[Product].[parentId].&[PRD0005]”, “[Product].[parentId].&[PRD0006]”, “[Product].[parentId].&[PRD0007]”],} Please note that “Measure” is technically a special structure. Therefore, in the cell context, the measure is listed as CustomDimension1. For instance, when measure “Amount” is listed in either row or column axis in the table widget in the example above, the cell context is as follow:    context: {      Account: “[Account].[parentId].&[700001]”,      Product: “[Product].[parentId].&[PRD0007]”,      CustomDimension1: “Amount”,    } ExamplesExample 1: Data action execution only on changed cells. To optimize the time and resource consumption, you prefer not to run a data action for the entire model, and instead wish to run the data action only on changed data.As a story developer, you can write scripts for the “onAfterDataEntryProcess” event to gather the scope of the changed data. Subsequently, you can write scripts for a button click event or a page navigation event to pass the scope of the changed data to a data action via data action parameters.PrerequisitesYou’ve created a story and added the following widgets:A table Table_1, which uses a planning modelA script variable ChangedData, whose data type is an Array of StringA button Button_1A data action technical object DataAction_1, who uses a data action with “Region” parameter In the edit mode, you’d like to write scripts to gather the regions whose data has been changed, and execute a data action to calculate on the changed data.1. Enter the following script for the table’s “onAfterDataEntryProcess” event to gather the regions whose data has been changed. for (var i=0;i<effectiveContext[“Regions”].length; i++){
ChangedData.push(effectiveContext[“Regions”][i]);

}; 2. Enter the following script for the button’s “onClick” event to execute a data action to calculate on the changed data via parameter.  DataAction_1.setParameterValue(“Region”, { type: DataActionParameterValueType.Member,members:ChangedData});

var result =DataAction_1.execute(); This approach helps to reduce the scope of data action calculation, thereby enhancing its performance. Example 2: Validate data correctness.As a planning analyst, you may want to ensure that data entry for certain cells meets predefined conditions.   Assume for example that we have a constrain that the requested budget should not exceed the originally allocated amount by more than 20%. If this validation is not met, we want to issue a warning to the user.PrerequisitesYou’ve created a story and added the following widgets:A table Table_1, which uses a planning modelIn the edit mode, you’d like to write scripts to validate the entered data after data proceed.Enter the following script for the table’s “onAfterDataEntryProcess” event. var allocatedBudget = 100; // this example uses a fixed allocated budget. You can also read the allocated budget from another version in your case.

For (var i=0;i<cells.length; i++){
if (ConvertUtils.stringToNumber(cells[i].newValue) > allocatedBudget * 1.2){
Application.showMessage(ApplicationMessageType.Warning, “It is not allowed to exceed the originally allocated amount by more than 20%.”)}
} You use newValue from event parameters to validate the constraint.In the view mode, if you change the value exceeding this constraint, a warning message will appear. Best PracticesAs the “onAfterDataEntryProcess” is associated with table widget, there are some best practices to optimize the functionality of this script in coherent with standard table workflow.Where data action execution is required as part of the calculation workflow, it is recommended to accumulate all data changes via the “onAfterDataEntryProcess” event, and then run data action for all changed in a single execution (e.g. by clicking a button or navigating to another page within story).Calling data actions directly within the “onAfterDataEntryProcess” event is recommended in selective scenarios, for example, a large amount of data is entered in a single end-user action (e.g., Mass Data Entry), and where corresponding data action execution is known to be quick.  Note, data changes through mass data entry are proceed after user clicks “Process Data” button.Where data actions are executed directly in the “onAfterDataEntryProcess” event, it is important that the data action being called does not change data in current table where the event itself is being called. Changing data in the current table through this event might cause a looped refresh, leading to unexpected refresh behavior in the table widget.  The “onAfterDataEntryProcess” execution blocks table UI actions in Single Data Entry (and Mass Data Entry) mode. Consequently, when Single Data Entry mode is enabled, it is not recommended to include heavy scripts in the event call so as to avoid the long wait times for the end-user.  To prevent an endless loop, avoid using the “submitData” script in the “onAfterDataEntryProcess” event. This is because the “submitData” script triggers this event, which in turn executes the “submitData” script again, creating an endless cycle.Page filters / story filters are not included in the “onAfterDataEntryProcess” event. The filter values can be retrieved from filter script functions. For more information about filters script functions, please refer to the following link:https://help.sap.com/doc/1639cb9ccaa54b2592224df577abe822/2024.25/en-US/index.html#InputControlhttps://help.sap.com/docs/SAP_ANALYTICS_CLOUD/18850a0e13944f53aa8a8b7c094ea29e/5bb384ea6b6342129bfa3823a2d859a7.html   Read More Technology Blogs by SAP articles 

#SAP

#SAPTechnologyblog

You May Also Like

More From Author