Thep Excel

Csv.Documentแปลงข้อมูล CSV เป็น Table ใน Power Query

Csv.Document แปลงข้อมูลรูปแบบ CSV (Comma-Separated Values) ให้เป็นตารางข้อมูล (table) ใน Power Query โดยรองรับการกำหนดตัวแบ่งข้อมูล (delimiter), รหัสภาษา (encoding) และโครงสร้างคอลัมน์ (column structure) แบบต่างๆ ได้ตามความต้องการ function นี้สามารถแยกวิเคราะห์ทั้งข้อมูลแบบ binary content ที่ได้จาก File.Contents และข้อความแบบ text string ที่ได้จาก Web.Contents พร้อมจัดการข้อความที่ครอบด้วย quote ตามมาตรฐานสากล CSV standard เหมาะสมสำหรับการนำเข้าไฟล์ CSV จากระบบไฟล์ในเครื่อง (local), ที่อยู่เว็บไซต์ (URL) หรือการตอบกลับจาก API (API response) ที่มีตัวแบ่งข้อมูลแบบกำหนดเอง (custom delimiter), เนื้อหาภาษาต่างประเทศ หรือโครงสร้างพิเศษที่ต้องการการควบคุมเฉพาะ คืนค่าออกมาเป็นตารางที่ทุกคอลัมน์มีประเภทข้อมูลเป็นข้อความ (text type) ควรใช้ร่วมกับ Table.PromoteHeaders เพื่อยกแถวแรกขึ้นเป็นหัวตาราง และ Table.TransformColumnTypes เพื่อแปลงประเภทข้อมูลให้เหมาะสมกับการใช้งาน

fx
=Csv.Document(source, [columns], [delimiter], [extraValues], [encoding]) as table

ความนิยม9/10
ความยาก3/10
ประโยชน์9/10

อัปเดต 18 December 2025

Syntax & Arguments

อาร์กิวเมนต์ ชนิด ค่าเริ่มต้น คำอธิบาย
source any ข้อมูลต้นทาง CSV สามารถเป็น binary content (จาก File.Contents), text string หรือ stream ก็ได้
[columns]ไม่บังคับ any null กำหนดโครงสร้าง column ได้ 4 รูปแบบ: null (auto-detect), number (จำนวน column), list of text (ชื่อ column), table type (กำหนดชื่อและ type พร้อมกัน) หรือ record (options ขั้นสูง)
[delimiter]ไม่บังคับ any "," ตัวแบ่ง column สามารถเป็น single character เช่น “,” “;” “|”, list of characters, หรือ “” เพื่อแบ่งด้วย whitespace
[extraValues]ไม่บังคับ nullable number null กำหนดวิธีจัดการ row ที่มี column มากกว่าหรือน้อยกว่าที่คาดหวัง ใช้ค่าจาก ExtraValues.Type (Ignore, Error, List)
[encoding]ไม่บังคับ nullable number 65001 รหัส text encoding ที่ใช้อ่านไฟล์ เช่น 65001 (UTF-8), 874 (Thai Windows), 1252 (Western European), 932 (Japanese Shift-JIS)

[ ] = อาร์กิวเมนต์ที่ไม่บังคับ

Additional Notes

Csv.Document เป็น function สำคัญใน Power Query ที่ใช้แปลงไฟล์ CSV ให้กลายเป็น table พร้อมใช้งานได้ทันที ครับ

function นี้รองรับทั้งการรับข้อมูลแบบ binary content จาก File.Contents (ไฟล์ในเครื่อง) และข้อความแบบ text string จาก Web.Contents (ดาวน์โหลดจากเว็บ) หรือแม้แต่ API response ที่ส่งมาเป็น CSV format ก็ใช้ได้

.

ที่เจ๋งคือ Csv.Document มีความยืดหยุ่นสูงมาก ครับ 😎

คุณสามารถควบคุมตัวแบ่งข้อมูล (delimiter), การเข้ารหัสภาษา (encoding), โครงสร้างคอลัมน์ (column structure) และวิธีจัดการข้อความที่ครอบด้วย quote ได้หมด

ทำให้นำเข้าข้อมูลจากแหล่งต่างๆ ได้อย่างแม่นยำ ไม่ว่าจะเป็นไฟล์ในเครื่อง, URL, หรือ API response

.

Csv.Document มักถูกใช้เป็นจุดเริ่มต้นในการ transform ข้อมูลภายใน Power Query โดยมักจะใช้ร่วมกับ Table.PromoteHeaders เพื่อยกแถวแรกขึ้นเป็นชื่อคอลัมน์ และใช้ร่วมกับ Table.TransformColumnTypes เพื่อแปลงประเภทข้อมูลจากข้อความ (text) เป็นประเภทที่เหมาะสมอย่างเช่น ตัวเลข (number), วันที่ (date) หรือค่าตรรกะ (logical) ตามความต้องการนะครับ

หลักการทำงานและคุณสมบัติสำคัญ

Csv.Document ทำงานโดยการแยกวิเคราะห์ (parse) ข้อมูล CSV ด้วยการแยกแถว (row) ตามเครื่องหมายขึ้นบรรทัดใหม่ (line break) และแยกคอลัมน์ (column) ตามตัวแบ่งข้อมูลที่กำหนด

.

โดยค่าเริ่มต้น (default) จะใช้เครื่องหมายจุลภาค (comma) ซึ่งเป็นมาตรฐานของไฟล์ CSV ครับ

.

