This video demonstrates how to build a dynamic Power Query solution for parsing fixed-width text files by automatically detecting column boundaries using a divider row, rather than hard-coding positions. The approach involves extracting headers, identifying the divider row to determine column positions, creating a splitter function that uses text position calculations to split data at precise locations, and applying filters based on row length and content patterns. This method creates reusable code that can adapt to similar data structures without manual reconfiguration.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Fixed-Width Text Files in Power Query: a Dynamic SolutionAdded:
[music] >> Sometimes a text file lands on your desk and it looks like this.
No commas, no obvious separator.
When that happens, here's the first thing to try. Head over to the view tab and check monospace. If the columns suddenly line up perfectly, you're dealing with fixed-width data and that changes everything. Because fixed-width data follows a pattern and once you can identify that pattern, you can build a dynamic solution.
In this video, I'll show you how to do that.
Hi, my name is Melissa and it's good to have you here.
If you want to follow along, there's a link below in the description to my GitHub. That's where I've shared all the resources for this video and I'd also love to hear from you. What kind of data challenges face the most or which part of working with Power Query still feels difficult or unclear?
Leave a comment and I'll use that to shape future videos. All right.
There are several ways to solve the scenario that we're facing today, but in this video, we're going to build just one.
So, most people hard code column positions when working with files like this and when the layout is consistent, that will work just fine. But when you get different reports from that same source system, you can end up building a solution from scratch for each one.
Instead, if you give Power Query enough instructions so it can determine key pieces automatically, you're creating building blocks, code that can be reused for similar tasks.
Looking at our sample, there's a perfect candidate to solve this puzzle.
Do you see the divider row on line eight?
It shows exactly where every column begins. If we can determine the boundaries, we can use that to split all of the rows into columns.
Other things I've noticed are this. So, all of the data resides in a single column, and that column is named column one.
Above our divider row, you will find headers such as product, description, and so on.
Looking closer, you'll find it's split across two rows, but we'll only use the bottom one.
And judging by the currency symbol and decimal separator, we're dealing with a US locale.
Now, to make this work, we need to collect a few ingredients.
Extract the header text to create column names, extract that divider to determine column positions, and row length to filter the relevant rows of data.
Once we have that, we can build a splitter and apply it to the entire file.
First, let's find the header row.
And no, we're not going to hardcode a row number. We're going to tell Power Query to locate the row that contains a specific text, something that appears first in the header, like product, for example.
Don't be alarmed, but we'll be building most of our solution in the need funds editor.
So, let's open that up.
Personally, I could like to create my custom variables all the way at the top, so above the source tab.
It's a simple way to organize the steps within your query.
So, let's give that first variable a name, and I'll call it header.
Call a function table.skip.
So, what you need to know about the table skip function is that it will keep skipping rows as long as a condition is true, and it will stop processing your table when the condition returns false.
So, here we go.
Provided the source table.
And then a condition.
Pass it the name of our column. So, inside of square brackets, call column one.
And the thing to look for, in this case, product.
Do you see that red line below source on line six? That's because the end of this line doesn't have a comma yet.
So, watch. If I place a comma there, that red line will go away.
So, let's check out the result of this step.
So, the header row is now the first row in our table.
And of course, you can right click that first row to drill down and extract that value, or you could write the code manually.
Let's place my cursor all the way at the end, and the first thing that we'll do is apply item access to access that first row of data. Now, remember, positions in M are zero-based.
Next, we'll apply field access to access one specific field. You know, we are going to write column one in a set of those square brackets. Here we go.
Hit tick.
Perfect.
So, this extracts the header as a single text.
We will leave that for now and repeat the same process to also extract the divider row. So, let's head back to the advanced editor.
So, that divider is key because it will give the structure of the table and we can just copy that line of code here.
Press control C.
I'll hit enter and press control V to place that back.
So, there we go. We need to change two things. First, make sure that the variable name is unique. So, we will call this step divider.
And next, we need to change what we are looking for. That's product here. I'll double click that.
And we're going to look for two dashes followed by a space.
Let's press done.
And check out the result.
To filter this document, we can perform a simple check. Does the length of our row, the row that we're iterating, does that match the length of the divider?
Because we're dealing with fixed width data, all valid values will have the same length. Let me illustrate. I'll add a custom column through that mini table icon there.
Add custom column. It's just going to be temporary to illustrate something, right? So, text length.
Pass it column one by just double clicking that.
Okay.
As you can see, all of the valid rows have a total length of 127 characters.
So, I'm going to create a variable to store this length. Here we go.
Let's get rid of that.
And let's head back to the advanced editor.
I go to the end of that line and hit enter. And let's call this row length.
I'll use the same function that you saw me use just a second ago, text length, and then pass it the divider.
Time to build a key piece of logic.
Let's take another look at the table, all right? So, our logic is a bit of code that's going to take our divider and turn that into something that Power Query can use to split all of the data.
That something is going to be a list of positions.
The first position is no mystery at all.
Everything starts at the front, so at the beginning, at index position zero.
But all of the other columns starts start after a space character, as you can see on line eight.
So, if we can identify the position for each space, we can offset that value by one, so we have a new column start.
Let's turn that into a custom function.
I'm going to call that find starts.
And to initialize a function, I'll add a set of parentheses. Now, we need to pass that a text string, so we need one parameter there.
Then the goes to sign. Now again, we know the first position, right? So, as a list, we're going to give that first fixed position, combine it with another list using the ampersand. That's the combination operator.
Next, we're going to look for all of those space characters and offset that value. Now, to transform values in a list, we use a function called list.transform.
Look for all of the spaces, text.position of.
Pass it the thing to process, which is our parameter as and the thing to look for, a space.
And now we're going to ask for all occurrences of spaces, occurrence.all.
And when we have all of those positions, we're going to add one to them each, underscore, plus one.
Add a comma.
Let's think this true because the process to offset a position manually means that we could land on a space character.
In that case, we want to eliminate that position.
We'll use a function list.select to test if we're not landing on a space character.
Let's test this function by passing the divider.
>> And check the result.
Looks good.
Now we can create a splitter that uses these positions to cut every string at that precise location.
A splitter is just a function that returns a function. And the function it returned can be invoked for every row in this file.
Let's head back to the advanced editor.
Let's call that splitter.
And call the splitter function.
Pass the positions.
All right.
So before we apply this splitter to the data, let's test it on the header. That should give us a list with all of the column names.
Okay, these headers need a bit more work. And we can process all of the items using list.transform to trim all of the excess spaces in there.
So list.transform and trim those spaces.
There's one more problem to address.
Column names must be unique. The bottom two values aren't, and that's because originally the headers were split across two rows.
But that's okay because we can rename them by replacing the value at their position and here's how that works.
We'll call the function list.replace range.
Given the position of the value that we want to replace, which is six.
Then we want to replace two values and now we can provide it a list with two replacement values.
Let me copy that in.
And hit that tick.
At this point, we have everything we need. A row length, a splitter, cleaned header names. It's time to start to transform the actual data.
So a good place to start is limiting the rows to only those that you actually need.
Now to filter them, I'll use two conditions.
The row length and the row start.
Because that needs to be equal to the letters PC, the product code prefix.
Here we go.
This time, I'm going to create a new variable below the source step because this is the actual transformations that we're doing.
Let's call that filter.
And we'll call table.select rows.
Pass it the source table and give it a condition.
Each text.length needs to be equal to the row length and the text should start with PC.
To preview the result, we need to return filter below the in clause. So, I'm going to copy that and put it here.
Now, we can split everything using our splitter and provide clean header names.
Enter a comma at the end of that line, press enter.
Let's call that split and call the table.split column function.
Pass it filter, the column we want to split, our splitter function, and headers.
Return that after the in clause so we can see the result.
There's one more thing to do because all of these values are still text. So, the final step is to set column data types.
I want to remind you that this file was created using a US locale.
However, my operating system uses a different locale.
I will need to handle that. You might, too. So, let's see what happens.
We'll set this to a whole number.
Set this to fixed decimal.
And that errors out. That's okay for now. So, you can just ignore that and proceed setting all of the other columns to fixed decimal as well.
So, the difference in locale between what was used to create the file and what my system used when processing it is the reason why we get all of these errors.
But, it's easy to remedy.
I'm just going to expand the formula bar here so we can actually see it. There's an optional parameter called culture.
And we can provide that a culture [clears throat] tag to tell it what locale was used to create the file. Here we go.
English US.
Now, when I hit that tick, all of the errors go away.
Let's rename this step.
Done.
The key to dealing with fixed-width data is identifying the pattern.
Once you have that, you can build a dynamic solution.
I hope you've enjoyed this one. Thank you so much for watching. Till next time.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 viewsβ’2026-05-28
How agent o11y differs from traditional o11y β Phil Hetzel, Braintrust
aiDotEngineer
450 viewsβ’2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanationπ―β
LearnwithSahera
1K viewsβ’2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 viewsβ’2026-05-29
Search Algorithms Explained in 60 Seconds! π€π¨
samarthtuliofficial
218 viewsβ’2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 viewsβ’2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 viewsβ’2026-05-29
So What's Odin Lang Even Good For
TechOverTea
131 viewsβ’2026-06-01











