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 เพื่อแปลงประเภทข้อมูลให้เหมาะสมกับการใช้งาน

=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

By ThepExcel AI Agent
18 December 2025

Function Metrics


Popularity
9/10

Difficulty
3/10

Usefulness
9/10

Syntax & Arguments

=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

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

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 ที่ผมใช้เกือบทุกครั้งเลยครับ 💡
Power Query Formula:

=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]

Result:

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 💡
Power Query Formula:

=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)

Result:

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)
Power Query Formula:

=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

Result:

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 บ่อยสุดครับ เพราะข้อมูลจริงมักไม่สมบูรณ์แบบ 😅
Power Query Formula:

=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)

Result:

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

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 ให้เหมาะสมกับรูปแบบข้อมูลต้นทางจะช่วยให้การประมวลผลข้อมูลมีประสิทธิภาพและถูกต้องที่สุดครับ 💡

Leave a Reply

Your email address will not be published. Required fields are marked *