Using an RPA to Create an InDesign PDF Filled with Web Data
Image expertly designed by Vasily Hall with help of copy-pasted icons acquired via googling for them.

Using an RPA to Create an InDesign PDF Filled with Web Data

With the advent of various RPA vendors it is now possible to integrate more applications than ever, using less coding or programming resources than ever. Let’s take a deep dive into a sample project, the concepts of which would have the potential in certain cases to consolidate non-creative tasks, produce value previously unachievable while keeping development budgets to a bare-minimum. Now that’s lean! However, as with many things, there are certain ground rules of which one has to be aware of in order to approach such solutions in the most efficient manner.

A note: this is quite a long article so if you wish to skip down to the result, scroll all the way down to the bottom and start at the section titled “The Workflow in Action”.

Another note: to the programmers interested in UiPath/InDesign integration, skip the riff-raff and scroll all the way down to the section titled “The InDesign Process”

What is an RPA?

The acronym stands for Robotic Process Automation. The word ‘robotic’ may inspire images of androids walking around and operating forklifts or sitting at a computer, however at the time of this writing these systems are all software-based and their purpose is to allow non-coding employees of a company to create digital workflows so as to minimize traditional computer work such as data-entry. The executable bits of digital process workflows created by an RPA system are referred to as ‘bots’ or ‘robots’, but they are essentially macros which can click the mouse or type in keyboard characters as well as perform a multitude of other operations a human user usually does. For an automation professional who comes from the more ‘old-school’ of all code-based automation, these bots are simply instances of scripts – except for one big difference: in most cases they can be constructed by users who do not need to know how to program in a computer language. Rather, they are able to use drag & drop interfaces to create visual flow-charts and therefore have to rely less on programming staff to accomplish workflow automation.

What is UiPath?

There are numerous RPA vendors who have sprung up in recent years, but one holds the title as most adoptable and price-effective for new users breaking into the industry: UiPath. Here is a description from their about-page:

We started in 2005 as a 10-people team based in Bucharest, led by Daniel Dines. In the beginning, we outsourced automation libraries and software to some of the world’s biggest companies.
Fast-forward to 2015. We launched free courses for UiPath Academy and started teaching RPA to over 35,000 now certified developers, propelling our rocketship growth.
Today, we have 5,000+ enterprise customers and have raised over $920M to a valuation of $7 billion. And the best is yet to come.

The top 3 RPA vendors other than UiPath right now are Automation Anywhere, Blue Prism and Pega. There’s a multitude of others and they all have the same goal of providing a visual method for workflow construction. The reason UiPath is so prevalent is due to their pro-active approach to getting new users: the free trial edition for personal practice offered is so far the best out of all the competition.

This free version is meant to allow interested parties to practice workflow creation without any obligation. Thus, workers who experiment in automating their work with the free edition ultimately turn into an organic sales-force who create the perfect custom demo for their leaders and the product easily sells itself.

The other vendors have much more limited trial editions if any.

As a product of this marketing methodology, an organic official and unofficial knowledge repository has been formed which yields the most comprehensive world-wide documentation of any RPA vendor to date. Simply put, the free trial versions are easily utilized for gaining experience and creating written or video tutorials for every possible usage of this tool, in a multitude of languages.

Case-in-point: this very article you are reading right now!

One last thing to mention about UiPath is that it is indeed a Windows-based software. This means one can run it easily on Windows without a problem, but to run it on Mac would require Parallels so as to have a Windows on the Mac in a virtual machine.

The Rules to Consider

As mentioned previously, there are some principles which should be considered when looking at creating such a solution. It mostly boils down to this: programmers are not obsolete; instead they are used more efficiently. Likewise the human operators are also not obsolete either, they too are used more efficiently. In both cases however there’s no question that a business now would require less of both.

The overarching principle is one of balance and carefully planning any one project so that resources are used most efficiently when creating the RPA solution. A project must not be overly-dependent on programmer support nor must it be overloaded with visual workflows which circumvent a software process only to produce inefficient work-arounds which would add to development time and execution duration.

In other words, if it requires a lot of time and a lot of extra visual workflow creation where a simple (or even complex) coded script could do the job faster, more elegant and succinct, then that is the point where such a piece of code would be plugged into the visual workflow to accomplish a particular task as part of the overall process.

An example of this can be seen as part of this demonstration project.

The Sample Project

The most valuable function of an RPA system is visual workflow creation for integration of different applications because it takes otherwise highly expensive programming efforts needed away from the silo of the IT department and into the hands of the actual workers who experience having to carry out tasks day in and day out.

