Learning Power Automate with Benji: Excel-to-Teams at Scale (256 Notifications)

There is no better way to learn a new piece of technology than by trying to break it. Recently, I had the pleasure of sitting down with Benji to dive headfirst into the world of Microsoft Power Automate. Our mission was seemingly simple: take a spreadsheet containing a list of data and send a notification to Microsoft Teams for every single row.
While this sounds straightforward, things get interesting when that spreadsheet has 256 rows. That is 256 discrete actions, 256 API calls, and—if you are the recipient—256 distinct "pings" on your phone. It was the perfect scenario to learn the mechanics of cloud flows, the importance of data structure, and the subtle art of not accidentally spamming your coworkers into oblivion. This journey took us from a basic concept to a functional automation, and we learned some valuable lessons along the way about how Power Automate thinks, executes, and scales.
Why We Automated This
In the business world, communication often involves repetitive data entry. Imagine you have a list of invoices, task updates, or shift assignments stored in Excel. Manually copying each row and sending a direct message to a colleague is not just boring; it is a recipe for human error. You might miss a row, paste the wrong value, or lose your place.
Automation solves this by introducing consistency. By connecting Excel to Teams via Power Automate, we ensure that every single line item is processed exactly the same way. Whether you have five rows or, in our case with Benji, 256 rows, the logic remains constant. This frees up human brainpower for work that actually requires creativity and judgment, rather than just movement.
The Flow Outline
To pull this off, we built an Instant Cloud Flow. This means we trigger it manually, rather than waiting for a scheduled time or an automated event. Here is the architecture we used to make it happen:
- Manually trigger a flow: The "Start" button for our experiment.
- List rows present in a table (Excel Online Business): This action connects to the specific Excel file and reads the structured data.
- Apply to each: This is the loop. It takes the output from the previous step and iterates through it one by one.
- Post message in a chat or channel (Microsoft Teams): Inside the loop, we use dynamic content from the current Excel row to construct a personalized message.
- Add a row (Excel/SharePoint List): A logging step we added to confirm the message was sent successfully.
Core Lessons from the Build
Working through this with Benji highlighted several foundational concepts that often trip up beginners.
Tables vs Ranges
Power Automate is picky about how it reads Excel files. You cannot simply point it at a sheet and hope for the best. The connector specifically asks for a Table. This means you must open your Excel file, highlight your data, and explicitly format it as a Table (usually Ctrl+T). If you skip this step, the "List rows" action will not see your data. It acts as a strict container that defines the boundaries of what the flow will process.
Dynamic Content is Magic
Once the flow knows about your table, column headers become distinct variables. Under the "Apply to each" loop, we could easily select "First Name," "Status," or "Task ID" from the dynamic content menu. This makes constructing the Teams message feel like writing a Mad Libs story, where the blanks are filled in automatically by the spreadsheet data.
The "Apply to Each" Behavior
When you add an action that relies on a list of items (like our Excel rows), Power Automate automatically wraps that action in an "Apply to each" block. It creates a container that says, "Do this specific thing for every item in that previous list." Understanding this hierarchy is crucial. If your Teams action is outside the loop, it will fail or only send one message. If it is inside, it executes 256 times.
Gotchas and Fixes
Of course, nothing works perfectly on the first try. Here are the specific hurdles we faced and how we cleared them.
1. Connection Permissions
The account running the flow needs access to both the Excel file (stored in OneDrive or SharePoint) and the Teams environment. We ran into a moment where the connection needed to be re-authenticated. Fix: Always check the connection status in your flow details page before a big run.
2. The "List Rows" Throttling
By default, the "List rows present in a table" action has a limit to how many rows it retrieves to keep things fast. If your table grows beyond 256 rows (the default pagination limit in some configurations), you might miss data. Fix: Go to the Settings of the Excel action, turn on Pagination, and set a Threshold distinct from the default if you plan to scale beyond basic testing.
3. Teams Rate Limits
Sending 256 messages in rapid succession is a reliable way to annoy Microsoft's spam filters. Power Automate might hit a "429 Too Many Requests" error. Fix: While the "Apply to each" loop runs sequentially by default (one after another), it can still move faster than Teams accepts. In a production environment, adding a "Delay" action of a few seconds inside the loop helps pace the execution.
4. Dirty Data
We noticed that if the Excel table had empty rows at the bottom that were technically still part of the table formatting, the flow would try to send blank messages. Fix: Use a "Condition" action inside the loop to check if a required field (like "Email" or "Message") is not empty before attempting to send the Teams notification.
Production Hardening: Going from Fun to Professional
Sending messages to Benji is fun, but deploying this for a client requires strict governance. If we were building this for a real enterprise workflow, we would add several layers of protection.
Idempotency
This is a fancy word for "handling duplicates." What happens if the flow crashes on row 100 and we restart it? We do not want to resend messages to the first 99 people. To solve this, we would add a "Status" column to the Excel table. The flow would look like this:
- Read the row.
- Check if Status equals "Sent".
- If yes, skip.
- If no, send message and update the row with "Sent".
Concurrency Control
Be careful with Concurrency Control in the "Apply to each" settings. Turning it on allows the loop to run multiple items in parallel (e.g., 50 at a time). While this is faster, it significantly increases the risk of hitting API rate limits with the Teams connector. For notifications, slow and steady is usually safer.
Secure Inputs
If the Excel sheet contained sensitive data, we would enable "Secure Inputs" and "Secure Outputs" on the actions to prevent that data from appearing in the run history logs.
Pseudocode and Checklist
If you want to replicate our experiment with your own version of "Benji," here is the logic in plain English and a checklist to get you started.
Logic Block:
LOOP through every Row in ExcelTable:
IF "MessageContent" is NOT empty:
Construct Teams Message using Row.Name
Send to TargetUser
Log "Success" to Console/List
ELSE:
Skip row
The "Don't Break It" Checklist
- Format as Table: Ensure your Excel data is a true Table object.
- Check Headers: Ensure your table headers do not contain weird characters.
- Validate Connections: Ensure you are signed into Excel Online and Teams.
- Test Small: Run the flow with 3 rows before you run it with 256.
- Monitor Flow Runs: Keep the "Run History" tab open to watch for failures in real-time.
Wrapping Up
This was a fantastic exercise in understanding the mechanics of Microsoft Power Automate. Big thanks to Benji for being the patient recipient of 256 test notifications. It proved that with just a few clicks, we can bridge the gap between static data in a spreadsheet and active communication in Teams.
Whether you are automating a simple notification list or architecting a complex enterprise integration, the principles remain the same: structure your data, respect the API limits, and always handle errors gracefully.
If you are looking to implement intelligent automation in your business without spamming your colleagues, let's talk. We specialize in turning these experiments into robust, scalable business systems.
Check out our availability at bookings.flowdevs.io and let's build something great together.
There is no better way to learn a new piece of technology than by trying to break it. Recently, I had the pleasure of sitting down with Benji to dive headfirst into the world of Microsoft Power Automate. Our mission was seemingly simple: take a spreadsheet containing a list of data and send a notification to Microsoft Teams for every single row.
While this sounds straightforward, things get interesting when that spreadsheet has 256 rows. That is 256 discrete actions, 256 API calls, and—if you are the recipient—256 distinct "pings" on your phone. It was the perfect scenario to learn the mechanics of cloud flows, the importance of data structure, and the subtle art of not accidentally spamming your coworkers into oblivion. This journey took us from a basic concept to a functional automation, and we learned some valuable lessons along the way about how Power Automate thinks, executes, and scales.
Why We Automated This
In the business world, communication often involves repetitive data entry. Imagine you have a list of invoices, task updates, or shift assignments stored in Excel. Manually copying each row and sending a direct message to a colleague is not just boring; it is a recipe for human error. You might miss a row, paste the wrong value, or lose your place.
Automation solves this by introducing consistency. By connecting Excel to Teams via Power Automate, we ensure that every single line item is processed exactly the same way. Whether you have five rows or, in our case with Benji, 256 rows, the logic remains constant. This frees up human brainpower for work that actually requires creativity and judgment, rather than just movement.
The Flow Outline
To pull this off, we built an Instant Cloud Flow. This means we trigger it manually, rather than waiting for a scheduled time or an automated event. Here is the architecture we used to make it happen:
- Manually trigger a flow: The "Start" button for our experiment.
- List rows present in a table (Excel Online Business): This action connects to the specific Excel file and reads the structured data.
- Apply to each: This is the loop. It takes the output from the previous step and iterates through it one by one.
- Post message in a chat or channel (Microsoft Teams): Inside the loop, we use dynamic content from the current Excel row to construct a personalized message.
- Add a row (Excel/SharePoint List): A logging step we added to confirm the message was sent successfully.
Core Lessons from the Build
Working through this with Benji highlighted several foundational concepts that often trip up beginners.
Tables vs Ranges
Power Automate is picky about how it reads Excel files. You cannot simply point it at a sheet and hope for the best. The connector specifically asks for a Table. This means you must open your Excel file, highlight your data, and explicitly format it as a Table (usually Ctrl+T). If you skip this step, the "List rows" action will not see your data. It acts as a strict container that defines the boundaries of what the flow will process.
Dynamic Content is Magic
Once the flow knows about your table, column headers become distinct variables. Under the "Apply to each" loop, we could easily select "First Name," "Status," or "Task ID" from the dynamic content menu. This makes constructing the Teams message feel like writing a Mad Libs story, where the blanks are filled in automatically by the spreadsheet data.
The "Apply to Each" Behavior
When you add an action that relies on a list of items (like our Excel rows), Power Automate automatically wraps that action in an "Apply to each" block. It creates a container that says, "Do this specific thing for every item in that previous list." Understanding this hierarchy is crucial. If your Teams action is outside the loop, it will fail or only send one message. If it is inside, it executes 256 times.
Gotchas and Fixes
Of course, nothing works perfectly on the first try. Here are the specific hurdles we faced and how we cleared them.
1. Connection Permissions
The account running the flow needs access to both the Excel file (stored in OneDrive or SharePoint) and the Teams environment. We ran into a moment where the connection needed to be re-authenticated. Fix: Always check the connection status in your flow details page before a big run.
2. The "List Rows" Throttling
By default, the "List rows present in a table" action has a limit to how many rows it retrieves to keep things fast. If your table grows beyond 256 rows (the default pagination limit in some configurations), you might miss data. Fix: Go to the Settings of the Excel action, turn on Pagination, and set a Threshold distinct from the default if you plan to scale beyond basic testing.
3. Teams Rate Limits
Sending 256 messages in rapid succession is a reliable way to annoy Microsoft's spam filters. Power Automate might hit a "429 Too Many Requests" error. Fix: While the "Apply to each" loop runs sequentially by default (one after another), it can still move faster than Teams accepts. In a production environment, adding a "Delay" action of a few seconds inside the loop helps pace the execution.
4. Dirty Data
We noticed that if the Excel table had empty rows at the bottom that were technically still part of the table formatting, the flow would try to send blank messages. Fix: Use a "Condition" action inside the loop to check if a required field (like "Email" or "Message") is not empty before attempting to send the Teams notification.
Production Hardening: Going from Fun to Professional
Sending messages to Benji is fun, but deploying this for a client requires strict governance. If we were building this for a real enterprise workflow, we would add several layers of protection.
Idempotency
This is a fancy word for "handling duplicates." What happens if the flow crashes on row 100 and we restart it? We do not want to resend messages to the first 99 people. To solve this, we would add a "Status" column to the Excel table. The flow would look like this:
- Read the row.
- Check if Status equals "Sent".
- If yes, skip.
- If no, send message and update the row with "Sent".
Concurrency Control
Be careful with Concurrency Control in the "Apply to each" settings. Turning it on allows the loop to run multiple items in parallel (e.g., 50 at a time). While this is faster, it significantly increases the risk of hitting API rate limits with the Teams connector. For notifications, slow and steady is usually safer.
Secure Inputs
If the Excel sheet contained sensitive data, we would enable "Secure Inputs" and "Secure Outputs" on the actions to prevent that data from appearing in the run history logs.
Pseudocode and Checklist
If you want to replicate our experiment with your own version of "Benji," here is the logic in plain English and a checklist to get you started.
Logic Block:
LOOP through every Row in ExcelTable:
IF "MessageContent" is NOT empty:
Construct Teams Message using Row.Name
Send to TargetUser
Log "Success" to Console/List
ELSE:
Skip row
The "Don't Break It" Checklist
- Format as Table: Ensure your Excel data is a true Table object.
- Check Headers: Ensure your table headers do not contain weird characters.
- Validate Connections: Ensure you are signed into Excel Online and Teams.
- Test Small: Run the flow with 3 rows before you run it with 256.
- Monitor Flow Runs: Keep the "Run History" tab open to watch for failures in real-time.
Wrapping Up
This was a fantastic exercise in understanding the mechanics of Microsoft Power Automate. Big thanks to Benji for being the patient recipient of 256 test notifications. It proved that with just a few clicks, we can bridge the gap between static data in a spreadsheet and active communication in Teams.
Whether you are automating a simple notification list or architecting a complex enterprise integration, the principles remain the same: structure your data, respect the API limits, and always handle errors gracefully.
If you are looking to implement intelligent automation in your business without spamming your colleagues, let's talk. We specialize in turning these experiments into robust, scalable business systems.
Check out our availability at bookings.flowdevs.io and let's build something great together.
Related Blog Posts


.jpg)