You want to produce an automation or part of a process as quickly as possible, but still maintain your ability to debug and test parts of it.
This pattern is about helping you become faster at developing workflows by initially doing everything in the Main workflow, then extracting it to child workflows. This will typically hook up most arguments and variables correctly and therefore save you a significant amount of time.
The basic idea is repeatedly applying the following steps:
- Identify a logically separate sub-process inside Main
- Test the sub-workflow
- Extract the sub-workflow into its own .xaml file
- Comment out the sub-workflow and go back to step 1. for the next sub-process
This allows you to rapidly accumulate sub-workflows as building blocks for the final automation - either to keep them in the same project, or to move them into a separate (and re-usable) sub-project or a library.
It is important to realize that the development order of the sub-workflows can be different from the process order of the sub-processes. It is perfectly fine (and often desirable) to start in the middle of the process by manually performing a few actions such as putting example data into variables, especially when you are dealing with a loop over similar items. See Divide&Conquer for more on this topic.
Each of these steps will be hosted in a sub-workflow. If you don’t understand why we would split things up like that, see the discussion in Divide&Conquer on why that is a good idea.
You might also want to check out the guide on co-development which fits neatly into this pattern
Applying Extract As You Go will boost your average speed of development with UiPath, in general, so it’s a good idea for anyone to be aware of this development style.
But there are a few situations where emphasizing speed is particularly important, sometimes even at the cost of quality:
- You are co-developing with a subject matter expert and want to use their time as effectively as possible
- Running a proof of concept (PoC) for experimental development or to convince a customer
- As a minimal viable prototype (MVP) to get feedback from business and iterate faster
- Single-shot automation (for applications such as data migration)
- Small attended helpers for your own consumption (citizen developer)
To make learning the pattern more interesting, let’s do it by example: we will create an automation that uses Google to search for a Wikipedia entry on a given company and extracts its revenue - as shown in the screenshot below.
I highly recommend following along by building this simple automation yourself while you are reading the different sections. Don’t worry, I’ll wait.
Here’s the top-down plan of what the robot has to do:
- Open the browser
- Search for a search term provided as a process argument
- Navigate to Wikipedia by clicking on the first search result
- Read the revenue number from the table (see the screenshot below)
- Display the revenue with a message box
- Close the browser
Generally, I think it’s a good idea to start with the part of the process you anticipate to be the most difficult. Because, if you cannot get that to work, you might as well not bother with the rest. Most business processes are what you might call a chain-like system where, if even one of the steps doesn’t work, the whole chain breaks. Or if you prefer computer science metaphors, it’s like an AND gate. You could, for example, start with step 3 - clicking the first search result - if you aren’t sure how (or if) that would even work.
But, given that this is a very simple process and I already know how to solve all the steps, we will save a bit of additional time and develop them in the same order as above.
First, create a new project of type Process and configure the project settings to your liking (I typically set the browser type to Chrome, Click type to SimulateClick, Text entry type to SimulateType and reduce the default timeout for development to 6000). Open Main.xaml.
Now we can get started for real: Create a new main sequence, then inside that another new sequence called LoadBrowser. Inside LoadBrowser, add an OpenBrowser activity and configure the URL to open Google
That’s pretty easy and all we have to do here. Now for the pattern: right-click the LoadBrowser sequence and click on Extract As Workflow. This will create a new .xaml file containing the sequence. Studio will ask you for a name for the new workflow file, which will be by default the display name of your sequence or flowchart without spaces. For the sake of this article, just leave it as the default.
In Main.xaml, the only thing that remains is an activity called Invoke Workflow File. When this activity is hit, it will dynamically compile the workflow file you entered and execute it.
Interesting piece of background knowledge: you can use Invoke to dynamically load files at runtime by supplying a variable here - the only issue is that configuring the arguments correctly is then your job, whereas if you have a hardcoded name, Studio will be able to configure them for you.
You may be asking if it’s really worth it to extract this workflow as a sub-process, considering it contains only a sequence and one activity we could also just leave it in Main. As there is no right answer and it’s largely a matter of taste, this is something you’ll have to make up your own mind about.
The advantage of extracting the workflow is that the logical separation makes the workflow easier to read and reason about, allows you to test the sub-process in isolation and makes it easier to turn it into a re-usable component.
But the disadvantage is that you now have to switch files to find out what’s going on inside it, need an extra click to check which arguments the sub-process uses, and there is some additional overhead when changing things (for example when you have to add arguments). Invoke Workflow is also slightly slower as the compilation takes a bit of time, but this difference is not usually relevant if you use UI automation
Personally, I like to split the process up into logical parts with a single responsibility that I can test individually. The latter will usually save me enough time to make the slight increase in overhead worth it.
Next, we have to enter our search term and then click on the Google Search button.
First, let’s create a workflow argument for the search term and give it a default value (I chose “Daimler AG”). Default values for variables and in-arguments are a great way to configure test content during development.
This helps you verify if the workflow is working on a very basic level, but you might want to modify them from time to time to check if it generalizes to other input values.
Now we can go about developing the search sequence, using our argument:Click is used instead of the enter key because send hotkey didn't work for me with *SendWindowMessages*
In case you are wondering about the TypeInto text: By default, Google takes into account your location, so prefixing our search with “site:en.wikipedia.org” ensures we only search in the English Wikipedia and don’t accidentally get a higher-ranked result from a different language.
This is the part where we start saving time and where most beginners - and even many seasoned RPA developers - waste countless hours unnecessarily waiting for their robot to do the same steps over and over again.
You see, our natural inclination seems to be to run the complete process from the start whenever we change any little thing. If that applies to you, you will now be inclined to close the browser now and re-run everything from the beginning to test if the search works.
Bad! Foolish! Anathema!Stefan Reutter
What we are going to do instead is leverage the fact that the browser is already open, i.e. that the target application is at a well-defined point in our business process - after opening the browser, but before starting a search - which we can restore at will.
How to define sub-processes is not always clear-cut in a complicated real business process, but with some brain power, it is usually possible to decompose it into small parts that adhere to the Single Responsibility Principle. For more discussion of this topic, see the pattern Divide And Conquer.
So how do we continue development where the robot left off, rather than running it from the start? Simple: comment out the LoadBrowser sequence by selecting it and pressing Ctrl+D or right-clicking it and selecting Disable Activity
Now that we commented it out, we can run and test just the search part by using Debug (F5) or Debug File (F6). Since late 2019, the new UiPath versions also have a Test Activity feature in the context menu that allows you to independently execute a certain activity, which can be quite helpful especially when performing maintenance.
I find commenting out more convenient during development as it saves a few clicks and key presses for each test and gives you more control over what happens, but the drawback is that you might forget to uncomment part of your process (especially if the comment is in a sub-workflow). You also cannot use Test Activity for activities inside a scope (such as Excel or even Attach Window).
Once we are convinced that the sequence is working correctly, we can also extract it as a workflow.
Note that UiPath automatically created an argument for SearchTerm in the new workflow and hooked it up to our existing argument, also called SearchTerm. Neat! Automatically hooking up arguments only works if the variable or argument is named exactly the same in both workflows, which will always be the case if you use Extract As Workflow
This little gem contributes more than you might think to the speed-up you get from Extract as You Go: Having to add the arguments manually takes at least a few seconds each, whereas doing it automatically via Extract as Workflow is nearly instantaneous.
Unfortunately, it doesn’t always get the direction right, so be sure to check the generated arguments (see Displaying the results)
Shall we continue? Now that we have a list of Google results, we want to click on the first hit. We continue following our procedure outlined in the Description, that is to say, comment out the previous step. The most convenient way to do that is to drag&drop it into the commented out area you already have.
This step is fairly simple: we just create a Sequence containing a single Click, but we have to modify the selector (as shown below) because, by default, it contains our search term and the link text. This sort of thing is one of the most common pitfalls for new RPA developers.
<html app='chrome.exe' title='site:en.wikipedia.org*Google Search' /> <webctrl parentid='rso' tag='SPAN' />
As a general guideline, it always pays to have a look at the generated selectors until you have an accurate feeling for whether or not UiPath generates good ones by default for your target application.
With the StudioX activities (or “modern” flavor in Studio in 20.10), the Unified Target subsystem also generates anchors, fuzzy selectors and images as fallback strategies by default, which makes it more likely to find the right element even when the data changes.
There’s no free lunch though, as this comes at the cost of control and specificity, i.e. the robot runs a slightly increased risk of performing an incorrect action where it would have errored out had you only used the exact selector.
Which approach to prefer largely depends on taste and how comfortable you are with creating good selectors, which is one of the more difficult skills to pick up in RPA development. I think for most people, the Unified Target behavior will likely be better, especially when they are just starting out or only occasionally develop robots.
Extract as Workflow and Comment Out - you know the drill by now. For the next part, make sure to create a variable called revenue in the main scope so we can profit from the auto-argument-generation magic:
Then, create a new Sequence and add a Get Text activity to it. Make sure to hook its Output to the revenue variable. Alternatively, you can also create the variable from here using Ctrl+K (this is most helpful if you have variables that have other types than string), just make sure that you change the variable scope to main.
We again have to modify the selector to make it independent of the company we are searching for
<html app='chrome.exe' title='*Wikipedia' /> <webctrl tag='TABLE' class='infobox vcard' /> <webctrl tag='TD' rowName='Revenue' />
Extract the read revenue sequence as a sub-workflow, but do not comment it out: we need the result for the next step. Normally, I test the read-out step with a Log Message or a breakpoint, but this one is so simple that I’m quite confident it will work (if not, we’ll see very shortly).
Last but not least, we should also return the result. Depending on how you want to use the process, converting revenue to an out-argument might make a lot of sense. For our simple example, I decided to use it as a simple attended helper and display a message box to the user instead.
Unfortunately, when extracting this sequence, UiPath inferred the argument direction incorrectly, so I had to manually reverse it. If that happens to you, too, the easiest way to change the argument direction is to open up your new workflow (called DisplayToUser in my case), change the direction, and save the file.
Then, you can use Import Arguments on the Invoke Workflow inside Main (it should be highlighted with the number of arguments in orange) to update the arguments. If you manually renamed the argument, it will probably lose the connection at this step, so double-check that everything is still as it should be.
Run the workflow and you should see the following result:
And that’s it! After removing the comment with Ctrl+E, you should have a fully functioning Wikipedia revenue search workflow that looks similar to this:
I hope you enjoyed this hands-on approach to learning this very useful development pattern.
- The workflow we created here is for illustrative purposes and obviously not production-ready. At the very least, you should add a way to gracefully close the browser in case of errors and some logging to see what’s going on.
- Adding a log message to the start and end of each workflow makes it easy to track down where the process failed.
- If you change revenue to an out-argument, this sort of small atomic workflow makes for a great re-usable sub-process that can be integrated into other processes or triggered with the Orchestrator API.
- If you need to do something like this quickly on demand, such as in a contact center scenario, check out the Inter-Process Communication (IPC).
- Extract as You Go works best when using a combination of top-down and bottom-up development styles.
- During maintenance, this pattern doesn’t help nearly as much. However, the habit of splitting up the process into sub-processes allows you to test them in isolation, which helps to quickly track down the bug you’rehunting.
- When planning to extract the loop body, you can still develop everything inside Main. You can do this by using a temporary break activity at the end of the loop - so you only ever execute one item. Just don’t forget to remove it after you extract the body.