In this sample project the focus is on a fictional workflow which traverses two different applications: the web browser and Adobe InDesign. The goal is to obtain a set of top Google search result names and urls based on an input of a set of search terms and then to export that set as a stylized table inside of a PDF document produced with the help of InDesign, a leading desktop publishing layout application.

These are the basic manual steps in such a workflow:

  1. The user receives some kind of list of search terms for their assignment.
  2. The user types in a search term into Google search and has the browser display the search result.
  3. The user then copies the top result’s title.
  4. The user opens InDesign and pastes the top result’s title into the first column of a table inside a document.
  5. The user then goes back to the browser and copies the top result’s url to the clipboard.
  6. Then, the user goes back to InDesign and pastes this url into the second column in the table.
  7. This process is repeated until every search term from the initial supplied list is accounted for.
  8. In the end, the user exports the created PDF and the task is complete.

As it stands, such a workflow is highly monotonous while also highly error-prone. What happens if there’s an interruption or an urgent email/task is received which throws off the pace? Can the worker accidentally omit one of the supplied words? It is guaranteed.

Now let’s take a look at the automated workflow steps created for this demonstration:

  1. The user receives a list of search terms in a spreadsheet format, a csv file or the like.
  2. The user activates the automated process which first prompts them to choose the source csv file.
  3. The robotic process opens a browser window and repeatedly initiates the Google search for each word in the list, gathering the result title and url into memory.
  4. The robotic process prompts the user to choose a location for their exported PDF.
  5. The robotic process executes an InDesign script to enter all result data into the table inside a template document and saves the PDF to the chosen location.

The end.

Revisiting the Balance Rule

In the above automated steps, items 1-4 are handled via the visual workflow while step 5 is a stand-out: it is an external piece of software activated from the visual workflow. While the RPA bot handles repeatedly Google-searching, in the end it hands off the resulting data to an InDesign script to have InDesign do what it does.

Why is that? After all, it is certainly possible to handle a desktop application such as InDesign with a visual workflow and screen-scraping actions. Conversely, it might be possible to use some sort of Google API to get the search results in a programmatic way, yet the visual workflow is chosen here.

The reason for this setup is how I have chosen to divide up my personal resources to accomplish this solution. As it were, I have multiple years of experience in writing scripts for InDesign but very little experience in anything like getting Google results without manually typing terms into the browser.

For these reasons I made the decision that my time would be best spent to handle searching with the available UiPath bot actions but use my scripting skills to quickly and efficiently automate InDesign outside the scope of UiPath bot actions.

This is not a universal mandate by any means. Consider the scenario where the reverse is true: a company employs a person who is readily available and very well-versed in obtaining Google results through some sort of API but has no person readily available or well-versed in writing an InDesign script. In such a scenario it may be more efficient to delegate the search-result procurement to the developer and have the visual workflow use their results in manipulation of InDesign through UiPath bot actions.

UiPath Installation and Setup

To install and get started with UiPath at the time of this writing is a very quick task: just google “UiPath”, find their website and sign up for the free trial version. Download the UiPath Studio application and start playing around. Yes, for the purpose of this demonstration that is all one needs to do.

Source Data File Setup

As mentioned in the process steps for this project, the user initially is supplied with a list of words to search in Google. This takes form of a CSV file as seen here:

No alt text provided for this image

InDesign Template Setup

An InDesign template is created by a graphic designer. The template contains one text frame which has a title and a table inside. The table has one header row and one blank row, it also contains a total of two columns: one for the result names and one for result urls.

No alt text provided for this image

Starting a UiPath Project

Inside the UiPath Studio, create a new Process. The default names for UiPath processes are “BlankProcess”. Each such process is a separate UiPath project that can contain many different workflows and workflow components. These workflows are stored as light-weight portable xaml files, text files which contain various logic needed to accomplish desired tasks.

Getting Around in UiPath

The Studio application has one central area in the middle where the user constructs their visual workflow. While it is possible to detach and float all windows of UiPath Studio to customize the UI, in this article the assumption is default UI configuration.

In the left-hand area of UiPath Studio there is a list which can display one of the chosen categories which are activated by pressing the tabs at the bottom of the list.

No alt text provided for this image

The Project tab will display all files inside the current project folder. The Activities tab contains a list of available UiPath bot actions which can be employed in a workflow. I am at the time of this writing not familiar with the Snippets tab, but it’s probably something very useful – I just had no urgent need of it in this project.

At the bottom of the Studio app there’s an area which also has 3 tabs and displays a given list.

