Say you want to create a library of utility functions to reuse throughout your RPA project. Say that library should contain the following functions
- Get the current processing running
- Expand environment variables
- Get the file name given a file path
- Get the file name without extension given a file path
Now you have a decision to make. Should you create 1 WAL script for each function? Well, you do not have to.
You can create 1 WAL script that receives which function to run as a parameter. It's like calling "
executeScript.MyFunction", but in a way IBM RPA supports it.
Utils.wal
defVar --name methodName --type String --parameter
goSub --label "${methodName}"
The above script receives a methodName
parameter and calls the routine with that name.
Let's define the ExpandEnvironmentVariables
routine, the input and output parameter environmentVariable
.
Utils.wal
defVar --name methodName --type String --parameter
defVar --name environmentVariable --type String --parameter --output
goSub --label "${methodName}"
beginSub --name ExpandEnvironmentVariables
endSub
Now my other WAL script can call the Utils.ExpandEnvironmentVariables like so:
Consumer.wal
defVar --name environmentVariable --type String
executeScript --name Utils --parameters "methodName=ExpandEnvironmentVariables,environmentVariable=%USERPROFILE%\\file.txt" --output "environmentVariable=${environmentVariable}"
What if my library has several functions and I want to call 2 or 3 of them at the same time?
That's easy, you can receive another parameter named methodNames
of List
type.
Utils.wal
defVar --name methodNames --type List --innertype String --parameter
defVar --name methodName --type String --parameter
if --left "${methodName}" --operator "Is_Null_Or_Empty" --negate
add --collection "${methodNames}" --value "${methodName}"
endIf
foreach --collection "${methodNames}" --variable "${methodName}" --distinct
//NOTE: if we had meta-programming here, we could validate whether the routine exists before trying calling it
goSub --label "${methodName}"
endFor
What about parameter validation?
Each method can validate the required parameters and throw errors if they were not specified.
You can also validate whether the methodName
or methodNames
was passed in:
defVar --name methodNames --type List --innertype String --parameter
defVar --name methodName --type String --parameter
#region validating
case --switches "CaseSwitchesAll"
when --left "${methodName}" --operator "Is_Null_Or_Empty"
when --left "${methodNames}" --operator "Is_Empty"
then
failTest --message "The parameter \'methodName\' or \'methodNames\' is required and was not specified"
endCase
#endregion
if --left "${methodName}" --operator "Is_Null_Or_Empty" --negate
add --collection "${methodNames}" --value "${methodName}"
endIf
foreach --collection "${methodNames}" --variable "${methodName}" --distinct
//NOTE: if we had meta-programming here, we could validate whether the routine exists before trying calling it
goSub --label "${methodName}"
endFor
Here is the full Utils.wal mentioned at the start of the article:
Utils.wal
defVar --name dummyFilePathForPowershell --type String
defVar --name success --type Boolean
defVar --name process --type DataTable --output
defVar --name processId --type Numeric --output
defVar --name processName --type String --output
defVar --name pidText --type String
defVar --name methodName --type String --parameter
defVar --name filePath --type String --parameter
defVar --name fileNameWithoutExtension --type String --output
defVar --name fileName --type String --output
defVar --name fileExtension --type String
defVar --name isDebug --type Boolean --output
defVar --name methodNames --type List --innertype String --parameter
defVar --name environmentVariable --type String --parameter --output
#region validating
case --switches "CaseSwitchesAll"
when --left "${methodName}" --operator "Is_Null_Or_Empty"
when --left "${methodNames}" --operator "Is_Empty"
then
failTest --message "The parameter \'methodName\' or \'methodNames\' is required and was not specified"
endCase
#endregion
if --left "${methodName}" --operator "Is_Null_Or_Empty" --negate
add --collection "${methodNames}" --value "${methodName}"
endIf
foreach --collection "${methodNames}" --variable "${methodName}" --distinct
//NOTE: if we had meta-programming here, we could validate whether the routine exists before trying calling it
goSub --label "${methodName}"
endFor
beginSub --name CurrentProcess
writeToFile --value dummy --createrandomfile --encoding "Default" dummyFilePathForPowershell=value
powerShell --apartmentState "MTA" --script "GET-PROCESS -Id $PID | SELECT -ExpandProperty \"ProcessName\" | OUT-FILE -FilePath \"${dummyFilePathForPowershell}\"" success=success
readAllText --filepath "${dummyFilePathForPowershell}" --encoding "Default" processName=value
trimString --text "${processName}" --trimoption "TrimStartAndEnd" processName=value
powerShell --apartmentState "MTA" --script "$PID | OUT-FILE -FilePath \"${dummyFilePathForPowershell}\"" success=success
readAllText --filepath "${dummyFilePathForPowershell}" --encoding "Default" pidText=value
trimString --text "${pidText}" --trimoption "TrimStartAndEnd" pidText=value
convertStringToNumber --culture "en-US" --text "${pidText}" processId=value
addColumn --dataTable ${process} --columnname Pid --type Numeric
addColumn --dataTable ${process} --columnname "Process Name" --type String
addRow --valuesmapping "Pid=${processId},Process Name=${processName}" --dataTable ${process}
onError --executenext --comment "if an error occurs in the \'delete file\' below, ignore it"
fileDelete --file "${dummyFilePathForPowershell}"
endSub
beginSub --name FileName
writeToFile --value dummy --createrandomfile --encoding "UTF8" dummyFilePathForPowershell=value
powerShell --apartmentState "MTA" --script "SPLIT-PATH -PATH \"${filePath}\" -Leaf | OUT-FILE -FilePath \"${dummyFilePathForPowershell}\""
readAllText --filepath "${dummyFilePathForPowershell}" --encoding "Default" fileName=value
trimString --text "${fileName}" --trimoption "TrimStartAndEnd" fileName=value
onError --executenext
fileDelete --file "${dummyFilePathForPowershell}"
endSub
beginSub --name FileNameWithoutExtension
goSub --label FileName
getRegex --text "${fileName}" --regexPattern "[a-z0-9\\- ]+(?<extension>\\.\\w+)" --regexOptions "IgnoreCase" --groupname extension fileExtension=value
replaceText --texttoparse "${fileName}" --textpattern "${fileExtension}" fileNameWithoutExtension=value
endSub
beginSub --name IsDebug
goSub --label CurrentProcess
setVarIf --variablename "${isDebug}" --value true --left "${processName}" --operator "Equal_To" --right Studio
endSub
beginSub --name ExpandEnvironmentVariables
writeToFile --value dummy --createrandomfile --encoding "UTF8" dummyFilePathForPowershell=value
powerShell --apartmentState "MTA" --script "[System.Environment]::ExpandEnvironmentVariables(\"${environmentVariable}\") | OUT-FILE -FilePath \"${dummyFilePathForPowershell}\""
readAllText --filepath "${dummyFilePathForPowershell}" --encoding "Default" environmentVariable=value
trimString --text "${environmentVariable}" --trimoption "TrimStartAndEnd" environmentVariable=value
onError --executenext --comment "if an error occurs in the \'delete file\' below, ignore it"
fileDelete --file "${dummyFilePathForPowershell}"
endSub
I hope you enjoyed this little trick. Take a look at the next article int the series: how to create connectors.
#TaskAutomation(RPA)#RoboticProcessAutomation(RPA)#lowcode