function นี้มีความสามารถพิเศษในการตรวจจับจำนวนคอลัมน์โดยอัตโนมัติ หรือคุณสามารถกำหนดจำนวนคอลัมน์, ระบุชื่อคอลัมน์, หรือแม้กระทั่งกำหนดทั้งชื่อคอลัมน์และประเภทข้อมูล (data type) พร้อมกันผ่านการระบุแบบ table type specification ได้ตามความต้องการ

.

สำหรับกรณีที่มีข้อความที่ถูกครอบด้วย double quote ระบบจะตีความตัวแบ่งข้อมูล (delimiter) และการขึ้นบรรทัดใหม่ (line break) ที่อยู่ภายใน quote เหล่านั้นว่าเป็นข้อความปกติ (literal text) ไม่ใช่ตัวแบ่งคอลัมน์หรือตัวแบ่งแถว ซึ่งเป็นไปตามมาตรฐาน CSV ครับ 😎

.

นอกจากนี้ function ยังรองรับการกำหนดรหัสภาษา (text encoding) เพื่อให้สามารถอ่านไฟล์ที่มีภาษาต่างๆ ได้อย่างถูกต้อง ไม่ว่าจะเป็น UTF-8 (รหัส 65001), Windows-874 (ภาษาไทย), หรือ Windows-1252 (ภาษายุโรปตะวันตก)

การระบุรหัสภาษาที่ถูกต้องจะช่วยป้องกันปัญหาการแสดงผลอักขระผิดพลาด (mojibake) ที่มักเกิดขึ้นบ่อยครั้งเมื่อรหัสภาษาไม่ตรงกันระหว่างไฟล์ต้นทางกับการตั้งค่าที่ใช้อ่านไฟล์ นะครับ

.

สำหรับกรณีที่ข้อมูลมีจำนวนคอลัมน์ที่ไม่สม่ำเสมอกันในแต่ละแถว (บางแถวมีคอลัมน์มากกว่าหรือน้อยกว่าที่กำหนดไว้) สามารถใช้ตัวเลือกพิเศษที่เรียกว่า ExtraValues option เพื่อควบคุมพฤติกรรมการจัดการได้ครับ

.

เช่น ExtraValues.Ignore จะละเว้นค่าที่เกินและเติมค่า null ให้กับคอลัมน์ที่ขาด, ExtraValues.Error จะแจ้งข้อผิดพลาดทันทีเมื่อพบความไม่สม่ำเสมอ, หรือ ExtraValues.List จะเก็บค่าที่เกินมาไว้ในรูปแบบของ list ซ้อนเพื่อไม่ให้ข้อมูลสูญหาย

.

นอกจากนี้ยังสามารถใช้รูปแบบ record format เพื่อระบุตัวเลือกขั้นสูงได้หลายตัวพร้อมกันในคำสั่งเดียว 💡

เช่น QuoteStyle เพื่อควบคุมว่าเครื่องหมาย quote จะถูกตีความอย่างไรในการแยกข้อมูล (QuoteStyle.Csv สำหรับมาตรฐาน CSV หรือ QuoteStyle.None สำหรับถือว่าเป็นอักขระธรรมดา) และ CsvStyle เพื่อกำหนดว่าเครื่องหมาย quote จะมีนัยสำคัญในสถานการณ์ใด (CsvStyle.QuoteAfterDelimiter หมายความว่ามีนัยสำคัญเฉพาะเมื่ออยู่หลังตัวแบ่งข้อมูล หรือ CsvStyle.QuoteAlways หมายความว่ามีนัยสำคัญเสมอทุกกรณี)

.

การใช้รูปแบบ record format จะทำให้โค้ดอ่านเข้าใจได้ง่ายกว่าการส่ง argument แยกกันหลายตัว และยังช่วยให้สามารถปรับแต่งพฤติกรรมการแยกวิเคราะห์ (parsing behavior) ได้อย่างละเอียดและครอบคลุมมากขึ้นครับ

.

เนื่องจาก Csv.Document จะคืนค่าออกมาเป็น table ที่ทุกคอลัมน์มีประเภทข้อมูลเป็นข้อความ (text type) ทั้งหมด จึงควรใช้ Table.TransformColumnTypes ตามหลังเพื่อแปลงคอลัมน์เป็นประเภทที่เหมาะสมกับข้อมูลจริง

เช่น Int64.Type สำหรับตัวเลขจำนวนเต็ม, type date สำหรับวันที่, type logical สำหรับค่าความจริง เพื่อให้สามารถกรองข้อมูล (filter), เรียงลำดับ (sort) และคำนวณผลลัพธ์ได้อย่างถูกต้องตามที่ต้องการนะครับ

สถานการณ์การใช้งานที่เหมาะสม

Csv.Document เหมาะสมอย่างยิ่งสำหรับการนำเข้าไฟล์ CSV จากระบบไฟล์ในเครื่อง (local file system) โดยใช้ร่วมกับ File.Contents หรือการดาวน์โหลดข้อมูลจาก URL โดยใช้ร่วมกับ Web.Contents โดยเฉพาะเมื่อต้องการควบคุมตัวแบ่งข้อมูล (delimiter), รหัสภาษา (encoding) หรือโครงสร้างคอลัมน์ (column structure) ด้วยตัวเองอย่างละเอียด

.

ใช้ได้ดีกับไฟล์ที่มีตัวแบ่งข้อมูลแบบกำหนดเอง (custom delimiter) เช่น เครื่องหมาย semicolon ซึ่งพบบ่อยในไฟล์จากประเทศในยุโรป, อักขระ tab สำหรับไฟล์รูปแบบ TSV, เครื่องหมาย pipe หรืออักขระอื่นๆ ที่ไม่ใช่ comma ทั่วไป

.