The Variables tab will display any variables, or identifiers for places in computer memory where data is stored, created by the user. There are some mild programming concepts such as data types and scope which have to be utilized by a UiPath user, but this is just about the extent of how proficient a non-developer user has to be when working in Studio.

The Arguments tab shows a list of special variables whose purpose is to carry data into and out of a particular open xaml file.

No alt text provided for this image

The Imports tab is probably something useful for some kind of task in UiPath, but for the purposes of this project I have not had to use it or know what it does at all. From the looks of it, this tab is used to manage any under-the-hood code libraries needed by UiPath for a given xaml file.

On the right-hand side there’s an area containing 4 tabs, the first of which is the Properties display. Properties will show a selected workflow item’s attributes and options. For example, if the “Select Folder” activity is selected inside the visual workflow (middle area), it will show the DisplayName property so the user can re-name this particular item from the generic “Select Folder” to something more specific like “Select My Special Folder”, and the “SelectedFolder” output variable selection where the user can assign whatever folder was chosen to a pre-created variable.

No alt text provided for this image


I have not had to use any of the other tabs in this area for this project, so they are not mentioned here.

Finally, at the top of the UiPath Studio there is a toolbar which contains various buttons to activate key UiPath features which aid in building a workflow.

No alt text provided for this image

Building the Visual Workflow

To get started building a workflow, one must first create a new xaml file (or use the Main.xaml file provided by default) which will serve as a logic container.

There are two main workflow logic containers which do essentially the same thing but in ways more suited to a particular situation: the Sequence and the Flow-Chart. When a new xaml file is created other activities could then be added to it.

To add new activities to the visual workflow, items are simply dragged from the Activities panel onto the middle area where the contents of a given xaml file are shown. For example, in the System > Dialog tree-view item there’s a “Message Box” activity. When this item is dragged into a flow-chart or sequence it will appear as a box entitled “Message Box”.

No alt text provided for this image

Sequences and Flow-Charts can be added to xaml files and even nested inside each other every-which way.

Working in Components

Since keeping all the work in just one file will likely make it very complex and unwieldy, using multiple separate xaml files can help make and test different parts of a workflow individually. This becomes especially important as a workflow’s steps increase and one has to step through 14 actions to test out how well step 15 is working. It is much easier and faster to test individual files to ensure they work by themselves and then connect them later within a parent logic container.

The Sample Project Flowchart

This is the Flowchart used for this demonstration:

No alt text provided for this image
  1. Start: the very start of the execution of this Flowchart. When the Debug File (play) button in the top toolbar is pressed, this is where the process kicks off.
  2. Sequence (Get source data): where the user is prompted to select a CSV file containing the supplied search words.
  3. Invoke Sequence_GoogleResulsPractice1 workflow: this box contains the sequence where the bot repeatedly enters the search terms into Google Search and collects obtained top-result names and urls as a text grid of data.
  4. Try Catch: this activity contains two blocks where the first one attempts a certain action and the second block handles the case should the attempt fail. In this particular block there’s a “Select Folder” activity. This is put in place to handle the scenario of a user cancelling the folder selection dialog instead of choosing a proper folder. The folder choice decides where the exported PDF would be saved to.
  5. Flow Decision: in flowchart-speak this is called a “decision diamond”, a flow node which directs the workflow conditionally between various activities. In this case it will either lead to exporting of the PDF (marker 7) should the user have selected the folder in the previous step, or it will show the result data in a message box (marker 6).
  6. Display Result in Message: this is a re-named Message Box activity which shows the data obtained in the Invoke Sequence_GoogleResulsPractice1 step (marker 3).
  7. Sequence_InDesignProcess: this sequence contains activities in charge of activating the InDesign script which exports the PDF.
  8. Message Box: this message box displays the result passed back from the execution of the InDesign script. If the script encounters an error, the error message will be displayed. Otherwise it will show a message telling the user where the resulting PDF has been saved to.

Sequence (Get source data)

No alt text provided for this image

 

In this sequence, a list of supplied search words is stored into computer memory. This is accomplished by using a “Select File” activity to allow the user to choose their CSV file and then using a “Read CSV” activity to read the data and store it inside a variable.

No alt text provided for this image

Let’s take a look at the properties of a “Select File” activity.

No alt text provided for this image

The Input section has a Filter item which specifies what kind of files a user is able to choose inside the dialog. This is a text string that unlike other kinds inside UiPath, does not need to be inside double quotes and adheres to a Windows format which can be googled to determine what kind of filter instruction is needed for any kind of file or kinds of files desired.

The Output section has a SelectedFile item where a variable is specified which will hold the file path which was selected by the user.

