#PowerPlatformTip 93: 'Add RowNumbers'
TL;DR: Add dynamic row numbers to any Power Apps gallery with a
With/ForAll/Sequenceformula that indexes each record in-app, no delegation issues.
💡 Challenge
Incorporating a row number feature in PowerApps galleries and other elements can significantly enhance user interaction and data management. However, understanding how and where this operation is executed is vital.
✅ Solution
Implement a row numbering system within your app to provide real-time, dynamically updated row numbers for each item in your data sets.
🔧 How It’s Done
Use the following formula (thanks to Matthew Devaney) to add a row number to each record:
With({locLoadedData: YOUR DATA},
Ungroup(
ForAll(
Sequence(CountRows(locLoadedData)),
{myRecord: Table(Index(locLoadedData, Value)), RowNumber: Value}
),
"myRecord"
)
)
Replace YOUR DATA with your specific formula. This operation is executed within the app, ensuring it’s regenerated with each app load or data refresh.
🎉 Result
Every time your app loads or the data is refreshed, each item in your gallery or data set will have an accurate and updated row number.
🌟 Key Advantages
🔸 Enhanced user experience with clear data referencing.
🔸 Real-time, in-app data processing for up-to-date row numbering.
🔸 No external processing or storage required.
🔸 The numbering runs inside the app on the rows that are already loaded; it sends nothing to the data source.
🔁 Shorter Alternative: Patch Inside ForAll
The Ungroup wrapper exists because ForAll returns one record per iteration and the data record has to be unpacked again. Patch on the indexed record does the same job in one step:
With({locLoadedData: YOUR DATA},
ForAll(
Sequence(CountRows(locLoadedData)) As s,
Patch(Index(locLoadedData, s.Value), {RowNumber: s.Value})
)
)
Tested on a four-row table (Anna, Ben, Cara, Ben): the result is the four original rows plus RowNumber 1 to 4, duplicate names included. The same formula numbered three filtered rows of a Dataverse table 1 to 3. As s is optional here; Patch(Index(locLoadedData, Value), {RowNumber: Value}) without it returns the same result.
Start value and step
🔸 Zero-based: Sequence(CountRows(locLoadedData), 0) and Index(locLoadedData, s.Value + 1) give RowNumber 0 to 3.
🔸 Steps of ten: Sequence(CountRows(locLoadedData), 10, 10) with Index(locLoadedData, (s.Value - 10) / 10 + 1) gives 10, 20, 30, 40.
🎥 Video Tutorial
🛠️ FAQ
1. Can I apply this technique to any data source in PowerApps?
Yes. As long as you can load your data into a local variable or collection, you can use the With({locLoadedData: …}) approach and generate dynamic row numbers.
2. How can I adjust the starting value of the row numbers?
You can customize the Sequence function by adding start or step parameters, or simply add/subtract an offset to Value in the record formula.
3. Will this method update row numbers automatically on data refresh?
Yes. Since the row numbering logic is part of your app’s formula, it recalculates whenever the app loads or the data source is refreshed, ensuring accurate numbering.
4. Is there a shorter formula without Ungroup?
Yes: ForAll(Sequence(CountRows(Data)) As s, Patch(Index(Data, s.Value), {RowNumber: s.Value})). It returns the original rows with a RowNumber column, numbered 1 to n, and needs no Ungroup.
5. Do duplicate rows get the same number?
No. Numbering is by position, so two identical rows get two different numbers (Ben got 2 and 4 in the test).
🔗 Related Tips
🔸 #PowerPlatformTip 16: ‘PowerApps: Collections Cookbook’ - more copy-paste With/ForAll/Sequence-style recipes for collections.
🔸 #PowerPlatformTip 32: ‘Optimize with GroupBy’ - another in-app, delegation-safe technique for reshaping loaded data.
This tip is by Marcel Lehmann, Microsoft MVP (Business Applications) and founder of the Power Platform Academy – live Power Platform workshops, free or CHF 49. Join the workshop waitlist to get notified about new dates. For companies that want this implemented for them, see KMUpower – Power Platform consulting & automation for SMEs (DACH).