Nathan Hands' Blog

UI5 applications consultant, entrepreneur, fantasy book lover and gamer

Simplify your SAP IRPA projects using polyfills

2 months ago · 5 MIN READ
#IRPA  #tutorial 

Introduction

I've been working with SAP IRPA for the last 6 months now, which I can hardly believe but 2020 has been a different year for us all and my complete change in routine probably had something to do with that. During those 6 months I've been diving deep into automations using the SAP GUI, Excel and outlook integrations exclusively, so expect more topics around those integrations.

If you need any sort of re-cap on setting up IRPA as well as making your first excel automation then please take a look at my first blog.

This blog is going to focus on improving our SAP IRPA JavaScript capability using a tequnique called a polyfill. Even with the death of Internet Explorer on the horizon it seems IRPA is going to keep this practice around at least for now.

What is a Polyfill?

A Polyfill is a piece of code that implements a feature that isn't supported by the native environment that you're working with. Typically this is used in the case of working with older versions of browsers such as Internet explorer. However, we're not using a brower, we're using IRPA which brings us swiftly onto my next header.

Why do we need to Polyfill for IRPA?

The IRPA desktop agent uses the native Microsoft JS engine named 'JScript' (used in Windows Scripting and Internet Explorer) which means we're not actually using JavaScript at all when we develop in IRPA! I'm still going to refer to it as JavaScript because JScript is based on JavaScript (actually called Ecmascript another common problem that I don't help by using them interchangeably).

So let's just say that we're running on an older version of a language that isn't quite JavaScript but is mostly the same but actually gives us access to other JScript objects if you're into that sort of thing.

Being an older version that means me coming from a SAP UI5 Fiori development background was confused when some of my more commonly used functions I'm used to in web development weren't working. The answer as to why lead me down the rabbit hole which is the above few paragraphs of text and why I am making this blog post.

If you want to use 'more modern' (I use this lightly because what we're going to polyfill today was actually implemented in Ecmascript version 5) JS functions then you're going to need to Polyfill.

The benefits of polyfilling will therefore give you readable, clean and working code from the years of experience that you've likely gained upto this point working in web based development. Understandably there will be some people who are taking there first dive into coding with IRPA so that won't really work for them, but if they do end up doing custom code functions they're going to likely stumble across things that JScript doesn't have out the box and will need to polyfill them too :).

Getting started

In today's example I'm going to just start a new project and a new workflow, aptly named 'Polyfill' which I will simply go straight into a 'custom' code block and then end the scenario. I've ran build and got my generated scenario code, but we're only really interested in our 'custom' step code block.

// ----------------------------------------------------------------
//   Step: Custom
// ----------------------------------------------------------------
GLOBAL.step({ Custom: function(ev, sc, st) {
    var rootData = sc.data;
    ctx.workflow('Polyfill', '908880e8-dbc6-4d73-ba94-c6a276abbde6') ;
    // Custom
    sc.endStep(); // End_scenario
    return;
}});

The requirement

The requirement that I have is to check if an array has a certain value in it already and if not to add that new value to the array. Simple right? Now I could loop through the entire array and check my new value against the existing values and do that each time I have this requirement or I could use the standard function indexOf which is already understood by millions of developers worldwide.

What happens without the polyfill?

Great question! and likely why you're already here in this blog, but for everyone else let's just write some code and run out workflow using the below:

// ----------------------------------------------------------------
//   Step: Custom
// ----------------------------------------------------------------
GLOBAL.step({ Custom: function(ev, sc, st) {
    var rootData = sc.data;
    ctx.workflow('Polyfill', '908880e8-dbc6-4d73-ba94-c6a276abbde6') ;
    // Custom
    var beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];

    ctx.log(beasts.indexOf('bison'));
    // expected output: 1

    // start from index 2
    ctx.log(beasts.indexOf('bison', 2));
    // expected output: 4

    ctx.log(beasts.indexOf('giraffe'));
    // expected output: -1

    sc.endStep(); // End_scenario
    return;
}});

The above is some very simple code, with our expected outputs commented next to each ctx.log line, when I run this in the debugger the following result occurs:

irpa-typeerror.png

which reads as TypeError, Object doesn't support this property or method which means that IRPA doesn't know what indexOf refers to and as such we need to polyfill it in.

How to add a custom script

First step we need to 'right click' in the white space on the 'scripts' view:

irpa-addscript.png

and select 'add a new script' and then give it some unique name, I went with 'JavaScriptPolyfill'.

irpa-addscript2.png

click 'save' and we should now have a new empty script file.

Getting our Polyfill code

Polyfill code is commonly and freely availiable on the internet typically found within the MDN web docs and this is no exception, goto google and search for 'indexof polyfill' and the IndexOf MDN web docs will likely be your first result.

Scrolling down a little bit until you find the section labelled 'polyfill' you will see two snippets of code, I've grabbed the first one which you can just copy from me here:

// This version tries to optimize by only checking for "in" when looking for undefined and
// skipping the definitely fruitless NaN search. Other parts are merely cosmetic conciseness.
// Whether it is actually faster remains to be seen.
if (!Array.prototype.indexOf)
  Array.prototype.indexOf = (function(Object, max, min) {
    "use strict"
    return function indexOf(member, fromIndex) {
      if (this === null || this === undefined)
        throw TypeError("Array.prototype.indexOf called on null or undefined")

      var that = Object(this), Len = that.length >>> 0, i = min(fromIndex | 0, Len)
      if (i < 0) i = max(0, Len + i)
      else if (i >= Len) return -1

      if (member === void 0) {        // undefined
        for (; i !== Len; ++i) if (that[i] === void 0 && i in that) return i
      } else if (member !== member) { // NaN
        return -1 // Since NaN !== NaN, it will never be found. Fast-path it.
      } else                          // all else
        for (; i !== Len; ++i) if (that[i] === member) return i 

      return -1 // if the value was not found, then return -1
    }
  })(Object, Math.max, Math.min)

Take the above copied code and paste it into our currently empty desktop studio script, save, build and run the project again.

Note: you will get a warning when you build from here on out, but it's a warning not an error with 'Constructor Object must be initilized at declaration'

The result

irpa-result.PNG The debugger result of running our project with the Polyfill in place.

Conclusion

Success! we have successfully polyfilled in the standard function indexOf into our IRPA project! Which means we can now use this throughout this project and additionally use other 3rd party libraries that might already make use of indexOf within their own libraries.

This is a rather basic example but one that I actually had to use in my work. There are other ways I could have achieved the same effect within my code, but this seemed easy to do and is now understood by any JavaScript developer who has worked within the industry within the last 10 years.

···

Nathan Hand

SAP Applications consultant working as a UI5 developer, Lover of automation, technology, fantasy books & games.
comments powered by Disqus


Proudly powered by Canvas · Sign In