To create a variable, the Variables panel (bottom default section) is used. One has to specify the data type which in this case is a “string” – meaning text. Also, the Scope of the variable has to be chosen such that a variable is visible by the program within the components it is needed in. Having all of the variables in one top-level scope will lead to too many variables to keep track of efficiently, so a lot of times it is useful to limit their scope just to a sequence they will be used in. In this case, since the file path is only used in the sequence whose purpose is to choose and read in a CSV, its scope is limited to just this sequence.

No alt text provided for this image

Note that when a user cancels the selection this will trigger an error and halt the bot execution. To account of the possibility of a user canceling their file-selection, a Try Catch activity can be used. For brevity it has been omitted from this particular sequence, but is used later in this demonstration.

Next, the data is read into memory using the Read CSV activity.

No alt text provided for this image

Inside the “Read from file:” section the SourceCsvPath variable is specified in order to pass the user’s selection from the previous activity as the location of the CSV file. Alternatively the value can be “hard-coded” or entered as a text string like so: “C:\MyPath\MyFile.csv” – but this would only be done in cases where the location is expected to never change.

In the “Output to:” section the gathered information is finally stored inside a UiPath variable. The variable type for storing a table of data is called “DataTable”.

No alt text provided for this image

This variable is used outside of the sequence, its Scope is set to the parent Flowchart. Note: Because this sequence was not created as a separate xaml file but was instead dragged into the flowchart from the Activities panel, it needs no extra work of using the Arguments panel as it simply assigns its output to the specified variable and does not need to pass the value to any parent xaml component.

When anything goes wrong and UiPath does not like it, an exclamation mark will appear indicating an error. Hovering over the marker will display the cause of the issue. To demonstrate this I changed the name of the variable “SourceDataTable” to “SourceDataTables” which adds the “s” on the end. Now this is seen as a whole different variable name, one which does not exist, therefore an error is produced. Removing the extra “s” turns it back to normal.

No alt text provided for this image

Now that this supplied list of words is stored in memory, it is time to do the more intensive part of using the web browser to repeatedly search the terms using Google Search.

The Visual Workflow

No alt text provided for this image

This sequence has been created as a separate xaml file because it has so many things inside that to build and test it is best done when one can work with all of those items inside a self-contained component. It is different from a sequence which is dragged inside a xaml file from the Activities panel: the activity box actually reads “Invoke…”, meaning run this separate sequence as a self-contained sub-process.

To use a self-contained component, or individual xaml file inside another one, instead of dragging the item from the Activities panel this pre-created item is dragged in from the Project panel. Remember, the Project panel contains all files related to a project which includes all the separate xaml files created inside of it.

One of the biggest differences is passing data in and out of such a sequence. While an Activites sequence can simply read from variables in the parent scope and also write to them, a self-contained sequence has to use the Arguments panel.

Once this Invoke activity is double-clicked, the workzone will show an expanded version of this activity box.

No alt text provided for this image

And when the Open Workflow button is pressed, it opens up the associated xaml file as its own tab in the middle workzone.

Before getting into the sequence itself, let’s see what the button “Import Arguments” does.

No alt text provided for this image

This is one part of being able to pass in data and return data from a separate sequence or flowchart component. To get this to work, argument variables are created whose names and data types must match counter-part arguments specified inside the sequence itself, as described later. The Value column of this window is where the argument variables are mapped to actual variables which are specified in the parent scope’s Variables panel. The variable SourceDataTable from a previous activity is used as the value for the argument called “InData”, while the argument OutString is used to assign the data returned from this sequence into the variable called “ResultDataString”.

This part can be slightly confusing because if one is used to a “left-to-right” convention, the direction of In/Out arguments to their values has to be by definition “flipped” for at least the “In” or the “Out” since the table displays an argument’s name and their respective values the same.


The actual innards of this sequence look like this:


No alt text provided for this image
No alt text provided for this image

This one is quite long, but it is as bad as it gets. Each activity box can be collapsed to conceal the nested items and free-up the visual clutter so as to allow one to focus on the work at hand.

No alt text provided for this image

Let’s dive in and power through this.

The first activity in the sequence is the Open Browser activity. It opens a browser of choice at a specified URL. The value “www.google.com” is hard-coded in the URL textbox.

No alt text provided for this image

There are numerous properties for the Open Browser activity, one important one to know is the BrowserType. This is dropdown selects which kind of browser to open.

An important note regarding this dropdown is that for every browser UiPath interacts with there has to be a counter-part UiPath browser extension installed and running inside that browser. To install such an extension, use the UiPath’s Home button at the very top-left and then select the Tools menu item in the bar on the left-hand side.

No alt text provided for this image

Now let’s get into the sequence immediately inside the Open Browser activity box.

No alt text provided for this image

In this sequence the very first item is a Build Data Table activity.

No alt text provided for this image
No alt text provided for this image

It is put in place for the purpose of starting the table which will be used as the output of this overall xaml file. A variable called “ResultsTable” whose scope is the entire xaml sequence was created first.

No alt text provided for this image

The button “DataTable…” in this activity box produces the following dialog which allows one to specify the columns and data types for them as well as any pre-populated data rows for the table.

No alt text provided for this image

In this case, there are no data rows needed and both columns specified use the String data type.

Next is a For Each Row activity.

No alt text provided for this image
No alt text provided for this image

This activity has an Input section into which a DataTable type variable has to be placed. To get the data from the parent xaml sequence which was read in from the CSV chosen by the user, an argument called “InData” is used. In discussion of the previous xaml sequence I went over the arguments created in the “Import Arguments” dialog. Now in this child xaml sequence, the Arguments panel has to be used to create the same exact arguments using the same names, data types and In/Out direction values.

No alt text provided for this image

Let’s look inside the For Each Row activity.

No alt text provided for this image

Here there is a statement labelled “ForEach” and then it contains inputs for two variables. It automatically creates a variable called “row” which I renamed to “sourceRow” and it also assigns the proper variable which was assigned as the Input: the InData argument variable.

And inside the Body of the For Each Row activity there’s a sequence which contains a Do block where all the action happens.

The Do statement was initially generated automatically thanks to UiPath’s Recording feature which is available at the topmost toolbar.

No alt text provided for this image
No alt text provided for this image

Using the Web recording feature it is possible to get data from a web page and even specify a pattern in which expected web page data occurs. This part is effective in most basic cases in taking a developer required for web-scraping code out of the loop.

When using the Web recording feature, click the record button and use the mouse to navigate and hover over desired elements.

No alt text provided for this image

A small rectangle will pop up showing the zoomed-partial picture of what is being hovered via the mouse. Sometimes it will appear as if the entire page is highlighted and it’s impossible to select one particular element. If this happens, use the F4 key to toggle between the various “UI Frameworks”. When first recording a series of web actions I was not able to select the individual elements until I toggled the framework options to the Default framework. However at a later time when trying to do the same, I had to toggle back to the “AA Framework”. Not sure what the issue here is, but one thing is certain, toggling to one which does work will yield the desired result. The result being, all the actions performed get rendered as activity boxes within a Do statement. After the activities are thus rendered, one is free to re-arrange and add or remove various activities as is needed.

No alt text provided for this image
No alt text provided for this image

Besides recording the sample text input, it is important to record the scraping of the actual desired web data. In order to create a scraping action which can be applied to websites of a similar format, the Web Recording feature’s Scrape Data button is used.

No alt text provided for this image
No alt text provided for this image

When this dialog is followed it allows for defining a pattern of web elements to create a table of extracted data.

No alt text provided for this image
No alt text provided for this image

When the Next button is pressed, a similar selection needs to be produced on any other item in the page which has a similar structure. In this case, another result title link is specified.

No alt text provided for this image

After this, the Configure Columns dialog appears where the resulting table columns are specified.

No alt text provided for this image

After doing so, the Extract Wizard dialog box appears. In this dialog box a preview is generated of all the scraped data from a given web page. Depending on how many results appear on a given web page, this list could vary in size accordingly.

No alt text provided for this image

Notice that some of the title link fields are blank. Why is this?

This is due to the scraper picking up similar link elements from Google’s “People also ask” accordion which sometimes appears somewhere around the top search result. In some cases it will be picked up before the very first non-“People also ask” result.

No alt text provided for this image

For the purposes of this demonstration this issue will be wholly ignored, but it’s highly likely that it can be worked around with various UiPath techniques.

Last of all, since the demonstration workflow is only concerned with the very top result, the extracted data is limited to only one record, which will be the very first one.

No alt text provided for this image

Once the Finish button is pressed, UiPath is intelligent enough to recognize that there are additional pages which will show even more results.

No alt text provided for this image

This demonstration requires no such thing, so I chose “No”.

Once the recording is finished and accepted, an Extract Structured Data activity is rendered in the sequence.

No alt text provided for this image

When all of the web recording items are rendered and arranged they look like this:

No alt text provided for this image

Notice the text “[k(enter)]” inside the “Type into ‘INPUT’” activity: this special instruction tells UiPath to send an Enter key which initiates the web search. However one important dropdown list has to be used to ensure it does not simply type this as plain-text.

No alt text provided for this image

The SimulateType property in the Options section of this activity’s properties must be set to False or else it will simply type “[k(enter)]” into the search input and not send the Enter key as desired.

Also notice that the value of the first Type Into activity has been manually replaced with a variable called “WebSearchWord”. This variable was created in the Variables panel and its scope is set to the Do statement.

No alt text provided for this image

The word “cats” is provided as the default value, but this was only done for testing purposes. In reality, the Assign activity does the job of taking a search word from the user-selected CSV table and assigning it to the variable “WebSearchWord”.

No alt text provided for this image

This is where one has to do the most programming in all of the project: to get the actual value from a data cell the statement “sourceRow.Item(0).ToString()” must be entered. The variable “sourceRow” was created in the For Each Row activity, and the available methods of this variable are shown when one types a dot immediately after the variable’s name.

No alt text provided for this image

This now enables the repeated search in the web browser using a different search word each time.

Back to the data extraction activity, its resulting data table is stored in a pre-created variable called “SingleResultTable” whose scope is the Do block.

No alt text provided for this image
No alt text provided for this image
No alt text provided for this image

Next, the resulting table from the data extraction activity is supplied to another For Each Row activity.

No alt text provided for this image

Even though the table created by data extraction contains only one single result row, it still has to be looped via the For Each Row activity to take the cells of this row and add it to the ResultsTable variable whose scope is the entire xaml sequence. For this “For Each Row” activity I kept the default row variable called “row”.

This is accomplished via the Add Data Row activity.

No alt text provided for this image
No alt text provided for this image

The DataTable property in the Input section specifies the global “ResultsTable” variable to which new rows would be added. The ArrayRow property has one more little bit of programming where the value is specified as “row.ItemArray”, basically the single-result row’s contents as can be used by UiPath in this type of activity.

This is the end of the main For Each Row activity, so now is the time to get the resulting table as a text body. To accomplish this in the easiest way a temporary CSV file is written to the file system and then read back in as text.

No alt text provided for this image

First the file is written using the Write CSV activity. The “Write to what file:” value is hard-coded to an arbitrary location in the filesystem. The “Write from:” value is specified as the ResultsTable variable.

Afterwards, a Read Text File activity is used to read from that exact location.

No alt text provided for this image

In the properties of this activity the Output section’s Content property is specified as the ResultStringDisplay variable.

After the CSV text is captured into memory, the Close Tab activity disposes of the browser window used in this sequence.

No alt text provided for this image

The final step of this sequence which is handled by the Assign activity which takes the variable ResultsTable and assigns it to the OutString argument.

No alt text provided for this image

Now it’s time to jump back out of this xaml sequence and go back to its parent xaml flowchart.

No alt text provided for this image

Next comes a Try Catch statement in which a Select Folder activity resides. The reason this activity is inside a Try Catch block is due to the need of handling a situation where the user chooses to cancel the folder selection. Notice this same concept is omitted from the Select File activity listed in the previously described sequence called “Sequence (Get source data)” for brevity and/or due to laziness.

No alt text provided for this image

The result of the Select Folder activity is stored inside the previously-created ChosenPdfDestination variable.

An important consideration is a special quirk of UiPath when using the Debug File button to run the workflow: the Select Folder activity and in some cases the Select File activity put the selection dialog behind all the windows which are shown on the computer! It can be easily assumed that UiPath is “stuck” but in fact once the windows are minimized or moved out of the way, the dialog is visible.

No alt text provided for this image
No alt text provided for this image

Note that the Try Catch activity is incomplete with at least something inside its Catches section. To enable this, simply select the generic Exception from the dropdown list.

No alt text provided for this image

Now comes the time to make a “decision” using UiPath flowchart’s Flow Decision activity.

No alt text provided for this image

The idea is that if a user cancels the folder selection, they will see the web-search result data in a message box. Otherwise, the workflow will proceed to sequence called “Sequence_InDesignProcess”.

The properties panel of the Flow Decision activity has a Condition item whose value must be some sort of programming expression which evaluates to True or False. This is yet another bit of programming which is easily googled by the non-programmer to utilize. In this case, the expression reads “Not string.IsNullOrEmpty(ChosenPdfDestination)”. This statement checks whether the variable ChosenPdfDestination has anything in its value. If the user had cancelled the folder selection dialog then this variable would be blank. Therefore if it is not blank, the output of this flow decision is True. UiPath uses the programming language VB.NET and as such it uses the keyword “Not” to perform a negation of a statement. It’s not so important for the non-programmer to know all this by memory so long as they can google a desired answer just as I did when constructing this workflow.

