How to create modular macro with functions?

Hi all, hope you are fine!

Is there a way to create functions in order to separate different tasks and avoid have a very long macro?

I’d like to have a main macro that calls macro1, maceo2, …, macroN. Each macro having some especific task or be able to run each macro separately.

I don’t know if would be an issue with the variables used in the whole process.

Thank you

I do this with a lot of my Macros so I can reuse pieces and only have to make modifications once. To do so, I use GLOBAL variables for anything that would have to cross Macros then run the “submacro”. For organization, I have a folder that holds all the full process macros that create/store the GLOBAL variables, call the “submacros”, and create log files then have other folders that hold the “submacros” based on the program they work within. For things like saving/verifying things saved correctly and logging into systems, it is fabulous. I believe there was more information on the run command on the UIVision site or by clicking on the Info for this command that I found helpful the first time.

I have also semi created functions within a macro if it does not make sense to create an additional sub-sub-macro by using labels and gotolabel

Though a tip from experience, when building the full process macro, I find it helpful to start and end by setting all GLOBAL variables I will use with a meaningless value (I use NULL just out of habit even though it stores the text NULL rather than a null value), just to be safe since GLOBAL variables are maintained until you close UIVision.

Example:

{
  "Command": "store",
  "Target": "${EndHolds[${!times}][2]}",
  "Value": "GLOBALHoldReason",
  "Description": ""
},
{
  "Command": "store",
  "Target": "${EndHolds[${!times}][3]}",
  "Value": "GLOBALHoldType",
  "Description": ""
},
{
  "Command": "run",
  "Target": "/BannerSubMacros/BannerSOAHOLD_EndHold",
  "Value": "",
  "Description": ""
},

(ignore all the reds, I need to sit down and figure out why it is erroring out at the end of times loops but for now it only errors out at the end and gets the job done)

2 Likes

That is a very useful post. Just one small clarification: Normal variables are also visible in the sub macros. And if a variable is changed in the sub macro, then it also changes the value in the main routine.

Of course, unlike global variables, all values are lost when the macro stops.

Hi @straussj

Thanks for your answer, explanation and example.

I’m kind of new doing macros. What are doing the first 2 commands in your sample code? are controlling the times the macro “BannerSOAHOLD_EndHold” will run?

What does mean this “${EndHolds[${!times}][2]}”? I assume EndHolds is an array but ${times} inside I don’t get what is doing.

And finally, I need to run routine1 if after login appears a window with form1, if after login appears window with form2 I need to run routine2 and so on. After login could appear 4 different events (different pages).

Then I was thinking in how to call specific macro, i.e. macro_routine1, macro_routine2..., macro_routine4 when needed based on what window appears after login. This without make a mess and a unique very long macro using several gotoLabel. The thing is that in my case, each macro_routineN could use a variable from main macro.

Thanks again.

I am taught by trial, error and this forum so I feel you, but once you get the hang of them, they are awesome!

Sorry, that snipit is running inside a times loop (I only copied a short portion of code just to show assigning GLOBAL variables and did not think of that additional piece). I have it reading from a CSV file with many records so the {!times} is in relation to the number of times through the loop (i.e. which line of the array). I refer to the variables a lot and found it much easier to name the variables something that was more meaningful to a human and meant that I could assign the values in the “Full Process” macro so different “full processes” that used the same “submacros” could assign the correct values even if the CSV/array had things in a different order.
I had a similar issue with saving things in one of the programs I use where there were several possible outcomes and each could need to handle something differently based on the Macro that I was saving from. There is probably a more elegant/efficient way to do but I handled it by creating a save “sub-macro” that used OCR Search/Visual Verify of the different conditions and if/else/end statements. If the message that it was checking for was displayed, it would send the value I assigned and then the macro that called the save would act based on the result in the GLOBAL variable (since it could differ based on what was being saved) but it sounds like you would want to replace storing GLOBALBannerSaveResults and gotolabel (which just was the last line of the Macro so it skipped any remaining checks that would have been redundant at that point and avoided nested if/else statements which can sometimes get hard to read when trying to fix an error) with run macro_routineN or creating a login macro and just listing the four options in if/else statements. Again, probably a better way but that was just what I could figure out.

{
  "Command": "OCRSearch",
  "Target": "Saved success",
  "Value": "count",
  "Description": ""
},
{
  "Command": "if",
  "Target": "${count}>0",
  "Value": "",
  "Description": ""
},
{
  "Command": "store",
  "Target": "Saved Successfully",
  "Value": "GLOBALBannerSaveResults",
  "Description": ""
},
{
  "Command": "gotoLabel",
  "Target": "SaveEnd",
  "Value": "",
  "Description": ""
},
{
  "Command": "else",
  "Target": "",
  "Value": "",
  "Description": ""
},
{
  "Command": "end",
  "Target": "",
  "Value": "",
  "Description": ""
},
{
  "Command": "OCRSearch",
  "Target": "No changes to save",
  "Value": "count",
  "Description": ""
},
{
  "Command": "if",
  "Target": "${count}>0",
  "Value": "",
  "Description": ""
},
{
  "Command": "store",
  "Target": "No changes",
  "Value": "GLOBALBannerSaveResults",
  "Description": ""
},
{
  "Command": "gotoLabel",
  "Target": "SaveEnd",
  "Value": "",
  "Description": ""
},
{
  "Command": "else",
  "Target": "",
  "Value": "",
  "Description": ""
},
{
  "Command": "end",
  "Target": "",
  "Value": "",
  "Description": ""
},
{
  "Command": "label",
  "Target": "SaveEnd",
  "Value": "",
  "Description": "Used as an alternate to nested if/else/end statements for simplicity to add additional conditions when needed in the future"
},
1 Like

Thanks so much for your help and time and example given. I’ll have mind those suggestions from your experience.

Regards