2.4 Adapting REFramework: Tabular Data, Collections & Linear Processes
Key Takeaways
Changing the transaction source means updating the TransactionItem type in Main.xaml and in the GetTransactionData, Process, and SetTransactionStatus arguments.
For tabular data, load the DataTable once into an In/Out argument and return
Rows(in_TransactionNumber - 1), because TransactionNumber starts at 1 while rows are zero-based.Returning
Nothingfrom GetTransactionData.xaml is what ends the run through the No Data transition.SetTransactionStatus.xaml calls Set Transaction Status only for QueueItem transactions, so non-queue projects need their own status record.
A linear process returns one item on the first cycle and Nothing on the second, and uses MaxRetryNumber for retries.
2.4 Adapting REFramework: Tabular Data, Collections & Linear Processes
Core Concept: The REFramework template assumes an Orchestrator queue, but the exam description expects you to adapt it in three other ways: a transactional project with tabular data (DataTable rows), a transactional project with a collection (a list of files, emails, or IDs), and a linear process that runs its business logic once. Every adaptation touches the same three places: the
TransactionItemtype,GetTransactionData.xaml, and the way the result is recorded.
Step 1: Change the TransactionItem Type Everywhere
TransactionItem is a variable in Main.xaml and an argument in several framework workflows. When you change its type, update all of them, or the project will not compile:
| Location | Name | Change it to (tabular example) |
|---|---|---|
Main.xaml variables | TransactionItem | System.Data.DataRow |
GetTransactionData.xaml | out_TransactionItem | System.Data.DataRow |
Process.xaml | in_TransactionItem | System.Data.DataRow |
SetTransactionStatus.xaml | in_TransactionItem | System.Data.DataRow |
For tabular data, also add a variable in Main.xaml, such as TransactionData of type DataTable, and pass it to GetTransactionData.xaml as an In/Out argument (io_TransactionData). The table is loaded once and then kept for every later cycle.
Step 2: Rewrite GetTransactionData.xaml
Tabular data (DataTable rows)
' GetTransactionData.xaml (tabular)
If in_TransactionNumber = 1 Then
' Read Range / Run Query once, store the result in io_TransactionData
End If
If in_TransactionNumber <= io_TransactionData.Rows.Count Then
out_TransactionItem = io_TransactionData.Rows(in_TransactionNumber - 1)
Else
out_TransactionItem = Nothing ' no more rows: go to End Process
End If
Two details trip people up:
TransactionNumberstarts at 1, butRowsis zero-based, so the index isin_TransactionNumber - 1.- Returning
Nothingis what triggers the No Data transition to End Process. Forgetting theElsebranch causes anIndexOutOfRangeExceptionafter the last row.
Loading the data only on the first cycle (or only when the table is Nothing) matters. Re-reading the Excel file on every cycle is slow and can pick up rows that changed during the run.
Collections (files, emails, IDs)
A collection works the same way with a different type. For a folder of PDFs, make TransactionItem a String (or FileInfo) and keep a String() array of paths:
If in_TransactionNumber = 1 Then io_FilePaths = Directory.GetFiles(in_Config("InputFolder").ToString, "*.pdf")
out_TransactionItem = If(in_TransactionNumber <= io_FilePaths.Length, io_FilePaths(in_TransactionNumber - 1), Nothing)
For mailboxes, a List(Of MailMessage) or an Integration Service email object plays the same role.
Linear process (run once)
A linear process, such as a nightly report download, has no records to loop over. Give it one "transaction" and then stop:
If in_TransactionNumber = 1 Then
out_TransactionItem = "RunOnce"
Else
out_TransactionItem = Nothing
End If
You keep the framework's benefits: configuration loading, clean initialization, the business versus system exception split, screenshots, and robot retries through MaxRetryNumber.
Step 3: Record the Outcome Without a Queue
SetTransactionStatus.xaml only calls the Set Transaction Status activity when the item is a QueueItem. The template checks with in_TransactionItem.GetType Is GetType(UiPath.Core.QueueItem) before calling it. For DataRows, files, or linear runs, that activity is skipped automatically, and the framework still does the following:
- logs the outcome with the transaction log fields (status, number, ID, and the two extra fields),
- increments
io_TransactionNumber, or the retry counter for robot retries, - takes a screenshot and closes the applications after a System Exception.
Because there is no queue to show status, you need your own record: write a Status column back to the DataTable and save it at End Process, move processed files to Done or Error folders, or send a summary email. Set out_TransactionID, out_TransactionField1, and out_TransactionField2 in GetTransactionData.xaml (for example, the invoice number) so every log line identifies the record.
Retries Without a Queue
Without Orchestrator's queue retry, MaxRetryNumber on the Constants sheet is the retry mechanism. Set it above 0 (for example, 2). A System Exception then keeps the same TransactionNumber, returns through Initialization, and fetches the same row or file again. A business exception never retries and moves on to the next record.
| Scenario | TransactionItem type | Data loaded | End condition | Retry setting |
|---|---|---|---|---|
| Queue performer (default) | QueueItem | Get Transaction Item on every cycle | Queue empty or stop requested | Queue Auto Retry; MaxRetryNumber = 0 |
| Excel or SQL rows | DataRow | Once, into io_TransactionData | TransactionNumber > row count | MaxRetryNumber > 0 |
| Folder of files | String or FileInfo | Once, into an array | Index past the array length | MaxRetryNumber > 0 |
| Linear run | String or Boolean | Not needed | Second cycle returns Nothing | MaxRetryNumber > 0 if a retry makes sense |
Tip
A tabular performer cannot be scaled across several robots, because each robot would read the same file and process the same rows. When volume or parallelism matters, convert the source into a queue with a Dispatcher.
A developer adapts REFramework to process rows from an Excel file loaded into io_TransactionData. How should GetTransactionData.xaml set out_TransactionItem on each cycle?
Call Get Transaction Item and cast the returned QueueItem to a DataRow.
Add each row to a temporary queue with Add Queue Item and fetch it back.
If in_TransactionNumber is at most the row count, return io_TransactionData.Rows(in_TransactionNumber - 1); otherwise return Nothing.
Re-read the Excel file on every cycle and filter it by in_TransactionNumber.
In a REFramework project adapted to a folder of PDF files, what happens inside SetTransactionStatus.xaml when a file is processed successfully?
The template calls Set Transaction Status with Status Successful, which fails because there is no queue.
The template skips the Set Transaction Status activity because the item is not a QueueItem, logs the outcome with the transaction log fields, and increments the transaction number.
The template automatically moves the PDF to a Done folder.
The template converts the file into a queue item so Orchestrator can track it.
Why does a linear REFramework process usually keep MaxRetryNumber above 0?
Because Orchestrator queue retries are unavailable without a queue, so robot retries are the only way to retry the single run after a System Exception.
Because a linear process needs MaxRetryNumber to decide when to stop fetching data.
Because MaxRetryNumber must always match the queue Max # of retries value.
Because business exceptions are retried only when MaxRetryNumber is above 0.
Sections you finish are checked off in the contents.