No alt text provided for this image

When the Flow Decision evaluates to False, the user sees the result as a text body within a message box.

No alt text provided for this image
No alt text provided for this image

This message box has been renamed to “Display Result in Message” and its value is the ResultDataString variable which was obtained from the previous sequence.

If the Flow Decision evaluates to True, however, this means that the user has indeed chosen a location to output their PDF and the flow proceeds to the sequence called “Sequence_InDesignProcess”.

No alt text provided for this image

The InDesign Process

This is where things take a turn toward the programming aspect of the workflow. In a real-life use-case a company may hire a developer who is experienced in a particular software when it is decided that this part of the workflow is most efficiently performed within code-based automation. Such is the case with InDesign which has a very powerful scripting automation api.

This section is for the programmers.

No alt text provided for this image
No alt text provided for this image

To run the process of taking a table of web-search results and creating a designer-stylized PDF from it, I have written a small InDesign script. It is an Adobe ExtendScript, the file extension of which can be JS or JSX. JSX as a file extension was in use by Adobe “before it was cool” starting sometime in the early 2000’s, way before something silly called “React” culturally appropriated it.

#target indesign
function MakeTable_InDesign (args) {


  function process (args) {
    if (typeof(args) != "undefined") {
      var doc = app.open(File(args.sourceTemplate));
      var table = doc.textFrames[0].tables[0];
      var thisRowData, newRow, thisCell, thisCellString;
      var sampleData = args.sampleData.split(/[\r\n]+/g);
      for (var i = 0; i < sampleData.length; i++) {
        thisRowData = sampleData[i].split(",");
        if (i == 0) {
          newRow = table.rows[1];
        } else {
          newRow = table.rows.add();
        }
        for (var j = 0; j < thisRowData.length; j++) {
          thisCellString = thisRowData[j];
          thisCell = newRow.cells[j];
          thisCell.contents = thisCellString;
        }
      }
      // save PDF in a destination.
      var pdfExportFileObj = File(args.pdfDestination + "/Output Table.pdf");
      doc.exportFile(ExportFormat.pdfType, pdfExportFileObj, false);
      doc.close(SaveOptions.NO);
      return "File saved at '" + decodeURI(pdfExportFileObj) + "'";
    } else {
      throw new Error ("No input arguments specified.");
    }
  }


  try {
    var processArguments = {
      sampleData : args[0],
      pdfDestination : args[1],
      sourceTemplate : args[2]
    };
    return process(processArguments);
  } catch (e) {
    return e.toString() + "\n" + e.line;
  }
};


var MakeTable_InDesign_ArgsExist = false;
try {
  if (arguments.length > 0) {
    var args = [];
    var thisArg;
    for (var i = 0; i < arguments.length; i++) {
      thisArg = arguments[i];
      args.push(thisArg);
    }
    MakeTable_InDesign_ArgsExist = true;
  } else {
    MakeTable_InDesign_ArgsExist = false;
  }
} catch (e) {
}
if (MakeTable_InDesign_ArgsExist) {
  MakeTable_InDesign_RESULT = MakeTable_InDesign(args);
} else {
  MakeTable_InDesign();
}

This extendscript is an ECMAScript-3 style javascript that uses no modern keywords or functions. Any methods not listed in ES3 specifications such as Array.indexOf() must be included as a supplementary bit of external code. For brevity, this example uses no advanced functions or CSV parsing, instead using string-splitting to work the incoming CSV data. Already one may foresee that a comma inside the web-search string table will cause problems.

The convention I use for writing such scripts is to always wrap the script body inside a function to prevent any variables from sticking around after a script has ran. However as passing arguments in is the goal, an extra block at the bottom is used to discern any incoming parameters. It does so by leveraging a real javascript treasure: the ‘arguments’ keyword which is an array-like object representing a list of parameters passed into a javascript function. When triggered from outside, the entire script body including the block at the bottom acts as one self-contained function. As the script is triggered with arguments, the bottom block will traverse the arguments object and push the items into a ‘real’ javascript Array object. This block is also configured to allow manual activation such as a user double-clicking the script file itself in which case it will run without arguments, triggering a handled error which says there are no arguments present. In a real-life scenario this would lead to a fall-back branch condition where the user would be given a chance to select any parameters from within the extendscript such as choosing the pdf destination and the like. Thus it’s very convenient to create scripts in such a way for manual usage as well as being plugged into an external workflow just as done in this demonstration.

I will spare the other details of this script, suffice it to say that it uses an existing template file which contains a table and it adds new rows to it with the incoming table data.

