0% found this document useful (0 votes)
146 views

Scripting (Optimized Story Experience and Analytics Designer)

The document provides custom documentation for SAP Analytics Cloud, focusing on scripting within analytic applications and stories. It outlines how to write scripts using a JavaScript-based language, configure widgets, and utilize various technical objects and API references to enhance interactivity. Additionally, it includes details on using script variables, keyboard shortcuts, and optimizing script performance for effective application design.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
146 views

Scripting (Optimized Story Experience and Analytics Designer)

The document provides custom documentation for SAP Analytics Cloud, focusing on scripting within analytic applications and stories. It outlines how to write scripts using a JavaScript-based language, configure widgets, and utilize various technical objects and API references to enhance interactivity. Additionally, it includes details on using script variables, keyboard shortcuts, and optimizing script performance for effective application design.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 166

2/9/25, 4:58 PM

SAP Analytics Cloud Help


Generated on: 2025-02-09 16:58:02 GMT+0000

SAP Analytics Cloud | Q4 2024 (2024.21)

Public

Original content: https://help.sap.com/docs/SAP_ANALYTICS_CLOUD/00f68c2e08b941f081002fd3691d86a7?locale=en-


US&state=PRODUCTION&version=release

Warning

This document has been generated from SAP Help Portal and is an incomplete version of the official SAP product documentation.
The information included in custom documentation may not reflect the arrangement of topics in SAP Help Portal, and may be
missing important aspects and/or correlations to other topics. For this reason, it is not for production use.

For more information, please visit https://help.sap.com/docs/disclaimer.

This is custom documentation. For more information, please visit SAP Help Portal. 1
2/9/25, 4:58 PM

Scripting (Optimized Story Experience and Analytics Designer)


As an application designer or story developer, you can add scripts to your analytic applications or stories to implement your
custom logic and offer viewers more interactions with them.

API Reference

Writing Your Scripts


Write Scripts in Script Editor

Use Value Help in Script Editor

Use Keyboard Shortcuts in Script Editor

Use Script Variables

Use Script Objects

Create Pattern-Based Functions

Optimize Type Libraries

Work with Automatic Refactoring

Debug Your Scripts

Check Errors in Scripting

Check References in Scripting

Using Scripts in Your Widgets


Create Buttons

Create Input Fields or Text Areas

Configure Sliders or Range Sliders

Bind Widgets’ Values to Variables

Using Technical Objects


Configure Bookmark Settings and Use Related APIs (Optimized Story Experience)

Use Bookmark Set Technical Objects in Analytic Applications

Use a Calendar Integration Technical Object and Related APIs

Enable Data Change Insights and Use Related APIs

Use an Export to PDF Technical Object

Use an Export to PowerPoint Technical Object (Optimized Story Experience)

Use a Text Pool Technical Object for Script Translation (Optimized Story Experience)

Set up Timers

Use Data Actions Technical Objects

This is custom documentation. For more information, please visit SAP Help Portal. 2
2/9/25, 4:58 PM
Use Multi Actions Technical Objects

Use an OData Service in Analytics Designer or Optimized Story Experience

Using API Scripting Patterns and Examples


Scripting Patterns and Examples

Optimizing Script Performance


View Script Performance in a Popup

Use MemberInfo Object in setDimensionFilter() API

API Reference
You can create interactive and highly custom-defined analytic applications and stories using APIs provided by SAP Analytics
Cloud.

To enable interactivity, as an application designer or story developer you can write scripts that are executed when end user
performs an action in view time. For example, you can add a button widget and assign scripts to its onClick event.

The scripts consist of one or more statements written in a JavaScript-based language, which follow a specific syntax. You can write
scripts in the script editor.

All objects, fields and functions available are listed in Analytics Designer API Reference (for analytic applications) and Optimized
Story Experience API Reference (for optimized stories).

Write Scripts in Script Editor


Script editor lets you, as an application designer or story developer, write scripts for each widget and thus create interactive and
highly custom-defined analytic applications or optimized stories.

Context

To enable interactivity, you configure the behavior of widgets and write scripts that are executed when the viewer performs an
action in the analytic application or story. For example, you can add a button widget and assign scripts to the its onClick event.
You can also write scripts based on other system events like the onInitialization event of the application or page or scripts
that are executed whenever data is changed.

Scripts consist of one or more statements written in a JavaScript-based language, which follow a specific syntax. You write scripts
in the script editor. You can find all objects, fields and functions available for scripting in Analytics Designer API Reference (for
analytic applications) or Optimized Story Experience API Reference (for optimized stories).

Procedure
1. In the Outline panel, hover over the widget, page, or popup to which you want to assign scripts, for example, Dropdown_1.

2. Select (Edit Scripts). If the widget supports multiple events, select (Edit Scripts) and then one of the supported
events.

This is custom documentation. For more information, please visit SAP Help Portal. 3
2/9/25, 4:58 PM
The script editor opens in a new tab, whose title includes the event and the widget, page or popup to which the scripts will
be assigned, for example, Dropdown_1 - onSelect.

 Tip
You can change the order of the multiple tabs by dragging and dropping them horizontally.

Additionally in Optimized Story Experience, you can manage multiple tabs by selecting Stack All Editor Tabs from the
dropdown menu. The tabs are stacked, and you can select one from the dropdown menu to write the scripts:

You can also open the script editor by selecting Edit Scripts in the widget's (More Actions) menu.

3. In the script editor, enter one or more statements with the syntax: <ComponentVariable>.<function>
(<arguments>);.

 Sample Code
//Gets the selected text of a dropdown.
var selectedText = Dropdown_1.getSelectedText();

 Tip
You can call the value help at any place in the script by pressing CTRL + Space . For more information, refer to Use
Value Help in Script Editor.

This is custom documentation. For more information, please visit SAP Help Portal. 4
2/9/25, 4:58 PM

4. When you've finished your scripts, you can close the tab.

Results
You've used the script editor to write scripts and add custom logic to your application or story. If a widget has related scripts,
there's a button to its side in Outline. You can run the scripts in view time to test them.

Related Information
Use Script Variables
Use Script Objects
Use Keyboard Shortcuts in Script Editor

Use Value Help in Script Editor


As an application designer or story developer, you can use different kinds of value help in the script editor depending on the
context in which you're working.

 Note
setVariableValue for tables and charts, and addMeasure for charts only support single variable values. That's why the
member selector also allows only single selection.

You can open the value help by pressing CTRL + SPACE .

 Tip
If pressing CTRL + SPACE doesn't display any values, make sure that the keyboard shortcut isn't used elsewhere. For
example, in some Chinese input methods, it's used to switch language between Chinese and English. To make the shortcut take
effect, you can do either of the following:

This is custom documentation. For more information, please visit SAP Help Portal. 5
2/9/25, 4:58 PM
Press FN with CTRL + SPACE .

In your device settings, disable the keyboard shortcut CTRL + SPACE , or replace it with new keys.

Value Help for Measure

To get measure metadata in the script editor, press CTRL + SPACE .

 Note
This value help is only available to chart.addmeasure().

Value Help for Measure

The member selector for metadata looks like this:

This is custom documentation. For more information, please visit SAP Help Portal. 6
2/9/25, 4:58 PM

Member Selector for Measure Metadata

The result of metadata selection looks like this in the script editor:

Selection Result for Measure Displayed in Script Editor

Value Help for Variable Values

To get metadata for variable values, press CTRL + Space . If you are working with a dimension variable, you can open the
member selector; otherwise you can only add or show the variable values in the code completion list.

This is custom documentation. For more information, please visit SAP Help Portal. 7
2/9/25, 4:58 PM

Value Help for Dimension Variable

The member selector for dimension variable looks like this:

Member Selector for Dimension Variable

The selection result looks like this:

Selection Result for Dimension Variable Displayed in Script Editor

If you work with a variable that is not a dimension, the value help is displayed in the following way:

This is custom documentation. For more information, please visit SAP Help Portal. 8
2/9/25, 4:58 PM

Value Help for Non-Dimension Variable

And the selection result in the script editor looks like this:

Selection Result for Non-Dimension Variable Displayed in Script Editor

Value Help for Selection Object

If a function needs a selection object as an argument, you can see available arguments by pressing CTRL + space . Value help is
provided for keys, which represent the dimensions of an associated data source, or for the values of keys, which represent
dimension members of the corresponding dimensions.

 Note
To start the selection object you have to type in braces {} within the parentheses ( ).

This is custom documentation. For more information, please visit SAP Help Portal. 9
2/9/25, 4:58 PM

Value Help 1 for Object Key, Dimension

Value Help 2 for Object Key, Dimension

Value Help for Object Value, Dimension Member

If you have a selection object like sel in the following examples, you can get value help for dimensions of an associated data
source and access its properties by pressing CTRL + space after the dot operator.

This is custom documentation. For more information, please visit SAP Help Portal. 10
2/9/25, 4:58 PM
You can also get value help for the corresponding dimension members of the dimension property when you try to assign or
compare properties.

Value Help for Property, Member Access, Dimension

Value Help for Binary Expression, Dimension Member

This is custom documentation. For more information, please visit SAP Help Portal. 11
2/9/25, 4:58 PM

Value Help for Assignment Expression, Dimension Member

Use Keyboard Shortcuts in Script Editor


When you work in the script editor, you can use keyboard shortcuts to simplify your work.

The following keyboard shortcuts are available in the script editor:

 Note
Keyboard shortcuts apply to both Windows and Mac. For Mac, replace the Windows keys with the mapping Mac keys.

Command Keyboard Shortcut (For Windows) Description

selectAll CTRL + A Select the whole content of the editor.

deleteLine CTRL + D Delete the whole line under the cursor,


including newline at the end.

saveApplication CTRL + S Save the whole application.

singleSelection ESC When multiple selections are present, this


deselects all but the last selection.

undo CTRL + Z Undo the last change.

redo CTRL + Y Redo the last undone change.

undoSelection CTRL + U Undo the last change to the selection, or if


there are no selection-only changes at the
top of the history, undo the last change.

redoSelection ALT + U Redo the last change to the selection, or the


last text change if no selection changes
remain.

goDocStart CTRL + Home Move the cursor to the start of the


document.

goDocEnd CTRL + End Move the cursor to the end of the


document.

This is custom documentation. For more information, please visit SAP Help Portal. 12
2/9/25, 4:58 PM

Command Keyboard Shortcut (For Windows) Description

goLineStart ALT + Left Move the cursor to the start of the line.

goLineStartSmart Home Move to the start of the text on the line, or if


we are already there, to the actual start of
the line (including whitespace).

goLineEnd ALT + Right Move the cursor to the end of the line.

goGroupLeft CTRL + Left Move to the left of the group before the
cursor. A group is a stretch of word
characters, a stretch of punctuation
characters, a newline or a stretch of more
than one whitespace character.

goGroupRight CTRL + Right Move to the right of the group after the
cursor. A group is a stretch of word
characters, a stretch of punctuation
characters, a newline or a stretch of more
than one whitespace characters.

delCharBefore SHIFT + Backspace Delete the character before the cursor.

delCharAfter Delete Delete the character after the cursor.

delGroupBefore CTRL + Backspace Delete to the left of the group before the
cursor.

delGroupAfter CTRL + Delete Delete from the start of the group after the
cursor.

indentAuto SHIFT + Tab Auto-indent the current line or selection.

find CTRL + F Find.

findNext CTRL + G Find next.

findPrev SHIFT + CTRL + G Find previous.

toggleComments CTRL + / Toggle between commenting and


uncommenting the selected lines.

Related Information
Use Accessibility Features in SAP Analytics Cloud

Use Script Variables


As an application designer or story developer, you use script variables, which are useful for storing intermediate results repeatedly
used in a script, for example.

About Script Variables


Script variables are reusable elements that store a value of a certain type, which exist throughout the runtime. The script variables
you create in an application or story are available to itself only. You can define their values not only in the application or story, but

This is custom documentation. For more information, please visit SAP Help Portal. 13
2/9/25, 4:58 PM
also in its URL by adding a specific URL parameter.

For each script variable, you can define name, optional description, type and a default value, which is optional and depends on the
variable type. A script variable can be defined as an array, which represents a set of values of the specified type. You can use the
following primitive types:

string

Represents text as a sequence of characters.

boolean

Represents a logical value, either true or false.

number

Represents a floating-point numerical value.

Can be entered in ordinary format or scientific notation format such as 1e+20 or 1e20. If the number is longer than 21
digits, it will be automatically displayed in scientific notation format.

integer

Represents a non-fractional numerical value.

Scientific notation format isn't supported for entering values. However, at runrime if the number is longer than 21 digits, it'll
be displayed in scientific notation.

In addition to the primitive types described above, you can select a wider variety of non-primitive types for the script variable, such
as button, category, chart, clock, data source and table.

Create a Script Variable

Procedure
1. In the Scripting area of the Outline panel, (for analytic applications) choose right next to Script Variables, or (for
optimized stories) choose Script Variables to add a new script variable.

You can see the variable beneath Script Variables, and a new panel, Script Variable, is opened.

2. In the panel, change the name of the script variable.

3. (optional) Enter the description for the script variable.

4. Choose the type of the script variable and whether to set it as an array.

5. Specify the default value depending on the type.

6. Choose Done to close the panel.

You can now use the variable in scripting within this application or story.

Define a Script Variable's Value via URL Parameter


You can initialize the application or story based on your needs by simply making some changes to its URL. The value defined in the
URL parameter can be passed to the corresponding script variable.

Procedure
This is custom documentation. For more information, please visit SAP Help Portal. 14
2/9/25, 4:58 PM
1. Choose the script variable you want to define, and go to the Scipt Variable panel.

2. Select Expose variable via URL parameter.

 Note
This option isn't available for array type variables and non-primitive type variables (types other than string, boolean,
integer and number).

3. Save the application or story with the changes and choose Run Analytic Application or View.

4. In the URL of the analytic application or story, enter a new parameter that starts with ;p_ and is followed by the script
variable's name and value.

For example, if you want to set the value of ScriptVariable_1 to 3.14, add the following parameter to the original URL:

;p_ScriptVariable_1=3.14

5. Reopen your application or story URL.

Use a Script Variable


You can use a script variable in your script as a local variable. For example, you change the value by assigning a new one and use
this value by passing it as argument when calling a function.

If you write scripts in the application or story, you can insert the script variable you've created by selecting it from the value help in
the script editor. You can activate the value help at any place in the script by pressing CTRL + Space .

If you need to use the script variable in calculation, you can type @ in the formula in Calculation Editor to insert it. All the available
script variables will be automatically displayed in the dropdown list. Note that only global variables of string, integer and number
types can be referenced in the calculation editor, while the array type isn't supported.

 Note
When you use the script variable as the judging expression in an If statement and the expression returns a null value, the If
statement will also return a null result. For example, if you write a script like this and set the script variable to undefined in
runtime, the data returned and displayed in the chart isn't -100, but null.

if (ScriptVariable_1 = "xxx"; 100 ; -100)

You can also define script variables as the source of dynamic text in a text widget.

Change or Delete a Script Variable


To change an existing scripting variable, select it in the Outline panel. You can see the Scipt Variable panel open again where you
can also make the changes there.

To delete an existing scripting variable, choose beside the script variable in the Outline panel, and select Delete.

 Note
If the variable’s been used in a calculated measure, you need to modify the calculation first before deleting the variable.

Use Script Objects


This is custom documentation. For more information, please visit SAP Help Portal. 15
2/9/25, 4:58 PM
As an application designer or story developer, you can use script objects to encapsulate a set of functions that can be reused in
scripting.

About Script Objects


A script object is a non-visible part of an analytic application or optimized story, which groups a set of functions. You can use it
directly in event handlers. This keeps you from duplicating codes and makes maintenance of applications or stories easier.

Once you've added a script object, you can write scripts for it, which act as a script function. Each script function has the following
elements:

name

return type

arguments

You can access the script object in scripts by entering its name like other widgets. Inside the function of a script object you have
access to all objects in the application or story such as widgets, global variables and popups.

Create a Script Object and Script Function

Procedure

1. In the Scripting area of the Outline panel, (for analytic applications) choose right next to Script Objects, or (for
optimized stories) choose Script Objects .

The new script object is displayed under Script Objects, and a Script Function panel opens.

2. In the Properties section, configure the following settings for the script function:

Element Description

Name The name is mandatory and it validates according to the same


rules as for global variables. Name can't be empty or a reserved
keyword and should begin with a letter.

Description (optional) A brief description of the function.

Return Type Can be void, string, boolean, integer or number. By default, the
return type is void.

Besides the primitive types described above, you can also


select a wide variety of non-primitive types like Button,
Category, Chart, Clock, DataSource, Table, UrlType.

Set as Array Only activated if the return type is not void.

 Note
All modifications take effect immediately without your having to select Done, for example, after you press enter on an
input, change the dropdown selection or switch to an array.

3. In the Arguments section select to create a new argument for the function.

This is custom documentation. For more information, please visit SAP Help Portal. 16
2/9/25, 4:58 PM
4. In the Argument panel, edit name and type of the argument.

If the argument should represent a list of this type, set it to array.

5. Choose Done to close the Argument panel and return to Script Function.

6. Optional: You can reorder the arguments by dragging and dropping them inside the panel.

This changes the order of the arguments in the defined function.

7. In the Outline panel select (Edit Scripts) right next to the script object to write scripts for the new script function.

Results
You've created a script object. You can use it in any widget event handler.

You can add multiple script functions to the script object by selecting Add Script Function next to it in the Outline
panel.

Example
The following example displays the elements of the script function computeAverage.

name: computeAverage

return type: number

arguments: value1, value2 and value3 (all number type)

scripts: return (value1 + value2 + value3) / 3.0;

Modify And Delete Script Objects and Script Functions


To change the name, description, arguments and return type of a script function, select it in the Scripting area of the Outline
panel. The panel opens where you can directly update your changes. After you've changed the elements, select Done to close the
panel.

To edit an argument, in the Arguments section of the Script Function panel, select (Edit) when hovering over it. To remove an
argument, select (Remove) next to it.

To delete a script object or script function, select next to it and then Delete.

Create Pattern-Based Functions


As an application designer or story developer, you can use pattern-based functions in analytic applications or optimized stories to
facilitate your work by only providing input and output examples instead of writing scripts.

Context
With pattern-based functions you can define how a certain input shall become a certain output. For example,
[email protected] shall become John Doe.

After creating a script object, you can add a pattern-based function to it by providing such input and output training examples.

This is custom documentation. For more information, please visit SAP Help Portal. 17
2/9/25, 4:58 PM

Procedure

1. In the Outline panel select next to a scripting object and then Add Pattern-Based Function.

You can see that the Pattern-Based Function panel opens and a new function is displayed under the script object in
Outline.

2. You can change the name of the pattern-based function and add description.

3. Select next to Create Pattern.

4. Under Training Example you can provide an input-to-output example.

 Note
Sometimes one training example might not be enough due to potential ambiguity. In this case you can use up to three.
You may find the example below.

5. Select Create so that a machine learning algorithm starts looking for a pattern that matches every example.

 Note
If you want to undo your changes on a training example, select Reset, which will set the pattern-based function to the
last working pattern with the according training examples.

6. Verify the pattern by entering test examples. Select next to Verify Pattern, and enter an input. In the output field you
should see the right output that follows the pattern defined.

7. After the pattern-based function's been successfully created, select Done.

You can use it in every script of the application or story just like any other script object functions:

Example: Transform Dates

Assume you have a list of dates in the form of month.day.year, for example, 10.11.2011, and you want to switch day and month and
only take the last two digits of the year. You type 10.11.2011 as input and 11.10.11 as output in the Training Example section.

However, the example is a bit ambigous as it is not clear whether 11 at the end means month or year. You need to provide a second
training example like 09.05.2020 as input and 05.09.20 as output.

If you have a list of appointments, for example, John Doe has an appointment on 06.07.20 at 3:00pm. and you'd like to transform
this into Name: John Doe, Date: 06.07.20, Time: 3:00pm, you can directly type them as input and output respectively.

Related Information

This is custom documentation. For more information, please visit SAP Help Portal. 18
2/9/25, 4:58 PM
Use Script Objects

Optimize Type Libraries


Since SAP Analytics Cloud, analytics designer version 2020.2, only types available in the standard library are suggested when you
create a new analytic application and call the value help in the script editor. For applications created prior to this version, you can
manually start the optimization.

Context

Once you've added a widget or a technical object to your application, the associated type library is displayed. If you remove the last
widget or technical object associated with a type library, the library is also removed and no longer displayed in the value help. Prior
to version 2020.2, all type libraries were displayed, which could affect your scripting experience and runtime performance.

Procedure
1. Open your application in design time.

2. From the toolbar choose (Edit Analytic Application) Optimize Type Libraries .

You can see a dialog Optimize Script Libraries informing you of the optimization effects.

3. Choose Optimize.

The type libraries will be cleaned up immediately. All the scripts will immediately be checked and any errors will be shown in
the info panel.

 Note
If you've already used some type libraries that aren't directly related to objects used in the application, for example,
you've used feed enum values in your application that contains no charts, this could lead to scripting errors. Please
check the error list after the optimization and update your scripts accordingly.

4. To finish the optimization process, save the application.

 Note
If you don't save the application, it will behave as before.

For further information about various type libraries, see Analytics Designer API Reference.

Work with Automatic Refactoring


As an application designer or story developer, if you want to rename an item in your analytic application or story, automatic
refactoring works, which reduces your efforts to manually adjust its references.

About Automatic Refactoring


In analytic applications or stories, you can enter names for widgets and other items to ease the handling efforts at design time. For
example, you can use the names repeatedly in scripting.

If you later want to rename some items, various references to it have to be adjusted, mainly scripts, dynamic texts and calculated
measures. Previously, you had to do this work manually, which is a tedious job, especially for large and complex applications or
stories.

This is custom documentation. For more information, please visit SAP Help Portal. 19
2/9/25, 4:58 PM
Automatic refactoring makes this process as simple as possible. Ideally, you don't need to do anything. Renaming just works,
keeping the application or story intact.

However, there are cases where renaming could result in scripting errors. In such cases you'll be informed of any issues, and you
can decide whether to cancel renaming or continue.

When you rename an item in either Outline or the Styling panel, these things will happen:

All the related scripts will be adjusted automatically if there's no error or overlapping name.

 Note
If the script declares a local variable with the same name as that specified during renaming, the local variable will be
automatically renamed in the pattern <oldName>_$.

For example, the script declares var OkButton = Button_1;, and now you rename Button_1 to OkButton. Then
the script will be changed to var OkButton_$ = OkButton;

If the renamed item is a script variable, two additional refactorings will be done automatically:

All the dynamic texts referencing it will use the new name.

All the calculations referencing it, which in this case have to be number or integer type, will use the new name.

Special Cases

In the following special cases, you have to interact with the system:

If the renamed item is a script variable that is exposed via URL parameter, a confirmation dialog will pop up saying that this
might break the application or story link with the variable parameter.

If the renamed item is found in scripts with errors, a confirmation dialog will pop up saying that these scripts will be skipped
and that you have to manually adjust them.

If the renamed item is found in a script that has parameter in conflict with the new name, a confirmation dialog will pop up
saying that the script will be skipped and that you have to manually adjust it.

 Example
The onPostMessageReceived event has two parameters, message and origin. If the item used in your script is
now renamed to message, this conflict can't be resolved. This also applies when the new name conflicts with a script
function argument name.

If scripts use built-in objects, such as console, ArrayUtils and MemberDisplayMode, which conflicts with the new
name, a confirmation dialog will pop up saying that the scripts will be skipped and that you have to manually adjust them.

 Note
In this case the scripts do not need to contain references to the renamed item.

In such cases, you can either continue, or cancel the refactoring and reconsider the new name, for example.

Debug Your Scripts

This is custom documentation. For more information, please visit SAP Help Portal. 20
2/9/25, 4:58 PM
As an application designer or story developer, to find errors in your scripts, you can use the web browser’s developer tools to set
breakpoints for debugging or use the debug mode in your analytic application or story.

Find Your Scripts in Web Browser's Development Tools


Before you start debugging your scripts, learn how to find and view them in the developer tools of the web browser, Google
Chrome.

After you run the analytic application or story, open the web browser's developer tools. You need to run the scripts at least once
during the current session so that you can find them there.

 Note
Before your scripts get executed at runtime, SAP Analytics Cloud transforms them. This is why the JavaScript in the web
browser's developer tools doesn't look exactly the same as the scripts you wrote in the script editor during design time.

Then to search for scripts by name, press Ctrl + P to open the search field, and enter the name.

The names of the scripts follow a specific pattern: <WIDGET_NAME>.<FUNCTION_NAME>.js. The scripts are grouped in a folder
named <APPLICATION_NAME>.

Component of Script Name Description

APPLICATION_NAME The name that you set for your application or story when you saved
it
If you defined scripts for the onInitialization event, the
WIDGET_NAME will be Application.

WIDGET_NAME The name of the widget or element in your application or story

FUNCTION_NAME The name of the function or event handler that holds the script you
wrote

 Note
Special characters in your application or story name will be replaced by _, except - and ., which will be kept as they are.

 Example
Let's assume you have an application called My Demo Application, which contains a button Button_1 with an onClick event
handler.

The name of the script would be Button_1.onClick.js and it would be located in a folder called My_Demo_Application
.

This is custom documentation. For more information, please visit SAP Help Portal. 21
2/9/25, 4:58 PM

You can also find scripts by using the file tree on the left of the developer tools. Select the Sources tab. On the top level of the file
tree, search for the entry that starts with sandbox.worker.main. Under AnalyticApplication, you'll find the folder with your
application or story's name where there're all the scripts that you've already executed in the current application or story.

Set Breakpoints in Your Scripts


You can set breakpoints at certain points in your scripts to pause and check any errors.

Open the scripts you want to pause during its execution, and to the left select the number of the line where you want to pause.

A blue marker indicates that the scripts will be paused here the next time they're executed.

This is custom documentation. For more information, please visit SAP Help Portal. 22
2/9/25, 4:58 PM

You can add more breakpoints in the same scripts to pause at different points during runtime.

To reset a breakpoint, just select the marker you want to remove, and the scripts won't be stopped at this point.

Use SAP Analytics Cloud Debug Mode


You can launch the SAP Analytics Cloud debug mode and use debugger; statements in your scripts, so that your scripts can
automatically pause at multiple points during runtime for you to detect any errors.

Instead of setting breakpoints at runtime, at design time you can add the debugger; statements to your scripts.

Then, to launch the debug mode, at runtime add parameter debug=true to the URL.

The runtime URL with debug mode enabled looks like this:

This is custom documentation. For more information, please visit SAP Help Portal. 23
2/9/25, 4:58 PM

https://<TENANT>/sap/fpa/ui/tenants/<TENANT_ID>/bo/application/<APPLICATION_ID>/?mode=present&debug

 Note
If the debug parameter receives a different value from true or no value at all, it's ignored and the debug mode isn't enabled.

When you run your analytic application or story in debug mode, the script will automatically stop its execution at the debugger;
statements.

In debug mode, your script comments are generated into the transformed JavaScript. This helps you recognize your scripts in the
web browser's developer tools.

 Note
The names of the scripts are generated differently in debug mode. All script names receive the suffix -dbg, for example,
Button_1.onClick-dbg.js.

Check Errors in Scripting


As an application designer or story developer, you can open the errors panel to view all the errors and warnings in your analytic
application or optimized story and quickly locate them in your scripts.

Procedure
1. Under Views in the toolbar, choose Show/Hide Info Panel.

The Errors panel is displayed.

 Note
The number displayed by the button only indicates the number of errors, but not warnings. All the errors in the
application or story are counted even if you set filters on them in the panel later.

2. Find the error or warning you want to fix.

To filter the errors and warnings, you can enter the name of the corresponding widget in the box.

This is custom documentation. For more information, please visit SAP Help Portal. 24
2/9/25, 4:58 PM
To display only errors or warnings, choose to the upper right corner of the panel, and select the corresponding
options.

To expand or collapse all the displayed items, choose to the upper right corner of the panel, and select Expand
All or Collapse All.

3. Select any error or warning for details and further actions.

You can see the corresponding script with the error highlighted.

4. Once an error or warning is fixed, it will no longer be displayed in the panel. After fixing all, choose Show/Hide Info Panel
again from the toolbar or in the panel to close the Errors panel.

Check References in Scripting


As an application designer or story developer, you can open the reference list to quickly check out where and how an element, such
as a widget, script variable, function or technical object is used in scripting.

Context
In the reference list of an element, you can find all the related elements referencing it. This is especially helpful when you want to
better build or understand the business logic of the analytic application or optimized story or want to change or delete a specific
element in a complex application or story.

Procedure
1. In Outline, hover over the element that you want to check, for example, Button_1.

You can see (More) is displayed right next to its name.

2. Choose Find Reference .

The Reference List panel opens.

3. You can find a list of referencing elements, corresponding events and exact line in scripting to do further actions.

 Tip
You can select any of the referencing elements in the panel to locate it in both application or story and Outline. You can
also select any script to directly open the script editor and locate the referenced element in scripting.

To expand or collapse all the referencing elements, choose in the upper right corner of the panel and select Expand
All or Collapse All.

This is custom documentation. For more information, please visit SAP Help Portal. 25
2/9/25, 4:58 PM
4. After finishing checking the reference list, choose or Show/Hide Info Panel under Views in the toolbar to close the
panel.

Create Buttons
As an application designer in SAP Analytics Cloud, analytics designer or story developer in Optimized Story Experience, you can
add buttons and define their interactions with script APIs.

Procedure
1. To add a button, from the Insert menu of the toolbar, select Button.

The button is added to your story or analytic application, with the default ID Button_1 displayed in the Outline panel. You
can change the ID here or in the Styling panel.

2. In the Styling panel of the button, enter the text displayed on it.

3. Optional: Enter the tooltip text, which appears when viewers hover over the button.

4. Optional: Under Type of the Button Style section, you can select the following predefined style for the button: Standard
Button (default), Lite Button, Emphasized Button, Positive (Accept) Button, or Negative (Reject) Button.

The styles have predefined border and background colors for different states including Default, Mouse Hover and Mouse
Down. For Standard Button you can customize the colors.

5. Optional: When the Show Icon switch is on, you can add an icon to the button:

a. Under Upload Icon, select  .

b. Select an image from your device.

c. Under Icon Position, choose either to place the icon to the left or right of the text.

The size of the uploaded icon is automatically adjusted to that of the button. Both the icon and text are center aligned.

6. Define interactions with the button. Hover over the button ID in Outline, and select  (Edit Scripts) onClick , for
example. In the script editor, write script that is run when viewers click the button.

In addition, the following script APIs are supported for buttons:

setText and getText, which set and get the text on the button respectively.

setTooltip and getTooltip, which set and get the tooltip text of the button respectively.

(Optimized Story Experience) setEnabled and isEnabled, which can disable the button and check whether it's
enabled respectively. When a button is disabled, it's grayed and not clickable.

 Example
As a story developer, you can add a button with scripts so that viewers can switch between chart and table views by
clicking it. For details, follow Interactive Tutorial: Creating an Advanced Story in Optimized Story Experience.

Create Input Fields or Text Areas


You can add input fields or text areas to your analytic applications or optimized stories so that viewers can enter values and
perform actions based on them.

Context

Viewers can enter text in both input fields and text areas. The difference between the two widgets is that input fields can only
display contents in a line, while text areas can automatically wrap texts according to its size. Text areas can hold 1000 characters

This is custom documentation. For more information, please visit SAP Help Portal. 26
2/9/25, 4:58 PM
at maximum in multiple lines.

Procedure

1. From the Insert area of the toolbar, select Input Field or Text Area to add the widget to the canvas,
popup or page.

2. In the Styling panel of the input field or text area, enter a name. By default it's InputField_1 or TextArea_1.

3. In the Input Field Value or Text Area Value section of the Builder panel, select the source of the input field value from the
dropdown of Data Source Type:

Manual Input

Under Display Hint, you can enter hint texts to be initially displayed in the input field. If you disable this option, no
hint will be displayed either in edit or view time. After this option is enabled, when viewers start to enter a value in
the input field at runtime, the hint texts will be overwritten by the users' inputs.

Script Variables

Model Variables

Tile Filters & Variables

Analytic Application/Story Properties

4. (optional) You can turn on Enable the write-back in runtime and select a script variable in your application or story if you
want the input field value to be passed to the variable in view time.

5. You can further leverage the following APIs to allow for more functionalities in the input field or text area:

To get and set the value in the input field or text area, use getValue() and setValue() respectively.

To tell whether the input field or text area is enabled and enable it, use isEnabled() and setEnabled()
respectively.

To tell whether the input field or text area is editable and make it editable, use isEditable() and
setEditable() respectively.

 Note
The input field is grayed out in view time when disabled, but not when uneditable.

To start the actions after the input, for example, when users enter the text and press Enter , use onChange().

For more information about APIs, you can refer to API Reference.

Configure Sliders or Range Sliders


As an application designer or story developer in SAP Analytics Cloud, you can configure sliders or range sliders so that viewers can
input and change values dynamically and initiate what-if scenarios based on the value.

Context
The difference between a slider and range slider is that a slider defines a single value while a range slider defines a specific range of
data.

Procedure

This is custom documentation. For more information, please visit SAP Help Portal. 27
2/9/25, 4:58 PM
1. To add a slider or range slider, from the toolbar select and then Slider or Range Slider.

You can see that the widget is added to your application or story with the default name Slider_1 or RangeSlider_1 displayed
in Outline. You can change the name there or in the Styling panel.

2. In the Builder panel, set minimum and maximum for the slider or range slider. Then:

For a slider, enter the default value under Current Value.

For a range slider, enter the default start and end values.

These values should be between maximum and minimum.

3. (Optional) Furthermore, you can select the following properties:

Display Min & Max Value Labels to display the minimum and maximum of the slider or range slider.

Display Current Value Labels to display the selected value of the slider or selected range of a range slider.

Enable Value Input to let viewers directly enter the value instead of sliding the bar.

Enable Step Selection to increase or decrease the value by a fixed number each step. Then for Step Size, enter a
positive value.

 Note
The differences among current value, maximum, minimum, end value, and start value should all be divisible by
the step value.

4. (Optional) In the Styling panel, you can define the styling properties such as color of the progress bar and background bar
(the remaining part other than the progress bar), and scale, scale format and decimal places of all the numbers on the
widget.

5. You can use the following APIs to let viewers interact with the slider or range slider:

 Code Syntax
// Get/set the value of a slider
getValue(): number
setValue(value: number): void

// Get/set the range of a range slider


getRange(): Range
setRange(range: Range): void

// Get/set the minimum value of a slider/range slider


getMinValue(): number
setMinValue(value: number): void

// Get/set the maximum value of a slider/range slider


getMaxValue(): number
setMaxValue(value: number): void

// Get/set the visibility of a slider/range slider


setVisible(value: boolean): void
isVisible(): boolean

// Event initiated when an end user finishes the interaction and releases the handler of th
onChange()

//Let end users create a range with a predefined start and end value.
Range.create(start: number, end: number): Range

Bind Widgets’ Values to Variables

This is custom documentation. For more information, please visit SAP Help Portal. 28
2/9/25, 4:58 PM
As an application designer or story developer, you can bind some simple widgets' values to variables like script variables, model
variables, tile variables (widget-level variables) and analytic application or story properties so that the values can be updated
automatically. The other way around, by binding you can enable writing the value set for a simple widget in view time back to a
certain variable and applying the variable wherever needed.

The simple widgets and corresponding variable types available for binding are:

list box, dropdown, checkbox group and radio button group

Their ID and display text can be bound to script variables, model variables or tile variables.

input field and text area

Their display text can be bound to script variables, model variables, tile variables or analytic application or story properties.

When the variable is an array, the values displayed will be separated by commas.

slider and range slider

Slider’s current value and range slider’s start and end values can be bound to script variables, model variables or tile
variables. The variables must be single values of the number type.

image

It can be bound to a script variable. The variable must be single value of the string type.

Image only supports such binding when dynamically setting image URL is enabled.

 Tip
The analytic application or story properties include current user, time or date, last modified date or date/time, last modifier
and creator.

 Tip
In general, if not specified, the variables available for binding are primitive type variables (string, boolean, integer or number)
and can be array or single value.

 Note
Push, pop or index of array in scripting won’t be reflected in the bound widget.

 Note
Align the type of widget’s value with the write-back script variable.

Example 1: Synchronize a Slider’s Current Value with a Chart’s Variable


Say you want to synchronize Slider_1’s current value with a script variable used in Chart_1, Variable_1.

1. Go to the Builder panel of Slider_1.

2. Under Data Source Type, select Script Variables from the dropdown list.

3. Under Current Value, select Variable_1 from the dropdown list.

4. Save the analytic application or story.

In view time, select (Edit Chart Prompts) in Chart_1 and adjust the value of Variable_1.

This is custom documentation. For more information, please visit SAP Help Portal. 29
2/9/25, 4:58 PM
Slider_1's value will be changed accordingly.

Example 2: Use a Slider’s Current Value as the Threshold of a Chart’s Conditional


Formatting
Say you want to use Slider_1’s current value that end users select in runtime as the threshold of Chart_1’s conditional formatting.

1. Create a number type variable Variable_2.

2. Go to the Builder panel of Slider_1.

3. In Slider Properties, turn on Enable the write-back in runtime.

4. Under Write current value back to the variable, select Variable_2 from the dropdown list.

5. Go to the Builder panel of Chart_1.

6. Select (Threshold Options) beside the measure you want to apply conditional formatting to and then Edit Ranges….

7. Configure the threshold. Under Comparison Measure, select Variable_2.

Current value of the slider is automatically written back to the variable applied to the chart’s conditional formatting. The threshold
of Chart_1 will always take the current value of Slider_1.

 Caution
If end user changes such a widget’s value directly or via API at runtime while you’ve defined a variable bound to this widget’s
value at design time, the variable binding will become invalid.

Related Information
Use Script Variables

Configure Bookmark Settings and Use Related APIs (Optimized


Story Experience)
As a story developer, you can configure settings and use related APIs for viewers to bookmark the state of the story.

Procedure
1. From View section in the toolbar, select Left Side Panel to open Outline.

2. Select Bookmarks.

The Bookmarks side panel opens, where you can configure settings for viewers to bookmark the state of the story.
Bookmarks is also the name of the bookmark technical object, which can be reused in scripting.

3. Enter a version number, which must be an integer.

This option is also available to story designers.

 Note
If you change the version, all the bookmarks created based on the previous version become invalid. To reopen the invalid
bookmarks, you need to change the version number back to the previous one.

This is custom documentation. For more information, please visit SAP Help Portal. 30
2/9/25, 4:58 PM
4. Select the components of bookmarks:

State-Changed Components Only: Bookmarks only include the widgets, technical objects, and script variables
whose states have been changed, such as the display of data, width and height and variable values.

All Components in the Story: All the widgets, technical objects, and script variables in the story are bookmarked,
whether their states have been changed or not.

Selected Components Only: Only the selected widgets, technical objects, script variables, pages, popups, story
filters, calculations, and so on are bookmarked.

In the Select Components dialog, you can select what to include in bookmarks:

5. Select Done.

6. In addition, you can use related APIs to let story viewers save a bookmark and its properties by clicking a button, for
example:

 Code Syntax
// Save bookmark contents with information such as name and properties in key-value pair
saveBookmark(BookmarkSaveInfo: BookmarkSaveInfo, overwrite?: boolean): BookmarkInfo

//BookmarkSaveInfo contains "name"(mandatory), "isGlobal", "isDefault", "properties", "isKe


//BookmarkInfo contains "id", "name", "displayName", "version", "isGlobal", "isDefault", an

 Note
You can also set the default page bookmark using startPageId:<Page_ID>. Replace <Page_ID> with the ID of the
page and not the page Title.

However, if the first page has an onInitialization or onActive script and startPageId is set to another page,
the saveBookmark API won’t work.

This is custom documentation. For more information, please visit SAP Help Portal. 31
2/9/25, 4:58 PM

 Note
In addition to the API, you can define whether story viewers’ last changes to the dynamic variable values can be saved
with bookmarks via Story Details. For more information, see Set Story Details.

If viewers save a bookmark when you haven’t enabled the option, it might be opened with the last changed variable
values of the last opened bookmark after you later set isKeepLastDynamicVariableValue? to true or selected
Override default settings and Keep last saved values for dynamic variables.

You can also leverage the following APIs to let viewers apply, list, delete bookmarks or open the bookmark sharing dialog in
the story:

 Code Syntax
apply(bookmark: string | BookmarkInfo): boolean // Apply bookmark to the current story.
getAll(): BookmarkInfo[] // Return all valid bookmarks of current story.
getAppliedBookmark(): BookmarkInfo // Return the bookmark which is applied to current stor
getVersion(): integer // Return current bookmark version of story.
deleteBookmark(bookmark: string | BookmarkInfo): boolean // Delete specified bookmark of s
openShareBookmarkDialog(bookmarkId : string) : void // Open the bookmark sharing dialog.

7. Save your story.

Example
Here are some script examples that show how to let story viewers save, list and delete bookmarks in view time.

 Example
In this example, you want to let viewers capture the state of the story and save it as a bookmark with property in a quicker way.

First, add an input field InputField_1 and a button Button_1 to the story.

Then, write the following script for Button_1:

 Sample Code

var bkName = InputField_1.getValue();


