Learn how to build a Power Automate Desktop flow that launches a Windows application, reads records from Excel, fills out forms field by field, and submits data reliably — even in legacy systems with no API. This hands-on lesson covers everything from UI element capture to loop structure and error recovery.

Picture this: every morning, your accounts payable team opens an aging vendor management system — a Windows desktop app that was built in 2003 and has never seen an API — and manually types invoice data from a spreadsheet into dozens of fields across multiple screens. It takes three hours, produces occasional typos, and nobody enjoys doing it. The system will never be modernized. But you can still automate it.
This is exactly the scenario where Power Automate Desktop (PAD) becomes your best friend. PAD is Microsoft's robotic process automation (RPA) tool that can interact directly with Windows applications at the UI level — clicking buttons, typing into text fields, selecting dropdown values, and reading confirmation messages — the same way a human would, but faster, tirelessly, and without fat-fingering the vendor code. By the end of this lesson, you'll know how to build a desktop flow that launches a Windows application, reads source data, navigates multi-screen forms, and submits records with confidence.
What you'll learn:
Before working through this lesson, you should have Power Automate Desktop installed and know how to create a basic desktop flow. If you're starting from scratch, work through Getting Started with Power Automate Desktop: Installing, Recording, and Running Your First Desktop Flow first.
You should also be comfortable with the idea of variables and data tables. If those feel unfamiliar, Variables, Lists, and Data Tables in Power Automate Desktop: A Complete Practitioner's Guide will bring you up to speed quickly.
Before you open PAD and start dragging actions, let's map out the logical structure of what we're building. A data entry automation almost always follows the same skeleton:
That's it. The complexity lives inside step 4 and 5, and that's where we'll spend most of our time. Let's build it piece by piece using a realistic scenario: entering new employee records into an HR desktop application called "Contoso HR Manager."
The source data for our automation lives in an Excel workbook called New_Employees.xlsx. It has columns for First Name, Last Name, Department, Job Title, Start Date, and Employee ID.
In PAD, open the Actions panel on the left side of the designer. Under Excel, drag in Launch Excel and point it at your workbook. Then use Read from Excel Worksheet with the option "Read all available values from worksheet" — this gives you a DataTable variable, which we'll call EmployeeData.
Your flow starts like this:
Launch Excel → File: "C:\HR\New_Employees.xlsx" → Instance: ExcelInstance
Read from Excel Worksheet → ExcelInstance → All available values → EmployeeData
Close Excel → ExcelInstance
We close Excel immediately after reading because we don't want it sitting open and getting accidentally modified while our bot runs. All the data we need is now in EmployeeData.
Tip
If your spreadsheet has a header row (which it almost certainly does), enable the "First line of range contains column names" toggle in the Read action. PAD will then let you reference columns by name — CurrentRow['LastName'] — instead of by index number, which makes your flow far more readable.
For a deeper dive into everything you can do with Excel automation, including writing results back and running macros, see Automating Excel with Power Automate Desktop: Reading, Writing, and Running Macros.
Now we need Contoso HR Manager to be open. In the Actions panel, find the System group and use the Run Application action. This is more reliable than double-clicking a desktop shortcut via UI automation because it directly invokes the executable.
Configure the action like this:
C:\Program Files\ContosoHR\ContosoHRManager.exeAfter the action runs, PAD will have launched the app, but "launched" doesn't mean "ready." Legacy Windows applications in particular can take several seconds to fully initialize their UI — connecting to databases, loading configuration, rendering their main window. If your next action tries to click a menu before the window is ready, it will fail.
The right approach is to add a Wait for UI Element to Appear action. Configure it to wait for a distinctive element in the app's main window — like the main menu bar or a specific label — before the flow continues. Give it a generous timeout, like 30 seconds, with a sensible retry interval.
Run Application → "C:\Program Files\ContosoHR\ContosoHRManager.exe"
Wait for UI Element to Appear → UI Element: MainMenuBar → Timeout: 30s
Warning
Never use a plain Wait action (a fixed sleep timer) as your only synchronization strategy. If the machine is slow one morning — maybe antivirus is running — a fixed 5-second wait will expire before the app is ready and your flow will crash. Waiting for a specific UI element is conditional: the flow proceeds as soon as the element appears, but waits if it needs to. Robust, not brittle.
With the app open, you need to navigate to the "Add New Employee" form. In Contoso HR Manager, this means clicking File → New Record → Employee. Each of those clicks is a Click UI Element action in PAD.
But before you can click, you need to tell PAD which element to click. This is done through the UI element capture process. In the action configuration window, click Add UI element, then move your mouse over the target app and click the element while holding Ctrl. PAD records a selector — a description of that element based on its properties like name, class, and position in the UI tree.
You'll build up a short navigation sequence:
Click UI Element → "File Menu"
Click UI Element → "New Record"
Click UI Element → "Employee"
Wait for UI Element to Appear → "Employee Entry Form Title"
That last Wait ensures the form is fully rendered before we start filling fields.
Key insight
How robust your selectors are will make or break the entire automation. PAD builds selectors based on UI properties like the element's name, automation ID, and class. The more specific attributes you use, the more reliably PAD will find the element — but overly rigid selectors break if the app updates. Learn how to fine-tune selectors in UI Elements and Selectors in Power Automate Desktop: Building Automations That Don't Break.
This is the heart of the automation. We'll use a For each loop to iterate over every row in EmployeeData. Each iteration represents one employee record.
Inside the loop, the pattern for each field is: click the field to focus it, clear any existing content, type the value. In PAD, this typically looks like:
For each CurrentRow in EmployeeData
# --- First Name ---
Click UI Element → FirstNameField
Populate Text Field → FirstNameField → Text: CurrentRow['First Name']
# --- Last Name ---
Click UI Element → LastNameField
Populate Text Field → LastNameField → Text: CurrentRow['Last Name']
# --- Department (Dropdown) ---
Select option in Drop-down List → DepartmentDropdown → Option: CurrentRow['Department']
# --- Job Title ---
Click UI Element → JobTitleField
Populate Text Field → JobTitleField → Text: CurrentRow['Job Title']
# --- Start Date ---
Click UI Element → StartDateField
Populate Text Field → StartDateField → Text: CurrentRow['Start Date']
# --- Employee ID ---
Click UI Element → EmployeeIDField
Populate Text Field → EmployeeIDField → Text: CurrentRow['Employee ID']
# --- Submit ---
Click UI Element → SaveButton
Wait for UI Element to Appear → "Record Saved Confirmation" → Timeout: 15s
Click UI Element → ConfirmationOKButton
End (For each)
Let's unpack a few things happening here.
Why use "Populate Text Field" instead of "Send Keys"? The Populate Text Field action is designed specifically for UI text inputs. It clears the field first and types the text in a controlled way. "Send Keys" simulates raw keystrokes and can cause problems — for example, if the field still has focus from a previous action, the old content might not get cleared properly.
Dropdowns are different from text boxes. You don't type into a dropdown — you use Select option in Drop-down List and pass the exact option text. If your data says "Information Technology" but the dropdown says "IT", the action will fail. Make sure your source data values match the dropdown options exactly, or add a mapping variable in your flow.
Dates need special attention. Desktop apps often have strict date format requirements — MM/DD/YYYY vs DD/MM/YYYY vs YYYY-MM-DD. If your Excel date comes through as a number or in the wrong format, use a Format datetime action to convert it before typing it into the form.
Tip
If your application uses Tab-key navigation to move between fields (very common in legacy apps), you can use Send Keys with {Tab} instead of clicking each field individually. This is often faster and more reliable because it uses the app's built-in field-traversal logic rather than relying on pixel-perfect UI element detection for every single input.
After hitting Save, the application will do one of several things: show a success dialog, show an error dialog, navigate to a new blank form, or simply update a status bar. Your flow needs to handle all of these possibilities without panicking.
The most common pattern is a modal dialog (a pop-up that blocks interaction until dismissed). Use Wait for UI Element to Appear to detect it, then Get text on screen to read its message, then click the appropriate button to dismiss it.
For error detection, you can check the dialog text with an If condition:
Get Details of UI Element → ConfirmationDialogMessage → AttributeValue: DialogText
If DialogText contains "Error" Then
# Log the failure — write to a log file or send an alert
Log_Error_To_File(CurrentRow, DialogText)
Else
# All good, proceed
End If
This pattern — check what actually happened before continuing — is the difference between an automation that's truly reliable and one that silently enters garbage data when something unexpected occurs.
For a full treatment of structured error handling strategies including retry logic and recovery screenshots, Error Handling in Desktop Flows: On Block Error, Retry Policies, and Recovery Screenshots is essential reading.
If you dump all 50 actions into a single flat flow, you'll regret it the first time something breaks and you're staring at an undifferentiated wall of steps. Structure matters.
Extract the form-filling logic into a Subflow called something like Enter_Employee_Record. Your main flow loop then calls that subflow for each iteration:
For each CurrentRow in EmployeeData
Run Subflow → Enter_Employee_Record
End (For each)
The subflow receives CurrentRow as context (since it's a flow-level variable, subflows can access it) and handles all the field interactions internally. Now if the form layout ever changes and you need to update the field-clicking logic, you edit one subflow instead of hunting through a monolithic flow.
You can read more about this pattern in Subflows and Reusable Logic in Power Automate Desktop.
Note
If you eventually want this desktop flow to run automatically on a schedule — say, processing overnight batch files without anyone sitting at the machine — you'll need to configure it for unattended execution. That requires a different machine setup and run mode. Attended vs Unattended RPA: Choosing a Run Mode and Configuring Machines in Power Automate walks through what that decision involves.
Build the following desktop flow to practice everything covered in this lesson. Use Notepad as your target "application" if you don't have a real Windows desktop app handy — it's available on every Windows machine and has a text input area you can type into.
Scenario: You have a small CSV of three product records. Each record has a Product Name and a SKU. Your flow should open Notepad, type each record on its own line in the format [SKU] - [Product Name], and then save the file.
Step-by-step:
notepad.exe)CurrentRow['SKU'] + " - " + CurrentRow['ProductName'] followed by {Return} to move to the next line{Ctrl}{S} to trigger SaveWhat to observe: Notice how using Wait for UI Element to Appear before typing makes the flow reliable even if Notepad is slow to open. Try removing that wait action and running the flow quickly — you'll often see the first keystrokes get swallowed.
The flow runs but fields are empty or partially filled. This usually means the field didn't have focus when typing began, or a previous keystroke navigated away from the field. Add an explicit Click UI Element action before each Populate Text Field to ensure focus is correct. Also check whether the application intercepts certain keystrokes (some apps swallow Tab or Enter at unexpected moments).
The UI element selector can't find the element at runtime. This is the most common failure mode in Windows desktop automation. The element may have a dynamic property — like an ID that changes each time the app opens. Edit the selector in PAD's UI Element editor and look for a more stable attribute. Automation IDs and element names are usually more stable than positional attributes. This topic is covered in depth in UI Elements and Selectors in Power Automate Desktop: Building Automations That Don't Break.
Dropdown selection fails with "Option not found." The value in your data doesn't exactly match the option text in the dropdown. Open the application manually, expand the dropdown, and copy-paste the exact text into your source data. Watch for trailing spaces, different capitalization, or special characters.
The app crashes or hangs mid-flow and the flow never recovers. Wrap your main loop body in an On Block Error handler. If the error occurs, the handler can close and relaunch the application, log the failed record, and continue with the next one rather than stopping entirely.
Date fields show the wrong format.
Add a Convert datetime to text or Format datetime action before populating the date field. Set the format string explicitly to match what the application expects — for example MM/dd/yyyy — rather than relying on the system's regional settings, which may differ across machines.
Warning
Avoid recording a macro with the built-in Recorder and assuming it will always play back correctly. The Recorder captures absolute UI positions and fixed waits, which makes fragile flows that break the moment a window is resized or a dialog appears unexpectedly. Use recorder output as a starting point — capture the element names — then replace fixed waits with conditional waits and add proper error handling before considering the automation production-ready. See Capturing and Replaying Mouse Clicks and Keystrokes with the Power Automate Desktop Recorder for guidance on using the recorder wisely.
You now know how to build a complete data entry automation for Windows desktop applications with Power Automate Desktop. You can launch an application programmatically, navigate to a form, loop through source records and fill fields reliably, handle dropdowns and date formatting, and structure your flow to handle failures without crashing.
The key principles to carry forward:
Where to go from here:
Power Automate Desktop & RPA
Automating Windows System Dialogs and Pop-Up Handling in Power Automate Desktop: Detecting, Dismissing, and Responding to Alerts Without Breaking Your Flow
Automating SAP GUI Interactions with Power Automate Desktop: Navigating Transactions, Extracting Table Data, and Handling Session Errors