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 fromFile.ContentsorWeb.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). AnExtraValuesvalue that controls rows with more values than there are columns.encoding(optional, nullable number). ATextEncodingcode for binary sources, for example65001for 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. Default65001(UTF-8).QuoteStyle. How quoted line breaks are handled.QuoteStyle.Csv(default) keeps them inside the cell;QuoteStyle.Noneends the row at every line break.CsvStyle. When quotes count at all.CsvStyle.QuoteAfterDelimiter(default) only honors quotes right after a delimiter;CsvStyle.QuoteAlwayshonors them anywhere.ExtraValues. What to do with rows that have too many values, same as the positionalextraValues.
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:
| Column1 | Column2 | Column3 |
|---|---|---|
| ShipmentID | City | WeightKg |
| SH-201 | Denver | 4.2 |
| SH-202 | Tucson | 1.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:
| ShipmentID | City | WeightKg |
|---|---|---|
| SH-201 | Denver | 4.2 |
| SH-202 | Tucson | 1.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:
| Appliance | AnnualKwh |
|---|---|
| Dishwasher | 270 |
| Chest Freezer | 310 |
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:
| Column1 | Column2 | Column3 |
|---|---|---|
| Attendee | Workshop | Notes |
| Mira Shah | Pottery | |
| Dev Kumar | Weaving | Evening 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.2arrives as the text"4.2". Add aTable.TransformColumnTypesstep (the UI’s “Changed Type”) to set real data types. - A list of names in
Columnsrenames, it does not select. The names apply positionally to the first columns. To keep only certain columns, load everything and useTable.SelectColumnsafter. - A
Columnscount 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.Errorraises an error,ExtraValues.Ignorediscards the surplus, andExtraValues.Listcollects it into a list. - Garbled accents mean the wrong
Encoding. Seeingéinstead oféis the classic sign. Try1252for older Windows exports; the default is65001(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. TheDataSource.Erroryou see comes fromFile.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: