Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member


Personas scripting has actions for copying data from SAPgui screens and pasting it back elsewhere. This is very commonly used to copy data between screens, or even between transactions. That basic technique is described here - SAP Screen Personas - How to fetch data from another screen. Once the script has finished executing, though, the values copied disappear. It isn't possible for another script to reference those values - each script execution starts in a completely clean environment. One work around for this is to paste values into hidden fields on a screen, from where other scripts can copy them again. This works well for small numbers of values. What if you have a lot of values, or if you don't know how many there will be until you run the transaction? In such cases this technique becomes unwieldy, or even impossible.

This second case, not knowing how many values there are, is exactly the situation I encountered when trying to build a custom table on the SAP home screen. Personas doesn't have a native custom table object and so I had to build a fake table out of unrelated text field objects and then manage the scrolling myself. The data from the table came from a simple report and obviously I didn't know until I ran the report how many rows it would return. Consequently it just wasn't possible to hold the whole table contents in hidden fields on my home screen. That meant that each time I scrolled the table I had to re-run the report and copy out the relevant rows. The details of this process are described here - Creating a custom table in Personas.

Personas scripts have  a limited number of standard actions but you can use Javascript within a Personas script to do many things that these standard actions do not provide. The scrolling for my custom table was implemented largely in Javascript. Within a piece of Javascript inside a Personas script, you can reference variables created by Copy Value or Copy Table actions. For example, once I've run my report, I use Copy Table to grab the data from the report into an object called "po_list" and then within Javascript I can reference this table, now a Javascript array, as "args.po_list":


Now this "args" object is exactly the object that's cleaned out at the end of a script execution, and so even in Javascript you can't reference values copied by another script. Notice, though, that as well as referencing values via this args object I also reference standard Javascript objects - rows and cols in the above example. I do this mostly to save typing - if the values aren't needed for pasting into screen field later they don't need to live inside the args object and I can save 5 keystrokes for each object reference. Programmers are lazy! But that got me thinking - are those values cleared out at the end of a script execution like the values in the args object? It turns out they are not. That means that from within a Javascript action I can save values that will persist and be visible to Javascript actions in other scripts no matter when those scripts are executed. The only thing that seems to delete such values is a browser refresh. Could I use this technique to build a cache behind my table? Then I'd need to run the report just once and subsequent scrolling will be done via the cache without the need to re-run the report.

In version 1 of the custom table, I had Javascript code like this after the Copy Table action:
rows = args.po_list[0].length;
args.rows = rows;
first = parseInt(args.first);
if(rows-first > 1) {
    args.ponum1 = args.po_list[0][first+1];
    args.vendor1 = args.po_list[1][first+1];
    args.date1 = args.po_list[3][first+1];
    args.relcode1 = args.po_list[4][first+1];
}
if(rows-first > 2) {
    args.ponum2 = args.po_list[0][first+2];
    args.vendor2 = args.po_list[1][first+2];
    args.date2 = args.po_list[3][first+2];
    args.relcode2 = args.po_list[4][first+2];
}
...

What I can do instead is copy that "args.po_list" table to a "po_list" table so it doesn't go away, like this:
cols = args.po_list.length;
rows = args.po_list[0].length;
po_list = new Array();

for(i =0; i < cols; i++) {
     po_list[i] = new Array();
     for(j = 0; j < rows; j++) {
          po_list[i][j] = args.po_list[i][j];
     }
}

This takes the "args.po_list" object created by the Copy Table and does a deep copy of it to an object called "po_list". A deep copy is needed because in Javascript a 2-dimensional array is actually a one dimensional array of one dimensional arrays. A simple shallow copy would leave us still with references to the args object, and they would disappear when the script execution finished. Then I can access the table like this (just losing the "args." references):
rows = po_list[0].length;
args.rows = rows-1;
first = parseInt(args.skip);

if(rows-first > 1) {
    args.ponum1 = po_list[0][first+1];
    args.vendor1 = po_list[1][first+1];
    args.date1 = po_list[3][first+1];
    args.relcode1 = po_list[4][first+1];
}
if(rows-first > 2) {
    args.ponum2 = po_list[0][first+2];
    args.vendor2 = po_list[1][first+2];
    args.date2 = po_list[3][first+2];
    args.relcode2 = po_list[4][first+2];
}
...

Finally I need to only run the report and copy the data if my "po_list" cached copy is empty.





Step 2 decides if the cache is empty or not, based on the number of entries in the array, and steps 3-9 run the report and cache the data only if necessary. Step 8 here is the deep copy process I described above.

You can use this technique to save data for reuse within a flavor as I do here. You can also use it to save data where it can be referenced by scripts in other flavors on other transactions. I'm sure there's a lot of potential here that waiting for somebody with suitable imagination to discover. If you have any suggestions, please do add them in the comments below!

It is really interesting to see how much you can achieve by combining Javascript with standard Personas scripting actions. Much more than I realised when I started my Personas journey.

Disclaimer

This is not an officially supported technique. I discovered it by accident and I can't promise it will continue to work. I'd be surprised if future patches for Personas v1 broke it but when the next major version comes along there's no telling what will happen to this technique. It may well not work. If you invest a lot of effort in building flavors that use this feature, you do so at your own risk!

11 Comments