Csv.Document()
Learn what Csv.Document actually returns before Table.PromoteHeaders runs — generic Column1/Column2 names and every value as text, not the named, typed columns the Get Data wizard makes it look like.
Csv.Document()
Csv.Document() parses raw CSV content into a table — the function behind Get Data > Text/CSV. What it returns is less finished than the wizard makes it look: generic column names, no header row, and every value as plain text.
Csv.Document(
csvSource as any,
optional columns as any,
optional delimiter as any,
optional extraValues as nullable number,
optional encoding as nullable number
) as tableBasic Example
Source = Csv.Document(File.Contents("Sales.csv")),
#"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars = true])Csv.Document() alone doesn't know the first row is meant to be headers — it's just the first row of data. Table.PromoteHeaders() is a separate, explicit step that takes that first row and turns it into column names.
Try it live
Csv.Document() output
| Column1 | Column2 | Column3 |
|---|---|---|
| Name | Region | Sales |
| Alice | East | 500 |
| Bob | West | 700 |
After Table.PromoteHeaders()
| Name | Region | Sales |
|---|---|---|
| Alice | East | 500 |
| Bob | West | 700 |
Edit the CSV text above — the raw Csv.Document() output never changes shape based on what's in the first row; it's Table.PromoteHeaders() that turns it into real column names, one step later.
Every Value Comes Back as Text
Even a column that's obviously numbers — 500, 700, 1200 — comes back from Csv.Document() as the text values "500", "700", "1200", not as numbers. Typing happens in a later, separate step.
#"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers", {{"Sales", Int64.Type}})The Get Data wizard runs Csv.Document, Table.PromoteHeaders, and a type-detection step automatically and shows you only the final result — which is why it's easy to not realize these are three separate steps until something in the middle needs adjusting (a locale-specific number format, for example).
Common Mistakes
Assuming Csv.Document Detects Headers Automatically
It doesn't — every row, including what looks like a header row, comes back as an ordinary data row named Column1, Column2, and so on. Table.PromoteHeaders() is what actually promotes a row to column names, and it has to be called explicitly (or generated by the wizard) to happen at all.
Assuming Numbers Import as Numbers
A column of numeric-looking text still needs an explicit Table.TransformColumnTypes() step — Csv.Document() itself never inspects or converts values, it only splits text into a grid.
Not Accounting for a Locale Mismatch on the Later Type Step
Once real typing happens via Table.TransformColumnTypes(), the same locale-mismatch risk applies as any other text-to-number or text-to-date conversion — see We Couldn't Convert to Number (or Date) for the decimal-separator and date-ordering versions of this.
Next Steps
Number.Round(), Number.RoundUp() & Number.RoundDown()
Learn how Number.Round, Number.RoundUp, and Number.RoundDown differ, why "round up" doesn't mean what it sounds like for negative numbers, and how negative digits round to the left of the decimal point.
Table.SplitColumn() & Table.CombineColumns()
Learn how Table.SplitColumn breaks one column into several across every row of a table, why a row with fewer parts than expected fills the extra columns with null instead of erroring, and how Table.CombineColumns merges columns back with a separator.