ใช้ได้ดีกับไฟล์ที่มีเนื้อหาเป็นภาษาพิเศษ เช่น ภาษาไทย ภาษาจีน ภาษาญี่ปุ่น โดยต้องระบุรหัสภาษา (encoding) ที่ถูกต้องเพื่อให้แสดงผลได้ถูกต้อง ไม่งั้นจะเจออักขระพิเศษแบบ mojibake แน่นอน 😅

.

ใช้ได้ดีกับข้อมูลที่ไม่มีแถวหัวตาราง (header row) โดยสามารถกำหนดชื่อคอลัมน์ขึ้นมาใช้เองได้

.

ใช้ได้ดีกับข้อมูลที่มีข้อความซับซ้อนที่ถูกครอบด้วย quote (มีตัวแบ่งข้อมูลหรือการขึ้นบรรทัดใหม่อยู่ภายในข้อความ) และยังใช้ได้ดีกับข้อมูลที่มีจำนวนคอลัมน์ไม่สม่ำเสมอในแต่ละแถวโดยสามารถใช้ ExtraValues option เพื่อจัดการได้

.

นอกจากนี้ยังใช้ได้ดีกับการรับข้อมูลจาก API ที่ตอบกลับมาในรูปแบบ CSV format โดยสามารถแยกวิเคราะห์ข้อความ (text string) ให้กลายเป็น table ได้ทันทีครับ 😎

เมื่อไหร่ที่ไม่ควรใช้

ในทางตรงกันข้าม สถานการณ์ที่ไม่เหมาะสมสำหรับการใช้ Csv.Document คือเมื่อต้องการอ่านไฟล์ Excel ที่เป็นรูปแบบ binary format เช่น .xlsx หรือ .xls ซึ่งควรใช้ Excel.Workbook แทนเพราะจะได้ข้อมูลที่สมบูรณ์พร้อมทั้งการจัดรูปแบบและสูตรคำนวณ

.

หรือเมื่อต้องการแยกวิเคราะห์ข้อมูลรูปแบบ JSON ซึ่งควรใช้ Json.Document แทนเพื่อให้ได้โครงสร้างข้อมูลที่ถูกต้อง

.

หรือเมื่อข้อมูลมีโครงสร้างเป็น list of lists อยู่แล้วในหน่วยความจำ (in-memory) ซึ่งควรใช้ Table.FromRows แทนเพราะจะเร็วกว่าและไม่ต้องแยกวิเคราะห์ข้อความอีกครั้ง

.

การเลือกใช้ function ให้เหมาะสมกับรูปแบบข้อมูลต้นทางจะช่วยให้การประมวลผลข้อมูลมีประสิทธิภาพและถูกต้องที่สุดครับ 💡

How it works

นำเข้าไฟล์ CSV จาก local file system

ใช้ร่วมกับ File.Contents เพื่ออ่านไฟล์ CSV จาก local path แล้ว parse เป็น table พร้อมยก row แรกเป็น header

ดาวน์โหลดและ parse CSV จาก URL หรือ API

ใช้ร่วมกับ Web.Contents เพื่อดาวน์โหลด CSV จาก URL หรือ API endpoint แล้ว parse ให้เป็น table

อ่าน CSV ที่ใช้ custom delimiter

จัดการไฟล์ที่ใช้ semicolon (ไฟล์จากยุโรป), tab (TSV), pipe หรืออักขระอื่นแทน comma

นำเข้า CSV ภาษาต่างประเทศด้วย encoding ที่ถูกต้อง

ระบุ encoding ที่เหมาะสมเพื่ออ่านภาษาไทย จีน ญี่ปุ่น หรือภาษาอื่นๆ ได้ถูกต้องโดยไม่เกิด mojibake

Parse CSV ที่ไม่มี header row

กำหนดชื่อ column เองผ่าน list of text เมื่อ CSV ไม่มี header row หรือ header ไม่ถูกต้อง

Examples

ตัวอย่างที่ 1: แปลง CSV text พื้นฐาน (Foundation)let // สร้าง CSV text จาก list of text (แต่ละ item = 1 row) CsvText = Text.Combine( { "OrderID,Product,Amount", "1,Laptop,25000", "2,Mouse,350", "3,Keyboard,890…

ตัวอย่างนี้แสดงขั้นตอนพื้นฐานของการ parse CSV ใน Power Query