Bookmarks.saveBookmark({name: bkName, isGlobal: true, properties: {"modelId": “BestRunJuice”}},

Viewers can create a global bookmark with the name entered in the input field, and the existing bookmarks are overridden if the
name duplicates. An additional property modelID with BestRunJuice as value is saved with the bookmark as well.

 Example
In this example, you want to let story viewers remove any bookmarks of the story from the dropdown.

This is custom documentation. For more information, please visit SAP Help Portal. 32
2/9/25, 4:58 PM

First, add a dropdown Dropdown_1 and another button Button_2 to the story.

Then write the following script for the widgets:

For Dropdown_1:

 Sample Code

var bookmarks = Bookmarks.getAll();


Dropdown_1.removeAllItems();
for (var i=0; i < bookmarks.length;++i)
{
Dropdown_1.addItem(bookmarks[i].id, bookmarks[i].name);
}
if (bookmarks.length > 0)
{
Dropdown_1.getSelectedKey();
}

For Button_2:

 Sample Code

Bookmarks.deleteBookmark(Dropdown_1.getSelectedKey());

When story viewers open the dropdown list, they can see and select any available bookmarks. Then, when clicking Remove
Bookmark, they can delete the bookmarks selected from the dropdown.

Related Information
Bookmark and Share Story Views

Use Bookmark Set Technical Objects in Analytic Applications


As an application designer, you can use a bookmark set technical object to let application users save the state of your analytic
application as a bookmark at runtime.

Procedure

1. In the Scripting section of Outline, select right next to Bookmark Set.

The side panel Bookmark Set opens, with the default name of the bookmark BookmarkSet_1 displayed. You can change
the name if you want to.

This is custom documentation. For more information, please visit SAP Help Portal. 33
2/9/25, 4:58 PM
2. Enter a version number. The number must be an integer.

 Note
To generate a new version of the bookmark set at any time, change the version number. After that, all the bookmarks
created based on the previous version will become invalid. To reopen the invalid bookmarks, you need to change the
version number back to the previous one.

3. Select Included Components to choose the canvas, popups, widgets and technical objects to be included in bookmarks.

4. Select Done to finish configuring the bookmark set technical object.

5. To let application users save a bookmark including its properties when viewing the analytic application, you need to add a
widget such as a button and write script for it, using the syntax below:

 Code Syntax
// Save bookmark contents with information such as name and properties in key-value pair
saveBookmark(BookmarkSaveInfo: BookmarkSaveInfo, overwrite?: boolean): BookmarkInfo

//BookmarkSaveInfo contains "name"(mandatory), "isGlobal", "isDefault", "properties" and "i


//BookmarkInfo contains "id", "name", "displayName", "version", "isGlobal", "isDefault", an

 Note
You can define whether application users’ last changes to the dynamic variable values can be saved with bookmarks via
API or Analytic Application Details. If application user saves a bookmark when you haven’t enabled the option, it might
be opened with the last changed variable values of the last opened bookmark after you later set
isKeepLastDynamicVariableValue? to true or selected Override default settings and Keep last saved values
for dynamic variables.

You can also leverage the following APIs to let application users apply, list, delete bookmarks or open the bookmark sharing
dialog in the application:

 Code Syntax
apply(bookmark: string | BookmarkInfo): boolean // Apply bookmark to the current applicatio
getAll(): BookmarkInfo[] // Return all valid bookmarks of current application.
getAppliedBookmark(): BookmarkInfo // Return the bookmark which is applied to current appl
getVersion(): integer // Return current bookmark version of application.
deleteBookmark(bookmark: string | BookmarkInfo): boolean // Delete specified bookmark of a
openShareBookmarkDialog(bookmarkId : string) : void // Open the bookmark sharing dialog.

6. Save and run the analytic application.

Results
After creating a bookmark set technical object and writing the scripts for it, you can let application users change the states of the
widgets at will, save different states as bookmarks and view them at any time.

Example
Here are some script examples that show how to let application users save, list and delete bookmarks in runtime by leveraging
bookmark related APIs.

 Example
In this example, you want to design an application that lets application users capture the application state and save it as a
bookmark with property.

This is custom documentation. For more information, please visit SAP Help Portal. 34
2/9/25, 4:58 PM

First, in addition to the technical object BookmarkSet_1, add an input field InputField_1 and a button Button_1 to the canvas.

Then write the following script for Button_1:

 Sample Code

var bkName = InputField_1.getValue();


BookmarkSet_1.saveBookmark({name: bkName, isGlobal: true, properties: {"modelId": “BestRunJuice”

Via this script, you can create a global bookmark with the name entered in the input field, and the existing bookmarks will be
overridden if the name duplicates. It also allows you to add an additional property modelID with BestRunJuice as value.

 Example
In this example, you want to let application users remove any bookmarks in the application that are all listed in the dropdown.

First, in addition to the technical object BookmarkSet_1, add a dropdown Dropdown_1 and another button Button_2 to the
canvas.

Then write the following script for the widgets:

For Dropdown_1:

 Sample Code

var bookmarks = BookmarkSet_1.getAll();


Dropdown_1.removeAllItems();
for (var i=0; i < bookmarks.length;++i)
{
Dropdown_1.addItem(bookmarks[i].id, bookmarks[i].name);
}
if (bookmarks.length > 0)
{
Dropdown_1.getSelectedKey();
}

For Button_2:

This is custom documentation. For more information, please visit SAP Help Portal. 35
2/9/25, 4:58 PM

 Sample Code

BookmarkSet_1.deleteBookmark(Dropdown_1.getSelectedKey());

When application users open the dropdown list, they can see all the available bookmarks. Then, when selecting Remove
Bookmark, they can delete the bookmarks selected from the dropdown.

Related Information
Bookmark Analytic Applications

Use a Calendar Integration Technical Object and Related APIs


As an application designer or story developer, you can add a calendar integration technical object and use related APIs to read,
create, update and perform status change of a calendar event.

Add a Calendar Integration Technical Object


To add a calendar integration technical object, in the Scripting section of the Outline panel, (for analytic applications) choose
right next to Calendar Integration, or (for optimized stories) choose Calendar Integration .

A side panel opens where you can set the ID of the technical object and choose whether the calendar toolbar is visible in view time.

Then, you can use the following APIs for the calendar integration technical object:

getCalendarEventById

getRelatedEventIds

getCurrentEvent

createCompositeTask

createProcess

Depending on the calendar role, additional APIs such as submit, decline, approve and reject, can be used for the following
task types:

General task

Composite task

Review task

To use these APIs, you first have to convert a calendar task to the target one using the cast API.

 Sample Code

var reviewTask = cast(Type.CalendarReviewTask, calendarTask);

Use getCalendarEventById API


This is custom documentation. For more information, please visit SAP Help Portal. 36
2/9/25, 4:58 PM
If you want to retrieve information about a specific event, you can use the getCalendarEventById API. Simply pass the
eventId from the query string in the URL. The analytic application or story doesn't need to be opened from the calendar event.

 Sample Code
The following code logs the result of the getType API to the browser console for any task:

var task = CalendarIntegration_1.getCalendarEventById("taskId");


if (task.getType() === CalendarTaskType.CompositeTask) {
console.log("This is a composite task");
} else if (task.getType() === CalendarTaskType.GeneralTask) {
console.log("This is a general task");
} else if (task.getType() === CalendarTaskType.ReviewTask) {
console.log("This is a review task");
}

Use getRelatedEventIds API


You can use the getRelatedEventIds API to retrieve all the calendar event IDs for which the opened application or story is a
working file. The API returns either an array of event IDs, or if no events are found, an empty array.

 Note
Recurring composite events are currently not delivered as part of the result.

 Sample Code
With this sample code snippet, you can retrieve all the events for which the opened analytic application or story is a working file

var allTasks = CalendarIntegration_1.getRelatedEventIds();


console.log(allTasks);

Use getCurrentEvent API

You can use the getCurrentEvent API to inquire the calendar event that is loaded with your analytic application or story.

This is necessary because a user can't perform operations on a calendar, like submit and decline or approve and reject, if an
analytic application or story isn't associated with a calendar through a working file.

 Sample Code

var calendarTask = CalendarIntegration_1.getCurrentEvent();


console.log(calendarTask);

Use createCompositeTask API

 Caution
The createCompositeTask API will be deprecated in the future with composite tasks. We recommend using the
createProcess API to create a calendar process with similar properties.

You can use the createCompositeTask API to create a composite task with properties and options.

This is custom documentation. For more information, please visit SAP Help Portal. 37
2/9/25, 4:58 PM
When creating a composite task, you can choose a name, startDate and endDate, which are the mandatory properties. You can
choose between an analytic application or a story when specifying the work file.

 Sample Code
With this sample code snippet, you can create a composite task that starts now and ends on January, 16th 2022. There's one
work file belonging to this composite task, the current opened application or story. One assignee is defined, the current logged
in user. Additionally, a reviewer is specified, in one review round. The option autoActivate represents the Activate the task
at start date automatically option.

var newTask = CalendarIntegration_1.createCompositeTask({


name: "newCompositeTask",
startDate:new Date(Date.now()),
endDate: new Date(2022, 0, 16, 0, 0, 0),
workFiles: [{
id: Application.getInfo().id,
type: CalendarTaskWorkFileType.AnalyticApplication,
}],
assignees: [Application.getUserInfo().id],
description: "Calendar Composite Task description",
reviewers: {
"1": ["reviewerId"],
}
}, {
autoActivate: true
});

Use APIs to Create Processes

Use createProcess API

You can use the createProcess API to create a calendar process with properties. Note that reviewer related properties aren't
available.

 Code Syntax
CalendarIntegration.createProcess(properties: CalendarProcessCreateProperties, options?: Calenda

Use createProcessFromTemplate API

In addition, you can use the createProcessFromTemplate API to create a calendar process from an existing template in the
file repository.

 Code Syntax
With the API, you can pass a template ID and start date to create a process based on the template. You can get the template ID
from the success message when creating the template, or from  Notifications. If end date isn't set, the process has the same
length as the template.

CalendarIntegration.createProcessFromTemplate(templateId: string, properties: CalendarProcessFro


CalendarProcessFromTemplateCreateProperties {
startDate: Date;
endDate?: Date;
parentId?: string;
dependencies?: Dependencies;
useTypeBasedNames?: boolean // false = from template (default), true = from event types
prefix?: string;

This is custom documentation. For more information, please visit SAP Help Portal. 38
2/9/25, 4:58 PM
suffix?: string;
}

Use APIs to Read Calendar Events

You can use APIs to get properties of a calendar event, such as its status, task type, child events, dependencies, owners, context
filters and reminders.

Use getStatus API

You can get the overall status of a calendar event by using the getStatus API.

 Sample Code
var status = CalendarIntegration_1.getCurrentEvent().getStatus();
switch (status) {
case CalendarTaskStatus.InProgress:
console.log("In Progress");
break;
case CalendarTaskStatus.Canceled:
console.log("Canceled");
break;
case CalendarTaskStatus.OnHold:
console.log("OnHold");
break;
case CalendarTaskStatus.Open:
console.log("Open");
break;
}

The code snippet returns the task status from the calendar task:

Use getType API

You can get the task type of a calendar task by using the getType API. The API returns the type of task that is created in the
calendar (general, composite, review task, or process).

 Sample Code
var calendarTaskType = CalendarIntegration_1.getCurrentEvent().getType();
console.log(calendarTaskType);

Use hasUserRole API

You can inquire the calendar user role of the currently loaded calendar task by using the hasUserRole API. The API accepts the
following roles:

This is custom documentation. For more information, please visit SAP Help Portal. 39
2/9/25, 4:58 PM
CalendarTaskUserRoleType.Reviewer

CalendarTaskUserRoleType.Owner

CalendarTaskUserRoleType.Assignee

The API returns true if the current logged in user has the specified user role given as parameter, and false otherwise.

 Sample Code
var calendarTask = CalendarIntegration_1.getCurrentEvent();
var isReviewer = calendarTask.hasUserRole(CalendarTaskUserRoleType.Reviewer);
console.log(isReviewer);

For more APIs, refer to Analytics Designer API Reference (for analytic applications) or Optimized Story Experience API Reference
(for optimized stories). Search for the component CalendarEvent.

Use APIs to Update Calendar Events


You can use APIs to update a calendar event, such as its start and end date, progress, owner, assignee, reminder, and context
filters.

Use addAssignee API

 Sample Code
With the following code snippet, you can add a user and a team as the assignees of the current event.

var calendarEvent = CalendarIntegration_1.getCurrentEvent();


calendarEvent.addAssignee(“JOHN”);
calendarEvent.addAssignee(“TEAM:Team1”);

Similarly, the APIs removeAssignee, addOwner, removeOwner, addReviewer, and removeReviewer are also available.

 Tip
You can directly use team ID in the APIs to add or remove a team as the assignee, owner, or reviewer.

Use setName API

 Sample Code
With the following code snippet, you can give the current event a new name.

var calendarEvent = CalendarIntegration_1.getCurrentEvent();


calendarEvent.setName("New Name");

Use setDependencies API

 Sample Code
With the following code snippet, you can make the current event start once the predecessor event becomes successful.

var calendarEvent = CalendarIntegration_1.getCurrentEvent();


var newDependencies = cast(Type.CalendarDependencies, {dependentOnIds: ["idOfPredecessorEvent"],

This is custom documentation. For more information, please visit SAP Help Portal. 40
2/9/25, 4:58 PM
calendarEvent.setDependencies(newDependencies);

Use addContextFilter API

 Sample Code
With the following code snippet, you can add a context filter based on an existing table to the current event.

var calendarEvent = CalendarIntegration_1.getCurrentEvent();


var dimension = Table_1.getDimensionsOnRows()[0];
var newContextFilter = cast(Type.CalendarContextFilter, {
members: [Table_1.getDataSource().getMembers(dimension)[0]],
hierarchy: Table_1.getDataSource().getHierarchy(dimension),
});
calendarEvent.addContextFilter(newContextFilter);

Use addReminder API

 Sample Code
With the following code snippet, you can add a reminder which occurs an hour before the start date of the current event.

var calendarEvent = CalendarIntegration_1.getCurrentEvent();


var reminder = cast(Type.CalendarReminder, {
measure: CalendarReminderMeasureType.Hour,
reference: CalendarReminderReferenceType.Start,
number: 1,
});
calendarEvent.addReminder(reminder);

For more APIs, refer to Analytics Designer API Reference (for analytic applications) or Optimized Story Experience API Reference
(for optimized stories). Search for the component CalendarEvent.

Use APIs to Change Calendar Event Status

You can use APIs to change the status of a calendar event, to activate, decline, submit, approve, reject or reopen an event.

Use activate API

Owners can activate a task and also specify the notify option via the activate() API. This API represents the Activate or
Activate and Notify option from the calendar view.

Use decline API

Assignees or reviewers can decline a composite task or general task via the decline API. The API returns true if successful,
false otherwise:

CalendarCompositeTask.decline()

CalendarGeneralTask.decline()

 Sample Code
To decline a composite task, you can use the following code snippet:

This is custom documentation. For more information, please visit SAP Help Portal. 41
2/9/25, 4:58 PM

var calendarTask = CalendarIntegration_1.getCurrentEvent();


var isAssignee = calendarTask.hasUserRole(CalendarTaskUserRoleType.Assignee);
var calendarTaskType = calendarTask.getType();
if (isAssignee && calendarTaskType === CalendarTaskType.CompositeTask) {
var compositeTask = cast(Type.CalendarCompositeTask, calendarTask);
var isSuccessfullyDeclined = compositeTask.decline();
if (isSuccessfullyDeclined) {
console.log("You have successfully declined your task.");
} else {
console.log("Sorry, something went wrong.");
}
}

Use submit API

Assignees can submit a calendar of type General Task or Composite Task via the submit API. The API returns true if successful,
false otherwise.

CalendarGeneralTask.submit()

CalendarCompositeTask.submit()

To submit a calendar task for a composite task, you can use the following code snippet:

 Sample Code

var calendarTask = CalendarIntegration_1.getCurrentEvent();


var isAssignee = calendarTask.hasUserRole(CalendarTaskUserRoleType.Assignee);
var calendarTaskStatus = calendarTask.getStatus();
var calendarTaskType = calendarTask.getType();
if (isAssignee && calendarTaskType === CalendarTaskType.CompositeTask && calendarTaskStatus ===
var compositeTask = cast(Type.CalendarCompositeTask, calendarTask);
var isSuccessfullySubmitted = compositeTask.submit();
if (isSuccessfullySubmitted) {
console.log("You have successfully submitted your task.");
} else {
console.log("Sorry, something went wrong.");
}
}

Use approve API

Reviewers can accept a composite task or a review task via the approve API. The assignee should have first submitted the task
before. The API returns true if successful and false otherwise:

CalendarCompositeTask.approve()

CalendarReviewTask.approve()

 Sample Code
To approve a calendar task for a review task, you can use the following code snippet:

var calendarTask = CalendarIntegration_1.getCurrentEvent();


var isReviewer = calendarTask.hasUserRole(CalendarTaskUserRoleType.Reviewer);
var calendarTaskType = calendarTask.getType();
if (isReviewer && calendarTaskType === CalendarTaskType.ReviewTask) {

This is custom documentation. For more information, please visit SAP Help Portal. 42
2/9/25, 4:58 PM
var reviewTask = cast(Type.CalendarReviewTask, calendarTask);
var isSuccessfullyApproved = reviewTask.approve();
if (isSuccessfullyApproved) {
console.log("You have successfully approved the task of the assignee.");
} else {
console.log("Sorry, something went wrong.");
}
}

Use reject API

Reviewers can reject a composite task or a review task for the assignee to have another look at it via the reject API. The assignee
should have first submitted the task before. The API returns true if successful and false otherwise.

CalendarCompositeTask.reject()

CalendarReviewTask.reject()

 Sample Code
To reject a composite task, you can use the following code snippet:

var calendarTask = CalendarIntegration_1.getCurrentEvent();


var compositeTask = cast(Type.CalendarCompositeTask, calendarTask);
var isSuccessfullyRejected = compositeTask.reject();
if (isSuccessfullyRejected) {
console.log("You have successfully rejected your task.");
} else {
console.log("Sorry, something went wrong.");
}

Use reopen API

Owners can reopen a calendar event via the reopen API.

 Code Syntax
reopen(includingChildren?: boolean): boolean

Use Status Change APIs for a Calendar Composite Task

You can use the submit, decline, approve or reject APIs for any composite task given a task ID.

 Sample Code
With this sample code snippet, you can submit any composite task given a task ID.

var task = CalendarIntegration_1.getCalendarEventById("taskId");


if (task.getType() === CalendarTaskType.CompositeTask) {
var compositeTask = cast (Type.CalendarCompositeTask, task);
compositeTask.submit();
}

Use Calendar Event Convenience APIs


You can use the calendar integration technical object together with the convenience APIs canUserDecline, canUserSumit,
canUserApprove, canUserReject and canUserReopen to check if you can perform a event status change.
This is custom documentation. For more information, please visit SAP Help Portal. 43
2/9/25, 4:58 PM
The APIs can be used depending on the calendar role and the following event types:

General task

Composite task

Review task

Process

 Note
To use these APIs, you first have to convert a technical object CalendarIntegration to the target event using the cast
API.

Use canUserDecline API

You can use the canUserDecline API for the user role assignee or reviewer on a composite or a general task to verify if the task
can be declined.

 Sample Code
The following code snippet verifies if the logged in user can decline the current opened task:

var task = CalendarIntegration_1.getCurrentEvent();

if (task.getType() === CalendarTaskType.CompositeTask) {


var compositeTask= cast (Type.CalendarCompositeTask, task);
console.log(compositeTask.canUserDecline());
} else if (task.getType() === CalendarTaskType.GeneralTask){
var generalTask = cast (Type.CalendarGeneralTask, task);
console.log(generalTask.canUserDecline());
}

Use canUserSubmit API

You can use the canUserSubmit API to verify if a calendar task is ready to be submitted for the assignee user role. If you use the
API when the task status is Open , the task status changes to In Progress.

 Sample Code
The following code snippet submits a task with the id "myTaskId" that is open:

var task = CalendarIntegration_1.getCalendarEventById("myTaskId");


var compositeTask = cast (Type.CalendarCompositeTask, task);
var canSubmit = compositeTask.canUserSubmit();
if (canSubmit) {
var submitSuccesfull = compositeTask.submit();
if (submitSuccesfull) {
console.log("Submitted");
} else {
console.log("Failed to submit, please try again.");
}
}

Use canUserApprove API

This is custom documentation. For more information, please visit SAP Help Portal. 44
2/9/25, 4:58 PM
You can use the canUserApprove API for the user role reviewer on a composite task, or for a user role assignee on a review task
to verify if the task can be approved.

 Sample Code
The following code snippet approves all the related tasks that can be approved, for the current logged in user, either for a review
or a composite task:

var allTasks = CalendarIntegration_1.getRelatedEventIds();

for (var i=0; i<allTasks.length;i++) {


var task = CalendarIntegration_1.getCalendarEventById(allTasks[i]);

if (task.getType() === CalendarTaskType.CompositeTask) {


var compositeTask = cast (Type.CalendarCompositeTask, task);
var canApprove = compositeTask.canUserApprove();
if (canApprove) {
console.log("Approving task with details" + task.getName() + "and with i
console.log(compositeTask.approve());
} else {
console.log("Cannot approve task with details" + task.getName() + "and w
}
} else if (task.getType() === CalendarTaskType.ReviewTask){
var reviewTask = cast (Type.CalendarReviewTask, task);
var canApproveReviewTask= reviewTask.canUserApprove();
if (canApproveReviewTask) {
console.log("Approving task with details" + task.getName() + "and with i
console.log(reviewTask.approve());
} else {
console.log("Cannot approve task with details" + task.getName() + "and w
}
}
}

Use canUserReject API

You can use the canUserReject API for the user role reviewer on a composite task or for the userrRole assignee on a review
task, to check if the task can be rejected.

 Sample Code
The following code snippet rejects all composite task for the current logged in user:

var allTasks = CalendarIntegration_1.getRelatedEventIds();

for (var i=0; i<allTasks.length;i++) {


var task = CalendarIntegration_1.getCalendarEventById(allTasks[i]);

if (task.getType() === CalendarTaskType.CompositeTask) {


var compositeTask = cast (Type.CalendarCompositeTask, task);
var canReject = compositeTask.canUserReject();
if (canReject) {
console.log("Rejecting task with details" + task.getName() + "and with i
console.log(compositeTask.reject());
} else {
console.log("Cannot reject task with details" + task.getName() + "and wi
}
}
}

Use canUserReopen API

You can use the canUserReopen API for the current user to check if the event can be reopened. The event can be reopened if it
has a final status and the user is the owner.
This is custom documentation. For more information, please visit SAP Help Portal. 45
2/9/25, 4:58 PM

 Code Syntax
canUserReopen(): boolean

Enable Data Change Insights and Use Related APIs


As an application or story designer, you can enable Data Change Insights for a story and its specific charts. As a developer, you can
use the related technical object and APIs to allow for more activities, such as saving a snapshot to capture any state of the analytic
application or optimized story for data comparison.

If you're a viewer, for more information about Data Change Insights, see Subscribe to and View Data Change Insights.

Enable Data Change Insights


To enable Data Change Insights for an analytic application, from File in the edit time toolbar, select (Edit Analytic
Application) Analytic Application Details .

Similarly, to enable Data Change Insights for an optimized story, from File in the edit time toolbar, select (Story Settings)
Story Details .

Then, to enable data change insights for an individual chart in the story, in its Styling panel select Data Change Insights under
Quick Menus. In view time Data Change Insights will then be available in the chart's context menu for viewers to select the
subscription mode.

 Note
To ensure that viewers receive notifications after subscription, you need to add an Export to PDF technical object.

Add a Data Change Insights Technical Object and Use Script APIs
You can add a Data Change Insights technical object and use related APIs to allow for more functionalities.

This is custom documentation. For more information, please visit SAP Help Portal. 46
2/9/25, 4:58 PM

Procedure
1. To add a Data Change Insights technical object, in the Scripting section of the Outline panel, (for analytic applications)
choose right next to Data Change Insights, or (for optimized stories) choose Data Change Insights .

The right side panel opens with a default name DataChangeInsights_1 displayed. You can change the name there.

2. Select a version type of the Data Change Insights technical object:

Auto Saved File Version (Default): The version of the Data Change Insights technical object uses the timestamp
when the application or story is saved.

Manually Defined Version: Enter an integer for the version of the Data Change Insights technical object.

If you change the version number or version type, the previous snapshots of applications or stories for data comparison
become invalid.

3. Select Done.

4. You can use APIs related to Data Change Insights to allow for more functionalities in view time.

 Code Syntax
Here're the APIs for snapshots of applications or stories for data comparison:

// Save a snapshot. One application or story can have only one snapshot per day, and the la
saveSnapshot(): Boolean

// Gets a date list which represents there is a snapshot of application or story saved at t
listRecentSnapshotDates(maximumNumber?: integer): Date[]

// Compares current application or story state with a previous snapshot.


compareApplicationStateWithSnapshot(target: Date, options?: DataChangeInsightsComparisonOpt
top?: Integer, // limit number of returned DataChangeInsight
}): DataChangeInsightsResult

// Compares snapshots of two different dates.


compareSnapshots(source: Date, target: Date, options?: DataChangeInsightsComparisonOptions
top?: Integer, // limit number of returned DataChangeInsight
}): DataChangeInsightsResult

//Returns the version of Data Change Insights technical object.


getVersion(): integer

// Returns whether the Data Change Insights snapshot task is running.


isRunBySnapshotGeneration(): Boolean

 Code Syntax
Here're the APIs for Data Change Insights subscription:

// Opens subscription dialog. Not supported on mobile.


openSubscriptionDialog();

//Sets the subscription level of chart.


setSubscriptionLevel(subscriptionLevel: DataChangeInsightsSubscriptionLevel): void
//Gets the subscription level chart.
getSubscriptionLevel(): DataChangeInsightsSubscriptionLevel

//Sets the value range for generating data change insights.


setSubscriptionRange(subscriptionRange: DataChangeInsightsSubscriptionRange JSON): void
//Gets the value range for generating data change insights.
getSubscriptionRange(): DataChangeInsightsSubscriptionRange

For more information about the APIs, see Analytics Designer API Reference or Optimized Story Experience API Reference.

This is custom documentation. For more information, please visit SAP Help Portal. 47
2/9/25, 4:58 PM

Configure Storage of Data Change Insights Snapshots


By default, data change insights snapshots are saved on the current SAP Analytics Cloud tenant. You can also save them in a
remote data repository by configuring the storage in the Data Change Insights Snapshots section in System Administration
Data Source Configuration .

 Note
To configure the storage of data change insights snapshots, you need to have the Create permission for the object type
Remote Repository Snapshot.

Choose a configured data repository.

 Restriction
Currently, saving data change insights snapshots isn't supported in remote data repositories based on XS Node.js.

Use an Export to PDF Technical Object


As an application designer or story developer, you can use an Export to PDF technical object and related APIs to let viewers export
an analytic application or story to a PDF file.

Context

Only visible contents can be exported to PDF. Therefore, the following invisible elements won't be exported:

Invisible part in scrollable charts, tables or containers including tab strips, panels, flow layout panels and page books

Popups that haven't been opened

Viewers can export popups that are opened via script API.

Collapsed table cells

Lazy rendered widgets

Lazy loaded data source

Comments on invisible data cells

Besides these invisible elements, web page widgets aren't exported.

 Note
For R visualizations, static plots are exported. However, R visualizations written in RHTML (iFrame) aren't fully supported, for
example, the ones with pictures from external sources.

 Note
Widgets might not keep all CSS styling settings when exported to PDF, for example, text decoration and opacity.

 Tip

This is custom documentation. For more information, please visit SAP Help Portal. 48
2/9/25, 4:58 PM
Custom widgets support PDF export now. However, to make sure that all the defined elements can be exported to PDF, custom
widget developers need to be aware of the export restrictions and test first and then set supportsExport to true in the
custom widget JSON file.

 Tip
If your image's hyperlink is an external URL, you can add a parameter to it to ensure that certified users can export this image
to PDF.

Parameter Options

imageCrossOrigin
useCertifications requires users’ credential to
Controls users’ access to the hyperlink of the image to be access the external URL linked to the image. When
exported to PDF. certified, users can export this image to PDF.

By default users are anonymous to the URL if you don’t add this anonymous means that certification won’t be passed
parameter. and users might not export the image to PDF if the
external server requires this process.

Procedure
1. In the Scripting section of the Outline, (for analytic applications) choose right next to Export to PDF, or (for
optimized stories) choose Export to PDF .

The side panel Export to PDF opens with a default name ExportToPDF_1.

2. In the side panel, select Included Widgets to choose the widgets you want to include in PDF export.

3. In addition, you can set the following properties according to your needs:

Name of the technical object

Exported file name

(Optimized Story Experience) Page range

Paper size: Auto, A2, A3, A4, A5, Letter or Legal

 Note
If you set the paper size to Auto for the Export to PDF technical object, exporting full contents on a table via API
uses A4 as the default.

Orientation: Landscape or Portrait

The Orientation option is disabled when the paper size is set to Auto.

(Analytics Designer) Location of page number: Header, Footer or None

Header

You can add text, date, and (Optimized Story Experience) page number to the header.

Footer

You can add text and (Optimized Story Experience) page number to the footer.

Appendix

This is custom documentation. For more information, please visit SAP Help Portal. 49
2/9/25, 4:58 PM
The appendix includes the list of filters applied to the application or story. It's exported as separate pages.

You can also add date to the appendix.

Whether to export the comments

Any page-level, widget-level, or data point comments are exported as separate pages. Comments on invisible
widgets won't be exported.

 Note
If you haven't enabled Commenting in embedded mode via System Administration System Configuration
, the commenting related settings and APIs won’t take effect.

Enable export in the background

Viewers can continue working while the file is being processed and saved. The response time is slower until the
export is complete.

 Restriction
This option isn't yet available in Optimized Story Experience.

Whether to fully display the exported widgets

All the contents on the selected tables are exported as a report.

(Optimized Story Experience) Batch Export

Select an existing filter to export the story based on each value in it one by one.

 Note
Currently, only dimension member filters are supported for batch export in Optimized Story Experience.

4. Select Done to finish creating the technical object.

5. Use exportView() API to export the analytic application or story to a PDF. For example, you can write the script for the
onClick() event of a button widget so that viewers can export via clicking the button.

 Note
The API that starts the export is supported only in Microsoft Edge and Google Chrome, but not in Internet Explorer.

 Restriction

When a table is exported to PDF via exportReport() or exportView() API, the in-cell texts won't be
exported if they exceed certain lengths, depending on the paper size of the export.

For exportReport() API:

The PDF exports don’t support Unicode (UCS-2 BE/UTF16 BE).

(Optimized Story Experience) The export won’t be generated if there’s no table in the whole story or
selected in the included widgets.

 Tip
In Optimized Story Experience, write scripts with exportView() at the end, so that multiple pages are exported in
view time without the interference of other running scripts.

This is custom documentation. For more information, please visit SAP Help Portal. 50
2/9/25, 4:58 PM
(Optimized Story Experience) You can use APIs setBatchExportEnabled and setDimensionFilter to enable and
set batch export. The setDimensionFilter API works only when batch export is enabled and selected dimension
members are included in the story filter. If the API is used more than once, batch export uses the last selected values as the
filter.

 Sample Code

ExportToPDF_1.setBatchExportEnabled(true);
ExportToPDF_1.getBatchExportDataSource("dataset1").setDimensionFilter("Product", "PC1");
ExportToPDF_1.exportView();

6. The properties you defined in the Export to PDF panel are the default export settings. To offer users the flexibility to
customize the export settings, you can design a new settings panel or dialog by leveraging related APIs. For detailed
information, refer to Analytics Designer API Reference (for analytic applications) or Optimized Story Experience API
Reference (for optimized stories).

Results
After creating an Export to PDF technical object, you can choose to manually generate PDF export via API in publication.
Compared to automatically generating PDF export, this option controls the timing of the PDF export more accurately and doesn't
miss any relevant scripting event happening after the completion of onInitialization event.

First, (for analytic applications) in the Styling panel of Canvas or (for optimized stories) from Global Settings in Outline, under
Schedule Publication Settings, select Manually generate PDF export via API.

Then, for the onInitialization event of Canvas or story page, write the following script as the last line:

If (Application.isRunBySchedulePublication()) {
Scheduling.publish();
}

Related Information
Export a Story as a PDF or a PPTX (Optimized Story Experience)

Use an Export to PowerPoint Technical Object (Optimized Story


Experience)
As a story developer, you can use the Export to PowerPoint technical object with script APIs to customize the view time export
experience.

Context

Only visible contents can be exported to PowerPoint. For more information, refer to Export a Story as a PDF or a PPTX (Classic
Story Experience).

Procedure
1. In the Scripting section of the Outline panel, select  Export to PowerPoint .

You've added the Export to PowerPoint technical object, whose default name is ExportToPPTX_1. You can change to
another name.

This is custom documentation. For more information, please visit SAP Help Portal. 51
2/9/25, 4:58 PM
2. Enter a name for the exported file. By default it takes the story name.

3. Specify the pages to include in the export, by default All. You can enter a range or page numbers.

4. Optional: Select Appendix to include an appendix with story filters and variables.

 Note
The story's URL is included in the appendix. If you don't want to include it, you need to enable Remove Story URL from
Appendix in the system configuration.

5. Optional: Select Batch Export and then an existing filter to export your story based on each filter value one by one.

 Note
Currently, only dimension member filters are supported for batch export in Optimized Story Experience.

You can further use APIs such as setBatchExportEnabled and setDimensionFilter to configure batch export
settings. Make sure that the selected dimension members in your scripts are included in the story filter.

6. Select Done to finish configuring the technical object.

7. Use APIs such as exportView() with the technical object to customize the view time export experience. For example, you
can write scripts for the onClick event of a button to let story viewers export the story to PowerPoint according to your
configuration.

For more information about the supported APIs, refer to Optimized Story Experience API Reference. Search for
ExportPptx there.

 Restriction
When a table is exported to PowerPoint via the API, the in-cell texts won't be exported if they exceed certain lengths,
depending on the paper size of the export.

 Tip
Write scripts with exportView() at the end, so that multiple pages are exported in view time without the interference
of other running scripts.

Related Information
Use an Export to PDF Technical Object
Export a Story as a PDF or a PPTX (Optimized Story Experience)

Use a Text Pool Technical Object for Script Translation (Optimized


Story Experience)
As a story developer, you can use a text pool technical object with related APIs to translate the texts in the scripts.

Prerequisites
To translate the texts used in the scripts, make sure to enable translation for the story. From the edit time toolbar, select  (Story
Settings) Story Details . Then, switch on Enable translation.

Context
In the following script example to apply Hello World to a text widget, the text is static and won't be translated:

This is custom documentation. For more information, please visit SAP Help Portal. 52
2/9/25, 4:58 PM

 Sample Code

Text_1.applyText("Hello World");

You can use a text pool technical object with related APIs, so that Hello World can be translated.

Procedure
1. In the Scripting section of the Outline panel, select   Text Pool.

You've added the text pool technical object, whose default name is TextPool_1. You can change to another name if you want.

2. In the Text Pool configuration panel, enter the texts to be used in the scripts and translated:

a. To add a text pool value, choose  (Add).

You've added a text pool value, whose default ID is Value_1. You can change the ID as you want, which is used in
scripting and corresponds to the text.

b. In the Text column, enter the corresponding source text for translation, for example, Hello World.

c. You can add other text pool values in ID and text pair in the same way.

 Note
You can only add one text pool technical object per story. Therefore, put all the texts you want to translate during the
configuration.

3. To finish the configuration, choose Done.

4. Use the getText API to get the text via the ID.

For example, you can write the following script to apply the text configured in the text pool technical object TextPool_1,
whose ID is Value_1, to the text widget Text_1:

 Sample Code

Text_1.applyText(TextPool_1.getText("Value_1"));

5. Translate the texts from the text pool technical object:

a. From the navigation bar, choose  (Translation).

b. In the Translation dashboard, select the story and then  (Edit Translations) from the toolbar.

c. You can find the texts from the text pool technical object, and translate them to the target language.

For more information about editing translations, refer to Edit Translations Manually.

Results
You've used the text pool technical object with related APIs to translate the texts in scripts to different languages. In view time,
these texts can be dynamically changed with the data access language, based on the translated texts in the Translation
dashboard.

Set up Timers
As an application designer or story developer, you can use the timer technical object with script APIs to initiate timing events in
view time.

This is custom documentation. For more information, please visit SAP Help Portal. 53
2/9/25, 4:58 PM

Context
By setting up timers, you can realize different scenarios such as:

Creating simple animations that make image or text widgets change their contents every couple of seconds

Sending notifications to end users at a certain interval

Refreshing analytic applications or optimized stories at a certain interval

Multiple timers can exist simultaneously, but each timer works independently from others.

Procedure

1. In the Scripting section of the Outline panel, (for analytic applications) choose right next to Timer, or (for optimized
stories) choose Timer .

The side panel Timer opens with a default name Timer_1 displayed. You can change the name at will.

2. Choose Done to finish adding the timer.

3. To start the timer in view time, you can use the following API for the canvas, page, popup or widget, for example, the
onClick event of a button if you want to start the timer when end users clicks it:

 Code Syntax
start(delayInSeconds: number)

 Note
The delay time set in the timer can be either an integer or a decimal, measured in seconds. For example, if you
write start(0.1), then the delay time is 100 milliseconds.

Calling the start() API on a timer that is already running overrides the first start() API. This means the
timer stops and immediately restarts to realize the delay time set by the second start() API.

4. To repeatedly restart a timer once time's out, you can go to its onTimeout event and use the start() API.

There are some other script APIs available for the onTimeout event of a timer, such as stop() and isRunning(). For
detailed information, refer to Analytics Designer API Reference (for analytic applications) and Optimized Story Experience
API Reference (for optimized stories).

Example

Here's an example of using the timer to automatically scroll images horizontally from right to left at a certain interval.

First, insert three different images, Image_1, Image_2 and Image_3 and place them side by side on the page. Take notes of their left
margins, which are 112px, 240px and 368 px.

This is custom documentation. For more information, please visit SAP Help Portal. 54
2/9/25, 4:58 PM
Then, create an image type script variable Animation_Widgets and an integer type script variable LeftMargins. Enable Set As
Array for the two script variables.

After that, add a script object Util_Animation with a function doAnimation and then add a timer Timer_1 .

Write the following scripts:

For the onInitialization event of page:

 Sample Code

console.log('onInitialization - begin');

LeftMargins = [112, 240, 368];


Animation_Widgets = [Image_1,Image_2,Image_3];

//Start the timer after 3 seconds after initializing the page.


Timer_1.start(3);

console.log('onInitialization - end');

For doAnimation:

 Sample Code

var num = 3;

//Redefine the sequence of the images.


var first = Animation_Widgets[0];
Animation_Widgets[0] = Animation_Widgets[1];
Animation_Widgets[1] = Animation_Widgets[2];
Animation_Widgets[2] = first;

// Update the left margin of each widget.


for(var i=0;i<num;i++) {
Animation_Widgets[i].getLayout().setLeft(LeftMargins[i]);
}

For Timer_1:

 Sample Code

//Run this script object once Timer_1 times out.


Util_Animation.doAnimation();

//Restart Timer_1 again after 3 seconds.


Timer_1.start(3);

When end users view the application or story, they can soon see the images automatically scroll from right to left in turn.

This is custom documentation. For more information, please visit SAP Help Portal. 55
2/9/25, 4:58 PM

Use Data Actions Technical Objects


As an application designer or story developer, you can use the Data Actions technical object and related script APIs to let viewers
perform data actions, set and read parameter values.

Prerequisites
Before you can use the data actions technical object, there have to be data actions created already.

Please consider as well the following permissions and roles:

To create or edit a Data Actions technical object, you need the permission to edit the analytic application or story.

To select a data action in the Data Action Configuration side panel, you need the read permission for it.

To run a data action, viewers need the execute permission for it.

Context
Data action is a flexible planning tool for making structured changes to a version of model data, such as copying data from one
model to another.

There're two ways for you to use this feature:

Using the Data Action Starter widget

For how to add a data action starter to your analytic application or story and configure related settings, refer to Set Up
Starters.

Using the Data Actions technical object and related APIs

You can do the following:

Setting parameter values of data actions

Reading parameter values of data actions

Performing data actions

Procedure
1. To add a data actions technical object, in the Scripting section of the Outline panel, (for analytic applications) choose
right next to Data Actions, or (for optimized stories) choose Data Actions .

The side panel Data Action Configuration opens.

2. From the Data Action dropdown, select one of the data actions that have been created already. The related parameters are
displayed below.

3. Enter the values for the parameters by either using the member selection or choosing the default value that was set in the
data actions designer.

 Note

To run a data action successfully, you need to enter the values of all parameters, either in Data Action
Configuration panel or via the API setParameterValue.

This is custom documentation. For more information, please visit SAP Help Portal. 56
2/9/25, 4:58 PM
The design of the data action itself can't be changed in Data Action Configuration, but you can adjust it by
setting parameter values there.

4. Select Done.

5. After adding the technical object, you can leverage the following APIs to work with data actions in your application or story:

Performing data actions

As a blocking operation. Other scripts won't be running until the data action is complete.

 Code Syntax

execute(): DataActionExecutionResponse;

As a non-blocking operation. Other scripts can be running at the same time without waiting for the data
action to complete.

 Code Syntax

executeInBackground(executionName: string): DataActionBackgroundExecutionRespons

The API returns the data action status, either accepted or error, and a unique execution ID.

In this case, the onExecutionStatusUpdate event of data actions technical object can be called when
the status changes:

 Code Syntax

// Called when an asynchronous Data Action execution changes its status. The new
onExecutionStatusUpdate(status: DataActionExecutionResponseStatus, executionId:

Getting the data action status by execution IDs

 Code Syntax
getExecutionProgress(executionId: string): DataActionExecutionResponseStatus

Getting parameter values

 Code Syntax
getParameterValue(parameterId: string): DataActionParameterValue;

Setting parameter values

 Code Syntax
setParameterValue(id: string, value: string | string[] | DataActionParameterValue JSO

In the following example, a set of dimension member filters is assigned to the parameters of a data action. The
scripts collect the relevant single value and multiple value dimension member filters into an array before the
assignment operation. Exclusive filters are ignored as they're not supported by data actions.

This is custom documentation. For more information, please visit SAP Help Portal. 57
2/9/25, 4:58 PM

 Sample Code

var filters = table.getDataSource().getDimensionFilters(dimensionId);


var filteredMemberIds = ArrayUtils.create(Type.string);

for(var i = 0; i < filters.length; i++) {


if (filters[i].type === FilterValueType.Single) {
var singleFilter = cast(Type.SingleFilterValue, filter
if (!singleFilter.exclude) {
filteredMemberIds.push(singleFilter.va
}
} else if (filters[i].type === FilterValueType.Multiple) {
var multiFilter = cast(Type.MultipleFilterValue, filte
if (!multiFilter.exclude) {
filteredMemberIds = filteredMemberIds.
}
}
}

dataAction.setParameterValue(parameterId, {
type: DataActionParameterValueType.Member,
members: filteredMemberIds
});

(Optimized Story Experience) When using the setParameterValue API, you can pass the member ID of the
planning model via PlanningModel.getMembers, for example, instead of manually constructing the ID.

 Sample Code

DataAction_1.setParameterValue(parameterId, {
type: DataActionParameterValueType.PlanningModelMember,
members: [PlanningModel_1.getMember("ResponsibilityCenter", "HREG0003")],
hierarchy: "Currencies"
//hierarchy is optional, by default either the fixed hierarchy of the paramet
});

Setting all members selected for a parameter

In the following script example, if all members are selected in an input control, they are also selected as the
parameter values:

 Sample Code

if (InputControl_1.getInputControlDataSource().isAllMembersSelected()) {
Copy_Accounts.setAllMembersSelected("LBHParam", "LBH2");
}

Getting whether all members are selected for a parameter

 Sample Code

This is custom documentation. For more information, please visit SAP Help Portal. 58
2/9/25, 4:58 PM

var bAllSelected = Copy_Accounts.isAllMembersSelected("LBHParam");

Use Multi Actions Technical Objects


As an application designer or story developer, you can use the Multi Actions technical object and related script APIs to let viewers
run multi actions, set and read parameter values.

Prerequisites
Before you can use the multi actions technical object, there have to be multi actions already created.

Consider the following permissions and roles as well:

To create or edit a multi actions technical object, you need the permission to edit the analytic application or story.

To select a multi action in the Multi Actions Configuration side panel, you need the read permission for it.

To execute a multi action, viewers need the execute permission for it.

Context

Multi action can help users save time when they need to run multiple data actions in sequence, publish versions, run predictive
scenarios or combine these operations. There're two ways for you to use this feature:

Using the Multi Action Starter widget

For how to add a multi action starter to your analytic application or story and configure related settings, refer to Set Up
Starters.

Using the Multi Actions technical object and related APIs

You can do the following:

Setting parameter values of multi actions

Reading parameter values of multi actions

Executing multi actions

Procedure
1. To add a multi actions technical object, in the Scripting section of the Outline panel, (for analytic applications) choose
right next to Multi Actions, or (for optimized stories) choose Multi Actions .

The side panel Multi Actions Configuration opens.

2. Under Multi Action, select one of the multi actions that have been created.

You can see the Parameters section.

3. Enter the values for the parameters, either by member selection or the default value set in the multi actions designer.

 Note

This is custom documentation. For more information, please visit SAP Help Portal. 59
2/9/25, 4:58 PM
To let viewers execute a multi action successfully, you need to enter the values of all parameters, either in Multi
Actions Configuration panel or via the API setParameterValue.

The design of the multi action itself can't be changed in Multi Actions Configuration, but you can adjust it by
setting parameter values here.

4. Select Done.

5. After adding the technical object, you can leverage the following APIs to work with multi actions in your application or story:

Executing multi actions

As a blocking operation. Other scripts won't be running until the multi action execution is complete.

 Code Syntax

execute(): MultiActionExecutionResponse

The API returns the execution status, either success, error or running.

As a nonblocking operation. Other scripts can be running at the same time without waiting for the multi
action execution to complete.

 Code Syntax

executeInBackground(executionName: string): MultiActionBackgroundExecutionRespon

The API returns the execution status, either accepted or error, and a unique execution ID.

In this case, the onExecutionStatusUpdate event of multi actions technical object can be called when
the execution status changes:

 Code Syntax

// Called when an asynchronous Multi Action execution changes its status. The ne
onExecutionStatusUpdate(status: MultiActionExecutionResponseStatus, executionId:

Getting parameter values

 Code Syntax
getParameterValue(id: string): MultiActionParameterValue

Setting parameter values

 Code Syntax
setParameterValue(id: string, value: string | string[] | MultiActionParameterValue JS

Use Data Upload Technical Object

This is custom documentation. For more information, please visit SAP Help Portal. 60
2/9/25, 4:58 PM
As an application designer or story developer, you can use the Data Upload technical object and related script APIs to let viewers
run data uploads., and decides actions to run before and after the upload.

Prerequisites

Before you can use the data upload starter technical object, there have to be data upload starters already created. Consider the
following permissions and roles as well:

To create or edit a data upload starter technical object, you need the permission to edit the analytic application or story.

To select a data upload starter in the Data Upload Configuration side panel, you need the read permission for it.

To execute a data upload starter, viewers need the execute permission for it.

Context

There're two ways for you to use this feature:

Using the Data Upload Starter widget:

For how to add a data upload starter to your analytic application or story and configure related settings, refer to Set Up
Starters.

Using the Data Upload starter technical object and related APIs

Procedure

1. To add a data upload technical object, for optimized stories, choose Starter Data Upload Starter .

The side panel Data Upload Starter opens.

2. Under Data Upload, select one of the data upload starter that have been created.

3. After adding the technical object, you can leverage the following APIs to work with data upload starters in your application
or story:

Decide the behavior of the data upload starter when it is clicked:

onBeforeExecute(): boolean

The API returns a <true> or <false> value. If this method returns <true> or returns no value, then the data upload is
executed. If this method returns <false>, then the data upload is ignored.

Get the status of the data upload starter after it has run:

onAfterExecute(status: DataUploadExecutionResponseStatus): void

The API returns the status of the upload, either success, error, canceled or warning.

Use an OData Service in Analytics Designer or Optimized Story


Experience
In SAP Analytics Cloud, analytics designer or Optimized Story Experience, you can define OData services based on an existing on-
premise SAP S/4HANA live connection in your system that was created via CORS (​​cross-origin resource sharing) connectivity.
Additionally, you can also define OData services based on SAP BW systems, SAP HANA systems, and SAP Business Planning and
Consolidation (BPC) systems that were also created via CORS.

This is custom documentation. For more information, please visit SAP Help Portal. 61
2/9/25, 4:58 PM
You can create an OData service, define the endpoint URL and use script APIs to let viewers perform transactional actions at the
backend, such as filling out an order form.

In analytics designer and Optimized Story Experience, OData actions can be called from and run in the backend system via
scripting. Furthermore, it's also possible to read and use the data of entity sets exposed via OData services via APIs.

What You Should Know


OData actions are operations exposed by an OData service, which may have side effects when invoked.

OData action imports, also called unbound actions, are not associated with any OData entity set or entity. They generally
expose simple parameters. All parameters are set via POST body.

OData bound actions are actions that may be invoked on a specific entity. They always contain a first parameter that is set
via URL to resolve the binding to the entity within the relevant entity set, and all other parameters are set via POST body.

In general, actions can be bound on every type, but in analytics designer and Optimized Story Experience, only binding on
single entities is supported.

For OData you should configure the direct connection CORS at the backend. To follow the instructions on the connection
configuration, refer to Live Data Connections to SAP S/4HANA. In connection configuration, the CORS connection is
referred to as direct connection.

 Note
Please find the following additional configuration information:

The service path you configure should correspond to the end-point URL of the OData service.

In addition to the service path listed in the documentation, you need to add another service path
/sap/opu/odata4/

The connection should also support if-match as allowed header.

There're following restrictions:

Only parameters of simple types are supported. Actions with mandatory parameters of unsupported types are not
available. For actions with optional parameters of unsupported types, the action itself is supported, but those parameters
are not.

In case of bound actions, actions bound to an entity collection are not supported. Only actions bound to a single entity are
supported. It's only possible to set this binding parameter by specifying the key of the entity on which the action should be
carried out.

Only the JSON format is supported.

Only S/4HANA on-prem is supported.

Only direct connection, CORS, is supported.

The following types are not supported:

Edm.Stream

Edm.Untyped

All Edm.Geography types

All types defined in different name space

This is custom documentation. For more information, please visit SAP Help Portal. 62
2/9/25, 4:58 PM

Add an OData Service


To run an OData action, you need to first add an OData service with the corresponding actions to your analytic application or
optimized story.

Prerequisites
The end-point URL of the OData service is available. You need to enter it manually when creating the service.

Procedure

1. In the Scripting section of Outline, (for analytic applications) choose right next to OData Services, or (for optimized
stories) choose OData Services .

The OData services technical object is created, with the default name ODataService_1 displayed in Outline. A side panel
opens on the right.

2. In the side panel, do the following:

a. (Optional) Change the default name of the new service to a meaningful name.

b. Under Connections, select the system from the list of available SAP S/4HANA systems whose connections were
already created in SAP Analytics Cloud.

c. Manually enter a valid end-point URL of the OData Service, in the format /some/end_point/url/.

You need to know the URL because browse catalog isn't available.

3. Select (Refresh) next to Metadata to review the metadata of the new OData service.

4. Select Done to close the panel.

Results
Now you can use the OData action. For more examples, see Scripting Example 1: Use OData Actions in Analytics Designer or
Optimized Story Experience and Scripting Example 2: Use OData Actions in Analytics Designer or Optimized Story Experience.

Use APIs to Read Data from OData Services


With OData services you can not only can access OData actions, but also read and use the data of entity sets exposed via OData
services.

This lets you use the data of the entity sets for any purpose except data visualization in a table or a chart. For example, you can
read and display one member in a text widget. To access entity sets exposed via OData Services, you can use two APIs in your
script:

getEntity: Retrieves a single OData entity from an entity set by specifying the key to the entity. This is similar to
selecting a single row from a SQL table via SELECT * FROM T1 WHERE ID = <id>.

getEntitiesFromEntitySet: Retrieves all entities from an OData entity set. This is similar to SELECT TOP <N> *
FROM T1. With this API you can use the OData system query options filter, orderby, select, count, top and skip.

 Note
The number of entities is limited to 1000 if no system query options have been used. If system query options are set,
there's no limit to the number of retrieved entities, unless you set a value for the system query option top.

This is custom documentation. For more information, please visit SAP Help Portal. 63
2/9/25, 4:58 PM
getEntitiesCountFromEntitySet: Retrieves the number of entities from an OData entity set. This API works like the
getEntitiesFromEntitySet API and you can also use the OData system query options filter, orderby, select,
count, top and skip.

 Example
The parameters filter, orderby and select have string values, which will be 1:1 used in the OData request. This allows you
to use all features supported by the query options. The parameters skip and top have integer values, which will be used in the
OData request. The second parameter in both API methods is passed as object, in which the system query options can be
combined in an arbitrary way.

 Sample Code

// returns a list of entities, filtered by the given system query option(s)


ODataService_1.getEntitiesFromEntitySet("Departments", {filter: "contains(Sector,'Consulting')",
// returns a list of entities, not filtered
ODataService_1.getEntitiesFromEntitySet("Equipments");
// returns the number of entities in the entity set "TEAMS"
ODataService_2.getEntitiesCountFromEntitySet("TEAMS");
// returns the number of entities in the entity set "EMPLOYEES", filtered by the given system qu
ODataService_2.getEntitiesCountFromEntitySet("EMPLOYEES", {skip: 5, top: 10});

 Note
There're following restrictions in reading data from OData services:

Chaining from one entity set to another isn't supported.

expand, analogous to joining, isn't supported.

Entity sets with parameters aren't supported.

Entity sets with mandatory filters aren't supported.

Scripting Patterns and Examples


When you start writing scripts in SAP Analytics Cloud, analytics designer, it might be helpful for you to go through typical use
cases and examples for scripting in analytic applications. This helps you adjust the scripts to your business needs.

Here you can find typical scripting patterns and examples to help you script with SAP Analytics Cloud, analytics designer:

Name Use Case More Information

Enable planning option and API Enable planning for tables to let planners Use Planning Enabled Property and
input data setEnabled API

getPlanningAreaInfo API Define planning area Use getPlanningAreaInfo API to Define


Planning Area

startEditMode API Start edit mode on specific planning area in Use startEditMode API on Public Versions
public version

This is custom documentation. For more information, please visit SAP Help Portal. 64
2/9/25, 4:58 PM

Name Use Case More Information

Version management APIs on SAP Analytics Publish public or private versions of Use publish API on Versions
Cloud data models: publish version API planning data

Version management APIs on SAP Analytics Publish a private version as a public one Use publishAs Public Version API
Cloud data models: publish as public
version API

Version management APIs on SAP Analytics Revert versions of planning data Use revert API on Versions
Cloud data models: revert version API

Version management APIs on SAP Analytics Delete a public or private version Use deleteVersion API
Cloud data models: delete version API

Version management APIs on SAP Analytics Create a private version from an existing Use copy API on Versions
Cloud data models: copy version API version

Version management APIs on SAP Analytics Check if a private version is owned by the Use getOwnerId API
Cloud data models: getOwnerId API current user

Version Management on SAP BPC Models Version Management APIs for SAP Business Use Version Management APIs on SAP BPC
Planning Consolidaton models Models

Calendar task APIs Change status and properties of a calendar Use a Calendar Integration Technical Object
task and Related APIs

Possible error messages How to prevent error messages when using Possible Error Messages in the Context of
APIs Version Management APIs

setUserInput and submitData API Change the value of a cell in a table at Use setUserInput and submitData Planning
runtime APIs

Data locking APIs Check if a model is data locking enabled Use Data Locking APIs
and set or get data locks

APIs related to BPC planning sequence Run a BPC planning sequence, open the Use APIs Related to BPC Planning
prompt dialog to modify the variable, set, Sequence
get, remove or copy the variable values

Formatting APIs Format certain values in an application Use Formatting APIs to Format Numbers
and Dates

Refresh data API Start data refresh Use Refresh Data API

Pause refresh options and APIs Pause data refresh Use Pause Refresh Options and APIs

Navigation APIs Navigate through analytic applications Use Navigation APIs

Layout APIs Set widget size and position dynamically in Use Layout APIs
the application

APIs for story filters and variables Show or hide filter panel, set, get or remove Use APIs on Story Filter and Variables
story filters and variables

Selection APIs for tables and charts Retrieve the currently selected members Use Selection API for Tables and Charts
and their dimensions

Result set APIs Get a result set based on an input data Use Result Set APIs
selection in a table or chart

This is custom documentation. For more information, please visit SAP Help Portal. 65
2/9/25, 4:58 PM

Name Use Case More Information

Range and exclude filters Set range and exclude filters Use setDimensionFilter API on Range and
Exclude Filters

getVariableValues API Return an array of the current values of a Use getVariablevalues API
specified variable

getDimensionFilters API Return an array of the current values of a Use getDimensionFilters API
specified dimension

openSelectModelDialog and Change a widget's model in view time either Use openSelectModelDialog and setModel
setModel API by calling the model selection dialog or APIs
directly with model ID

NULL members and total members NULL members and total members are Use NULL Members and Totals Members in
supported in script APIs. Script APIs

sendNotification API Send notifications to application users Use sendNotification API

Comment-related APIs Handle data cell comments, widget Use Comment-Related APIs
comments and comments on comment
widgets

Busy indicator APIs Define busy indicators on different levels for Define Busy Indicators and Use Related
long-running actions APIs

APIs to get user information Get information, teams and roles of user Use APIs to Get User Information

OData Actions scripting example 1 Run OData actions exposed by a connected Scripting Example 1: Use OData Actions in
on-premise system Analytics Designer or Optimized Story
Experience

OData Actions scripting example 2 Display backend system's response in story Scripting Example 2: Use OData Actions in
or analytic application Analytics Designer or Optimized Story
Experience

Best Practices

Here you can find typical use cases for creating analytic applications and setting up the interaction among widgets by scripting:

Use Case More Information

Switch between a chart and a table by using a toggle Best Practice: Switch Between Chart and Table

Filter a table or a chart by using a single measure selected from a Best Practice: Filter Table and Chart Through Dropdown (Single
dropdown Selection)

Filter a table or a chart by using multiple measures selected from a Best Practice: Filter Table and Chart Through Checkboxes (Multi-
checkbox group Selections)

Filter a table, a chart or an R visualization by using a filter line Best Practice: Use Filter Line for Filtering Switchable Table and
Chart

Filter dimensions and display data according to hierarchies Best Practice: Filter Table and Chart Through Cascaded Filtering

Control which measures and dimensions are displayed in tables Best Practice: Add and Remove Dimensions on a Table

This is custom documentation. For more information, please visit SAP Help Portal. 66
2/9/25, 4:58 PM

Use Case More Information

Filter a table or a chart by using popup window Best Practice: Filter Table and Chart Through Settings Panel
(Popup Window)

Create and open a popup window that contains extra information Best Practice: Handle Selections in Table and Chart and Open a
about the selected element Details Popup

 Note
The openNavigationPanel and closeNavigationPanel APIs were originally intended for Explorer, which is now fully
covered by Data Analyzer. We highly recommend using Data Analyzer for your data exploration scenarios.

Scripting and API Restrictions


The scripts on one page can't access the widgets and popups from others.

Value help for dimensions, measures and all their members aren’t supported for geo map related scripting, but you can
manually input the parameters.

In script APIs, name of a calculated or restricted measure is still treated as description rather than ID, while ID corresponds
to its UUID.

Customized dimension descriptions in memberInfo won't be shown on tables.

The onResultChanged event isn't initiated when the chart or table is invisible and set to Refresh Active Widgets Only.
When the widget becomes visible, the necessary query is sent and onResultChanged event is initiated.

The onSelect event is only supported for dimension member input controls and calculation input controls, while not
supported for other types, such as range filters and dimension input controls.

The onSelect event isn't supported for cluster bubble charts.

The input control APIs, getActiveSelectedMembers, setSelectedMembers, isAllMembersSelected and


setAllMembersSelected, are only supported for dimension member input controls and calculation input controls.

The setSelectedMembers and setSelectedMembersWithUnbooked APIs don't support selecting input control
members whose IDs are empty strings.

When opened by setVariableValue API, the variable dialog doesn’t display member description for charts and tables.

In view mode, setting multiple values on tables and R visualizations using an API like setDimensionFilter changes the
selection mode of a filter even if it was set to Single Selection in edit mode.

On the table navigation panel, which is opened by the openNavigationPanel() API, the option to deselect all account
dimensions isn't available.

Callback isn't supported for the sort() API. Therefore, only array of primitive types such as number and string can be
sorted via API.

Use Planning Enabled Property and setEnabled API


As an application designer or story developer, when you use a planning model for the table in your analytic application or
optimized story, you can enable planning in the Builder panel or leverage setEnabled() API to let planners input data.

When you add a table with planning model, Planning Enabled is by default active in its Builder panel. This property determines
whether the table is input-enabled or not.

This is custom documentation. For more information, please visit SAP Help Portal. 67
2/9/25, 4:58 PM

 Note
If you use BPC live data connections, planners can switch between read-only and input mode for tables in view time by
selecting Switch to Read-Only Mode or Switch to Input Mode from the context menu.

In addition, you can use setEnabled() API to let planners turn on read-only mode or input mode.

 Example
For a button, if you write Table.getPlanning().setEnabled(false) for its onClick event, the table is switched to
read-only mode when the end user clicks the button. If you write Table.getPlanning().setEnabled(true), the table is
switched to input mode upon the click.

 Note
If you set the setEnabled() API to false, on a table with BPC live data connection with an input-ready query, two cases can
occur:

If no data cells've been changed, the table is set to read-only and the according locks in BPC are released.

If data cells've been changed, no publish dialog is shown. The table is set to read-only mode and the locks and changed
data are kept in the BPC System. If the data is published or reverted with the help of APIs, the kept data is removed, and
the BPC locks are deleted.

Use getPlanningAreaInfo API to Define Planning Area


As an application designer or story developer, you can use getPlanningAreaInfo with filter related APIs to define the planning
area. You can further use startEditMode and copy API to edit or copy the customized planning area.

You can use getPlanningAreaInfo API, which returns the PlanningAreaInfo object, which is intialized with filters applied
to the table. If the data source associated with the table doesn't support planning, undefined is returned.

 Code Syntax

getPlanningAreaInfo(): PlanningAreaInfo | undefined

You can use the following APIs with the PlanningAreaInfo object to define the planning area that isn't in the table context:

removeFilter: Remove any filter that is set on the dimension.

 Code Syntax

removeFilter(dimension: string | DimensionInfo): PlanningAreaInfo

changeFilter: Sets a filter on the dimension. Any existing filter on the dimension is overwritten.

 Code Syntax

changeFilter(dimension: string | DimensionInfo, memberInfo: PlanningAreaMemberInfo): Planni

This is custom documentation. For more information, please visit SAP Help Portal. 68
2/9/25, 4:58 PM
The PlanningAreaMemberInfo object can be passed as a JSON object to method arguments. It has members and
hierarchy as properties.

getFilters: Returns filters that define the planning area. Filters on Version and Measure dimensions are ignored.

 Code Syntax

getFilters(): PlanningAreaFilter[]

The PlanningAreaFilter has dimension, members, hierarchy and property as properties.

Here's a script example that defines the planning area with filters applied to Table_1:

 Sample Code

var planningAreaInfo = Table_1.getPlanning().getPlanningAreaInfo(); // Returns a PlanningAreaInf

if (planningAreaInfo){
planningAreaInfo.removeFilter("Date"); // ignore filters on "Date" dimension
planningAreaInfo.changeFilter("Generic", { "hierarchy": "H1", "members": ["[Generic].[H1].&[A]

var planningAreafilters = planningAreaInfo.getFilters();


console.log(planningAreafilters); // Prints out filters
/* Examples of the filters
[{
"dimension": "Generic",
"hierarchy": "H1",
"members": [
"A"
],
"property": "ID"
}]
*/
}

Related Information
Use startEditMode API on Public Versions
Use copy API on Versions

Use Version Management APIs on SAP Analytics Cloud Data


Models
As an application designer or story developer, you can use version management APIs to publish, delete and revert versions, even if
the table isn't planning-enabled, for example.

You can use the following APIs for version management:

Planning.getPrivateVersion, Planning.getPrivateVersions, Planning.getPublicVersion,


Planning.getPubllicVersions

This is custom documentation. For more information, please visit SAP Help Portal. 69
2/9/25, 4:58 PM
PlanningPublicVersion.startEditMode

For more information, refer to Use startEditMode API on Public Versions.

PlanningPrivateVersion.publish, PlanningPublicVersion.publish

For more information, refer to Use publish API on Versions.

PlanningPrivateVersion.publishAs

For more information, refer to Use publishAs Public Version API.

PlanningPublicVersion.isDirty

PlanningPublicVersion.revert

For more information, refer to Use revert API on Versions.

PlanningVersion.deleteVersion

For more information, refer to Use deleteVersion API.

PlanningVersion.copy

For more information, refer to Use copy API on Versions.

PlanningVersion.getDisplayId

PlanningVersion.getId

privateVersion.getOwnerId

For more information, refer to Use getOwnerId API.

 Note
If you don't want version management scripts to be executed when planning is disabled for the table, use
Table.getPlanning().isEnabled() to set this.

Use startEditMode API on Public Versions


As an application designer or story developer, you can use startEditMode API to start edit mode on specific planning areas in
public versions.

You can use the following API to start edit mode:

 Code Syntax

startEditMode(planningPublicEditOption: PlanningPublicEditOption, planningAreaFilters?: PlanningA

For the parameter PlanningPublicEditOption, you can specify the planning area:

AllData: Start edit mode on all data.

CustomizedPlanningArea: Start edit mode on customized planning area. You need to specify the dimensions and
members that construct the planning area via PlanningAreaFilters, which is mandatory. For more information, refer
to the following section.

This is custom documentation. For more information, please visit SAP Help Portal. 70
2/9/25, 4:58 PM
PlanningArea: Start edit mode on planning area with data access control and data locking.

TableContextWithPlanningArea: Start edit mode on planning area with table context, data access control and data
locking.

 Note
The startEditMode API won't be affected by the setting Auto-generate based on the table context in tables' Builder
panel.

Start Edit Mode on Customized Planning Area


Here's a script example to start edit mode on customized planning area with specified filters:

 Sample Code

var PlanningAreaFilters = Table_1.getPlanning().getPlanningAreaInfo();

// Remove predefined Date dimension filter


PlanningAreaFilters.removeFilter("Date");

// Change predefined filter.


PlanningAreaFilters.changeFilter("GenericDimension", {"hierarchy":"H1","members":["[ GenericDime

// Assign filter
var filters = PlanningAreaFilters.getFilters();

// Start edit mode with CustomizedPlanningArea option and filters


Table_1.getPlanning().getPublicVersion("Actual").startEditMode("Actual2", planningPublicEditOpti

Related Information
Planning on Public Versions

Use publish API on Versions


As an application designer or story developer, you can use the publish API for publishing public or private versions.

Before You Start

Before using the publish API, make sure that you've checked the following:

You've created an application or optimized story that contains a table and SAP Analytics Cloud planning model.

You've assigned the planning model to the table.

You've made up your mind on how to visualize or expose the publish API to the viewers. For example, you want them to
click on a button to publish a version.

If users try to publish a version that exceeds the resource limits and there're not enough resources available in the system
for the publishing operation, they'll see a corresponding message.

This is custom documentation. For more information, please visit SAP Help Portal. 71
2/9/25, 4:58 PM

Examples for Publishing Public Versions

The following example shows how you can use the publish API for publishing the public version Actual:

 Sample Code

var actualVersion = Table_1.getPlanning().getPublicVersion("Actual");


if (actualVersion) {
if(actualVersion.isDirty()) {
actualVersion.publish();
};
};

The following example shows how you can use the publish API for publishing all public versions:

 Sample Code

var publicVersions = Table_1.getPlanning().getPublicVersions();


for (var j = 0; j < publicVersions.length; j++) {
if (publicVersions[j].isDirty()){
publicVersions[j].publish();
};
};

Examples for Publishing Private Versions

You can use the publish API for private versions in two different ways:

1. No parameters are specified. In this case, the original version from which the private version was created is overwritten.

 Sample Code

// override the original version from which myActual was created


var myActualVersion = Table_1.getPlanning().getPrivateVersion("myActual");
if (myActualVersion) {
myActualVersion.publish();
};

2. The target version is specified. You can further specify the default behavior for publishing a private version to an unrelated
public version by the parameter updateChangedDataOnly. If it's false, the entire private version overwrites the public
target version. If it's true, only the changed data is published to the public target version.

 Sample Code

// override the forecast version with myActual and update only changed data
var myActualVersion = Table_1.getPlanning().getPrivateVersion("myActual");
var forecastVersion = Table_1.getPlanning().getPublicVersion("Forecast");
if (myActualVersion && forecastVersion) {
myActualVersion.publish(forecastVersion, true);
};

This is custom documentation. For more information, please visit SAP Help Portal. 72
2/9/25, 4:58 PM

APIs to Resolve Publish Conflicts

You can specify the parameter in the publish API to let viewers resolve changes in conflict with another viewer's when publishing
a version.

 Note
The API works whether Display options to resolve version with publish conflicts is enabled or not in the system configuration.

For publishing public versions, you can choose to show the warning dialog for viewers to resolve conflicting changes, directly
publish the version with conflicting changes overwritten by another viewer without showing the dialog, or revert the version
without showing the dialog:

//option 1: Shows the warning dialog for viewers to resolve conflicting changes.
{ publicPublishConflict: PublicPublishConflict.ShowWarning }

//option 2: Publishes the version with conflicting changes overwritten by another viewer without sh
{ publicPublishConflict: PublicPublishConflict.PublishWithoutWarning }

//option 3: Reverts the version without showing the conflict warning dialog.
{ publicPublishConflict: PublicPublishConflict.RevertWithoutWarning }

For publishing private versions, you can choose to either show the warning dialog for viewers to resolve conflicting changes, or
directly publish the version with conflicting changes overwritten by another user without showing the dialog:

//option 1: Shows the warning dialog for viewers to resolve conflicting changes.
{ privatePublishConflict:PrivatePublishConflict.ShowWarning }

//option 2: Publishes the version with conflicting changes overwritten by another viewer without sh
{ privatePublishConflict:PrivatePublishConflict.PublishWithoutWarning }

Use publishAs Public Version API


As an application designer or story developer, you can use the publishAs API for creating a public version from a private one.

Before You Start

Before using the publishAs API, make sure that you've checked the following:

You've created an application or optimized that contains a table and SAP Analytics Cloud planning model.

You've assigned the planning model to the table.

You've made up your mind on how to visualize or expose the publishAs API to the end users.

If users try to publish a version that exceeds the resource limits and there're not enough resources available in the system
for the publishing operation, they'll see a corresponding message.

Via publishAs API you can specify the name for the new public version. Optionally, you can specify its category. If no category is
specified, the category of the private version is used.

Example

This is custom documentation. For more information, please visit SAP Help Portal. 73
2/9/25, 4:58 PM
In the following example, the private version myActual is published as a public budget version called newBudget when the script
gets executed:

 Sample Code
var myActualVersion = Table_1.getPlanning().getPrivateVersion("myActual");
if (myActualVersion) {
myActualVersion.publishAs("newBudget", Category.Budget);
};

Use revert API on Versions


As an application designer or story developer, you can use the revert API for reverting versions of planning data.

Before You Start

Before using the revert API make sure that you've checked the following:

You've created an application or optimized story that contains a table and SAP Analytics Cloud planning model.

You've assigned the planning model to the table.

You've made up your mind on how to visualize or expose the revert API to the end users. For example, you may want them
to click on a button to revert a version.

Example
The following example shows how you can use the revert API for reverting the modified public plan version:

 Sample Code

var planVersion = Table_1.getPlanning().getPublicVersion("Plan");


if (planVersion) {
if(planVersion.isDirty()) {
planVersion.revert();
};
};

In the following example you can use the revert API for reverting all the modified public versions:

 Sample Code

var publicVersions = Table_1.getPlanning().getPublicVersions();


for (var j = 0; j < publicVersions.length; j++) {
if (publicVersions[j].isDirty()){
publicVersions[j].revert();
};
};

Use deleteVersion API


This is custom documentation. For more information, please visit SAP Help Portal. 74
2/9/25, 4:58 PM
As an application designer or story developer, you can use the deleteVersion API for deleting a public or private version.

Before You Start

Before using the deleteVersion API, make sure that you've checked the following:

You've created an application or optimized story that contains a table and SAP Analytics Cloud planning model.

You've assigned the planning model to the table.

You've made up your mind on how you to visualize or expose the deleteVersion API to the end users.

Example
The following script shows how you can use the deleteVersion API for deleting a specific version:

 Sample Code
// delete private version "actualPrivateVersionToDelete"
var versionToDelete = Table_1.getPlanning().getPrivateVersion("actualPrivateVersionToDelete");
if (versionToDelete ) {
versionToDelete.deleteVersion()
};

Use copy API on Versions


As an application designer or story developer, you can use the PlanningVersion.copy API for creating a private version from
an existing version. This function only works for SAP Analytics Cloud models.

Before You Start

Before using the copy API make sure that you've checked the following:

You've created an application or optimized story that contains a table and SAP Analytics Cloud planning model.

You've assigned the planning model to the table.

You've made up your mind on how to visualize or expose the copy API to the end users. For example, you may want them to
click on a button to copy a version.

If a planning area is to be copied, make sure that a recommended planning area has been defined for the model.

If users try to copy a version that exceeds the resource limits and there aren't enough resources available in the system for
the copying operation, they'll see a corresponding message.

 Note
All versions are copied with the default currency conversion, which can't be changed.

Script API and Examples


You can use the following API to copy and create versions:

This is custom documentation. For more information, please visit SAP Help Portal. 75
2/9/25, 4:58 PM

 Code Syntax

copy(newVersionName: string, planningCopyOption: PlanningCopyOption, versionCategory?: PlanningC

You can specify the area to be copied via the parameter planningCopyOption:

AllData: All data is included when the version is copied.

The following script copies all data from a private version to create a private one in budget category:

 Sample Code

var originalVersion = Table_1.getPlanning().getPrivateVersion("privateVersionToCopy");


if (originalVersion) {
originalVersion.copy("targetVersionName", PlanningCopyOption.AllData, PlanningCategory.
};

NoData: No data is included when the version is copied.

The following script creates a blank version from a public one without changing the category:

 Sample Code

var originalVersion = Table_1.getPlanning().getPublicVersion("publicVersionToCopy");


if (originalVersion) {
originalVersion.copy("targetVersionName", PlanningCopyOption.NoData)
};

VisibleData: Only data in the viewport is included when the version is copied.

CustomizedPlanningArea: Only data in the customized planning area is included when the version is copied. You need
to specify the dimensions and members that construct the planning area via PlanningAreaFilters, which is
mandatory in this case.

The following script applies filters and then copies the data in the customized planning area from an actual version to
create another one:

 Sample Code

var PlanningAreaFilters = Table_1.getPlanning().getPlanningAreaInfo();

// Remove predefined Date dimension filter


PlanningAreaFilters.removeFilter("Date");

// Change predefined filter.


PlanningAreaFilters.changeFilter("GenericDimension", {"hierarchy":"H1","members":["[ Generi

// Assign filter
var filters = PlanningAreaFilters.getFilters();

// Copy version with CustomizedPlanningArea option and filters


Table_1.getPlanning().getPublicVersion("Actual").copy("Actual2", planningPublicEditOption.C

This is custom documentation. For more information, please visit SAP Help Portal. 76
2/9/25, 4:58 PM

Use getOwnerId API


As an application designer or story developer, you can use the getOwnerId API for getting the ID of the user creating the private
version.

Getting the ID of the user who created the private version can check whether the version is owned by the current user. The check is
necessary because a user can't perform certain operations on a private version like deleting, copying or publishing if the user
doesn't own it.

 Note
This API can only be called on a private version and is therefore not relevant for BPC models.

 Sample Code

// check if the private version is owned by the current user


var privateVersion = Table_1.getPlanning().getPrivateVersion("privateVersionName");
if (privateVersion && privateVersion.getOwnerId() === Application.getUserInfo().id) {
privateVersion.deleteVersion();
} else {
// fallback. e.g. show message to user that they may not do certain operations on this versi
}

Use Version Management APIs on SAP BPC Models


You can use the Version Management APIs for SAP BPC models in analytic applications and optimized stories.

In SAP Business Planning and Consolidation (SAP BPC), there's always a version (of type public version with ID "All Versions"),
which you can't delete. Therefore, when working with SAP BPC models, you don't have to think about private version APIs or the
deleteVersion API.

To retrieve the SAP BPC version, you can use either the getPublicVersions()[0] or getPublicVersion("All
Versions") API. Both API calls return the same version.

Example
This example shows how you can use the publish API to publish modified data on SAP BPC:

 Sample Code
var bpcVersion = Table_1.getPlanning().getPublicVersion("All Versions");
if (bpcVersion) {
if(bpcVersion.isDirty()) {
bpcVersion.publish();
};
};

Example
This example shows how you can use the revert API to revert a version.

This is custom documentation. For more information, please visit SAP Help Portal. 77
2/9/25, 4:58 PM

 Sample Code
var bpcVersion = Table_1.getPlanning().getPublicVersions()[0];
if (bpcVersion) {
if(bpcVersion.isDirty()) {
bpcVersion.revert();
};
};

Possible Error Messages in the Context of Version Management


APIs
Learn how to prevent possible error messages when you use version management APIs.

Operate on Deleted Planning Versions


A previously deleted version, whether it was deleted by the script API or end user interaction, behaves differently from a non-
deleted one.

Return Values for Calls Made on Deleted Versions

Use the following getter functions on versions:

PlanningVersion.getId() => returns last ID before deletion


PlanningVersion.isDirty() => returns last modified stated before deletion
PlanningVersion.deleteVersion() => returns true (the promised state was reached)
PlanningVersion.publish() => returns false (the promised state cannot be reached)
PlanningVersion.publishAs() => returns false (the promised state cannot be reached)
PlanningVersion.revert() => returns true (the promised state was reached)

Reproduction

The easiest way to reproduce this is to delete any version and simply continue with script execution:

// delete new Budget version and operate on it afterwards


var newBudgetVersion = Table_1.getPlanning().getPublicVersion("newBudget");
if (newBudgetVersion) {
console.log("VersionId before deletion:" + newBudgetVersion.getId());
newBudgetVersion.deleteVersion();
console.log("VersionId after deletion:" + newBudgetVersion.getId());
newBudgetVersion.publish();
};

When calling any action function (revert, publishAs, publish or delete), the following error message is displayed:
Version 'newBudget' does not exist anymore.

Publish a Private Version with a Wrong Name

There are several errors that can occur when you use the publishAs API.

Empty String as Version Name

This is custom documentation. For more information, please visit SAP Help Portal. 78
2/9/25, 4:58 PM
The following code leads to an error, as the version name shouldn't be empty:

//Don't use this code as it leads to error


var myActualVersion = Table_1.getPlanning().getPrivateVersion("myActual");
if (myActualVersion) {
myActualVersion.publishAs("");
};

The following error message is shown: Enter a name for your version before you publish it.

String Too Long to Be a Version Name

The following code leads to an error, as the version name is too long:

//Don't use this code as it leads to error


var myActualVersion = Table_1.getPlanning().getPrivateVersion("myActual");
if (myActualVersion) {
myActualVersion.publishAs("255characters");
};

The following error message is displayed: Enter a version name that is shorter than 255 characters.

Unauthorized Characters in Version Name

The following code leads to an error, as the version name contains characters that aren't allowed:

//Don't use this code as it leads to error


var myActualVersion = Table_1.getPlanning().getPrivateVersion("myActual");
if (myActualVersion) {
myActualVersion.publishAs("\:Version");
};

The following error message is displayed: Enter a version name that doesn't contain the characters \\ : ; ' =
[ ].

Using Existing Version Name

The following code leads to an error, as the version name already exists:

//Don't use this code as it leads to error


var myActualVersion = Table_1.getPlanning().getPrivateVersion("myActual");
if (myActualVersion) {
myActualVersion.publishAs("Actual");
};

The following error message is displayed: You can't save this version with name 'Actual', because this name
already exists. Please use a different name.

Deleting Actual Version

The following code leads to an error, as the actual version shouldn't be deleted.

//Don't use this code as it leads to error


var actualVersion = Table_1.getPlanning().getPublicVersion("Actual");
if (actualVersion) {
actualVersion.deleteVersion();
};

This is custom documentation. For more information, please visit SAP Help Portal. 79
2/9/25, 4:58 PM
The following error message is displayed: You can't delete the public version of category 'Actual'. This
version always has to be available.

Use setUserInput and submitData Planning APIs


As an application designer or story developer, you can use setUserInput and submitData APIs to enable end users to change
the value of a cell in a table in view time.

There're following prerequisites:

You've assigned a planning model to the table - either a SAP BPC model or an SAP Analytics Cloud planning model.

You've set the table to planing-enabled. Just check whether you've selected the table property Planning enabled.

The setUserInput and submitData APIs work together.

Work with Booked and Unbooked Cells


When you change a booked value, the leaf members that aggregate up to that value are adjusted proportionally to reflect your
change. When you enter a new value in an unbooked cell, which displays a dash character (-) instead of a value, values are also
booked to one or more leaf members for each dimension that aggregates up to the cell.

 Note
Be aware that you can’t use the setUserInput API for planning on a null cell displaying a # character for SAP BPC models as
it's currently not supported.

Use setUserInput API


This API updates the cell of a table with a specified value and returns true if the operation was successful and false if the operation
failed.

 Sample Code

Table_1.getPlanning().setUserInput(selection: Selection, value: string):boolean

The selection must be a selection from the table, and the value must be supplied according to the user formatting settings. It can
be one of the following:

A string representing a number

 Note
When setting a value for a key figure of a BPC model, in addition to using a string that represents a number, you can use
digits, letters, and special characters in the value.

The string can have 17 characters at maximum.

If you attempt to use anything else than a number for a value, an error message mentioning that the value is invalid is
displayed. For example:

If you use an empty string like Table_1.getPlanning().setUserInput({<selection>}, "");.

This is custom documentation. For more information, please visit SAP Help Portal. 80
2/9/25, 4:58 PM
If you try to reset the value of a cell like Table_1.getPlanning().setUserInput({<selection>}, "-
");

If you use an empty space for planning like Table_1.getPlanning().setUserInput({<selection>}, "


");

A scalar of the form *[multiplying factor]

The scalar can have seven characters at maximum.

Use submitData() API

This API submits the updated cell data with all the modified data and initiates the refresh of data. It returns true if the operation
was successful and false if the operation failed.

 Sample Code

Table_1.getPlanning().submitData();

The submitData API should be called after all the desired cells have been planned. Just call submitData() once to observe the
results on the planned table.

Example

The example is based on a table called Table_1 that has an underlying planning model.

Method Sample Code

Planning a cell with the


 Sample Code
selection object
Table_1.getPlanning().setUserInput({<selection>}, "5000000");
Even if the table is
Table_1.getPlanning().submitData();
hidden, it's still possible
to plan a cell.

Planning a cell with the


 Sample Code
selection from the table
Table_1.getPlanning().setUserInput(Table_1.getSelections()[0], "500000000.99");
Table_1.getPlanning().submitData();

Planning a cell with the


 Sample Code
value from an input field
Table_1.getPlanning().setUserInput({<selection>}, InputField_1.getValue());
In this example, there's
Table_1.getPlanning().submitData();
an input field widget
called InputField_1.

Useful Details
When you work with the APIs, note the following information:

If you add a new dimension using an API, you must first expand the dimension to be able to plan the cell.

If you plan a cell with the same value, the API returns true and overwrites the existing value.

This is custom documentation. For more information, please visit SAP Help Portal. 81
2/9/25, 4:58 PM
If you plan setUserInput() with an invalid value, an error message is displayed and the API returns false.

If there's more than one table with the same underlying model, all the tables are updated once you plan a cell.

 Note
After calling setUserInput(), it's best to immediately submit your input with Planning.sumbitData(). Otherwise,
unexpected results may occur. For example, if other operations are performed in scripts or by user interaction that lead to the
refresh of the planning table before your input submission, your input could be discarded.

Related Information
Enter Planning Data in Tables

Use Data Locking APIs


You can use data locking APIs in analytic applications and optimized stories to check if a model is data-locking enabled and to set
or get data locks, even if the table is not planning enabled.

You can use the following APIs for data locking:

Table.getPlanning().getDataLocking

Table.getPlanning().getDataLocking.getSate

Table.getPlanning().getDataLocking.setState

The following prerequisites must be met:

You have assigned an SAP Analytics Cloud planning model to the table.

You have a license that allows you to read the data locking state.

 Note

Data locking and the data locking APIs are not supported for SAP BPC models.

If data locking is disabled for a model, all locks will be deleted. If it is turned on again later, all members are reset to the
default lock state. The same happens if the default lock state or driving dimensions are changed.

Using the getDataLocking API

You can use the getDataLocking API to check if a planning model is enabled for data locking.

The check is necessary because an end user cannot perform certain operations on a table, like setState and getState, if the
model is not data-locking enabled.

 Example

 Sample Code

var planning = Table_1.getPlanning();

This is custom documentation. For more information, please visit SAP Help Portal. 82
2/9/25, 4:58 PM

//gets the DataLocking object of the table - if DataLocking is enabled on the model

console.log(planning.getDataLocking());

Using the getState API

You can maintain the locking state of a cell belonging to a driving dimension by using the
Table.getPlanning().getDataLocking.getSate API. This API function only works for SAP Analytics Cloud planning
models that are enabled for data locking.

 Example
Please have a look at the example below for how to set the data lock state for a selected cell, instead of using the Manage Data
Locksquick actions menu option of the table.

 Sample Code

var selection = Table_1.getSelections()[0];

//get the state of the selection


var selectionLockState = Table_1.getPlanning().getDataLocking().getState(selection);

To make this example work, you have to select a cell on the table for which you want to retrieve the lock state. Alternatively, you
can define the selection yourself in the script editor.

The API returns the state of the selection, which can be OPEN, RESTRICTED, LOCKED, or MIXED. If the state of the selection can't
be determined, the API returns undefined. This can happen under following conditions:

Your selection is invalid.

The cell that belongs to the selection is not found.

The cell has an unknown state.

The cell has been created by the quick action menu "Add Calculation" at runtime.

You don't have a license that allows you to maintain the data locking state.

If you have activated the option to show data locks for the table (select Show/Hide Data Locks in the table's quick action
menu), the lock icons will be updated after the API has been run.

Using the setState API

You can lock a cell belonging to a driving dimension by using the Table.getPlanning().getDataLocking.setSate API.
This API function only works for SAP Analytics Cloud planning models that are enabled for data locking.

The API returns true if the setting of the lock was successful, and false for the following cases:

You can't set the data lock state on a private version. In this case, the error message You can only set data locks on public
versions. Please use a public version and try again. is displayed.

This is custom documentation. For more information, please visit SAP Help Portal. 83
2/9/25, 4:58 PM
If you try to set the state with the value Mixed, you will be notified in the script editor with the error message You can't set
the state with the value 'mixed'. Please specify either 'open', 'restricted' or 'locked' as value.. The same error message is
shown at runtime, if you attempt to execute the script, and the script fails.

If you select multiple cells and attempt to set the state, only the selection of the first cell will be considered when setting
the state.

 Example
Set the selection to the locked state

 Sample Code

var selection = Table_1.getSelections()[0];

/sets the selection to Locked


var isSetStateSuccessful = Table_1.getPlanning().getDataLocking().setState(sel, DataLockingSta

 Note
This API replaces the table's quick action menu Manage Data Locks.

Use APIs Related to BPC Planning Sequence


As an application designer or story developer, after adding a BPC Planning Sequence Starter widget, you can use related APIs to
let viewers run the planning sequence without manually setting any variable values and do various operations on the variable
values of planning functions in view time.

You can add a BPC Planning Sequence Starter widget to let viewers run a planning sequence with one or more planning functions
with BPC live data connection.

Then, you can use a combination of related APIs to offer viewers more options to interact with it. For example, they can run a
planning sequence with the pre-defined variable values and modify the values at runtime as well.

 Note
As BPC live data connection isn't supported for mobiles, the related APIs aren't supported as well.

You can use the following variable related APIs on data source level for setting, getting, removing and copying the variable values of
a planning sequence:

 Code Syntax

//Sets the variable values of a planning sequence.


BpcPlanningSequence.getBpcPlanningSequenceDataSource().setVariableValue(variable: string | Varia
//Gets the variable values of a planning sequence.
BpcPlanningSequence.getBpcPlanningSequenceDataSource().getVariableValues(variable: string | Vari
//Gets all variables of a planning sequence.
BpcPlanningSequence.getBpcPlanningSequenceDataSource().getVariables(): VariableInfo[];
//Removes variable values from a planning sequence.
BpcPlanningSequence.getBpcPlanningSequenceDataSource().removeVariableValue(variable: string | Va

This is custom documentation. For more information, please visit SAP Help Portal. 84
2/9/25, 4:58 PM
//Copies variable values of a planning sequence.
BpcPlanningSequence.getBpcPlanningSequenceDataSource().copyVariableValueFrom(sourceDataSource: D

The following API is for running a planning sequence:

 Code Syntax

BpcPlanningSequence.execute(): BpcPlanningSequenceExecutionResponse;

The following API is for opening the prompt dialog where viewers can modify the variables:

 Code Syntax

BpcPlanningSequence.openPromptDialog();

Use Formatting APIs to Format Numbers and Dates


You can write scripts in analytic applications and optimized stories to let viewers format the existing number values and date
values.

There're following format options for these two types of values:

number values

Set maximum decimal places

Example: 1.23456 will be turned into 1.234 if the maximum decimal place is set as 3.

Set minimum decimal places

Example: 1.23 will be turned into 1.230 if the minimum decimal place is set as 3.

Set the decimal separator

Example: 1.23 will be turned into 1 23 if the decimal separator is set as empty space.

Enable digit grouping

Example: If digital grouping is enabled, 123456 will be turned into 123,456.

Set separator of digit grouping

Example: 123,456 will be turned into 123.456, if dot is set as the separator of the digital grouping.

Display sign and set sign format

Example: In a normal case, “+” and “-” can be set as the sign format. In some special cases, “()” can be set to
indicate negative value too.

Display scale and set scale multiplier and affix

Example: E can be used as the scale multiplier, such as 1E-3; M can be set as a scale affix so that 123,456,789 can be
set as 123M.

 Note

This is custom documentation. For more information, please visit SAP Help Portal. 85
2/9/25, 4:58 PM
Number format APIs only apply to measures on axes, Feed.ValueAxis and Feed.ValueAxis2. Tooltip measures
on axes, Feed.TooltipValueAxis, aren’t supported, for example.

date values

Set date format: For example, 2016/01/10 will be turned into Jan 10, 2016 if you set a date pattern in MM dd, yyyy format.

For detailed information about all related APIs, refer to Analytics Designer API Reference (for analytic applications) and Optimized
Story Experience API Reference (for optimized stories).

 Example
You'd like to let end users view the formatted current system date in a text widget Text_1 via clicking a button. Write the
following script for the button:

 Sample Code

var s = DateFormat.format(new Date(), "MM dd, yyyy");


Text_1.applyText(s);

 Example
You'd like to let end users format the digit grouping of a number input in the widget InputField_1 according to their user
preference settings via clicking a button. Write the following script for the button:

 Sample Code

var s = InputField_1.getValue();
var n = Number.parseFloat(s);
Text_1.applyText(NumberFormat.format(n));

The formatted number will be displayed in the widget Text_1.

 Example
You'd like to let end users format the digit grouping of a number input in the widget InputField_1 according to your customized
setting. Here's the script for the button:

 Sample Code

var s = InputField_1.getValue();
var n = Number.parseFloat(s);
var nf = NumberFormat.create();
nf.setMinimumDecimalPlaces(3);
nf.setGroupingSeparator(".");
nf.setDecimalSeparator(",");
Text_1.applyText(nf.format(n));

In this case, the new format will apply the digit grouping separator “.” and the decimal separator “,” and the formatted number
will be displayed in the widget Text_1.

This is custom documentation. For more information, please visit SAP Help Portal. 86
2/9/25, 4:58 PM

Use Refresh Data API


By leveraging the refreshData API in analytic applications or optimized stories, you can let viewers refresh data at widget, data
source, application, or story level.

Refresh All or Specific Data Sources of an Application or Story


You can use the following API to refresh all data sources of an application or story, which updates all the widgets associated with
each data source:

 Code Syntax
Application.refreshData(dataSources?: DataSource[]): void

You can also specify the data sources, and only the widgets associated with these data sources will be updated. The supported
widgets are chart and table.

 Note
Currently, R visualization isn't supported.

The script is fully executed without waiting for all the associated widgets to be updated.

Refresh a Specific Data Source


c The supported widgets are chart, table and geo map.

 Code Syntax
DataSource.refreshData(): void

Refresh Data of a Specific Widget


You can use the following API to refresh the data of a specific widget:

 Code Syntax
Widget.getDataSource().refreshData();

Example

You can write the following script for the onClick event of a button, so that all the data sources of your analytic application or
story will be refreshed when end users click this button:

 Sample Code

Application.refreshData();

This is custom documentation. For more information, please visit SAP Help Portal. 87
2/9/25, 4:58 PM
In this example, you want to let end users click a button to refresh the data sources of Chart_1 and Table_1. Write the following
script for the onClick event of the button:

 Sample Code

var ds1 = Chart_1.getDataSource();


var ds2 = Table_1.getDataSource();
Application.refreshData([ds1, ds2]);

In this example, you'd like to refresh data of Chart_1 and Chart_2 every one minute at runtime. You can use refresh data API
together with timer API for the onTimeout event of Timer_1:

 Sample Code
Chart_1.getDataSource().refreshData();
Chart_2.getDataSource().refreshData();
Timer_1.start(60);

For more information about how to set up and use a timer, see Set up Timers.

Related Information
Configure Auto Refresh in Stories
Use Pause Refresh Options and APIs

Use Pause Refresh Options and APIs


In edit time, as an application designer or story developer, you can configure data refresh and interaction settings of specific
charts or tables in the Builder panel or via script APIs to improve the efficiency of retrieving and updating data after the widgets're
initially loaded in view time.

 Note
Currently, R visualization widgets aren't supported for the settings.

Modes of Data Refresh


Under Data Refresh in the Builder panel of a widget or the whole canvas, you can find the following three modes for data refresh:

Always Refresh (default)

Refresh Active Widgets Only: Under this mode, you can avoid unnecessary data refresh. Visible widgets refresh, while data
refresh for invisible widgets is automatically paused except when they're called by specific fetch data script APIs.:

DataSource.getResultSet, DataSource.getData, DataSource.isResultEmpty,


DataSource.getResultMember, DataSource.getDataSelections, DataSource.expandNode,
DataSource.refreshData

Table.getColumnCount, Table.getRowCount

Query is sent by tables even if the latest data’s been fetched, but won’t be sent by charts.

This is custom documentation. For more information, please visit SAP Help Portal. 88
2/9/25, 4:58 PM

 Note
Widgets in inactive popup dialogs, tabs in tab strips and pages in page books are treated as invisible ones.

(For analytic applications) The onResultChanged event is still initiated when the result set from an invisible widget is
updated by script APIs such as setDimensionFilter and setVariableValue.

(For optimized stories) The onResultChanged event isn't initiated.

When invisible widgets become visible, any previously paused operations that result in data refresh impact them again and
update their data. Query is sent by tables whether data are changed or not.

Always Pause: No data refresh takes place in view time, including initial loading.

We recommend selecting Disable Interaction as most of the interactions won’t take effect.

Later when you disable this mode, DataSource.refreshData and other refresh activities can be automatically
resumed except for planning activities, which needs to be manually initiated.

Script APIs

You can also leverage DataSource.setRefreshPaused API to let end users set the data refresh mode in view time. The script
is fully executed without waiting for all the widgets associated with the data source to be updated when their pause mode isn't on.
The supported widgets are charts and tables.

 Code Syntax
// Set the pause mode of the data refresh.
DataSource.setRefreshPaused(paused: PauseMode | boolean): void

// Get data refresh mode, which returns On, Off or Auto.


DataSource.getRefreshPaused(): PauseMode

The modes defined in script APIs correspond to the options in the Builder panel:

In Script APIs In Builder Panel

PauseMode.On Always Pause

PauseMode.Off Always Refresh

PauseMode.Auto Refresh Active Widgets Only

You can also use ApplicationPage.setRefreshPaused (in Optimized Story Experience) and
Application.setRefreshPaused to enable or disable data refresh on page, story or application levels in view time. When the
pause of data refresh is disabled, the widgets associated with the data sources are updated at the same time with data refresh.

 Sample Code
setRefreshPaused(dataSources: DataSource[], paused: boolean): void

 Note
If you set data refresh mode for the same widget in both Builder panel and script editor, scripting will overwrite the settings in
the panel.

This is custom documentation. For more information, please visit SAP Help Portal. 89
2/9/25, 4:58 PM

 Note
When planning is enabled, viewers can't pause a widget via setRefreshPaused API. They need to disable planning first via
setPlanningEnabled API.

Influence on Other Functionalities When Widgets are in Pause Mode

Refresh in the toolbar in view time won’t work on this widget.

All context menus (including right-click menu and quick action menu) are disabled.

All data related actions that can start query are disabled.

Planning is automatically disabled, which means:

In edit time, Planning Enabled in the widget’s Builder panel is automatically disabled. If the widget is later set to
always refresh, the Planning Enabled option becomes available and is selected by default.

In view time, planning is disabled. If the widget is later set to always refresh via API, planning won’t be resumed
automatically. It needs to be enabled via setPlanningEnabled API.

If viewers change to another planning model, planning is still automatically disabled.

Changing planning data in another table from the same planning model won’t start data refresh in the table in pause
mode.

All planning APIs (including ones that enable planning) won’t take effect or return default value according to its
return type declaration (except for submitData, setUserInput and setPlanningEnabled, which return
false instead).

Viewers can enable planning for tables in pause mode. However, they will receive a warning message that they can't
change to PauseMode.On or PauseMode.Auto again once planning is enabled. To prevent them from enabling
planning and losing planning data they input, we recommend you to disable planning before enabling widgets to
pause.

Changing script variables used in calculated measure won’t result in the refresh of related widgets.

PDF exporting is based on currently rendered result.

All modifications of time series forecast, smart grouping and navigation panel are applied to the widget’s existing state.

All APIs can be called, but won’t start data refresh of the widget, which means:

Application.refresh and DataSource.refreshData won’t work on the widget.

All Getter APIs will return results based on the widget’s existing state.

All Setter APIs will apply to the widget’s existing state and no data refresh occurs.

 Note
However, some local property and styling setting APIs such as DataSource.setMemberDisplay can cause
the widget to re-render.

Open Explorer API and Smart Insights use the current state of the widget.

 Note
However, pause mode doesn’t work on this widget in Explorer.

This is custom documentation. For more information, please visit SAP Help Portal. 90
2/9/25, 4:58 PM
Prompt APIs can be called but the widget won’t refresh after prompt values are set.

SearchToInsight result API can be called but the widget won’t refresh.

If no values are defined for mandatory variables in a widget’s data source, the variable dialog pops up, for example, when
the table in pause mode is called by setModel API.

Exceptional Cases When Widgets are in Pause Mode


There’re exceptional cases where some queries are still initiated even when widgets don't always refresh:

APIs Queries (First Time Query Without Cache)

DataSource.getMembers Query remote dimension members.

DataSource.setDimensionFilter Fetch member information if no MemberInfo object is specified in the API.

 Note
Therefore, we recommend you set MemberInfo if possible like the example below:

Chart_1.getDataSource().setDimensionFilter("Location_4nm2e04531", {

dimensionId: "Location_4nm2e04531",

id: "[Location_4nm2e04531].[State_47acc246_4m5x6u3k6s].&[SA1]",

description: "California",

displayId: "California"

});

DataSource.setVariableValue
For application-level or story-level variable in SAP BW model, five queries are initiated
by submitStoryVariable action:

reInitVariablesAfterSubmit

reInitVariablesAfterSubmit

submitVariables

updatePromptDescriptions

processSynchronization

For widget-level variable in SAP BW model:

Two queries are initiated in chart:

submitVariables

reInitVariablesAfterSubmits

One query is initiated in table:

submitVariables

 Note

This is custom documentation. For more information, please visit SAP Help Portal. 91
2/9/25, 4:58 PM

APIs Queries (First Time Query Without Cache)

This is applicable when variable is set via scripting in view time or initial value is set in edit
time.

DataSource.setHierarchy For SAP BW model, two queries are initiated:

ProcessHierarchyCatalogManagerCreation

getHierarchiesFromCatalog

DataSource.expandNode For SAP BW model, two queries are initiated:

submitVariable

fetchMembersWithDescription

DataSource.collapseNode For chart in SAP BW model, two queries are initiated:

submitVariable

processSynchronization

Table.setModel For SAP BW model, five queries are initiated:

Table.openSelectModelDialog turnOffBatchAndShutdownQueryManager

buildquerymanager

activateVariableVariant

submitVariables

submitVariables

For other models, two queries are initiated:

turnOffBatchAndShutdownQueryManager

processMemberHelp (to fetch members of Account)

Initial loading of application or story with Two queries are initiated:


SAP BW model and variables
fetchStoryVariableDetail

submitBWVariableforActivePage

For table, extra four queries are initiated:

submitVariable

processSynchronization

processSynchronization

processSynchronization

Example
Let’s say you want to let end users turn on or off data refresh and interaction of Chart_1 and Table_1 via two switches,
Switch_Refresh and Switch_Interaction.

This is custom documentation. For more information, please visit SAP Help Portal. 92
2/9/25, 4:58 PM

First, leave the options Always Refresh selected and Disable Interaction unselected in the Builder panel of both Chart_1 and
Table_1. Meanwhile, both switches’ default status is on.

Write the following scripts for Switch_Refresh:

 Sample Code
if (Switch_1.isOn()) {
Chart_1.getDataSource().setRefreshPaused(PauseMode.Off);
Table_1.getDataSource().setRefreshPaused(PauseMode.Off);
} else {
Chart_1.getDataSource().setRefreshPaused(PauseMode.On);
Table_1.getDataSource().setRefreshPaused(PauseMode.On);
}

Write the following scripts for Switch_Interaction:

 Sample Code
Chart_1.setEnabled(!Chart_1.isEnabled());
Table_1.setEnabled(!Table_1.isEnabled());

When viewers turn off the two switches, the chart and table won’t refresh when they perform various activities, such as adding
filters to and setting hierarchy level of the chart and table, setting the variable value used by the reference line in the chart and
collapsing the parent node in the table.

Once they turn on the two switches again, the chart and table automatically refresh and display the latest results.

Related Information
Use Refresh Data API

Use Navigation APIs


This is custom documentation. For more information, please visit SAP Help Portal. 93
2/9/25, 4:58 PM
As an application designer or story developer, you can use navigation APIs to let end users navigate from one analytic application
or story to another application or a specific page of a story in view time.

You can define the target story or analytic application to navigate to, parameters to append to its URL, and whether to open it in a
new tab by using the following APIs:

 Code Syntax
NavigationUtils {
openStory(storyId: string, pageId: string, parameters ? : UrlParameter | UrlParameter[], newT
openApplication(appId: string, parameters ? : UrlParameter | UrlParameter[], newTab ? : bool
createStoryUrl(storyId: string, pageId: string, parameters ? : UrlParameter | UrlParameter[]
createApplicationUrl(appId: string, parameters ? : UrlParameter | UrlParameter[]): string
openUrl(url: string, newTab ? : boolean): void
}

 Note
We highly recommend you specify the desired mode for the target application or story via the URL parameter in the API.

 Sample Code

NavigationUtils.openStory("story_id", "page_id", UrlParameter.create('mode','embed'),false);


NavigationUtils.openApplication("application_id", UrlParameter.create('mode','embed'),false);
NavigationUtils.createStoryUrl("story_id", "page_id", UrlParameter.create('mode','embed'));
NavigationUtils.createApplicationUrl("application_id", UrlParameter.create('mode','embed'));

For a list of display parameters, see Use Application URL and Open Story URL.

Example

If you want to let users go to a specific page in a story when they click a button, and the story will be opened in view mode with 123
assigned to script_var_1, write the following script for the button:

 Sample Code

NavigationUtils.openStory("story_id", "page_id", [UrlParameter.create('mode','view'), UrlParamet

In the script above, you don’t need to enter story ID and page ID manually. By entering Ctrl + Space , you can open the value
help. Choose Open story selector, and you can go to My Files and select the corresponding story.

Use Layout APIs


As an application designer or story developer, in addition to directly setting a widget's size and position in a parent container in the
Styling panel, you can use layout related APIs to let viewers to dynamically set a widget's size and position according to the
application or story logic and window size.

In some special cases, API calls will be ignored as they set invalid values:

Changing the height of widgets, such as dropdown, filter line, input slider, and range slider, won't take effect because they
are read-only.

This is custom documentation. For more information, please visit SAP Help Portal. 94
2/9/25, 4:58 PM
Different widgets have minimal width and height size differences. Input values smaller than the minimal size won't take
effect.

Cannot set the size and position of a canvas. You can only get a canvas' current size and position (always {top: 0px, left:
0px}) and set them to a widget.

Related Layout script APIs are as bellow:

 Code Syntax
LayoutUnit.Pixel // sets the unit of the layout as Pixel
LayoutUnit.Auto // sets the unit of the layout as Auto
LayoutUnit.Percent // sets the unit of the layout as Percent
LayoutValue.create(value: number, LayoutUnit: Unit) // sets the layout value by creating a value

getLayout(): Layout // gets the layout of a widget


Layout.getLeft(): Unit; // Returns the left margin between the widget that you define layout for
Layout.setLeft(value: Unit); // Sets the left margin between the widget that you define layout f
Layout.getRight(): Unit; // Returns the right margin between the widget that you define layout f
Layout.setRight(value: Unit); // Sets the right margin between the widget that you define layout
Layout.getTop(): Unit; // Returns the top margin between the widget that you define layout for a
Layout.setTop(value: Unit); // Sets the top margin between the widget that you define layout for
Layout.getBottom(): Unit; // Returns the bottom margin between the widget that you define layout
Layout.setBottom(value: Unit); // Sets the bottom margin between the widget that you define layo
Layout.getWidth(): Unit; // Returns the width of the widget that you define layout for.
Layout.setWidth(value: Unit); // Sets the width of the widget that you define layout for.
Layout.getHeight(): Unit; // Returns the height of the widget that you define layout for.
Layout.setHeight(value: Unit); // Sets the height of the widget that you define layout for.

// Application Canvas Resize Event, the event is cached to be dispatch every 500ms when the appl
Application.onResize() = function() {
};

Application.getInnerHeight() // If canvas' size is fixed, it returns the height of the canvas; i


Application.getInnerWidth() // If canvas' size is fixed, it returns the width of the canvas; if

 Example
Add a table Table_1, a button Button_1 and two shapes Shape_1 and Shape_2 to the canvas or page. Write the script for
Button_1 so that it can set table size to 600*400, and meanwhile set the top margin of Shape_1 to 60 px and the top margin of
Shape_2 to 10 percent of its parent container:

 Sample Code

Table_1.getLayout().setWidth(600);
Table_1.getLayout().setHeight(400);
Shape_1.getLayout().setTop(LayoutValue.create(60,LayoutUnit.Pixel));Shape_2.getLayout().setTop(L

If you set the canvas or page’ size to dynamic, after you click the button and resize your window, the top margin of Shape_1 will
stay as 60 px while the top margin of Shape_2 will automatically fit to new size of the window.

 Example
When the application or story's canvas size is dynamic, write the script for the onResize event to make the size of Table_1
automatically adjust to the size of the window whenever you resize the window.

 Sample Code

var ResponsiveHeight = Application.getInnerHeight().value;


var ResponsiveWidth = Application.getInnerWidth().value;

This is custom documentation. For more information, please visit SAP Help Portal. 95
2/9/25, 4:58 PM

Table_1.getLayout().setHeight(ResponsiveHeight);
Table_1.getLayout().setWidth(ResponsiveWidth);

Related Information
Understand Styling Options of Canvas and Widgets in Analytic Applications

Use APIs on Story Filter and Variables


In Optimized Story Experience, as a story developer, you can use script APIs related to story filters and variables to let story
viewers change the visibility of the filter panel, set story filters and set story variables, for example.

Use APIs Related to Filter Panel


You can use the following APIs to let viewers show or hide the filter panel and check its visibility respectively:

 Code Syntax

FilterPanel.setVisible(bVisible: boolean): void


FilterPanel.isVisible(): boolean

Use APIs Related to Story Filters


You can use script APIs related to story filters, which are applied to all widgets with the same data source across pages. The APIs
also work for linked analysis applied to All Widgets in the Story.

You can use the following script APIs to set, remove and get the story filters respectively:

 Code Syntax

// Only model already in the document is supported.


Application.getFileDataSource(modelId: string): +FileDataSource

// Account or measure member filter is not supported. The API is aligned with UI.
FileDataSource.setDimensionFilterWithHierarchy(dimension: string|+DimensionInfo, hierarchy: stri
FileDataSource.removeDimensionFilter(dimension: string|+DimensionInfo)
FileDataSource.getDimensionFilters(dimension: string|+DimensionInfo):[+FilterValue]

 Tip
For the setDimensionFilterWithHierarchy API, the hierarchy parameter is mandatory. If there's no hierarchy in the
dimensions, use Alias.FlatHierarchy for the parameter.

 Note
Dimension and fixed date range filters are supported, while widget-level measure and dynamic date filter aren't supported by
the APIs.

This is custom documentation. For more information, please visit SAP Help Portal. 96
2/9/25, 4:58 PM
In addition, via the APIs you can let viewers create custom current date (CCD) input controls based on either calendar or fiscal
time:

 Sample Code

class CurrentDateTime {
createCalendarDateTime(calenderTime: +CalendarTime): CurrentDateTime;
createFiscalDateTime(modelId: string, dimension: string|+DimensionInfo/*time dimension*/, fis
}

// API to take effect


Application.setCurrentDateTime(ccd: CurrentDateTime);

// Use case 1 (year)


var calenderYearCCD = CurrentDateTime.createCalendarDateTime({granularity: CalendarTimeGranulari
Application.setCurrentDateTime(calenderCCD);

// Use case 2 (day)


var calenderDayCCD = CurrentDateTime.createCalendarDateTime({granularity: CalendarTimeGranularit
Application.setCurrentDateTime(calenderDayCCD);

// Use case 3 (fiscal year)


var ccdFiscalYear = CurrentDateTime.createFiscalTime("C5ULLISAVFR6N0HM0ZIVIIHURK", "Date_703i190
granularity: FiscalTimeGranularity.FiscalYear,
fiscalYear: 2022
});
Application.setCurrentDateTime(ccdFiscalYear);

Here're the parameters for calendar time:

enum CalendarTimeGranularity {
Year,
HalfYear,
Quarter,
Month,
Week,
Day
}
class CalendarTime {
granularity: CalendarTimeGranularity,
year: integer, // >= 0, for example, 2013
halfYear?: integer, // for example, 1..2
quarter?: integer, // for example, 1..4
month?: integer, // for example, 1..12
week?: integer, // for example, 1..53
day?: integer, // for example, 1..31 (day need to work together with month
}

Here're the parameters for fiscal time:

enum FiscalTimeGranularity {
FiscalYear,

This is custom documentation. For more information, please visit SAP Help Portal. 97
2/9/25, 4:58 PM
FiscalQuarter,
Period,
FiscalDay
}

class FiscalTime {
granularity: FiscalTimeGranularity,
fiscalYear:integer, // >= 0, for example, 2013
fiscalQuarter?: integer, // for example, 1..4
period?: integer, // for example, 1..12
fiscalDay?: integer, // for example, 1..31 (fiscalDay need to work together with period and f
}

Use APIs Related to Story Variables


You can use the following script APIs to set, remove and get the story variables respectively:

 Code Syntax

FileDataSource.setVariableValue(variable: string|+VariableInfo, variableValue: string|number|+Va


FileDataSource.removeVariableValue(variable: string|+VariableInfo)
FileDataSource.getVariableValues(variable: string|+VariableInfo):[+VariableValue]

Use Selection API for Tables and Charts


You can use the selection API for tables and charts in analytic applications and optimized stories to retrieve the currently selected
members and their dimensions.

Get a Selection

The getSelections() API returns an array of Selection objects, each representing a single selection.

Selection API Functions

Selection API Function Return Value

Table_1.getSelections() array of Selection (= Object<string>)

Chart_1.getSelections() array of Selection (= Object<string>)

The properties of such a Selection object are the dimension IDs. The values are the member IDs.

 Sample Code

"dim1": "member1",

"dim2": "member2"

This is custom documentation. For more information, please visit SAP Help Portal. 98
2/9/25, 4:58 PM

You can access the selected member of a dimension using var memberId = selection[“dimensionId”];

You can iterate over all dimensions of a selection with a for-in loop like this:

 Sample Code

var selection = Table_1.getSelections()[0];

for (var dimensionId in selection) {

var memberId = selection[dimensionId];

Use a Selection

With a selection you can retrieve specific data from data sources.

DataSource.getData() expects a selection object:

 Sample Code

var selection = Table_1.getSelections()[0];

var dataCell = Table_1.getDataSource().getData(selection);

When you specify the selection object to be passed onto a getData() call, a value help for dimensions and members helps you
enter the required dimension and member IDs.

Related Information
Use Value Help in Script Editor

Use Result Set APIs


You can use result set API in analytic applications and optimized stories to get a result set based on an input data selection in a
table or chart, so that you can traverse and get each data cell in the result set.

Before the result set API is introduced, you can retrieve individual data cells using DataSource.getData(). However, it can't
retrieve all members for a dimension in a specific result set.

In a result set API, the input data selection specifies all or an arbitrary subset of the initial data set, for example:

 Sample Code

This is custom documentation. For more information, please visit SAP Help Portal. 99
2/9/25, 4:58 PM

//A selection that retrieves values of "sales", "profit" if "maritial_status" is in "M" or "S".
{"marital_status": ["M", "S"], "(MEASURES_DIMENSION)": ["sales", "profit"]}

If the input data selection is left empty, all values of the initial data set will be retrieved.

For a chart with multiple measures per data point, for example, a bubble or scatterplot chart, the result set API will return all
available measures of each data point as different records. And if the source data has a hierarchy, parent member information will
also be returned.

Some changes made by end users at runtime will affect data returned by the result set API as well, including:

Adding rows or columns to a table

Hiding or excluding rows or column in a table.

Only data of visible rows or columns will be returned.

Collapsing parent node in a table.

All its children won't be returned.

Showing total value in a chart

Showing parent in a chart

Getting the new dimension or measure added by smart grouping and new forecast data in a predictive scenario

Adding or removing comments in a chart or table

 Note
If data source is set to lazy load, getResultset(), getDataSelections() returns [ ] and getResultMember() returns
undefined.

 Note
For tables, getDataSource.getData(), getDataSource.getDataSelections(),
getDataSource.getResultMember() and getDataSource.getResultSet() APIs only retrieve data from displayed
cells, which are by default an upper limit of 500 rows and 60 columns. Therefore, if your table has more data to render, you can
set its drill limit to unlimited so that these APIs work on all the data in it. For more information, refer to Use Tables to Visualize
Data.

Script APIs
Take table as an example:

 Code Syntax
// Returns the result sets according to the selections.
Table_1.getDataSource().getResultSet(selection?: Selection | Selection[] | SelectionContext, off

// Returns the context of the data cells.


Table_1.getDataSource().getDataSelections(selection?: Selection | Selection[] | SelectionContext

//Returns the result member by dimension ID and selection. This works for data cells and header
Table_1.getDataSource().getResultMember(dimension: String | DimensionInfo, selection: Selection)

//Returns number of visible rows and columns to help users understand current table structure.

This is custom documentation. For more information, please visit SAP Help Portal. 100
2/9/25, 4:58 PM
Table.getRowCount(): integer
Table.getColumnCount(): integer

For more information about the APIs, refer to Analytics Designer API Reference (for analytic applications) or Optimized Story
Experience API Reference (for optimized stories).

Code Examples

 Example
The first example specifies that the input parameter location equals CT1.

 Sample Code

Chart_1.getDataSource().getResultset({
"@MeasureDimension": "[Account_BestRunJ_sold].[parentId].&[Gross_Margin]",
"Location_1": "[Location_1].[State_1].&[CT1]"
});

It returns the following result set:

 Output Code

[{
"@MeasureDimension": {
"id": "[Account_BestRunJ_sold].[parentId].&[Gross_Margin]",
"description": "Gross Margin",
"formattedValue": "489000000",
"rawValue": "489000000"
},
"Location_1": {
"id": "[Location_1].[State_1].&[CT1]",
"description": "California",
"parentId": "[Location_1].[State_1].&[SouthAmerica]"
}
}]

 Example
The second example leverages the getDataSelections API to get the product members of the selected data in the table.

 Sample Code

// Get distinct product member of the table widget


var selections = Table_1.getDataSource().getDataSelections();
var memberIds = ArrayUtils.create(Types.string);
for (var i = 0; i < selections.length; i++) {
var member = Table_1.getDataSource().getResultMember("Product_1", selections[i]);
if (member && member.id && memberIds.indexOf(member.id) < 0) {
memberIds.push(member.id);

This is custom documentation. For more information, please visit SAP Help Portal. 101
2/9/25, 4:58 PM
}
}

Use setDimensionFilter API on Range and Exclude Filters


As an application designer or story developer, you can use script API DataSource.setDimensionFilter() on range filters
and exclude filters.

Exclude Filters

You can filter out members from the drill-down with exclude filters. The following examples show the use of exclude filters:

In the following example, a single filter value is set for dimension "EMPLOYEE_ID". This keeps only the member with
employee ID 230 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {value: "230"});

In the following example, a single but excluding filter value is set for dimension "EMPLOYEE_ID". This removes the
member with employee ID 230 from the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {value: "230", exclude: true});

In the following example, multiple filter values are set for dimension "EMPLOYEE_ID". This keeps the members with
employee IDs 230 and 240 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {values: ["230", "240"]});

In the following example, multiple but excluding filter values are set for dimension "EMPLOYEE_ID". This removes the
members with employee IDs 230 and 240 from the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {values: ["230", "240"], exclude: true});

Range Filters
You can filter ranges of members in the drill-down with range filters.

Numeric Dimensions

 Note

This is custom documentation. For more information, please visit SAP Help Portal. 102
2/9/25, 4:58 PM
SAP BW doesn't support numeric dimensions.

The following examples show the use of range filters on numeric dimensions:

In the following example, the range filter applied to dimension "EMPLOYEE_ID" keeps the members with employee IDs
between 230 and 240 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {from: "230", to: "240"});

In the following example, the range filter applied to dimension "EMPLOYEE_ID" keeps the members with employee IDs
less than 230 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {less: "230"});

In the following example, the range filter applied to dimension "EMPLOYEE_ID" keeps the members with employee IDs
less or equal than 230 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {lessOrEqual: "230"});

In the following example, the range filter applied to dimension "EMPLOYEE_ID" keeps the members with employee IDs
greater or equal than 230 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {greaterOrEqual: "230"});

In the following example, the range filter applied to dimension "EMPLOYEE_ID" keeps the members with employee IDs
greater than 230 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", {greater: "230"});

You can also apply multiple range filters at once.

In the following example, the range filter applied to dimension "EMPLOYEE_ID" keeps the members with employee IDs
less than 230 and greater than 240 in the drill-down:

 Sample Code

DS_1.setDimensionFilter("EMPLOYEE_ID", [{less: "230"}, {greater: "240"}]);

Time Dimensions

This is custom documentation. For more information, please visit SAP Help Portal. 103
2/9/25, 4:58 PM
You can set time range filters via the setDimensionFilter API. Multiple ranges are supported.

 Restriction
Only fixed time range is supported, while dynamic one isn't supported.

Here's a scripting example, where time range granularity, start and end are specified:

 Sample Code

var current_date = new Date(Date.now());


var current_year = current_date.getFullYear()-8;
var current_month = current_date.getMonth()+1;
var current_quarter = Math.ceil(current_month/3);
var previous_year = current_year -1;

console.log(current_date);
console.log(current_year);
console.log(current_month);
console.log(current_quarter);

//Note : Month is 0 based

//Current Calendar Year


var CurrentYearStart = new Date(current_year,0,1);
var CurrentYearEnd = new Date(current_year,11,31);

//Previous Calendar Year


var PreviousYearStart = new Date(previous_year,0,1);
var PreviousYearEnd = new Date(previous_year,11,31,0,0,0);

var CurrentYearFilter = TimeRange.create(TimeRangeGranularity.Month, CurrentYearStart, CurrentYe


var PreviousYearFilter = TimeRange.create(TimeRangeGranularity.Month, PreviousYearStart, Previo

Table_1.getDataSource().setDimensionFilter("Date_703i1904sd",[CurrentYearFilter,PreviousYearFilt
Chart_1.getDataSource().setDimensionFilter("Date_703i1904sd",[CurrentYearFilter,PreviousYearFilt

 Note
If the time dimensions are set to flat presentation:

For tables, the setDimensionFilter() API still works based on the default dimension hierarchy.

For charts, the setDimensionFilter() API won't take effect. In other words, to set time range filter on charts via
API, make sure that the time dimensions are in hierarchy. For example, you can use setHierarchy() before
setDimensionFilter() API:

 Sample Code

Chart_2.getDataSource().setHierarchy("Date_703i1904sd","YHM");
Chart_2.getDataSource().setDimensionFilter("Date_703i1904sd",[CurrentYearFilter,PreviousYea

This is custom documentation. For more information, please visit SAP Help Portal. 104
2/9/25, 4:58 PM

Use getVariablevalues API


You can use API getVariableValues() in analytic applications and optimized stories, which returns an array of the current
values of the specified variable.

About getVariableValues() API

getVariableValues( variable: string | VariableInfo ) : VariableValue[]

The following example shows how the API is used:

 Sample Code

var values = Table_1.getDataSource().getVariableValues("V_Country"); // 'values' is an array of V

Each value in the array is an instance of either SingleVariableValue, MultipleVariableValue or


RangeVariableValue, which all inherit from VariableValue. To access type-specific properties, define the
VariableValueType property in scripting. See the following section.

 Note
Currently for variables using SAP BW models, in analytics designer getVariableValues() and other variable related APIs
can only access input-ready ones, while in optimized story experience non-input-ready ones are now supported. Customer Exit
variables can’t be accessed via these APIs.

 Note
The following variable related APIs don't work on R visualizations using SAP BW data models:

getDataFrame().getDataSource().getVariables()

getDataFrame().getDataSource().getVariableValues()

getDataFrame().getDataSource().setVariableValue()

Access Type-Specific Properties

 Sample Code

var value = Table_1.getDataSource().getVariableValues("V_Country")[0];


switch (value.type) {
case VariableValueType.Single:
var singleValue = cast(Type.SingleVariableValue, value);
console.log(singleValue.value); // can access the 'value' property now
break;
case VariableValueType.Multiple:
var multiValue = cast(Type.MultipleVariableValue, value);
console.log(multiValue.values); // can access the 'values' property now
break;
case VariableValueType.Range:
var rangeValue = cast(Type.RangeVariableValue, value);
console.log(rangeValue.from); // can access the 'from' property now

This is custom documentation. For more information, please visit SAP Help Portal. 105
2/9/25, 4:58 PM
console.log(rangeValue.to); // can access the 'to' property now
// further range properties: 'less', 'lessOrEqual', 'greater', 'greaterOrEqual'
break;
default:
break;
}

 Note
What you set with setVariableValue is not necessarily the same as what is returned from getVariableValues. For
example, you have several options to set multiple values, and the following two are equivalent:

 Sample Code

Table_1.getDataSource().setVariableValue("V_Country", { values: [ "DE", "FR" ], exclude: true })

Table_1.getDataSource().setVariableValue("V_Country", [ { value: "DE", exclude: true }, { value:

The getVariableValues API will always return as few VariableValue objects as possible, grouping all single values with
the same sign (including or excluding) into one. In the previous example, an array with only one object is returned by
getVariableValues:

[ { values: [ "DE", "FR" ], exclude: true } ]

Use getDimensionFilters API


You can use the API getDimensionFilters() in analytic applications and optimized stories, which returns an array of the
current filter values of the specified dimension.

API Definition

getDimensionFilters(string | +DimensionInfo) : FilterValue[]

The following example shows how the API is used (sample call).

 Sample Code

var values = Table_1.getDataSource().getDimensionFilters("COUNTRY"); // 'values' is an array of

Each value in the array is an instance of either SingleFilterValue, MultipleFilterValue, or RangeFilterValue,


which all inherit from FilterValue.

To work with such an instance, that is, to access its type-specific properties, it needs to be cast to the corresponding type first
using the type property. Please see the following section.

Accessing Type-Specific Properties

This is custom documentation. For more information, please visit SAP Help Portal. 106
2/9/25, 4:58 PM

 Sample Code

var value = Table_1.getDataSource().getDimensionFilters("COUNTRY")[0];


switch (value.type) {
case FilterValueType.Single:
var singleValue = cast(Type.SingleFilterValue, value);
console.log(singleValue.value); // can access the 'value' property now
break;
case FilterValueType.Multiple:
var multipleValue = cast(Type.MultipleFilterValue, value);
console.log(multipleValue.values); // can access the 'values' property now
break;
case FilterValueType.Range:
var rangeValue = cast(Type.RangeFilterValue, value);
console.log(rangeValue.from); // can access the 'from' property now
console.log(rangeValue.to); // can access the 'to' property now
// further range properties: 'less', 'lessOrEqual', 'greater', 'greaterOrEqual'
break;
default:
break;
}

Known Restrictions
Currently the API does not return time range filters.

In SAP BW backend systems you can create valid filters that are not supported by SAP Analytics Cloud yet, for example,
mixing single, multiple, and range filters. As this API implementation is based on SAP Analytics Cloud capabilities, it is also
not able to fully support all filters possible in SAP BW backend systems.

In SAP BW backend systems you can create valid filters that are not yet supported by SAP Analytics Cloud. As this API
implementation is based on SAP Analytics CloudSAP Analytics Cloud, it supports the capabilities of SAP Analytics Cloud.

Use openSelectModelDialog and setModel APIs


As an application designer or story developer in the optimized story experience, you can change the table's model in view time by
using the openSelectModelDialog API to open the Select Model dialog, or directly via the setModel API.

 Note
The setModel API was originally intended for Explorer, which is now fully covered by Data Analyzer. We highly recommend
using Data Analyzer for your data exploration scenarios.

The openSelectModelDialog API opens the model selection dialog:

 Sample Code

Table_1.openSelectModelDialog();

The setModel API lets you directly set a model via its ID.

This is custom documentation. For more information, please visit SAP Help Portal. 107
2/9/25, 4:58 PM

 Code Syntax

setModel(modelID:string);

 Tip
To get the ID of a model, open it in the Modeler, and copy the ID from the URL:

 Sample Code

//Set model via CUID


Table_1.setModel("Cday9flz5ihs3xt1aoaoa5iw3k");

//Set model via EPMObjectId


Table_1.setModel("sap.epm:BestRunJuice_SampleModel");

Use NULL Members and Totals Members in Script APIs


You can use NULL members and Totals members in script APIs in analytic applications and optimized stories.

NULL members often occur in SAP HANA models, where the joining of database tables can produce NULL values. Many existing
APIs didn't handle the NULL member correctly.

Totals members are virtual members that play a role in tables.

 Note
Charts currently don't support totals.

If Show Totals is enabled for a dimension in a table's Builder panel or Totals is enabled in Show/Hide of its  (More Actions)
menu, the Totals member is added to the table. You can use Alias.TotalsMember to refer to it in your scripts.

 Note

This is custom documentation. For more information, please visit SAP Help Portal. 108
2/9/25, 4:58 PM
When writing your scripts, use Alias.TotalsMember to refer to the total of a dimension in the table, and “Total” to refer
to the ID Total in the model.

In addition, you can use Alias.NullMember to refer to the NULL member.

The following DataSource APIs have been enhanced to handle or return NULL or Totals members correctly:

getMembers(): Returns Alias.NullMember for the NULL member's ID.

setDimensionFilter(): Allows to filter on Alias.NullMember.

setVariableValue(): Allows to set Alias.NullMember as the value of a dimension member variable.

getData(): Allows to specify Alias.NullMember in the passed selection, and for tables, also Alias.TotalsMember
to retrieve the value of a totals data cell.

getResultSet(), getDataSelections(): Allows to specify Alias.NullMember and Alias.TotalsMember in


the passed selection.

getResultMember(): Allows to specify Alias.NullMember in the passed selection.

The following table and chart APIs have been enhanced:

getSelections(): Returns Alias.NullMember and Alias.TotalsMember if the corresponding cells have been
selected.

The following planning APIs have been enhanced:

setUserInput(): Allows to specify Alias.TotalsMember in the passed selection, in order to plan a totals cell.

DataLocking.getState(): Allows to specify Alias.TotalsMember in the passed selection.

 Note
Totals cells currently can't be locked, which means setState() doesn't work on them.

Use sendNotification API


You can use sendNotification API in analytic applications and optimized stories to send notifications to viewers. Notifications
can be accessed in the Notifications panel, and via email by configuration in the script.

With sendNotification API, you can send notifications when the analytic application or optimized story is running at the
backend, for example, when it’s scheduled for publication. You can also send in view time, for example, upon click of a button or
initialization of the application or story.

 Note
If you want to send notifications without scheduling, ensure that your own mail server’s been configured. For more information,
refer to Configure Email Server.

 Code Syntax
Application.sendNotification({
title: string,
content?: string,

This is custom documentation. For more information, please visit SAP Help Portal. 109
2/9/25, 4:58 PM
receivers?: string[], // default: current user
mode?: ApplicationMode, // default: Present
parameters?: UrlParameter[], // array, no optional single URL parameter
isSendEmail?: boolean, // default: false
IsSendMobileNotification?: boolean // default: false
});

Each notification includes a title and a button to open the analytic application or story.

You can also configure the following elements:

Contents (in HTML format with limited support, including tags <i>, <b>, <u>, <a> and <br>)

Recipients

 Note
Recipients should be SAP Analytics Cloud users. Currently, notifications can't be sent to non-SAP Analytics Cloud users
via the API.

Application or story mode (Present, Embed or View)

URL parameters as key-value pairs

Whether to send an email notification or not

Whether to send the notification to SAP Analytics Cloud iOS mobile app or not

 Example
In this example, when the application or story is opened, it will send notifications to Jack if <quantitySold> is below 50 million.
He can receive notifications in both Notifications panel and email, and open the application or story in presentation mode. The
notification title is Quantity sold below 50M, and content is The quantity sold is below estimation. For more details, please
check it out..

Write the following script for the onInitialization event of canvas:

 Sample Code

if (quantitySold < 50) {


var notificationTitle = "Quantity sold below 50M";
var notificationContent = “The quantity sold is below estimation. For more details, please ch
Application.sendNotification({
title: notificationTitle,
content: notificationContent,
receivers: ["Jack"],
mode: ApplicationMode.Present,
isSendEmail: true
});
}

Related Information
Configure Scheduling of Publication

This is custom documentation. For more information, please visit SAP Help Portal. 110
2/9/25, 4:58 PM

Use Comment-Related APIs


As an application designer or story developer, you can use APIs to let viewers show or hide all comments, handle table cell
comments and manage filters on comment widgets.

The comment APIs support comment widgets and SAP BW live data models. Data cell comments edited by APIs are synchronized
with comment widgets as well.

API to Show or Hide Comments


You can use the following API to enable or disable comment mode, which means showing or hiding all the comments:

 Code Syntax

setCommentModeEnabled(isEnabled: boolean): void

APIs to Manage Table Cell Comments


You can use the APIs to let viewers get, remove, add, update and like table cell comments.

 Code Syntax
CommentInfo { //For BW commenting, CommentInfo always refers to latest comment
'commentId': 'string', // For BW commenting, commentId refers to the unique technical Docume
'text': 'string',
'createdAt': 'string',
'numberOfLikes': 'integer', //For BW commenting, this field should be undefined
'createdBy': '+UserInfo'
}

getComment(commentId: string): CommentInfo


getAllComments(selection: Selection): CommentInfo[]//For BW commenting, returns the only comment

removeComment(commentId: string): boolean


removeAllComments(selection: Selection): boolean//For BW commenting, removes the only comment al

addComment(selection: Selection, value: string): CommentInfo


addComments(selection: Selection, value: string[]): CommentInfo[]//Not supported for BW commenti

updateComment(commentId: string, value: string): CommentInfo//Updates comment with the latest ve

setCommentLiked(commentId: string, isLiked: boolean): boolean//Not supported for BW commenting,

 Example
For example, you’ve created an input field InputField_1 and would like to let viewers:

1. Select Button_1 to see the comment on a table cell in the input field.

2. Select Button_2 and post the comment in the input field to any selected table cell.

First, write the following script for Button_1:

 Sample Code

var comments = Table_1.getDataSource().getComments().getAllComments(Table_1.getSelections()[0]);


console.log(comments);
var str = "";

This is custom documentation. For more information, please visit SAP Help Portal. 111
2/9/25, 4:58 PM
for (var i = 0; i < comments.length; i++) {
var txt = comments[i].text;
str = str + txt;
}
InputField_1.setValue(str);

Then write the following script for Button_2:

 Sample Code

var str = InputField_1.getValue();


Table_1.getDataSource().getComments().addComment(Table_1.getSelections()[0], str);

APIs to Manage Filters on Comment Widgets


You can also use the following APIs to set, get or remove filters on comment widgets:

 Code Syntax

setDimensionFilter(dimension: string | DimensionInfo, member: string | string[] | MemberInfo | M


getDimensionFilters(dimension: string | DimensionInfo) : FilterValue[]
removeDimensionFilter(dimension: string | DimensionInfo)

 Example
Here’s a script example that shows how to make a comment shown in a specific comment widget and apply the same filter as
table to it.

Write the following script, so that when 2021 is selected in the filter Date, the comments in CommentWidget_1 are displayed:

 Sample Code

CommentWidget_1.getCommentingDataSource().setDimensionFilter("Date_703i1904sd", "[Date_703i1904s

Furthermore, write the following script to copy the filter Location from Table_1 to CommentWidget_1:

 Sample Code

var filter = Table_1.getDataSource().getDimensionFilters("Location_4nm2e04531")[0];


if (filter.type === FilterValueType.Single) {//Table_1 has dimension filter "Location=SA1"
var singleFilter = cast(Type.SingleFilterValue, filter);
CommentWidget_1.getCommentingDataSource().setDimensionFilter("Location_4nm2e04531", singleFi
} else if (filter.type === FilterValueType.Multiple) {//Table_1 has dimension filters "Location=
var multipleFilter = cast(Type.MultipleFilterValue, filter);
CommentWidget_1.getCommentingDataSource().setDimensionFilter("Location_4nm2e04531", multiple
}

Related Information
This is custom documentation. For more information, please visit SAP Help Portal. 112
2/9/25, 4:58 PM
Add Comment Widgets to Stories
Add Comments to Data Cells in Tables
Collaborate by Adding Comments to Stories

Define Busy Indicators and Use Related APIs


As an application designer or story developer, you can define busy indicators and use related APIs to temporarily block viewers
from doing other actions, for example, when the analytic application or optimized story is loading or when the script is running.

There are two types of busy indicators:

Busy indicator that displays automatically when loading is longer than the predefined delay. Once it’s prompted, the
actions in the entire analytic application or optimized story are blocked.

Busy indicator that’s owned by an analytic application or optimized story, popup or container, such as a tab strip or panel.
It’s defined by APIs and when it’s prompted, only the actions on that specific level are blocked.

Define an Automatic Busy Indicator


You can define an automatic busy indicator, which can be prompted by loading activities on either application or story level or
widget level. Whenever there’s a loading that exceeds the predefined delay time, the entire application or story is blocked.

Procedure
1. For analytic applications, go to the Styling panel of Canvas. For optimized stories, select Global Settings from the
Outline panel.

2. Under Loading Indicator Settings, select Enable loading indicator when necessary.

3. Optional: Enter information text that you want to display with the loading indicator icon.

4. Under Loading Indicator Delay, define the time in millisecond to be delayed before the loading indicator shows up.

Results
In view time, the loading indicator automatically appears when the loading activity exceeds the time you've defined, and
disappears after it's completed.

API to Enable an Automatic Busy Indicator


You can also use API for enabling an automatic busy indicator.

 Code Syntax
Application.setAutomaticBusyIndicatorEnabled (enabled: boolean)

The information text and loading indicator delay time follow the settings in the Styling panel of canvas (for analytic applications)
or Global Settings (for optimized stories).

APIs to Enable Busy Indicators on Different Levels


This is custom documentation. For more information, please visit SAP Help Portal. 113
2/9/25, 4:58 PM
You can use APIs to show or hide busy indicators on different levels so that only the actions on the specific levels are blocked when
such busy indicators are prompted in view time.

You can leverage APIs to show or hide busy indicators for:

Applications or stories

Popups

Containers (including tab strips and panels)

 Code Syntax
// Show busy indicator. And if the text parameter is specified, show the text along with the bus
Application.showBusyIndicator(text?: string) // cover the whole page
Popup_1.showBusyIndicator(text?: string) // cover the pop up only
TabStrip_1.showBusyIndicator(text?: string) // cover the tab strip only
Panel_1.showBusyIndicator(text?: string) // cover the panel only

// Hide busy indicator


Application.hideBusyIndicator()
Popup_1.hideBusyIndicator()
TabStrip_1.hideBusyIndicator()
Panel_1.hideBusyIndicator()

The automatic busy indicator is fully independent of the busy indicators defined in this way, which means that when the automatic
busy indicator is enabled, it won’t affect calls to Application.showBusyIndicator() or
Application.hideBusyIndicator().

Example

In this example, you can write scripts to show the busy indicator when a request is sent via a postMessage event and hide it
when a response is received from the outside page:

 Sample Code

button.onClick() {
Application.showBusyIndicator(); // Show application manual indicator
Application.postMessage(PostMessageReceiver.Parent, message, "http://localhost:8080");
}

Application.onPostMessageReceived(message:string, origin: string) {


if (message === "JOB_DONE") {
Application.hideBusyIndicator();// Hide application manual indicator when getting the re
}
}

Use APIs to Get User Information


As an application designer or story developer, you can use getUserInfo(), getTeamsInfo() and getRolesInfo() APIs,
which return information about the current user in view time.

You can use getUserInfo() API to get information about the user currently using your analytic application or optimized story:

This is custom documentation. For more information, please visit SAP Help Portal. 114
2/9/25, 4:58 PM

 Sample Code

Application.getUserInfo()

It returns the following user information, for example:

 Output Code

{
"id": "666666",
"displayName": "John",
}

In addition, you can use the following APIs respectively if you only want to get the team or role of the current user.

 Sample Code
Application.getTeamsInfo()

The getTeamsInfo() API returns all the teams the current user belongs to, for example:

 Output Code

[
{ "name": "DataActionRole_Admin", "description": "" },
{ "name": "127", "description": "127 Test" },
{ "name": "MultiActionRole_Admin", "description": "" },
{ "name": "Team_Supervisor", "description": "" }
]

 Sample Code
Application.getRolesInfo()

The getRolesInfo() API returns all the roles of the current user, for example:

 Output Code

[
"Admin",
"BI Admin"
]

 Note
To use getTeamsInfo() or getRolesInfo() API, viewers need to have the Read permission for the object type Team or
Role.

This is custom documentation. For more information, please visit SAP Help Portal. 115
2/9/25, 4:58 PM

Scripting Example 1: Use OData Actions in Analytics Designer or


Optimized Story Experience
As an application designer or story developer, you can let viewers execute OData (V4) actions within an analytic application or
optimized story, which are exposed by a connected on-premise SAP S/4HANA system.

Prerequisites
You've created an analytic application or optimized story and added an OData service to it.

Context
In this example, there're following elements for ODataService_1:

The system: FUB

The end-point URL for the OData service

As metadata, the OData version and two actions, Flight/Book and CancelMyFlights

This is custom documentation. For more information, please visit SAP Help Portal. 116
2/9/25, 4:58 PM

Procedure
1. Add a button widget.

2. In the Properties section of the button's Styling panel, change the text to Cancel Flight.

3. Select in the quick actions menu of the widget to open the script editor.

You'd like to write a script to run the OData action in the source system.

4. In the script editor, do the following:


This is custom documentation. For more information, please visit SAP Help Portal. 117
2/9/25, 4:58 PM
a. Type the name of the OData service you've added and specified, ODataService_1, followed by ..

b. Press CTRL + Space , and the script editor assists you with code completion and value help wherever possible.
Select the function executeAction().

c. Place the mouse cursor between the brackets ( () ), press CTRL + Space , and then select action
CancelMyFlights from the value help of executeAction(), followed by , and {}.

d. Place the mouse cursor between the brackets ({}), press CTRL + Space , and select the parameter DateFrom
from value help, followed by : .

e. Type the date 2019-01-01, followed by ,.

f. Press CTRL + Space , and select DateTo from value help, folllowed by :.

g. Type in the date 2019-12-31, and finish with ;.

You've created a script to execute an OData action. This action has a simple syntax with two parameters and looks like this:

ODataService_1.executeAction("CancelMyFlights", {DateFrom: "2019-01-01", DateTo: "2019-12-31"

5. Insert another button, rename it to Book Flight in the Styling panel, and open the script editor.

The BookFlight Action is a bound action, which is more complex than the first one.

6. Type the following script in the script editor by using code completion and value help:

ODataService_1.executeAction("Flight/Book", {Flight:{Airline:"UA",Flightconnection:"0941", Fl

Results
You've configured a simple OData action. Now you can run your application or story, and book and cancel flights for the selected
values.

You can enhance your application or story and start using other script methods to fill the parameter values dynamically with local
or global variables.

Finally, you can make the response from the back end system visible in the application or story via a text field. To find out more
details, see Scripting Example 2: Use OData Actions in Analytics Designer or Optimized Story Experience.

Scripting Example 2: Use OData Actions in Analytics Designer or


Optimized Story Experience
As an application designer or story developer, you can display the back end system's response to an OData action run in your
analytic application or optimized story via text widgets and scripts.

Prerequisites
You've created an analytic application or optimized story with OData actions and two buttons to book and cancel flights for
selected values.

Procedure
1. Add six text widgets.

2. For Text_6, enter MessageBox as its ID and MessageBox as the text.

This is custom documentation. For more information, please visit SAP Help Portal. 118
2/9/25, 4:58 PM

3. For the Book Flight button, rewrite with the following script:

var ret = ODataService_1.executeAction("Flight/Book", {Flight:{Airline:"UA",Flightconnection:


var succ = "";
if (ret.ok === true) {
succ = "SUCCESS";
} else {
succ = "ERROR";
}
MessageBox.applyText(succ);
Text_2.applyText(succ + " message :" + ret.error.message);
Text_3.applyText(succ + " code :" + ret.error.code);
Text_4.applyText("target :" + ret.error.target);
Text_5.applyText("");

4. For the Cancel Flight button, rewrite with the following script:

var ret = ODataService_1.executeAction("CancelMyFlights", {DateFrom: "2019-01-01", DateTo: "2


console.log(ret);
var succ = "";
if (ret.ok === true) {
succ = "SUCCESS";
} else {
succ = "ERROR";
}
MessageBox.applyText(succ);
Text_2.applyText(succ + " message :" + ret.error.message);
Text_3.applyText(succ + " code :" + ret.error.code);
Text_4.applyText("target :" + ret.error.target);
var info = "";
//if (false) {
if (ret.ok === true) {
var numberofoccupiedseats = ConvertUtils.integerToString(ret.value[0].Numberofoccupiedseats);
var flightprice = ConvertUtils.numberToString(ret.value[0].Flightprice);
var totalnumberofseats = ConvertUtils.integerToString(ret.value[0].Totalnumberofseats);
var currency = ret.value[0].Currency;
info = "Your flight price was " + flightprice + " " + currency + ". " + "There are " + number
}
Text_5.applyText("" + info);

This is custom documentation. For more information, please visit SAP Help Portal. 119
2/9/25, 4:58 PM
5. Run the application or story, and book and cancel a flight to see the error messages.

Best Practice: Switch Between Chart and Table


As an application designer or story developer, learn how to let viewers switch between a chart and a table by a toggle.

Prerequisites
You've already added a table and a chart widget and placed them on top of each other.

For the table, if the pagination option (Auto-Size and Page Table Vertically) was selected, you've deselected it.

 Note
The visibility setting that is used for the script is also used for table pagination. Using table pagination and the visibility
script in the same story tab may not provide the results that you expect to see.

To follow this sample use case, use the model BestRun_Advanced as data source.

Context

To switch between the chart and table, you add one image that represents a chart and the other one that represents a table. Then
you write scripts for each of the images so that when viewers click on the chart image, the chart appears and the table is hidden,
and vice versa.

The default view time settings are to have the table visible and the chart invisible.

Procedure
1. For the table widget:

a. Go to the Styling panel. Under Actions, (for analytic applications) make sure that Show this item at view time is
selected, or (for optimized stories) set the view time visibility to Visible.

b. Under (for analytic applications) Analytics Designer Properties or (for optimized stories) Generic Properties,
change the name of the widget to Table.

2. For the chart widget:

a. Go to the Styling panel. Under Actions, (for analytic applications) deselect Show this item at view time, or (for
optimized stories) set the view time visibility to Hidden.

b. Under (for analytic applications) Analytics Designer Properties or (for optimized stories) Generic Properties,
change the name of the widget to Chart.

3. Add the images you want viewers to click on when they toggle between chart and table.

For example: and .

a. Insert an image widget.

b. Optional: If you need to upload the image first, click Upload Image and upload your images.

c. Select the chart image from the image library.

d. Repeat the steps for the table image, and place the table image directly on top of the chart image.

When viewers click on the chart image, the table image appears in the same place.

4. To enable the switch between table and chart, you need to edit the names and then the scripts of both images. Change the
name of the table image to Switch_to_Table_display, and the name of the chart image to
Switch_to_Chart_display.
This is custom documentation. For more information, please visit SAP Help Portal. 120
2/9/25, 4:58 PM
5. To edit the chart image's script, from the chart image's context menu, select Edit Scripts... onClick .

The script editor of this image's onClick event opens. Here, write a script that makes it possible to switch from the chart
to the table.

6. Enter this script:

 Sample Code

Chart.setVisible(true);
Table.setVisible(false);
Switch_to_Table_display.setVisible(true);
Switch_to_Chart_display.setVisible(false);

This script makes the chart visible and the table invisible, and it makes the table image visible and the chart image invisible.
You've configured the application or story in a way that when the chart is visible, the table image is visible indicating that
viewers can switch back to the table.

7. Similarly, from the table image's context menu, select Edit Scripts... onClick .

8. Enter this script in the script editor:

 Sample Code

Chart.setVisible(false);
Table.setVisible(true);
Switch_to_Table_display.setVisible(false);
Switch_to_Chart_display.setVisible(true);

This script makes the table visible and the chart invisible, and it makes the chart image to visible and the table image
invisible. You've configured the application or story in a way that, when the table is visible, the chart image is visible
indicating that viewers can switch back to the chart.

9. Save the application or story, and open it in view time.

Results
In view time, the application or story looks like this:

This is custom documentation. For more information, please visit SAP Help Portal. 121
2/9/25, 4:58 PM

The table is displayed, because you've set it to be visible by default. When you click on the chart image, the chart appears
instead of the table, and the image is changed to a table icon:

When you click on the table image, the table appears instead of the chart, and the image is changed to a chart icon, back to the
default view.

Best Practice: Filter Table and Chart Through Dropdown (Single


Selection)

This is custom documentation. For more information, please visit SAP Help Portal. 122
2/9/25, 4:58 PM
As an application designer or story developer, learn how to let viewers filter on a table or a chart by selecting a single measure from
a dropdown widget.

Prerequisites
You've already added a table and a chart widget and placed them on top of each other.

To follow all functions of this sample use case, you've completed the exercise Best Practice: Switch Between Chart and
Table and can now enhance your analytic application or optimized story.

Context
The dropdown widget lists all the measures of your data source, which acts as measure filter. When viewers select a measure from
it, the filter is applied to both table and chart.

Procedure
1. Insert a dropdown.

2. Change the name of the dropdown to Dropdown_Measures.

3. Add a label to the dropdown to indicate to viewers that they can select measures through the dropdown.

a. Insert a text widget

b. Place the text widget to the left of the dropdown.

c. Enter a text, Selected Measure, for example.

d. Optional: Resize the text widget.

4. To let viewers select a value from the dropdown, define a script variable that acts as a global variable, which can be
accessed from anywhere in your application or story.

a. From Scripting in Outline, add a script variable.

b. In the Script Variable panel, enter CurrentMeasureFilterSelection as name, leave type as string, and enter
[Account_BestRunJ_sold].[parentId].&[Gross_MarginActual] as default value.

c. To close the Script Variable panel, select Done.

5. To define what happens when users select a value from the dropdown, create a script object. In this object, write a function
that sets the measure filter according to what the user has chosen from the dropdown.

a. From Scripting in Outline, add a script object.

b. To rename the folder, hover over ScriptObject_1, and select (More) Rename . Enter Utils.

c. To rename the function, hover over function1, and select (More) Rename . Enter setMeasureFilter.

d. Select the function setMeasureFilter, and when the Script Function panel opens, select (Add Argument).

e. Enter selectedId as name of the argument, leave type as string, and select Done.

f. To write the script for the function, hover over the function setMeasureFilter, select (Edit Scripts). Enter the
following script in the script editor:

 Sample Code

Table.getDataSource().removeDimensionFilter("Account_BestRunJ_sold");
if (CurrentMeasureFilterSelection !== "") {
Chart.removeMeasure(CurrentMeasureFilterSelection, Feed.ValueAxis);
}

This is custom documentation. For more information, please visit SAP Help Portal. 123
2/9/25, 4:58 PM
Table.getDataSource().setDimensionFilter("Account_BestRunJ_sold",selectedId);
Chart.addMeasure(selectedId, Feed.ValueAxis);

With this script you define what happens to the table and the chart when users select a measure from the
dropdown. The existing filters applied to the table and chart are removed and replaced with captured values.

6. To define how to pass the captured value to the setMeasureFilter function, write script for the onSelect event of the
dropdown widget. Hover over the dropdown widget in Outline, select (Edit Scripts), and enter the following script:

 Sample Code

Utils.setMeasureFilter(Dropdown_Measures.getSelectedKey());

This script gets the selected value of the dropdown and passes it to the setMeasureFilter function as parameter.

7. To define what happens when the analytic application or optimized story is first run, write script for the
onInitialization event of the application or story page. In Outline hover over Canvas (for analytic applications) or the
relevant page (for optimized stories), select (Edit Scripts) onInitialization , and enter the following script:

 Sample Code

var measures = Table.getDataSource().getMeasures();


var selectedKey = "";
if (measures.length > 0) {
for (var i=0;i<measures.length; i++){
// Measure
Dropdown_Measures.addItem(measures[i].id,measures[i].description);
if (selectedKey === "" && i === 0) {
selectedKey = measures[i].id;
Dropdown_Measures.setSelectedKey(selectedKey);
console.log(["selectedKey ", selectedKey]);
}
console.log(["CurrentMeasure ", measures]);
}
}
Utils.setMeasureFilter(selectedKey);

With this script you can make sure that on initialization, all the available measures of the table are loaded into the
dropdown. The first measure in the list is the selected value and filter.

8. Save the application or story, and open it in view time.

Results
Your application or story looks like this when opened in view time:

This is custom documentation. For more information, please visit SAP Help Portal. 124
2/9/25, 4:58 PM

You can select a measure from the dropdown list to filter on the table:

You can select to switch to the chart:

The measure selected from the dropdown filters on the chart as well. When you select Discount, the chart looks like this:

This is custom documentation. For more information, please visit SAP Help Portal. 125
2/9/25, 4:58 PM

Best Practice: Filter Table and Chart Through Checkboxes (Multi-


Selections)
As an application designer or story developer, learn how let viewers to filter on a table or a chart by selecting multiple measures
from a checkbox group.

Prerequisites
You've already added a table and a chart widget and placed them on top of each other.

To follow all functions of this sample use case, you've completed the exercise Best Practice: Switch Between Chart and
Table and can now enhance your analytic application or optimized story.

Context

Compared to the dropdown widget, the checkbox group widget allows for multiple selections. In this use case, you add a checkbox
group widget, which lists all the measures of your data source and acts as measure filters. On top of that, you add three buttons:

Button set selected, which filters on the table and chart according to the selected measures from the checkbox group

Button remove all, which removes all the selected measures and saves from deselecting them one by one in the checkbox
group

Button set all, which applies all the available measures to the table and chart and saves from selecting them one by one in
the checkbox group

Procedure
1. Add a checkbox group, and place it on the left side of your table.

2. Change the name of the checkbox group to CheckboxGroup_Measures.

3. In the Builder panel of the checkbox group, select Value 1 and then (Delete) to remove it. Remove Value 2 in the same
way.

4. Add a label to the checkbox group to indicate to viewers that they can select measures through the checkboxes.

a. Insert a text widget.

This is custom documentation. For more information, please visit SAP Help Portal. 126
2/9/25, 4:58 PM
b. Place the text widget on top of the checkbox group.

c. Enter a text, Measures, for example.

d. Optional: Resize the text widget.

5. For easy access to the checkbox group's measures, add the three buttons mentioned earlier:

a. Insert three buttons and place them beneath the label.

b. In the Styling panel of the first button, enter Button_setMeasureFilter as name and set selected as text.

c. In the Styling panel of the second button, enter Button_removeAllMeasures as name and remove all as
text.

d. In the Styling panel of the third button, enter Button_setAllMeasures as name and set all as text.

6. To access the values that viewers select in the checkbox group, create two script variables, which act as global variables
and can be accessed from anywhere in your application or story:

The first script variable AllMeasures is set as an array and holds all the measures that viewers can select in the
checkbox group.

The second script variable CurrentMeasureFilterSelection is set as a string and holds the measures that
viewers have selected in the checkbox group.

a. From Scripting in Outline, add a script variable.

b. In the Script Variable panel, enter AllMeasures as name, leave type as string, and switch on Set As Array.

c. To close the Script Variable panel, select Done.

d. Repeat the steps to create a second script variable. Enter CurrentMeasureFilterSelection as name, leave
type as string, and switch on Set As Array.

7. To define what happens when viewers select a filter value in the checkbox group, create a script object. In this object, write
a function that sets the measure filter according to what viewers have chosen from the checkbox group.

a. From Scripting in Outline, add a script object.

b. To rename the folder, hover over ScriptObject_1, and select More Rename . Enter Utils.

c. To rename the function, hover over function1, and select More Rename . Enter setMeasureFilter.

d. Select the function setMeasureFilter, and when the Script Function panel opens, choose (Add Argument) in the
Arguments section.

e. Enter selectedIds as name of the argument, leave type as string, switch on Set As Array. Choose Done twice to
close the panels.

f. To write the script for the function setMeasureFilter, hover over it in Outline, and choose (Edit Scripts). Enter
the following script in the script editor:

 Sample Code

// remove Measures
Table.getDataSource().removeDimensionFilter("Account_BestRunJ_sold");
if (CurrentMeasureFilterSelection !== [""]) {
for (var i=0;i<CurrentMeasureFilterSelection.length; i++){
Chart.removeMeasure(CurrentMeasureFilterSelection[i], Feed.ValueAxis)
}
}

// add Measures
Table.getDataSource().setDimensionFilter("Account_BestRunJ_sold",selectedIds);
for (i=0;i<selectedIds.length; i++){

Chart.addMeasure(selectedIds[i], Feed.ValueAxis);

This is custom documentation. For more information, please visit SAP Help Portal. 127
2/9/25, 4:58 PM
}
// save the current selection into global variable
CurrentMeasureFilterSelection = selectedIds;

With this script you define what happens to the table and the chart when viewers select filter values in the checkbox
group:

The set measures of the table and chart are removed.

The values selected in the checkbox group are added as new measures of the table and chart.

The currently selected measures are saved in the script variable CurrentMeasureFilterSelection.

8. Define what happens when viewers click on the buttons.

a. Hover over the set selected button in Outline, select , and enter the following script in the script editor:

 Sample Code

Utils.setMeasureFilter(CheckboxGroup_Measures.getSelectedKeys());

The script calls the Utils.setMeasureFilter function and passes to it the selected measures of the checkbox
group.

b. Hover over the remove all button in Outline, select , and enter the following script in the script editor:

 Sample Code

CheckboxGroup_Measures.setSelectedKeys([""]);
Utils.setMeasureFilter([""]);

The script removes all the selected measures from the checkbox group and passes an empty array to
Utils.setMeasureFilter, which updates your table and chart as well as your global variable
CurrentMeasureFilterSelection.

c. Hover over the set all button in Outline, select , and enter the following script in the script editor:

 Sample Code

CheckboxGroup_Measures.setSelectedKeys(AllMeasures);
Utils.setMeasureFilter(AllMeasures);

The script sets the selected keys of the checkbox group to the AllMeasures script variable you defined before and
passes the same variable to the Utils.setMeasureFilter function.

9. Define what happens when the application or story is first run.

a. In Outline hover over Canvas (for analytic applications) or the relevant page (for optimized stories), select
(Edit Scripts) onInitialization .

b. Enter the following script in the script editor:

 Sample Code

// get all measures from the table data source


var measures = Table.getDataSource().getMeasures();

This is custom documentation. For more information, please visit SAP Help Portal. 128
2/9/25, 4:58 PM

// define array or the selected Keys


var selectedKeys = ArrayUtils.create(Type.string);

if (measures.length > 0) {
for (var i=0;i<measures.length; i++){
// add the Measure to checkbox group
CheckboxGroup_Measures.addItem(measures[i].id,measures[i].description
//add the measure to the selectedKeys
selectedKeys.push(measures[i].id);
CheckboxGroup_Measures.setSelectedKeys(selectedKeys);

console.log(["CurrentMeasure ", measures]);


}
}

console.log(["selectedKey ", selectedKeys]);


AllMeasures = selectedKeys;
Utils.setMeasureFilter(selectedKeys);

With this script, you make sure that on initialization, all the available measures of the table's data source are loaded.
You define a selected keys array of type string and, using a loop, you add the measures to your checkbox group and
the selected keys array. You also call on the setSelectedKeys function of the checkbox group and set its selected
keys to your array. Finally, you set the script variable AllMeasures and the measure filter to the selected keys.

10. Save the application or story, and open it in view time.

Results
When you run the application or story, it looks like this:

If you click on the remove all button, all measures are deselected, and there's no data on the table.

This is custom documentation. For more information, please visit SAP Help Portal. 129
2/9/25, 4:58 PM

If you click on the set all button, all measures are selected and the table looks the same as when you first ran the application or
story.

Let's select a few measures, Gross Margin Plan, Quantity Sold, Original Sales Price abs Dev, and Discount, in the checkbox group
and click on the set selected button. The table is updated accordingly.

This is custom documentation. For more information, please visit SAP Help Portal. 130
2/9/25, 4:58 PM

The same applies to the chart after you click on .

Best Practice: Use Filter Line for Filtering Switchable Table and
Chart
As an application designer or story developer, learn how to make a filter line apply to both your chart and table, which are switched
between each other.

Prerequisites

You've already added a table and a chart widget and placed them on top of each other.

To follow all functions of this sample use case, you've completed the exercise Best Practice: Switch Between Chart and
Table and can now enhance your analytic application or optimized story.

Procedure
1. Add a filter line, and place it above the table.

2. Change the name of the filter line to FilterLine.

3. In the Builder panel of the filter line:

a. Under Source Widget, select the table.

b. Under Dimension Selection, choose + Add Dimension, and select Location, Product, Sales Manager and Store
from the dropdown list.

4. Write the script to ensure that the filters stay the same after table and chart switch:

a. Hover over the table in Outline, and select (Edit Scripts) onResultChanged .

b. Enter this script in the script editor:

 Sample Code

console.log('OnResultChanged');
Chart.getDataSource().copyDimensionFilterFrom(
Table.getDataSource(), "Location_4nm2e04531");
Chart.getDataSource().copyDimensionFilterFrom(

This is custom documentation. For more information, please visit SAP Help Portal. 131
2/9/25, 4:58 PM
Table.getDataSource(), "Product_3e315003an");
Chart.getDataSource().copyDimensionFilterFrom(
Table.getDataSource(),
"Sales_Manager__5w3m5d06b5");
Chart.getDataSource().copyDimensionFilterFrom(
Table.getDataSource(),
"Store_3z2g5g06m4.Store_GEOID");

The script copies each of the dimension filters added in the filter line.

5. Save the application or story, and open it in view time.

Results
When you run the application or story, it looks like this:

When you select the filter line, the four measures you've configured appear.

When you select one of the measures, in this example, Location, a window pops up, which lets you choose the members to be
included in the table or chart. Let's select San Francisco, Las Vegas and Portland.

This is custom documentation. For more information, please visit SAP Help Portal. 132
2/9/25, 4:58 PM

The table is updated. The same applies to the chart when you switch to it.

This is custom documentation. For more information, please visit SAP Help Portal. 133
2/9/25, 4:58 PM

Best Practice: Filter Table and Chart Through Cascaded Filtering


As an application designer or story developer, learn how to let viewers filter on dimensions and then according to hierarchies (such
as flat presentation and category) to display the data.

Prerequisites
You've already added a table and a chart widget and placed them on top of each other.

To follow all functions of this sample use case, you've completed the exercise Best Practice: Switch Between Chart and
Table and can now enhance your analytic application or optimized story.

Context
You'd like to add two dropdowns, one for filtering on dimension and the other for filtering on hierarchy. The dropdown for the
hierarchy filter changes according to the chosen dimension. There's always one consistent option for hierarchy, which is Flat
Presentation, and there might be only this or more options depending on the chosen dimension. Viewers can add different filters
by selecting from the dropdown lists.

Procedure
1. Add a dropdown widget, and place it above your table.

2. Change the ID of the dropdown to Dropdown_Dimensions.

3. Add another dropdown widget, and place it above the table next to the other dropdown. Leave some space in between the
dropdowns so you can add labels to them later on.

4. Change the ID of the dropdown to Dropdown_Hierarchies.

5. Add the options to the first dropdown.

a. Go to the Builder panel of Dropdown_Dimensions.

b. Under Dropdown Value, add four values.

c. Configure the four values:

For Value 1, enter Location_4nm2e04531 as the ID and Location as the text.

This is custom documentation. For more information, please visit SAP Help Portal. 134
2/9/25, 4:58 PM
For Value 2, enter Product_3e315003an as the ID and Product as the text.

For Value 3, enter Store_3z2g5g06m4 as the ID and Store as the text.

For Value 4, enter Sales_Manager__5w3m5d06b5 as the ID and Sales Manager as the text.

d. Select Location as default value.

6. Add labels to distinguish the two dropdowns.

a. Add a text widget, and place it to the left of Dropdown_Dimensions.

b. Enter Dimension as the text.

c. Change the ID of the text widget to Dropdown_Dimensions_Label.

d. Add another text widget, and place it to the left of Dropdown_Hierarchies.

e. Enter Hierarchies as the text.

f. Change the ID of the text widget to Dropdown_Hierarchies_Label.

7. Create a script variable.

a. In the Scripting section of Outline, add a script variable

b. In the Script Variable panel, change the name to CurrentDimension, and select string as the type.

c. Enter Location_4nm2e04531 as the default value.

d. Select Done to save the changes.

8. In the Outline panel, hover over Dropdown_Hierarchies, and select . In the script editor, write the following script for the
onSelect event of the dropdown:

 Sample Code

var sel = Dropdown_Hierarchies.getSelectedKey();


// set hierarchy for Table
Table.getDataSource().setHierarchy(CurrentDimension, sel);
// set hierarchy for Chart
Chart.getDataSource().setHierarchy(CurrentDimension, sel);

This script gets the selected value of the dropdown list and accordingly sets the hierarchy of the table and the chart when
the script variable CurrentDimension is referenced, so that the hierarchy dropdown displays the filtered options.

9. In the Outline panel, hover over Dropdown_Dimensions, and select . In the script editor, write the following script for the
onSelect event of the dropdown:

 Sample Code

var sel = Dropdown_Dimensions.getSelectedKey();


// Table
Table.removeDimension(CurrentDimension);
Table.addDimensionToRows(sel);
//Chart
Chart.removeDimension(CurrentDimension, Feed.CategoryAxis);
Chart.addDimension(sel, Feed.CategoryAxis);
// write filter information into the browser console
console.log( ['CurrentDimension: ', CurrentDimension ]);
console.log( ['Selection: ', sel ]);
// save the current selection (dimension) into a global variable
CurrentDimension = sel;
// get hierarchies from the current dimension
This is custom documentation. For more information, please visit SAP Help Portal. 135
2/9/25, 4:58 PM
var hierarchies = Table.getDataSource().getHierarchies(CurrentDimension);
var flag = true;
// remove all current items form the Dropdown_Hierarchies
Dropdown_Hierarchies.removeAllItems();
// loop
for (var i=0;i<hierarchies.length; i++){
if (hierarchies[i].id === '__FLAT__') {
Dropdown_Hierarchies.addItem(hierarchies[i].id, 'Flat Presentation');
}
else {
Dropdown_Hierarchies.addItem(hierarchies[i].id, hierarchies[i].description);
if (flag === true) {
var hierarchy = hierarchies[i].id;
flag = false;
}
}
}
// write hierarchy information to browser console
console.log( ['Hierarchy: ', hierarchy ]);
console.log( ['Current Dimension: ', CurrentDimension ]);
// set Flat Hierarchie als Default
Dropdown_Hierarchies.setSelectedKey('__FLAT__');
// Table
Table.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');
// Chart
Chart.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');

This script gets the selected option from the dimension dropdown and saves it in a variable sel.

All the dimensions are removed from the table and chart and replaced with the selected dimension.

All the hierarchies are removed from the table and chart. The hierarchies available to the selected dimension are got
from the data and loaded in the hierarchy dropdown list.

Flat Presentation is set as the default hierarchy.

10. In the Outline panel, hover over Canvas (for analytic applications) or the relevant page (for optimized stories), and select
onInitialization . Write the following script:

 Sample Code
// get hierarchies from the current dimension
var hierarchies = Table.getDataSource().getHierarchies(CurrentDimension);
var flag = true;
// loop
for (var i=0;i<hierarchies.length; i++){
if (hierarchies[i].id === '__FLAT__') {
Dropdown_Hierarchies.addItem(hierarchi es[i].id, 'Flat Presentation');
}
else {
Dropdown_Hierarchies.addItem(hierarchi es[i].id, hierarchies[i].description);
if (flag === true) {
var hierarchy = hierarchies[i].id;
flag = false;
}
}
}
// write hierarchy information to browser console
console.log( ['Hierarchy: ', hierarchy ]);
console.log( ['Current Dimension: ', CurrentDimension ]);
// set Flat Hierarchie als Default
This is custom documentation. For more information, please visit SAP Help Portal. 136
2/9/25, 4:58 PM
Dropdown_Hierarchies.setSelectedKey('__FL AT__');
//Table
Table.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');
//Chart
Chart.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');

With this script, on initialization all the available hierarchies of the dimensions are loaded, and Flat Presentation is set as
the default option of the hierarchy dropdown. The script is the same as a part of what happens when a dimension is chosen.

11. Save the application or story, and open it in view time.

Results
When you run the application or story, it looks like this:

If you keep the dimension Location and change the hierarchy to States, the table displays location in state hierarchy instead of flat
presentation.

This is custom documentation. For more information, please visit SAP Help Portal. 137
2/9/25, 4:58 PM
If you change the dimension to Product, and the hierarchy dropdown list changes accordingly. You can select Category, and
products are displayed in categories.

Best Practice: Add and Remove Dimensions on a Table


As an application designer or story developer, learn how to let viewers control which measures and dimensions to be displayed on
the table.

Prerequisites

You've already added a table with Table as the ID.

To follow this sample use case, use the model BestRun_Advanced.

Context
To let viewers add and remove dimensions and measures on a table, you'd like to add the following five checkbox groups:

The first one displays all the available measures for them to select for the table.

The second one displays the available dimensions for them to select for the columns.

The third one displays the available dimensions for them to select for the rows.

The fourth one displays the dimensions for them to add to the second or third checkbox group.

The fifth one is invisible at view time and only needed to sort dimensions.

On top of that, you add seven buttons for easy access to the checkbox groups' measures.

Procedure
1. Create the first checkbox group, which displays all the available measures.

a. Add a checkbox group widget, and place it to the left of your table. Leave some space above so that you can add
labels and buttons later on.

b. Change the ID of the widget to CheckboxGroup_Measures.

c. In the Builder panel of the widget, remove the initial values Value 1 and Value 2 from the checkbox group value list.

This is custom documentation. For more information, please visit SAP Help Portal. 138
2/9/25, 4:58 PM
2. Add a label to the checkbox group.

a. Add a text widget, and place it above the checkbox group.

b. Enter Measures as the text.

c. Change the ID of the widget to CheckboxGroup_Measures_Label.

3. Similarly, create a second checkbox group with the ID CheckboxGroup_Columns, which displays the available
dimensions for columns. Add a label with CheckboxGroup_Columns_Label as the ID and Columns as the text.

4. Create a third checkbox group with the ID CheckboxGroup_Rows, which displays the available dimensions for rows. Add
a label with CheckboxGroup_Rows_Label as the ID and Rows as the text.

5. Create a fourth checkbox group with the ID CheckboxGroup_Free, which displays the available dimensions for columns
and rows checkbox group. Add a label with CheckboxGroup_Free_Label as the ID and Free as the text.

6. Create the last checkbox group:

a. Add a checkbox group, and enter CheckboxGroup_AllDimensions as its ID.

b. Since the last checkbox group is invisible, it doesn't need a label and can be placed anywhere, for example, on the
right.

c. To make the checkbox group invisible, under Actions in its Styling panel, deselect Show this item at view time (for
analytic applications), or select Hidden under View Time Visibility (for optimized stories).

7. For easy access to the checkbox groups' measures, add the seven buttons:

For the first button, enter Button_setMeasureFilter as the ID and set selected as the text. Place it
between Measures and the first checkbox group.

This button sets the selected measures from the measures checkbox group as the measures on the table.

For the second button, enter Button_removeAllMeasures as the ID and remove all as the text. Place it to
the right of the first button.

This button deselects all the measures from the measures checkbox group and removes all from the table.

For the third button, enter Button_setAllMeasures as the ID and set all as the text. Place it to the right of
the second button.

This button sets all the available measures as the measures on the table.

For the fourth button, enter Button_ColRemove as the ID and Remove as the text. Place it next to Columns.

This button removes the selected dimensions from the columns checkbox group and the dimension columns from
the table.

For the fifth button, enter Button_RowRemove as the ID and Remove as the text. Place it next to Rows.

This button removes the selected dimensions from the rows checkbox group and the dimension rows from the
table.

For the sixth button, enter Button_AddToCol as the ID and add to Column as the text. Place it next to Free.

This button adds the selected dimensions to the columns.

For the seventh button, enter Button_AddToRow as the ID and add to Row as the text. Place it next to the sixth
button.

This button adds the selected dimensions to the rows.

8. To access the values viewers select from the checkbox group, create five script variables, which act as global variables and
can be accessed from anywhere in your application or story:

The first script variable, called AllDimensions, is string type set as an array and holds all the dimensions in the
dataset.

This is custom documentation. For more information, please visit SAP Help Portal. 139
2/9/25, 4:58 PM
The second script variable, called AllMeasures, is string type set as an array and holds all the measures that
viewers can select from the checkbox group.

The third script variable, called CurrentDimensionColumn, is string type set as an array and holds the selected
dimensions to add to columns.

The fourth script variable, called CurrentDimensionRows, is string type set as an array and holds the selected
dimensions to add to the rows.

The fifth script variable, called CurrentMeasureFilterSelection, is string type set as an array and holds the
selected measures from the measures checkbox group.

9. To define what happens when viewers make selections in one of the checkbox groups, create a script object, and write
functions in it.

a. In the Scripting section in Outline, add a script object.

b. Hover over ScriptObject_1, and select (More) Add Script Function .

c. Rename ScriptObject_1 to Utils.

d. Rename function1 to setDimensionCheckboxes, and.function2 to setMeasureFilter.

e. In the Script Function panel of setMeasureFilter, add an argument, with selectedIds as the name, string as the
type and Set As Array on.

f. To write the script for the first function, hover over the setDimensionCheckboxes in the Outline panel, and select
. Enter the following script in the script editor:

 Sample Code
CheckboxGroup_Columns.removeAllItems();
CheckboxGroup_Rows.removeAllItems();
CheckboxGroup_Free.removeAllItems();

CurrentDimensionColumn = ArrayUtils.create(Type.string);
CurrentDimensionRows = ArrayUtils.create(Type.string);
console.log(["CurrentDimensionColumn should empty",
CurrentDimensionColumn.slice()]); console.log(["CurrentDimensionRows should empty", C

// Dimension in Columns
var dimCol = Table.getDimensionsOnColumns();
if (dimCol.length > 0) {
for (var i=0;i<dimCol.length; i++){
CurrentDimensionColumn.push(dimCol[i]);
console.log(["CurrentDimensionColumn ", dimCol[i]]);
}
}

// Dimension in Rows
var dimRows = Table.getDimensionsOnRows();
if (dimRows.length > 0) {
for (i=0;i<dimRows.length; i++){
CurrentDimensionRows.push(dimRows[i]);
console.log(["CurrentDimensionRows ",
dimRows[i]]);
}
}

// get all Dimensions


if (AllDimensions.length > 0) {
for (i=0;i<AllDimensions.length; i++){
if (AllDimensions[i] !== "") {
CheckboxGroup_AllDimensions.setSelectedKeys([AllDimensions[i]]);
var dimdesc = CheckboxGroup_AllDimensions.getSelectedTexts();
CheckboxGroup_Free.addItem(AllDimensions[i],dimdesc[0]);
console.log(["AllDimensions",AllDimensions[i], dimdesc[0]]);
}
}
}

This is custom documentation. For more information, please visit SAP Help Portal. 140
2/9/25, 4:58 PM

console.log(["CurrentDimensionColumn",CurrentDimensionColumn]);
console.log(["CurrentDimensionRows",CurrentDimensionRows]);

// remove the dimensions from the free list, which are in rows / columns
if (CurrentDimensionRows.length > 0) {
for (i=0;i<CurrentDimensionRows.length;i++){
if (CurrentDimensionRows[i] !== "") {
CheckboxGroup_Free.setSelectedKeys([CurrentDimensionRows[i]])
dimdesc = CheckboxGroup_Free.getSelectedTexts();
CheckboxGroup_Rows.addItem(CurrentDimensionRows[i],dimdesc[0]
CheckboxGroup_Free.removeItem(CurrentDimensionRows[i]);
}
}
}

if (CurrentDimensionColumn.length > 0) {
for (i=0;i<CurrentDimensionColumn.length;i++){
if (CurrentDimensionColumn[i] !== "") {
CheckboxGroup_Free.setSelectedKeys([CurrentDimensionColumn[i]]);
dimdesc = CheckboxGroup_Free.getSelectedTexts();
CheckboxGroup_Columns.addItem(CurrentDimensionColumn[i],dimdesc[0]);
CheckboxGroup_Free.removeItem(CurrentDimensionColumn[i]);
}
}
}

g. Write the following script for the second function setMeasureFilter:

 Sample Code

// remove Measures
Table.getDataSource().removeDimensionFilter("Account_BestRunJ_sold");

// add Measures
Table.getDataSource().setDimensionFilter("Account_BestRunJ_sold",selectedIds);

// save the current selection into global variable


CurrentMeasureFilterSelection = selectedIds;

10. Write scripts to define what happens when viewers click on the buttons you just created.

a. For setMeasureFilter, write the following script:

 Sample Code

Utils.setMeasureFilter(CheckboxGroup_Measures.getSelectedKeys());

This onClick function script calls the Utils.setMeasureFilter function and passes to it the selected
measures of the checkbox group.

b. For removeAllMeasures, write the following script:

 Sample Code

CheckboxGroup_Measures.setSelectedKeys([""]);
Utils.setMeasureFilter([""]);

This onClick function script removes all the selected measures from the checkbox group and passes an empty
array to the Utils.setMeasureFilter, which updates your table.

This is custom documentation. For more information, please visit SAP Help Portal. 141
2/9/25, 4:58 PM
c. For setAllMeasures , write the following script:

 Sample Code

CheckboxGroup_Measures.setSelectedKeys(AllMeasures);
Utils.setMeasureFilter(AllMeasures);

This onClick function script sets the selected keys of the checkbox group to the AllMeasures script variable
you defined before and passes the same variable to the Utils.setMeasureFilter function.

d. For ColRemove, write the following script:

 Sample Code

var selKeys = CheckboxGroup_Columns.getSelectedKeys();

for (var i=0;i<selKeys.length; i++){


// remove dimension
Table.removeDimension(selKeys[i]);
}

Utils.setDimensionCheckboxes();

This onClick function script gets the selected keys of the columns checkbox group and removes these dimensions
from the table. It then calls the setDimensionCheckboxes function to set the checkboxes according to the new
selections.

e. For RowRemove, write the following script:

 Sample Code

var selKeys = CheckboxGroup_Rows.getSelectedKeys();

for (var i=0;i<selKeys.length; i++){


// remove dimension
Table.removeDimension(selKeys[i]);
}

Utils.setDimensionCheckboxes();

This onClick function script gets the selected keys of the rows checkbox group and then removes these
dimensions from the table. It calls the setDimensionCheckboxes function to reset the checkboxes again
according to the new selections.

f. For AddtoCol, write the following script:

 Sample Code

var selKeys = CheckboxGroup_Free.getSelectedKeys();

for (var i=0;i<selKeys.length; i++){


// add dimension to Column in table
Table.addDimensionToColumns(selKeys[i]);
}

This is custom documentation. For more information, please visit SAP Help Portal. 142
2/9/25, 4:58 PM

Utils.setDimensionCheckboxes();

This onClick function script gets the selected keys of the free checkbox and adds the dimensions to the columns
of the table. The script then calls the setDimensionCheckboxes function to set the checkboxes according to the
new selection.

g. For AddtoRow, write the following script:

 Sample Code

var selKeys = CheckboxGroup_Free.getSelectedKeys();

for (var i=0;i<selKeys.length; i++){


// remove dimension
Table.addDimensionToRows(selKeys[i]);
}

Utils.setDimensionCheckboxes();

This onClick function script gets the selected keys of the free checkbox and adds the dimensions to the rows of
the table. It also calls the setDimensionCheckboxes function to set the checkboxes according to the new
selection.

11. Define what happens when the application or story is first run by creating the onInitialization function.

a. In the Outline panel, hover over Canvas (for analytic applications) or the relevant page (for optimized stories), and
select onInitialization .

b. Enter the following script in the script editor:

 Sample Code

// Measures
// get all measures from the table data source
var measures = Table.getDataSource().getMeasures();

// define array or the selected Keys


var selectedKeys = ArrayUtils.create(Type.string);

if (measures.length > 0) {
for (var i=0;i<measures.length; i++){
// add the Measure to checkbox group
CheckboxGroup_Measures.addItem(measures[i].id,measures[i].description
//add the measure to the selected Keys
selectedKeys.push(measures[i].id);
}
}
CheckboxGroup_Measures.setSelectedKeys(selectedKeys);
console.log(["selectedKey ", selectedKeys]);
AllMeasures = selectedKeys;

// define array or the selected Keys


var selectedDims = ArrayUtils.create(Type.string);
var dims = Table.getDataSource().getDimensions();

This is custom documentation. For more information, please visit SAP Help Portal. 143
2/9/25, 4:58 PM
if (dims.length > 0) {
for (i=0;i<dims.length; i++){
CheckboxGroup_AllDimensions.addItem(dims[i ].id,dims[i].description);
selectedDims.push(dims[i].id);
}
}

console.log(["selectedDims ", selectedDims]);


AllDimensions = selectedDims;

Utils.setMeasureFilter(selectedKeys);

Utils.setDimensionCheckboxes();

With this script, you make sure that on initialization, all the available measures of the table's data source are loaded.

You define a selected keys array of type string and, using a loop, you add the measures to your measures checkbox
group and the selected keys array. You set the selected keys of the checkbox group to the selectedKeys variable
and set your script variable AllMeasures to selectedKeys since it still holds all the measures of your dataset.

Afterwards, you define another string array and put all the dimensions of the data source in it, and add these
dimensions as items of the checkbox group of all dimensions CheckboxGroup_AllDimensions.

Next, you set the script variable AllDimensions to the string array selectedDims that you created to store the
dimensions in.

Finally, you call the functions of setMeasureFilter to set the selected keys to the array selectedKeys and to
call the setDimensionCheckboxes function to set the dimension checkboxes to its initial state.

12. Save the application or story, and open it in view time.

Results
When you run the application or story, it looks like this:

This is custom documentation. For more information, please visit SAP Help Portal. 144
2/9/25, 4:58 PM
If you select Time in the Free checkbox and select add to Column, this dimension gets added to the table columns so that you can
get a more detailed view.

If you select Location and select add to Row, you can see the columns filtered on time and rows on location.

This is custom documentation. For more information, please visit SAP Help Portal. 145
2/9/25, 4:58 PM

You can get back to starting condition by selecting Remove of the column and row checkboxes.

 Note
You can't remove all the dimensions from the columns because at least one dimension is needed.

Best Practice: Filter Table and Chart Through Settings Panel


(Popup Window)
As an application designer or story developer, learn how to let viewers filter a table or a chart using a popup window.

Prerequisites
You've already added a table and a chart widget and placed them on top of each other.

To follow all functions of this sample use case, you've completed the exercise Best Practice: Switch Between Chart and
Table and can now enhance your analytic application or optimized story.

Context
Through a dropdown list, viewers can filter the table and chart according to certain measures of the dataset, including Gross
Margin, Discount, Quantity Sold and Original Sales Price.

This is custom documentation. For more information, please visit SAP Help Portal. 146
2/9/25, 4:58 PM
In the popup widget, they can then switch between chart and table through a radio button and control the measures Actual, Plan,
Absolute and % of Deviation through a checkbox group.

Procedure
1. Create a dropdown widget, and add a label to it.

a. Add a dropdown widget, and place it above your table.

b. Change the ID of the dropdown to Dropdown_MeasureGroup.

c. To add a label to the dropdown, add a text widget, and place it to the left of the dropdown. Enter Measures Group
in it.

d. Change the ID of the text widget to Dropdown_Measures_Label.

2. Select which measures can be filtered on in the dropdown.

a. In the Builder panel of Dropdown_MeasureGroup, under Dropdown Value choose (Add).

b. Enter Gross_Margin as ID and Gross Margin as dedicated text.

c. Similarly, add three more values. Enter Discount as ID and Discount as dedicated text.

d. Enter Quantity_sold as ID and Quantity Sold as dedicated text.

e. Enter Original_Sales_Price as ID and Original Sales Price as dedicated text.

3. To let viewers open the popup by clicking on a settings icon, add an image.

a. Add an image widget, and place it next to the dropdown.

b. Choose Upload Image, and upload this image .

c. Change its ID to Settings_Logo.

4. Add a popup.

a. In the Outline panel, (for analytic application) choose next to Popups, or (for optimized stories) hover over the
relevant page, and select Add Popup .

b. Change the ID the popup to Popup_Settings.

c. In the Builder under Popup Settings, switch on Enable header & footer.

d. Enter Settings as Title.

e. Under Buttons add two buttons, OK and Cancel. For the first button, enter Ok_button as ID and OK as dedicated
text. Then, select all the options Emphasized, Enabled and Visible.

f. For the second button, enter Cancel_button as ID and Cancel as dedicated text. Then, select the options
Enabled and Visible.

g. Choose Apply to save the changes.

5. To let viewers switch between table and chart, add a radio button group.

a. Add a radio button group widget, and place it in the middle of the popup window.

b. In the Builder panel under Radio Button Group Value, enter Show Table as text for Value 1 and Show Chart as
text for Value 2, and set Show Table as default.

c. In the Styling panel, enter RadioButtonGroup_View as ID, and select Vertical Layout under Display Option.

6. To let viewers choose the displayed measures, add a checkbox group.

a. Add a checkbox group widget, and place it under the radio button group widget.

This is custom documentation. For more information, please visit SAP Help Portal. 147
2/9/25, 4:58 PM
b. In the Styling panel of the checkbox group, enter CheckboxGroup_Measure_Selection as ID, and select
Vertical Layout under Display Option.

c. Switch on Label Text, and enter Measures.

d. In the Builder panel, under Checkbox Group Value, choose twice to create Value 3 and Value 4.

e. For Value 1, enter Actual as ID and text respectively. For Value 2, enter Plan as ID and text respectively. For Value
3, enter _Abs as ID and Absolute as dedicated text. For Value 4, enter _Percent as ID and % Deviation as
dedicated text.

f. Set all four values as Default.

7. Hover over the Settings_Logo in the Outline panel, and choose .

In the script editor, enter the following script:

 Sample Code

Popup_Settings.open();

This onClick function opens the settings popup.

8. Add three global script variables, which access the selections from any widget.

a. In Scripting of Outline, add a script variable.

b. In the Script Variable panel under Structure, enter CurrentMeasureFilterSelectionPopup as name, leave
type as string, and switch on Set As Array.

c. Choose Done to close the panel.

This script variable holds the concatenated filter of the dropdown list on the page and the checkbox group in the
popup window.

d. Similarly, create the second script variable. Enter CurrentMeasureGroup as name, and instead of switching on
Set As Array, enter Gross_Margin under Default Value.

This script variable holds the current measure filter from the dropdown list.

e. For the third script variable, name it as CurrentMeasureSelection.

This script variable holds the selected measures from the checkbox group in the popup window.

9. To define what happens when a filter is selected, create a script object. In this object, write a function that sets the measure
filter according to what viewers have chosen from the checkbox group.

a. In Scripting of Outline, add a script object.

b. Rename ScriptObject_1 to Utils.

c. Rename function1 to setMeasureFilter.

d. Select the function setMeasureFilter, and when the Script Function panel opens, choose (Add Argument).

e. Enter selectedId as name of the argument, leave type as string, and choose Done twice.

f. To write the script for the function, hover over setMeasureFilter in the Outline panel, and choose .

Enter the following script in the script editor:

 Sample Code
Table.getDataSource().removeDimensionFilter("Account_ BestRunJ_sold");
if (CurrentMeasureGroup !== "") {
Chart.removeMeasure(CurrentMeasureGroup, Feed.ValueAxis);
}

This is custom documentation. For more information, please visit SAP Help Portal. 148
2/9/25, 4:58 PM
Table.getDataSource().setDimensionFilter("Account_Bes tRunJ_sold", selectedId);
Chart.addMeasure(selectedId, Feed.ValueAxis);

This script removes the set measure filters from table and chart and instead inserts the selected measure sent to
the function.

10. In the Outline panel, hover over Dropdown_MeasureGroup, and select . Enter the following script in the script editor:

 Sample Code
var sel = Dropdown_MeasureGroup.getSelectedKey();

if (CurrentMeasureGroup === 'Gross_Margin') {


Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Gross_MarginActual]", Fe
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Gross_MarginPlan]", Feed
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Gross_Margin_Abs]", Feed
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Gross_Margin_Percent]",
}
else if (CurrentMeasureGroup === 'Discount') {
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[DiscountActual]", Feed.V
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[DiscountPlan]", Feed.Val
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Discount_Abs]", Feed.Val
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Discount_Percent]", Feed
}
else if (CurrentMeasureGroup === 'Quantity_Sold') {
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Quantity_soldActual]", F
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Quantity_soldPlan]", Fee
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Quantity_sold_Abs]", Fee
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Quantity_sold_Percent]",
}
else if (CurrentMeasureGroup === 'Original_Sales_Price') {
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Original_Sales_PriceActu
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Original_Sales_PricePlan
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Original_Sales_Price_Abs
Chart.removeMeasure("[Account_BestRunJ_sold].[parentI d].&[Original_Sales_Price_Per
}

// save the current selection (measure filter) into a global variable


CurrentMeasureGroup = sel;

// get Measures Selection


var Selected_Measures = CheckboxGroup_Measure_Selection.getSelectedKeys();

// remove the current measures from Chart


for (var i = 0; i < CurrentMeasureFilterSelectionPopup.length; i++){
Chart.removeMeasure(CurrentMeasureFilterSelectionPopup[i], Feed.ValueAxis);
}

// help variables
var Filter_Pattern_1 = "[Account_BestRunJ_sold].[parentId].&[";
var Filter_Pattern_2 = "]";
var Filter_Area = ArrayUtils.create(Type.string);

// loop over the selected measures


for (i = 0; i < Selected_Measures.length; i++) {
//concate all selection information together to a valid filter statement
var Filter = Filter_Pattern_1 + CurrentMeasureGroup + Selected_Measures[i]
Filter_Area.push(Filter);

// add Measure to Chart


Chart.addMeasure(Filter, Feed.ValueAxis);
}

// remove the "old" filter and set the new filter selection
Table.getDataSource().removeDimensionFilter("Account_ BestRunJ_sold");
Table.getDataSource().setDimensionFilter("Account_Bes tRunJ_sold", Filter_Area);

// save the current measure filter selection into a global variable


// Note --> this global variable need to be set with the default values on the onIn
CurrentMeasureFilterSelectionPopup = Filter_Area;
CurrentMeasureSelection = Selected_Measures;

This is custom documentation. For more information, please visit SAP Help Portal. 149
2/9/25, 4:58 PM

// write the current measure filter selection to the browser console


console.log(["Measure Selection: ", CurrentMeasureSelection]);
console.log(["Measure Filter Selection: ", CurrentMeasureFilterSelectionPopup]);

First, this script shows which value was selected and removes the measures of the measure groups. It then saves the
current selection in the script variable CurrentMeasureGroup. The script filters on all the inputs given by showing the
selected measures in the checkbox in the popup.

After getting these values, all old filters get removed so the new ones can be applied. To get a valid filter, the selected
measures get concatenated to a filter statement.

Finally, the concatenated filter statement is saved in the script variable CurrentMeasureFilterSelectionPopup and
the selected keys of the checkbox group in the script variable CurrentMeasureSelection.

11. To write the script for the buttons OK and Cancel, in Outline hover over Popup_Settings, and choose . Enter the
following script:

 Sample Code
if (buttonId === "Ok_button") {

// get Measures Selection


var Selected_Measures = CheckboxGroup_Measure_Selection.getSelectedKeys();

if (CurrentMeasureSelection !== Selected_Measures) {

// remove the current measures from Chart


for (var i = 0; i < CurrentMeasureGroup.length; i++){
Chart.removeMeasure(CurrentMeasureFilterSelectionPopup[i], Feed.ValueAxis);
}

// help variables
var Filter_Pattern_1 = "[Account_BestRunJ_sold].[parentId].&[";
var Filter_Pattern_2 = "]";
var Filter_Area = ArrayUtils.create(Type.string);

// loop over the seleced measures


for (i = 0; i < Selected_Measures.length; i++) {

// concate all selection information together to a valid filter statemant


var Filter = Filter_Pattern_1 + CurrentMeasureGroup + Selected_Measures[i]
Filter_Area.push(Filter);
// add Measure to Chart
Chart.addMeasure(Filter, Feed.ValueAxis);
}

// remove the "old" filter and set the new filter selection
Table.getDataSource().removeDimensionFilter("Account_ BestRunJ_sold");
Table.getDataSource().setDimensionFilter("Account_Bes tRunJ_sold", Filter_Area);

// save the current measure filter selection into a global variable


// Note --> this global variable need to be set with the default values on the onIn
CurrentMeasureFilterSelectionPopup = Filter_Area;
CurrentMeasureSelection = Selected_Measures;

// write the current measure filter selection to the browser console


console.log(["Measure Selection: ", CurrentMeasureSelection]);
console.log(["Measure Filter Selection: ", CurrentMeasureFilterSelectionPopup]);

// set the visibiltiy of Chart and Table --> Script from the RadioButtonGroup_View onSelect
var sel = RadioButtonGroup_View.getSelectedKey();

if (sel === 'Show Table') {


Table.setVisible(true);
Chart.setVisible(false);
}

This is custom documentation. For more information, please visit SAP Help Portal. 150
2/9/25, 4:58 PM
else {
Table.setVisible(false);
Chart.setVisible(true);
}
}

Popup_Settings.close();

This script starts off with an if statement that differentiates the buttons according to their IDs.

It then gets the selections from the checkbox group in the popup window and removes the measures currently being used
as filters for the chart.

To get a valid filter, the selected measures are concatenated to a filter statement that is saved in the script variable
CurrentMeasureFilterSelectionPopup and the selected keys of the checkbox group in the script variable
CurrentMeasureSelection.

Afterwards, the script gets the selected key of the radio button group in the popup window. If Show Table is selected, the
table is set to visible and the chart to invisible, and vice versa if Show Chart is selected.

Lastly, the popup window closes if you click on either of the buttons.

12. Save the application or story, and open it in view time.

Results

When you run the analytic application or optimized story, it looks like this:

When you click on the settings icon, the popup window appears.

This is custom documentation. For more information, please visit SAP Help Portal. 151
2/9/25, 4:58 PM

If you select Show Chart from the popup window and leave all the measures selected, the settings are left as they were, and the
only change is that the chart is now displayed.

If you select the two items Actual and Plan from the checkbox in the popup window and change the dropdown selection to
Discount, the chart looks like this:

This is custom documentation. For more information, please visit SAP Help Portal. 152
2/9/25, 4:58 PM

If you switch back to the table via popup window, the previous filters and settings remain.

Best Practice: Handle Selections in Table and Chart and Open a


Details Popup
As an application designer or story developer, learn how to create a popup window for viewers that contains extra information
about the selected elements.

Prerequisites
You've already added a table and a chart widget and placed them on top of each other.

To follow all functions of this sample use case, you've completed the exercise Best Practice: Switch Between Chart and
Table and can now enhance your analytic application or optimized story.

Context
Viewers can open a popup window, which displays information about their selections.

In the table, they can select a measure cell, a dimension cell or a data cell. In the chart, they can select a dimension cell and a
measure or dimension chart bar, for example, Gross Margin Plan for Lemonade.

This is custom documentation. For more information, please visit SAP Help Portal. 153
2/9/25, 4:58 PM
You also add two dropdown lists.

The first lets them choose which dimension (Location, Product, Store or Sales Manager) to be filtered on the table or
chart.

The second displays the available hierarchies that can be used to change how the data is displayed.

 Note
In this example, only single selection is supported for the table and chart.

Procedure
1. Create two dropdown lists.

a. Add a dropdown widget, and place it above your table.

b. Change the ID of the dropdown to Dropdown_Dimensions.

c. Add another dropdown, and place it above the table next to the other dropdown. Leave some space in between the
dropdowns so you can add name labels for them later on.

d. Change the ID of the dropdown to Dropdown_Hierarchies.

2. Add the values to be selected from the dropdowns.

a. In the Builder panel of Dropdown_Dimensions, under Dropdown Value choose (Add).

b. For Value 1, enter Location_4nm2e04531 as ID and Location as dedicated text.

c. Add a second value, with Product_3e315003an as ID and Product as dedicated text.

d. Add a third value, with Store_3z2g5g06m4 as ID and Store as dedicated text.

e. Add a fourth value, with Sales_Manager__5w3m5d06b5 as ID and Sales Manager as dedicated text.

f. Set Location as default value.

3. To distinguish the dropdown lists, create a label for each of them.

a. Add a text widget, and place it to the left of Dropdown_Dimensions.

b. Enter the text Dimension.

c. Change the ID of the text widget to Dropdown_Dimensions_Label.

d. Add another text widget, and place it to the left of Dropdown_Hierarchies.

e. Enter the text Hierarchies.

f. Change the name of the text widget to Dropdown_Hierarchies_Label.

4. Create a popup.

a. In the Outline panel, (for analytic application) choose next to Popups, or (for optimized stories) hover over the
relevant page, and select Add Popup .

b. In the Styling panel of the popup, change the ID to Popup_Details. Under Popup Size, set its width to 800 and
height to 400.

c. In the Builder panel of the popup, switch on Enable header & footer.

d. Enter Details as title .

e. Add a Cancel button. Enter BTN_Cancel as ID and Cancel as dedicated text. Then, check all three options
Emphasized, Enabled and Visible.

f. Choose Apply to save the changes.

5. To display the extra information on the popup, add a chart.

This is custom documentation. For more information, please visit SAP Help Portal. 154
2/9/25, 4:58 PM
a. Change the ID of the chart to Details_Chart.

b. In the Builder panel, use the model BestRun_Advanced as the data source.

c. Select Time Series as the chart type.

d. Add Gross Margin, Gross Margin % Dev, Gross Margin Abs Dev and Gross Margin Plan as the measures.

e. Under Time, add Time as the dimension.

6. To access the selected values, create two script variables that act as global variables, which can be accessed from
anywhere in your application or story.

The first script variable, called CurrentDimension, holds the current selection from the dimensions dropdown
list.

The second script variable, called CurrentMeasures, is set as array and holds the selected measures.

The third script variable, called CurrentDetailsMeasures, is set as an array and holds the data about the
selections to display the data in the popup window.

a. In the Scripting section of Outline panel, add a script variable.

b. In the Script Variable panel, enter CurrentDimension as name and leave type as string.

c. To close the Script Variable panel, choose Done.

d. Add a second script variable, with CurrentMeasures as name, string as type and Set As Array switched on.

e. Add a third script variable, with CurrentDetailsMeasures as name, string as type and Set As Array switched
on.

f. To close the Script Variable panel, choose Done.

7. Hover over Dropdown_Dimensions in the Outline panel, choose (Edit Scripts), and enter the following script in the
script editor:

 Sample Code

Table.addDimensionToRows(sel);

//Chart
Chart.removeDimension(CurrentDimension,Feed.CategoryAxis);
Chart.addDimension(sel, Feed.CategoryAxis);

//Details_Chart remove dimension filter


Details_Chart.getDataSource().removeDimensionFilter(CurrentDimension);

// write filter information into the browser console


console.log(['CurrentDimension: ',CurrentDimension]);
console.log(['Selection: ', sel]);

// save the current selection (dimension) into a global variable


CurrentDimension = sel;

// get hierarchies from the current dimension


var hierarchies = Table.getDataSource().getHierarchies(CurrentDimension);
var flag = true;

// remove all current items form the Dropdown_Hierarchies


Dropdown_Hierarchies.removeAllItems();

// loop
for (var i = 0; i < hierarchies.length; i++) {

This is custom documentation. For more information, please visit SAP Help Portal. 155
2/9/25, 4:58 PM
if (hierarchies[i].id === '__FLAT__') {
Dropdown_Hierarchies.addItem(hierarchies[i].id,'Flat Presentation');
}
else {
Dropdown_Hierarchies.addItem(hierarchies[i].id,hierarchies[i].description);
if (flag === true) {
var hierarchy = hierarchies[i].id;
flag = false;
}
}
}
// write hierarchy information to browser console
console.log(['Hierarchy: ', hierarchy]);
console.log(['Current Dimension: ',CurrentDimension]);

// set Flat Hierarchy as Default


Dropdown_Hierarchies.setSelectedKey('__FLAT__');

// Table
Table.getDataSource().setHierarchy(CurrentDimension,'__FLAT__');

// Chart
Chart.getDataSource().setHierarchy(CurrentDimension,'__FLAT__');

// Details_Chart
Details_Chart.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');

This onSelect function first gets the selected element of the list. It then replaces any already set dimensions in table and
chart by the newly selected dimension. This dimension is also added to the details chart in your popup window. It writes the
filter information in the browser console and saves the selection in the script variable CurrentDimension.

To set the available hierarchies for the selected dimension, the script loops through the available hierarchies of the data
source in relation to the current dimension to push all available hierarchies in the dropdown list.

Finally, the default hierarchy for table, chart and details chart is set to flat presentation.

8. Hover over Dropdown_Hierarchies in the Outline panel, click (Edit Scripts), and enter the following script in the script
editor:

 Sample Code

var sel = Dropdown_Hierarchies.getSelectedKey();

// set hierarchy for Table


Table.getDataSource().setHierarchy(CurrentDimension,sel);

// set hierarchy for Chart


Chart.getDataSource().setHierarchy(CurrentDimension,sel);

// set hierarchy for Details Chart


Details_Chart.getDataSource().setHierarchy(CurrentDimension, sel);

This onSelect function simply sets the hierarchy of table, chart and details chart to the selected element in the dropdown
list.

This is custom documentation. For more information, please visit SAP Help Portal. 156
2/9/25, 4:58 PM
9. In the Outline panel, hover over Table, choose (Edit Scripts), and enter the following script in the script editor:

 Sample Code

var sel = Table.getSelections();


console.log(['Table Selection: ', sel]);
Details_Chart.getDataSource().removeDimensionFilter(CurrentDimension);
var Popup_show = false;
if (sel.length > 0) {
var selection = sel[0];
for (var dimensionId in selection) {
var memberId = selection[dimensionId];
if (dimensionId === '@MeasureDimension') {
// Measure
console.log(['Selection Measure: ',dimensionId]);
console.log(['Selection Member: ', memberId]);
// remove current measure
console.log(['CurrentMeasures: ',CurrentMeasures]);
for (var i = 0; i < CurrentMeasures.length;i++) {
Details_Chart.removeMeasure(CurrentMeasures[i],Feed.ValueAx
Details_Chart.addMeasure(memberId,Feed.ValueAxis);
}
// Details_Chart.addMeasure(memberId,Feed.ValueAxis);
CurrentDetailsMeasures.push(memberId);
Popup_show = true;
}
// Dimension
else {
console.log(['Selection Dimension: ',dimensionId]);
console.log(['Selection Member: ', memberId]);
Details_Chart.getDataSource().setDimensionFilter(dimensionId, memberId);
Popup_show = true;
}
}
}
if (Popup_show === true) {
Popup_Details.open();
}

This onSelect function captures the selection made in the table and writes it into the console.

Until the selected element is determined, the popup window is set invisible. The script loops over the table, captures
whether it was a measures, dimension or data cell and then pushes this information unto the Details chart. Then the
selected measures are saved in the variable CurrentDetailsMeasures.

Finally, the popup is set to visible and the popup window opens.

10. In the Outline panel, hover over Chart, choose (Edit Scripts), and enter the following script in the script editor:

 Sample Code

var sel = Chart.getSelections();


console.log(['Chart Selection: ', sel,CurrentMeasures]);
var Popup_show = false;

This is custom documentation. For more information, please visit SAP Help Portal. 157
2/9/25, 4:58 PM
if (sel.length > 0) {

Details_Chart.getDataSource().removeDimensionFilter(CurrentDimension);

// remove the current measures


for (var i = 0; i < CurrentMeasures.length; i++) {
Details_Chart.removeMeasure(CurrentMeasures[i],Feed.ValueAxis);
}

for (i = 0; i < sel.length; i++) {


var selection = sel[i];

for (var dimensionId in selection) {


var memberId = selection[dimensionId];

if (dimensionId === '@MeasureDimension') {


// Measure
console.log(['Add Selection Measure: ',dimensionId]);
console.log(['Add Selection Member: ',memberId]);

Details_Chart.addMeasure(memberId,Feed.ValueAxis);
CurrentDetailsMeasures.push(memberId);
Popup_show = true;

}
// Dimension
else {
console.log(['Selection Dimension: ',dimensionId]);
console.log(['Selection Member: ',memberId]);

Details_Chart.getDataSource().setDimensionFilter(dimensionI
Popup_show = true;
}
}
}
}

if (Popup_show === true) {


Popup_Details.open();
}

This onSelect function gets the selected element of the chart and saves it in the variable sel.

The popup window is set to invisible. The script removes the current measures from Details_Chart and replaces with
the measure or dimension filter. Then, the selected measures are saved in the variable CurrentDetailsMeasures.

Finally, the popup is set to visible and the popup window opens.

11. To write the script for the button Cancel, hover over Popup_Details in the Outline panel, select (Edit Scripts), and enter
the following script in the script editor:

 Sample Code
// remove the current measure selection and set all default measures for the details chart
for (var i = 0; i < CurrentDetailsMeasures.length; i++) {
Details_Chart.removeMeasure(CurrentDetailsMeasures[i], Feed.ValueAxis);
This is custom documentation. For more information, please visit SAP Help Portal. 158
2/9/25, 4:58 PM
}
CurrentDetailsMeasures = ArrayUtils.create(Type.string);
for (i = 0; i < CurrentMeasures.length; i++) {
Details_Chart.addMeasure(CurrentMeasures[i], Feed.ValueAxis);
}

// close the popup


Popup_Details.close();

This opens the OnButtonClick script of the popup.

This script removes the content of the variable CurrentDetailsMeasures from Details_Chart and sets the default
measures from the script variable CurrentMeasures as the measure of the details chart.

Lastly, the popup window closes when viewers click on the button.

12. Define what happens when the application or story is first run by creating the onInitialization function.

a. In the Outline panel, hover over Canvas (for analytic applications) or the relevant page (for optimized stories), and
select (Edit Scripts) onInitialization .

b. Enter the following script in the script editor:

 Sample Code

// get hierarchies from the current dimension


var hierarchies = Table.getDataSource().getHierarchies(CurrentDimension);
var flag = true;

// loop
for (var i = 0; i < hierarchies.length; i++) {
if (hierarchies[i].id === '__FLAT__') {
Dropdown_Hierarchies.addItem(hierarchies[i].id, 'Flat Presentation');
}
else {
Dropdown_Hierarchies.addItem(hierarchies[i].id, hierarchies[i].descri
if (flag === true) {
var hierarchy = hierarchies[i].id;
flag = false;
}
}
}
// write hierarchy information to browser console
console.log(['Hierarchy: ', hierarchy]);
console.log(['Current Dimension: ', CurrentDimension]);

// set Flat Hierarchy as Default


Dropdown_Hierarchies.setSelectedKey('__FLAT__');

//Table
Table.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');

//Chart
Chart.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');

//Details_Chart
Details_Chart.getDataSource().setHierarchy(CurrentDimension, '__FLAT__');

This is custom documentation. For more information, please visit SAP Help Portal. 159
2/9/25, 4:58 PM
//fill global Variable CurrentMeasures
CurrentMeasures.push('[Account_BestRunJ_sold].[parentId].&[Gross_MarginActual]');
CurrentMeasures.push('[Account_BestRunJ_sold].[parentId].&[Gross_MarginPlan]');
CurrentMeasures.push('[Account_BestRunJ_sold].[parentId].&[Gross_Margin_Abs]');
CurrentMeasures.push('[Account_BestRunJ_sold].[parentId].&[Gross_Margin_Percent]');

With this script you make sure that on initialization, the hierarchies are loaded into Dropdown_Hierarchies, and
the hierarchy is in flat presentation by default.

After doing that, you fill the script variable CurrentMeasures with the available measures of gross margin, actual,
plan, absolute and percent.

13. Save the application or story, and open it in view time.

Results
When you run the application or story, it looks like this:

If you select dimension data cell Los Angeles, the popup window appears. It gives an overview of the measures Gross Margin, Plan,
Absolute and Percent for the location Los Angeles over time.

This is custom documentation. For more information, please visit SAP Help Portal. 160
2/9/25, 4:58 PM

In the browser console, you can always see the current selection printed here.

If you select the measure cell Gross Margin Actual, this measure is shown in the popup window in relation to time.

You can also select an individual data cell. If you change the dimension to Store and select the data cell at the crossover of Gross
Margin Plan and Country Fair Foods, the popup shows plan gross margin in relation with time and with a store filter of Country
Fair Foods.

This is custom documentation. For more information, please visit SAP Help Portal. 161
2/9/25, 4:58 PM

If you change the dimension to Location, the hierarchy to States and choose Nevada, the popup window appears.

If you switch to the chart, select Product as dimension and choose Lemonade, the popup shows all the measures over time for this
product.

This is custom documentation. For more information, please visit SAP Help Portal. 162
2/9/25, 4:58 PM

Select the measure Gross Margin Abs Dev in regard to the dimension Orange with pulp.

The popup then looks like this.

This is custom documentation. For more information, please visit SAP Help Portal. 163
2/9/25, 4:58 PM

You can always check the filters.

Use MemberInfo Object in setDimensionFilter() API


Use a MemberInfo object in addition to member ID in setDimensionFilter() API. This improves your story or analytic
application's performance as there’s no roundtrip to the backend to fetch the member’s description.

If you use the method setDimensionFilter() on a data source and pass only a member ID, then there's a roundtrip to the
backend to fetch the member’s description:

var memberId = Dropdown_1.getSelectedKey();


Table_1.getDataSource().setDimensionFilter("sap.epm:Department", memberId);
// Roundtrip performed to fetch member description

When you pass a MemberInfo object instead, which contains a description, then there's no roundtrip to the backend:

 Sample Code
var memberId = Dropdown_1.getSelectedKey();
var memberDescription = Dropdown_1.getSelectedText();
Table_1.getDataSource().setDimensionFilter("sap.epm:Department", {id: memberId,
description: memberDescription});
// No roundtrip performed to fetch member description. It's already present.

You can also use an array of MemberInfo objects:

 Sample Code
var resultSet = Table_2.getDataSource().getResultSet();
var memberInfos = ArrayUtils.create(Type.MemberInfo);
for (var i = 0; i < resultSet.length; i++) {
var member = resultSet [i]["sap.epm:Department"];
var memberId = member.id;

This is custom documentation. For more information, please visit SAP Help Portal. 164
2/9/25, 4:58 PM
var memberDescription = member.description;
memberInfos.push({id: memberId, description: memberDescription});
}
Table_1.getDataSource().setDimensionFilter("sap.epm:Department", memberInfos);
// No roundtrips performed to fetch member descriptions. They're already present.

Whenever the member description is available to you, use MemberInfo to improve your story or application's performance.

 Note
If the descriptions in the filter aren't visible to the end users, simply use a dummy description.

View Script Performance in a Popup


You can open your analytic application in view mode to view and analyze the performance of the running scripts in the script
performance popup, which appears as a swim lane diagram.

Launch Script Performance Popup

To enable the script performance popup, from Tools in the edit time toolbar, select (Performance Optimization) Analyze
Script Performance in View Time .

The application opens in a new tab. When it's fully loaded, press Ctrl + Shift + A or Ctrl + Shift + Z . The script performance
popup opens.

Analyze Script Performance


In the script performance popup, the performance results are displayed in a swim lane diagram where each script event is
represented as a blue lane. The events are numbered according to the running sequence. As the scale is the same for all events,
you can immediately identify the long running events.

From tooltip you can see the exact running duration of an event.

If there are some performance relevant events when the script is run, which can be ideally optimized by application designers, they
are displayed below the corresponding event as separate red swim lanes with the same scale.

There are currently two cases that are marked as red:

Waiting for [widget name] to be loaded in background means that a script tries to access a widget that is not loaded at
the particular point in time. The scripts are in waiting position until the widget is loaded in the background. This can only be
the case if background loading for widgets is used. To avoid the long waiting time for a widget, you can do one of the
following:

This is custom documentation. For more information, please visit SAP Help Portal. 165
2/9/25, 4:58 PM
Use the widget at a later point in time.

Set the widget to Always initialize on startup in the Styling panel.

Fetch description for member [member ID] from dimension [dimension ID] means that fetching description from the
backend system for the member ID is necessary because only the member ID is used in setDimensionFilter API. To
avoid fetching description, you can use a MemberInfo object such as {id:"some_id", description:"Some
Description"} for filtering instead of only the member ID string.

To have a clearer view, you can hide some measurements by selecting the lanes. To refresh and show all measurements again,
select Show All.

Related Information
Best Practices for Performance Optimization in Your Analytic Application Design

This is custom documentation. For more information, please visit SAP Help Portal. 166

You might also like