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 table

Basic 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

Column1Column2Column3
NameRegionSales
AliceEast500
BobWest700

After Table.PromoteHeaders()

NameRegionSales
AliceEast500
BobWest700
— the top table treats every row, including the first, as plain data; the bottom table is the same rows after promoting row 1 to headers.

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