เริ่มจากใช้ Text.Combine สร้าง CSV text จาก list โดยแต่ละ item คือ 1 row แล้วเชื่อมด้วย line break (#(cr)#(lf) คือ carriage return + line feed ซึ่งเป็น standard line ending)

จากนั้น Csv.Document จะ parse text นี้โดยใช้ comma เป็น delimiter (ค่า default) และตรวจจับจำนวน column อัตโนมัติเป็น 3 column 😎

ผลที่ได้เป็น table ที่ทุก column เป็น text type และ row แรกยังเป็นข้อมูลธรรมดา (ยังไม่ใช่ header)
ดังนั้นใช้ Table.PromoteHeaders ยก row แรกขึ้นเป็นชื่อ column และใช้ Table.TransformColumnTypes แปลง OrderID และ Amount จาก text เป็น Int64 เพื่อให้สามารถคำนวณได้

นี่คือ pattern มาตรฐานสำหรับการนำเข้า CSV ที่ผมใช้เกือบทุกครั้งเลยครับ 💡

fx
=let
// สร้าง CSV text จาก list of text (แต่ละ item = 1 row)
CsvText = Text.Combine(
{
"OrderID,Product,Amount",
"1,Laptop,25000",
"2,Mouse,350",
"3,Keyboard,890"
},
"#(cr)#(lf)" // Line break (carriage return + line feed)
),

// Parse CSV ด้วยค่า default (comma delimiter, auto-detect 3 columns)
ParsedTable = Csv.Document(CsvText),

// ยก row แรก (OrderID,Product,Amount) ขึ้นเป็นชื่อ column
WithHeaders = Table.PromoteHeaders(ParsedTable, [PromoteAllScalars=true]),

// แปลง column type จาก text เป็น number
TypedTable = Table.TransformColumnTypes(
WithHeaders,
{
{"OrderID", Int64.Type},
{"Amount", Int64.Type}
}
)
in
TypedTable
// Result: Table with 3 rows
// [OrderID = 1, Product = "Laptop", Amount = 25000]
// [OrderID = 2, Product = "Mouse", Amount = 350]
// [OrderID = 3, Product = "Keyboard", Amount = 890]

ผลลัพธ์Table with 3 rows and 3 columns (OrderID: Int64, Product: text, Amount: Int64)
ตัวอย่างที่ 2: ใช้ custom delimiter (Practical)let // Case 1: Semicolon CSV (ไฟล์จากยุโรปที่ใช้ comma เป็นทศนิยม) EuropeanCsv = Text.Combine( { "Name;Country;Score", "Alice;USA;95", "Bob;UK;87", "Carol;Franc…

ตัวอย่างนี้แสดง 2 รูปแบบ delimiter ที่พบบ่อยนอกจาก comma

รูปแบบแรกคือ semicolon-separated values ซึ่งมักพบในไฟล์ CSV จากประเทศยุโรป
เพราะเขาใช้ comma เป็นทศนิยม (เช่น 3,14 แทน 3.14) จึงใช้ semicolon แบ่ง column แทน
ระบุโดยส่ง ";" เป็น argument ที่ 3 และใช้ null เป็น argument ที่ 2 เพื่อให้ระบบตรวจจับจำนวน column อัตโนมัติ 😎

รูปแบบที่สองคือ tab-separated values (TSV) ซึ่งใช้ tab character เป็น delimiter
โดยใน M language เขียนเป็น #(tab)
ไฟล์ TSV มักใช้เมื่อ export จาก database หรือโปรแกรมบางตัว

สำหรับทั้ง 2 กรณีใช้ Table.PromoteHeaders ยก row แรกขึ้นเป็น header ตามปกติ
delimiter อื่นๆ ที่ใช้ได้ เช่น pipe "|", colon ":", หรืออักขระใดก็ได้ที่เป็น single character 💡

fx
=let
// Case 1: Semicolon CSV (ไฟล์จากยุโรปที่ใช้ comma เป็นทศนิยม)
EuropeanCsv = Text.Combine(
{
"Name;Country;Score",
"Alice;USA;95",
"Bob;UK;87",
"Carol;France;92"
},
"#(cr)#(lf)"
),
// ระบุ delimiter เป็น semicolon (argument ที่ 3)
ParsedEU = Csv.Document(EuropeanCsv, null, ";"),
WithHeadersEU = Table.PromoteHeaders(ParsedEU),
TypedEU = Table.TransformColumnTypes(WithHeadersEU, {{"Score", Int64.Type}}),

// Case 2: Tab-delimited (TSV file)
TsvData = Text.Combine(
{
"Product#(tab)Price#(tab)InStock",
"Coffee#(tab)120#(tab)Yes",
"Tea#(tab)80#(tab)No"
},
"#(cr)#(lf)"
),
// ใช้ #(tab) เป็น delimiter
ParsedTSV = Csv.Document(TsvData, null, "#(tab)"),
WithHeadersTSV = Table.PromoteHeaders(ParsedTSV),

Result = [
European = TypedEU,
TSV = WithHeadersTSV
]
in
Result
// Result: Record with 2 tables
// [European]: 3 rows × 3 columns (Name, Country, Score)
// [TSV]: 2 rows × 3 columns (Product, Price, InStock)

ผลลัพธ์Record containing 2 tables with different delimiters successfully parsed
ตัวอย่างที่ 3: จัดการ encoding และกำหนดชื่อ column (Advanced)let // Case 1: CSV ไม่มี header row (กำหนดชื่อ column เอง) CsvWithoutHeader = Text.Combine( { "001|Electronics|15000", "002|Clothing|3500", "003|Food|1200" }, "…

ตัวอย่างนี้แสดง 2 สถานการณ์พิเศษที่เจอบ่อยครับ

กรณีแรกคือ CSV ที่ไม่มี header row (row แรกคือข้อมูลเลย)
วิธีแก้คือสร้าง list ของชื่อ column ขึ้นมาเอง {"ProductCode", "Category", "Revenue"} แล้วส่งเป็น argument ที่ 2 ของ Csv.Document
ทำให้ไม่ต้องใช้ Table.PromoteHeaders เพราะชื่อ column ถูกกำหนดไปแล้วตั้งแต่ต้น
ใช้ร่วมกับ delimiter "|" (pipe character) 😎

กรณีที่สองคือการอ่าน CSV ภาษาไทยที่ save ด้วย Windows-874 encoding (legacy Thai encoding ใน Windows เก่า)
ถ้าไม่ระบุ encoding จะเกิด mojibake (อักขระแสดงผิด) 😭

วิธีแก้คือใช้ record format [Delimiter=",", Encoding=874] เพื่อระบุทั้ง delimiter และ encoding พร้อมกัน
สำหรับ CSV ที่เป็น UTF-8 ไม่ต้องระบุ encoding เพราะค่า default คือ 65001 (UTF-8) อยู่แล้ว

💡 **Tip:** encoding อื่นๆ ที่ใช้บ่อย: 1252 (Western European), 932 (Japanese)

fx
=let
// Case 1: CSV ไม่มี header row (กำหนดชื่อ column เอง)
CsvWithoutHeader = Text.Combine(
{
"001|Electronics|15000",
"002|Clothing|3500",
"003|Food|1200"
},
"#(cr)#(lf)"
),
// ส่ง list of text เป็น argument ที่ 2 (แทน null)
ColumnNames = {"ProductCode", "Category", "Revenue"},
ParsedNoHeader = Csv.Document(
CsvWithoutHeader,
ColumnNames,
"|"
),
TypedNoHeader = Table.TransformColumnTypes(
ParsedNoHeader,
{{"Revenue", Int64.Type}}
),

// Case 2: CSV ภาษาไทย (Windows-874 encoding)
ThaiCsv = "รหัส,ชื่อสินค้า,ราคา#(cr)#(lf)P001,กาแฟ,120#(cr)#(lf)P002,ชา,80",
// ใช้ record format เพื่อระบุ Delimiter และ Encoding พร้อมกัน
ParsedThai = Csv.Document(
ThaiCsv,
[Delimiter=",", Encoding=874]
),
WithHeadersThai = Table.PromoteHeaders(ParsedThai),
TypedThai = Table.TransformColumnTypes(
WithHeadersThai,
{{"ราคา", Int64.Type}}
),

Result = [
Products = TypedNoHeader,
ThaiProducts = TypedThai
]
in
Result
// Result: Record with 2 tables
// [Products]: 3 rows with custom column names (ProductCode, Category, Revenue)
// [ThaiProducts]: 2 rows with Thai text correctly displayed

ผลลัพธ์Record containing 2 tables: one with custom column names, one with Thai encoding correctly handled
ตัวอย่างที่ 4: จัดการ quoted text และ column ไม่สม่ำเสมอ (Complex)let // Case 1: CSV ที่มี quoted text ซับซ้อน (มี delimiter และ line break ข้างใน) ComplexCsv = Text.Combine( { "ID,Name,Description", "1,Product A,""Premium qua…

ตัวอย่างนี้แสดงการใช้ record format กับ advanced options ครบทุกตัว

กรณีแรกคือ CSV ที่มี quoted text (ครอบด้วย double quote) ซึ่งภายในมี delimiter (comma, semicolon) และ line break
ตามมาตรฐาน CSV ถ้าข้อความครอบด้วย double quote ตัว delimiter และ line break ภายในจะถือเป็น literal text ไม่ใช่ตัวแบ่ง column หรือ row

ใช้ QuoteStyle=QuoteStyle.Csv บอกว่าให้ตีความ quote ตามมาตรฐาน CSV (quote มีนัยสำคัญเสมอ)
และใช้ CsvStyle=CsvStyle.QuoteAfterDelimiter บอกว่า quote จะมีนัยสำคัญต่อเมื่ออยู่หลัง delimiter เท่านั้น (ไม่ใช่อยู่กลาง field)

กรณีที่สองคือ CSV ที่ row บางตัวมี column เกิน (5 column แทน 3) หรือขาด (2 column แทน 3)
โดยใช้ ExtraValues=ExtraValues.Ignore จะละเว้น column ที่เกิน (column ที่ 4 และ 5 จะถูกตัดทิ้ง)
และเติม null ให้ column ที่ขาด (row ที่สองจะมี column C = null)
ทำให้ได้ table ที่มีโครงสร้างสม่ำเสมอ 3 columns เสมอ 😎

💡 **Tip:** Options อื่นคือ ExtraValues.Error (แจ้ง error ถ้าไม่สม่ำเสมอ) หรือ ExtraValues.List (เก็บค่าที่เกินใน nested list)
ส่วนตัวผมใช้ ExtraValues.Ignore บ่อยสุดครับ เพราะข้อมูลจริงมักไม่สมบูรณ์แบบ 😅

fx
=let
// Case 1: CSV ที่มี quoted text ซับซ้อน (มี delimiter และ line break ข้างใน)
ComplexCsv = Text.Combine(
{
"ID,Name,Description",
"1,Product A,""Premium quality"" with",
"multiple lines and, commas",
"2,Product B,Standard item",
"3,Product C,""Features: comma, semicolon; and pipe|"""
},
"#(cr)#(lf)"
),
// ใช้ record format กับ QuoteStyle และ CsvStyle options
ParsedComplex = Csv.Document(
ComplexCsv,
[
Delimiter=",",
Columns=3,
QuoteStyle=QuoteStyle.Csv, // ตีความ quote ตามมาตรฐาน CSV
CsvStyle=CsvStyle.QuoteAfterDelimiter, // Quote มีนัยสำคัญหลัง delimiter
Encoding=65001
]
),
WithHeadersComplex = Table.PromoteHeaders(ParsedComplex),

// Case 2: CSV ที่ row บางตัวมี column ไม่สม่ำเสมอ
UnevenCsv = Text.Combine(
{
"A,B,C",
"1,2,3,4,5", // 5 columns (เกิน)
"6,7", // 2 columns (ขาด)
"8,9,10" // 3 columns (ถูกต้อง)
},
"#(cr)#(lf)"
),
// ใช้ ExtraValues.Ignore เพื่อจัดการ column ที่ไม่สม่ำเสมอ
ParsedUneven = Csv.Document(
UnevenCsv,
[
Columns=3,
ExtraValues=ExtraValues.Ignore // ละเว้นค่าที่เกิน, เติม null ให้ค่าที่ขาด
]
),
WithHeadersUneven = Table.PromoteHeaders(ParsedUneven),

Result = [
ComplexQuotes = WithHeadersComplex,
UnevenColumns = WithHeadersUneven
]
in
Result
// Result: Record with 2 tables
// [ComplexQuotes]: Table with quoted text containing delimiters and line breaks
// [UnevenColumns]: Table with 3 rows × 3 columns (extra values ignored, missing filled with null)

ผลลัพธ์Record with 2 tables: complex quoted text handled correctly, uneven columns normalized to 3 columns

FAQs

Csv.Document ต่างจาก Excel.Workbook, Json.Document และ Table.FromRows อย่างไร+

Csv.Document ใช้สำหรับแยกวิเคราะห์ข้อมูล CSV (ข้อความธรรมดาที่แบ่งด้วยตัวแบ่งข้อมูล delimiter) ให้กลายเป็นตารางข้อมูล (table) โดยสามารถตรวจจับโครงสร้างโดยอัตโนมัติ (auto-detect) Excel.Workbook ใช้สำหรับอ่านไฟล์ Excel ที่เป็นรูปแบบ binary format เช่น .xlsx หรือ .xls ซึ่งมีข้อมูลแผ่นงาน (worksheet), การจัดรูปแบบ (formatting) และสูตรคำนวณ (formula) อยู่ด้วย Json.Document ใช้สำหรับแยกวิเคราะห์ข้อความรูปแบบ JSON ให้กลายเป็น record หรือ list ตามโครงสร้างของ JSON ส่วน Table.FromRows ใช้สำหรับสร้างตารางข้อมูลจาก list of lists ที่มีโครงสร้างชัดเจนอยู่แล้วในหน่วยความจำ เช่น {{1,"A"},{2,"B"}} โดยไม่ต้องแยกวิเคราะห์ข้อความอีก ดังนั้นการเลือกใช้ควรพิจารณาจากรูปแบบข้อมูลต้นทาง: ข้อความ CSV → Csv.Document, ไฟล์ Excel → Excel.Workbook, ข้อความ JSON → Json.Document, รายการของรายการ → Table.FromRows เพื่อให้การประมวลผลมีประสิทธิภาพสูงสุด

วิธีอ่านไฟล์ CSV จาก local file, URL และ API ได้อย่างไร+

สำหรับการอ่านไฟล์จากเครื่องคอมพิวเตอร์ (local file) ให้ใช้ File.Contents ร่วมกับ Csv.Document ตัวอย่างโค้ด: let Source = File.Contents("C:\\Data\\sales.csv"), Parsed = Csv.Document(Source) in Parsed โดย File.Contents จะอ่านไฟล์เป็น binary content แล้ว Csv.Document จะแยกวิเคราะห์เป็นตารางข้อมูล สำหรับการดาวน์โหลดไฟล์จากที่อยู่เว็บไซต์ (URL) ให้ใช้ Web.Contents ตัวอย่างโค้ด: let Source = Web.Contents("https://example.com/data.csv"), Parsed = Csv.Document(Source) in Parsed โดย Web.Contents จะดาวน์โหลดเนื้อหาเป็น binary content เช่นเดียวกัน สำหรับการรับข้อมูลจาก API ที่ส่งกลับมาเป็นข้อความ CSV ให้ใช้ Web.Contents และอาจต้องใช้ Text.FromBinary ก่อนแปลงเป็นข้อความ (ถ้าจำเป็น) ทั้ง File.Contents และ Web.Contents จะคืนค่าออกมาเป็น binary content ซึ่ง Csv.Document สามารถแยกวิเคราะห์ให้กลายเป็นตารางข้อมูลได้ทันที จากนั้นควรตามด้วย Table.PromoteHeaders เพื่อยกแถวแรกขึ้นเป็นหัวตารางและ Table.TransformColumnTypes เพื่อแปลงประเภทข้อมูลให้ถูกต้องตามปกติ

ทำไม Csv.Document อ่านภาษาไทยแล้วเป็นอักขระพิเศษ (mojibake) จะแก้ไขอย่างไร+

เกิดจาก text encoding ไม่ตรงกับไฟล์ต้นทาง… เคยเจอปัญหานี้บ่อยมากครับ 😭

CSV ภาษาไทยมักใช้ UTF-8 (encoding 65001, ค่า default) หรือ Windows-874 (legacy Thai encoding ใน Windows เก่า)

วิธีแก้คือระบุ encoding ด้วย record format:
– Csv.Document(source, [Encoding=874]) สำหรับไฟล์ที่ save จาก Excel ภาษาไทยเวอร์ชันเก่า
– Csv.Document(source, [Encoding=65001]) สำหรับ UTF-8

ถ้าไม่แน่ใจให้ลองทั้ง 2 ค่า หรือเปิดไฟล์ด้วย Notepad++ เพื่อตรวจสอบ encoding ที่ถูกต้อง

💡 **Tip:** สำหรับภาษาอื่น: 932 (Japanese Shift-JIS), 936 (Simplified Chinese GBK), 1252 (Western European)

วิธีอ่าน CSV ที่ใช้ semicolon, tab, pipe หรือ delimiter อื่นๆ+

ระบุ delimiter ผ่าน argument ที่ 3 หรือใช้ record format สำหรับ semicolon (ไฟล์จากยุโรป): Csv.Document(source, null, ";") สำหรับ tab character (TSV): Csv.Document(source, null, "#(tab)") สำหรับ pipe: Csv.Document(source, null, "|") หรือใช้ record format: Csv.Document(source, [Delimiter=";"]) สามารถใช้ delimiter อื่นๆ ได้ เช่น colon ":", space " ", หรืออักขระใดก็ได้ที่เป็น single character ถ้าต้องการ split ด้วย whitespace ให้ใช้ "" (empty string) ถ้าต้องการ multi-character delimiter ให้ส่งเป็น list of characters แทน

จะจัดการ CSV ที่แต่ละ row มี column จำนวนไม่เท่ากันได้อย่างไร+

ใช้ ExtraValues option ควบคุมพฤติกรรม มี 3 แบบ:

1. **ExtraValues.Ignore** (ละเว้นค่าที่เกิน, เติม null ให้ค่าที่ขาด, ใช้บ่อยที่สุด 😎)
เหมาะกับข้อมูลที่ต้องการโครงสร้างสม่ำเสมอ

2. **ExtraValues.Error** (แจ้ง error ถ้า column ไม่สม่ำเสมอ)
เหมาะกับข้อมูลที่ต้องการความแม่นยำสูง

3. **ExtraValues.List** (เก็บค่าที่เกินใน nested list)
เหมาะกับข้อมูลที่ต้องการเก็บทุกค่า

ตัวอย่าง: Csv.Document(source, [Columns=3, ExtraValues=ExtraValues.Ignore]) จะบังคับให้ table มี 3 column เสมอโดยตัดค่าที่เกินและเติม null ให้ค่าที่ขาด

💡 **Tip:** ส่วนตัวผมแนะนำ ExtraValues.Ignore สำหรับงานส่วนใหญ่ครับ เพราะข้อมูลจริงมักมีความไม่สมบูรณ์แบบอยู่แล้ว

ต้องใช้ Table.PromoteHeaders ทุกครั้งหรือไม่ และทำไมต้องใช้ Table.TransformColumnTypes+

Table.PromoteHeaders ไม่จำเป็นถ้า CSV ไม่มี header row หรือต้องการกำหนดชื่อ column เอง

โดยส่ง list of column names เป็น argument ที่ 2: Csv.Document(source, {"ID","Name","Amount"}, ",") จะได้ table ที่มีชื่อ column กำหนดไว้แล้ว

ส่วน Table.TransformColumnTypes จำเป็นเพราะ Csv.Document คืน table ที่ทุก column เป็น text type ทำให้ไม่สามารถคำนวณหรือเปรียบเทียบตัวเลขได้ถูกต้อง

ตัวอย่าง: "10" > "9" เป็น false เพราะเปรียบเทียบเป็น text 😭

ต้องแปลงเป็น type ที่เหมาะสม: Table.TransformColumnTypes(table, {{"Amount",Int64.Type}, {"Date",type date}}) เพื่อให้ filter, sort และคำนวณได้ถูกต้อง

💡 **Tip:** ส่วนตัวผมเคยเจอ bug จาก text type นี้บ่อยมากครับ เลยเป็นนิสัยที่จะ transform type ทุกครั้งเลย 😅

จะจัดการ CSV ที่มี quoted text (ข้อความครอบด้วย double quote) ซับซ้อนได้อย่างไร+

Csv.Document จัดการ quoted text ตามมาตรฐาน CSV โดย default ถ้าข้อความครอบด้วย double quote ตัว delimiter และ line break ภายในจะถือเป็น literal text ไม่ใช่ตัวแบ่ง column หรือ row สามารถควบคุมพฤติกรรมด้วย QuoteStyle option: QuoteStyle.Csv (default, quote มีนัยสำคัญเสมอ) หรือ QuoteStyle.None (ถือว่า quote เป็น text ธรรมดา, line break ทุกตัวแบ่ง row) และ CsvStyle option: CsvStyle.QuoteAfterDelimiter (quote มีนัยสำคัญเฉพาะหลัง delimiter) หรือ CsvStyle.QuoteAlways (quote มีนัยสำคัญตลอด) ตัวอย่าง: Csv.Document(source, [QuoteStyle=QuoteStyle.Csv, CsvStyle=CsvStyle.QuoteAfterDelimiter]) เหมาะกับ CSV standard

ถ้า Csv.Document parse ข้อมูลผิดพลาด จะวินิจฉัยและแก้ไขอย่างไร+

ตรวจสอบสาเหตุที่พบบ่อย:

1. **Delimiter ผิด** → ลองระบุอย่างชัดเจน [Delimiter=";"]/[Delimiter="#(tab)"]
2. **Encoding ไม่ตรง** → ทดสอบ [Encoding=874]/[Encoding=1252]/[Encoding=65001]
3. **Quoted text ซับซ้อน** → ปรับ [QuoteStyle=QuoteStyle.Csv, CsvStyle=CsvStyle.QuoteAfterDelimiter]
4. **Column ไม่สม่ำเสมอ** → ใช้ [ExtraValues=ExtraValues.Ignore]
5. **ไฟล์ไม่ใช่ CSV จริง** → เปิดด้วย Notepad++ ตรวจสอบ delimiter และ line ending

ถ้ายังแก้ไม่ได้ ลองใช้ Lines.FromBinary แล้ว parse แต่ละ line ด้วย Text.Split เอง

หรือถ้าเป็นไฟล์ .xlsx ที่ save as CSV ให้ใช้ Excel.Workbook อ่านจากไฟล์ต้นฉบับแทน

💡 **Tip:** ส่วนตัวผมเคยเจอปัญหา encoding บ่อยที่สุดครับ เลยแนะนำให้เช็ค encoding ก่อนเป็นอันดับแรก 😅

Resources & Related

ฟังก์ชันที่ผู้เขียนโยงไว้กับ Csv.Document จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง

ฟังก์ชันนี้Csv.DocumentAccessing data functions
Accessing data functions (5)
Excel.Workbook

Excel.Workbook อ่าน binary content ของไฟล์ Excel แล้วคืนค่าเป็น table ที่แต่ละ row แทนด้วย worksheet, named range หรือ Excel table โดยมี columns คือ Item (ชื่อ), Kind (ประเภท), Name (ชื่อเต็ม), Data (nested table ของข้อมูลจริง), และ Hidden (boolean) รองรับ useHeaders และ delayTypes เป็น parameters แต่ Microsoft แนะนำให้ใช้ Table.PromoteHeaders แทนเพื่อหลีกเลี่ยงปัญหา culture conversion นอกจากนี้ยังมี InferSheetDimensions option สำหรับแก้ปัญหา metadata ที่ผิดพลาด ใช้ร่วมกับ File.Contents หรือ Web.Contents สำหรับโหลดไฟล์

File.Contents

File.Contents ใช้อ่านข้อมูล binary ของไฟล์จากพาธที่ระบุ เพื่อนำเข้าข้อมูลจากระบบไฟล์ลงในโปรแกรม

Folder.Files

Folder.Files ใช้สำหรับอ่านรายชื่อไฟล์ทั้งหมดในโฟลเดอร์ที่กำหนด รวมถึงโฟลเดอร์ย่อยด้วย คืนค่าเป็น table ที่มีข้อมูลไฟล์เช่น ชื่อ วันที่สร้าง ขนาด และลิงก์เข้าถึงไฟล์

Json.Document

Json.Document ใช้สำหรับแปลง JSON text หรือ binary data ให้เป็น Power Query record ทำให้คุณสามารถเข้าถึง field แต่ละตัวได้อย่างง่ายดาย

Web.Contents

Web.Contents เป็นฟังก์ชันสำหรับดาวน์โหลดเนื้อหาจากเว็บไซต์หรือแหล่งข้อมูลบนอินเทอร์เน็ตผ่าน URL และคืนค่าเป็นข้อมูลแบบ binary data ที่สามารถนำไปประมวลผลต่อได้
.
รองรับการเชื่อมต่อและเรียกใช้งาน REST API อย่างครบถ้วนพร้อมระบบการยืนยันตัวตนผ่านทางตัวเลือกต่างๆ เช่น การกำหนดค่า Headers สำหรับส่งข้อมูลเพิ่มเติมในคำขอ การใช้ Query parameters สำหรับการกรองข้อมูลและส่งพารามิเตอร์ และการระบุ ApiKeyName เพื่อจัดเก็บคีย์การเข้าถึงอย่างปลอดภัย
.
เหมาะอย่างยิ่งสำหรับการเชื่อมต่อกับบริการเว็บและจุดเชื่อมต่อ API แบบไดนามิก โดยใช้ความสามารถของ RelativePath และตัวเลือก Query เพื่อสร้าง URL แบบยืดหยุ่นและทำให้กระบวนการรีเฟรชข้อมูลทำงานได้อย่างราบรื่นและมีประสิทธิภาพในระบบ Power BI Service

Table functions (3)
Table.FromRows

Table.FromRows สร้างตารางจาก List ของ List โดยแต่ละ List ย่อยแทนข้อมูลในแถวหนึ่ง คล้ายกับการ transpose ข้อมูลแบบแถว-คอลัมน์ แต่ทำให้เป็นตารางจริงในทันที

Table.PromoteHeaders

Table.PromoteHeaders เลื่อนข้อมูลในแถวแรกของตารางขึ้นมาเป็นชื่อคอลัมน์ และลบแถวนั้นออกจากส่วนข้อมูล รองรับพารามิเตอร์เสริม options เป็น record ที่มีฟิลด์ PromoteAllScalars สำหรับอนุญาตให้ค่าที่ไม่ใช่ข้อความ เช่น ตัวเลขและวันที่ ถูกแปลงเป็นชื่อคอลัมน์ได้ และ Culture สำหรับกำหนดรูปแบบการแปลงค่าตามภูมิภาค
.
ที่เจ๋งคือ PromoteAllScalars=true ช่วยให้หัวตารางที่เป็นตัวเลขหรือวันที่ก็ใช้ได้ ไม่ติดว่าต้องเป็นข้อความอย่างเดียว

Table.TransformColumnTypes

Table.TransformColumnTypes เปลี่ยน Data Type ของคอลัมน์ที่ระบุให้เป็นประเภทใหม่ (เช่น Text เป็น Number, Date เป็น Text) โดยใช้ built-in conversion methods เบื้องหลัง รองรับการแปลงหลายคอลัมน์พร้อมกัน และสามารถระบุ culture parameter เพื่อจัดการ locale-specific formatting สำหรับวันที่และตัวเลข เหมาะสำหรับขั้นตอนเตรียมข้อมูลก่อน Load เข้า Data Model เพื่อป้องกัน conversion errors และเพิ่มประสิทธิภาพ ใช้ร่วมกับ Table.TransformColumns, Number.From, Text.From และ Date.From เมื่อต้องการ custom transformation logic

enumerations (1)
CsvStyle.Type

Enumeration type ที่ระบุว่าเครื่องหมายคำพูด (quote) ในไฟล์ CSV จะมีความสำคัญเมื่อไหร่ ใช้กับ Csv.Document เพื่อควบคุมการแยกวิเคราะห์ข้อมูล

Lines functions (1)
Lines.FromBinary

Lines.FromBinary ใช้สำหรับการประมวลผล

Text functions (1)
Text.FromBinary

Text.FromBinary ใช้สำหรับแปลงค่า Binary เป็นข้อความ โดยใช้การเข้ารหัส UTF-8 เป็นค่าเริ่มต้น รองรับการเข้ารหัสอื่นๆ เช่น UTF-16 และ ASCII

Comments

อีเมลของคุณจะไม่ถูกเผยแพร่