The most important question for this workflow is: how does one trigger this script with arguments from UiPath and better yet, how does one return a result from this script?

The answer is UiPath’s Invoke COM Method activity!

No alt text provided for this image

The first order of business is to specify the correct COM identifier for an application. Regarding Adobe graphic software, these identifiers as well as methods are exposed inside the VBScript documentation for Adobe scripting of any such app. I have verified that InDesign is “InDesign.Application”, Photoshop is “Photoshop.Application” and Illustrator is “Illustrator.Application”. They all have a method to run a javascript file, but these methods differ when it comes to the InDesign app. While Photoshop and Illustrator have a “DoJavaScript” method, InDesign has a generic “DoScript” method which has an additional parameter to specify the exact scripting language used. The “DoScript” method can also run Visual Basic and AppleScripts, and an extra argument is supplied to identify the specific language. Both InDesign’s “DoScript” and Illustrator & Photoshop’s “DoJavaScript” methods have a parameter to specify an argument array.

Now then, let’s take a look at the definition of these arguments for InDesign.

No alt text provided for this image

The “Define…” button shows this dialog where the arguments are provided. I believe that the order of these arguments is the only thing that matters and names are used purely for the developer’s convenience. The first parameter specifies the location of a script file. The second parameter “1246973031” (but it's a number, not a string, keep in mind) is InDesign’s identifier for the javascript language. Finally the third argument is in this case an array of strings which are transformed into javascript’s ‘arguments’ keyword in the triggered JSX file.

And now the script is ready to run! But the final step is actually receiving a result back inside of the caller workflow. The bottom section of the JSX script has one variable which holds the data returned from the main function called “MakeTable_InDesign_RESULT”. This variable has no ‘var’ keyword in front of it, making it belong to whatever scope is calling the entire script. It is the ‘last man standing’ inside the JSX file and gets passed back to the executing workflow.

This result is captured by the Invoke COM Method activity’s Output/Result property. Here the variable called “InDesignResultObj” is assigned to catch the result.

The data type of this result must be of type Object, even if whatever is returned by the JSX script is a string anyway.

No alt text provided for this image

To display the result as a string, the object is converted into a string using the .ToString() function.

No alt text provided for this image

The Workflow in Action

Finally it’s time to push the play button and watch the robotic process in action!

No alt text provided for this image

The UiPath Studio takes a second to jump into action and produces the Select File dialog properly.

No alt text provided for this image

I now choose the “source data.csv” file.

No alt text provided for this image

The UiPath bot repeatedly enters the search terms into Google Search and scrapes the name and url of a top result for every term.

Interestingly, the UiPath now produces the Select a Folder dialog properly – other times it was sent behind every window on my desktop.

No alt text provided for this image

I choose to Cancel the dialog to test the False branch of the Flow Decision.

No alt text provided for this image

The resulting CSV string is shown inside a message box.

No alt text provided for this image

Now let’s run the same thing again and now select the folder.

Everything runs the same up until it’s time to Select Folder when the dialog is now placed behind everything else. Having minimized other windows and moved the Studio app out of the way, the dialog is now visible.

No alt text provided for this image

The UiPath bot triggers the InDesign script and it creates the stylized PDF document (whose title was hard-coded inside the JSX script) inside the specified destination. As part of the JSX execution, the created file is also closed, leaving InDesign just as it was beforehand.

No alt text provided for this image

Finally, the resulting message is displayed by the UiPath bot inside a message box.

No alt text provided for this image

Conclusion

While the steps to create a visual workflow may look ponderous, with practice and with the mountains of available documentation a non-programming user can create just the kinds of workflows their organization needs.

Although RPAs are designed to cut out some of the development efforts in digital workflows, at times it may be more efficient or even necessary to employ specialized automation for specific kinds of software as well.

It is my hope that this article inspires some new advances in the automation of graphic art workflows, thank you for making it this far.

Loic Aigon

Product Manager - Enfocus PitStop Line

4y

Wow Vasily Hall I am a bit jealous I didn't write this article myself. Thanks for sharing so much information and all the great efforts you accomplished to both making this work and have the people know. While I consider this POC very interesting, I am not sure I would have tackled this workflow this way. Not only it's always a bit risky to drive InDesign from an external endpoint legally speaking (even if in your case, it's fine) but you could have used HTML to PDF converters or XSL-FO engines to output a nice PDF without the need of Adobe Products for such documents. But of course, if you needed the advanced typographic and composition tools from InDesign, it's still a tremendous demonstration. Thanks again, congrats!

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics