Csv.Document Function (Power Query M)

Csv.Document takes CSV data, either plain text or the binary contents of a file, and returns it as a table.

If you want to import a CSV file into Power Query, or parse comma separated text inside a query, this is the function doing the work under the hood.

In this article, I’ll show you how to use it, from a one-line parse to the exact pattern the Get Data wizard generates.

Syntax of Csv.Document Function

Csv.Document(source as any, optional columns as any, optional delimiter as any, optional extraValues as nullable number, optional encoding as nullable number) as table

where

  • source (required, any). The CSV data to parse. It can be plain text, or binary content coming from File.Contents or Web.Contents.
  • columns (optional, any). A column count, a list of column names, a table type, or an options record. When omitted, the column count is worked out from the data.
  • delimiter (optional, any). A single character, a list of characters, or "" to split on consecutive whitespace. Defaults to ",".
  • extraValues (optional, nullable number). An ExtraValues value that controls rows with more values than there are columns.
  • encoding (optional, nullable number). A TextEncoding code for binary sources, for example 65001 for UTF-8.

Returns: a table holding the parsed CSV data. Every value is loaded as text, and the header row is not promoted automatically.

In plain terms, you hand it CSV content and get back a Power Query table, one column per delimited field.

Most of the time you skip the positional arguments and pass a record as the second argument instead. That record is what the Get Data wizard generates, and it accepts these fields:

  • Delimiter. The column separator. Default ",".
  • Columns. A column count, a list of names, or a table type. Fixes the width of the table.
  • Encoding. The text encoding of a binary source. Default 65001 (UTF-8).
  • QuoteStyle. How quoted line breaks are handled. QuoteStyle.Csv (default) keeps them inside the cell; QuoteStyle.None ends the row at every line break.
  • CsvStyle. When quotes count at all. CsvStyle.QuoteAfterDelimiter (default) only honors quotes right after a delimiter; CsvStyle.QuoteAlways honors them anywhere.
  • ExtraValues. What to do with rows that have too many values, same as the positional extraValues.

Example 1: Parse CSV text into a table

Csv.Document does not need a file. Plain text works too, which is handy for quick tests. Here the CSV lives right inside the formula (#(lf) is a line break).

let
Source = Csv.Document("ShipmentID,City,WeightKg#(lf)SH-201,Denver,4.2#(lf)SH-202,Tucson,1.8")
in
Source

The result is a table with generic column names:

Column1Column2Column3
ShipmentIDCityWeightKg
SH-201Denver4.2
SH-202Tucson1.8

Notice the columns are called Column1, Column2, Column3, and the real headers are sitting in row 1 as data. That is the default behavior.

Example 2: Promote the first row to headers

To turn that first row into proper column headers, pair Csv.Document with Table.PromoteHeaders.

let
Source = Csv.Document("ShipmentID,City,WeightKg#(lf)SH-201,Denver,4.2#(lf)SH-202,Tucson,1.8"),
Promoted = Table.PromoteHeaders(Source)
in
Promoted

Now the headers are where they belong:

ShipmentIDCityWeightKg
SH-201Denver4.2
SH-202Tucson1.8

This two-step pattern, parse then promote, is the one you will use in almost every CSV query.

Example 3: Read semicolon separated data with the Delimiter option

Many European exports use semicolons because the comma is the decimal separator there. Pass Delimiter=";" in the options record.

let
Source = Csv.Document("Appliance;AnnualKwh#(lf)Dishwasher;270#(lf)Chest Freezer;310",[Delimiter=";"]),
Promoted = Table.PromoteHeaders(Source)
in
Promoted

The semicolons split the columns correctly:

ApplianceAnnualKwh
Dishwasher270
Chest Freezer310

Without the Delimiter option, each row would land in a single column because there are no commas to split on.

Example 4: Force a fixed column count with the Columns option

Real exports sometimes have ragged rows, where an optional trailing field is simply missing. Columns fixes the table width so every row lines up.

In this registration list, Mira’s row has no Notes value at the end.

let
Source = Csv.Document("Attendee,Workshop,Notes#(lf)Mira Shah,Pottery#(lf)Dev Kumar,Weaving,Evening batch",[Delimiter=",",Columns=3])
in
Source

The result still has three columns in every row:

Column1Column2Column3
AttendeeWorkshopNotes
Mira ShahPottery
Dev KumarWeavingEvening batch

The short row’s missing value comes through blank, so downstream steps never hit a misaligned column.

Example 5: Handle quoted line breaks with QuoteStyle

CSV fields sometimes contain line breaks inside quotes, like a two-line address. QuoteStyle decides whether that break stays in the cell or starts a new row.

Here the Hilltop Hall address contains a quoted line break. With QuoteStyle.Csv (the default), it stays part of the data. The query counts the rows so the difference is easy to see.

let
Source = Csv.Document("Venue,Address#(lf)Hilltop Hall,""12 Brewer Ln#(lf)Floor 2""#(lf)Lakeside Room,9 Dock St",[Delimiter=",",QuoteStyle=QuoteStyle.Csv]),
Result = Table.RowCount(Source)
in
Result

Result: 3

Three rows: the header row plus one row per venue. The address break stayed inside its cell.

Now the same data with QuoteStyle.None:

let
Source = Csv.Document("Venue,Address#(lf)Hilltop Hall,""12 Brewer Ln#(lf)Floor 2""#(lf)Lakeside Room,9 Dock St",[Delimiter=",",QuoteStyle=QuoteStyle.None]),
Result = Table.RowCount(Source)
in
Result

Result: 4

Every line break now ends a row, so the address splits and Hilltop Hall becomes two broken rows. One thing to be clear on: QuoteStyle only governs quoted line breaks. Whether quotes are honored at all is the job of CsvStyle.

Example 6: Import a CSV file from your computer

This is the real-world form, and exactly the shape of code the Get Data wizard writes for you. File.Contents supplies the binary, and the options record sets the delimiter, encoding, and quote style.

let
Source = Csv.Document(File.Contents("C:\Data\client-orders.csv"),[Delimiter=",",Encoding=65001,QuoteStyle=QuoteStyle.Csv]),
Promoted = Table.PromoteHeaders(Source)
in
Promoted

This loads client-orders.csv as a table, with the file’s first row promoted to column headers. Swap in your own path and you have a working CSV import.

Things to keep in mind with Csv.Document

  • Every value loads as text. A number like 4.2 arrives as the text "4.2". Add a Table.TransformColumnTypes step (the UI’s “Changed Type”) to set real data types.
  • A list of names in Columns renames, it does not select. The names apply positionally to the first columns. To keep only certain columns, load everything and use Table.SelectColumns after.
  • A Columns count lower than the data drops the extras. The surplus input columns are simply ignored. Example 4 showed the opposite, higher-count case.
  • Rows with too many values are governed by ExtraValues. ExtraValues.Error raises an error, ExtraValues.Ignore discards the surplus, and ExtraValues.List collects it into a list.
  • Garbled accents mean the wrong Encoding. Seeing é instead of é is the classic sign. Try 1252 for older Windows exports; the default is 65001 (UTF-8).
  • Tab-delimited files need Delimiter="#(tab)". Multi-character delimiters work too, passed as a list of characters.
  • A bad file path never reaches Csv.Document. The DataSource.Error you see comes from File.Contents, so that is where to check the path.
  • No query folding. A CSV is a flat file, so there is no source engine to push work to. The whole file is read locally, which is fine for typical file sizes.

Common questions about Csv.Document

Can Csv.Document read a CSV straight from a URL?

Yes. Wrap the URL in Web.Contents and pass the binary in: Csv.Document(Web.Contents("https://example.com/data.csv")). The options record works the same way.

What is the difference between Csv.Document and Json.Document?

Csv.Document parses delimited text and always returns a table. Json.Document parses JSON and returns a record or list that you then expand into a table yourself.

Should I use Csv.Document for Excel files?

No. It is for delimited text only. For .xlsx files, use Excel.Workbook with File.Contents instead.

List of All Power Query Functions

Related Power Query Functions / Articles:

I am a huge fan of Microsoft Excel and love sharing my knowledge through articles and tutorials. I work as a business analyst and use Microsoft Excel extensively in my daily tasks. My aim is to help you unleash the full potential of Excel and become a data-slaying wizard yourself.