---
title: Csv.Document – แปลงข้อมูล CSV เป็น Table ใน Power Query
url: https://www.thepexcel.com/functions/power-query/accessing-data-functions/csv-document/
type: function-explainer
program: Power Query
syntax: "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"
date: 2025-12-18
scores:
  popularity: 9
  difficulty: 3
  usefulness: 9
---

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

> แปลงข้อมูล CSV เป็น table พร้อมควบคุม delimiter, encoding และ column structure

## คำอธิบาย

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

## Syntax

```excel
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
```

**Variant**

```excel
Csv.Document(source)
```

Parse CSV ด้วยค่า default (comma delimiter, auto-detect columns, UTF-8 encoding)

**Variant**

```excel
Csv.Document(source, null, delimiter)
```

กำหนด custom delimiter เช่น semicolon ";", tab "#(tab)", pipe "|" แต่ใช้ auto-detect columns

**Variant**

```excel
Csv.Document(source, columnNames, delimiter)
```

กำหนดทั้งชื่อ column (เป็น list of text) และ delimiter พร้อมกัน

**Variant**

```excel
Csv.Document(source, [Delimiter=";", Encoding=874, Columns=3, QuoteStyle=QuoteStyle.Csv])
```

ใช้ record format เพื่อระบุ options ขั้นสูงหลายตัวพร้อมกันอย่างชัดเจน

## Arguments

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

## เคสการใช้งาน

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

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

_เหมาะกับ:_ data-import

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

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

_เหมาะกับ:_ web-data

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

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

_เหมาะกับ:_ custom-delimiter

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

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

_เหมาะกับ:_ encoding-handling

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

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

_เหมาะกับ:_ no-header

## ตัวอย่าง

### 1. ตัวอย่างที่ 1: แปลง CSV text พื้นฐาน (Foundation)

```excel
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)`

ตัวอย่างนี้แสดงขั้นตอนพื้นฐานของการ 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 ที่ผมใช้เกือบทุกครั้งเลยครับ 💡

### 2. ตัวอย่างที่ 2: ใช้ custom delimiter (Practical)

```excel
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`

ตัวอย่างนี้แสดง 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 💡

### 3. ตัวอย่างที่ 3: จัดการ encoding และกำหนดชื่อ column (Advanced)

```excel
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`

ตัวอย่างนี้แสดง 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)

### 4. ตัวอย่างที่ 4: จัดการ quoted text และ column ไม่สม่ำเสมอ (Complex)

```excel
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`

ตัวอย่างนี้แสดงการใช้ 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 บ่อยสุดครับ เพราะข้อมูลจริงมักไม่สมบูรณ์แบบ 😅

## หมายเหตุเพิ่มเติม

💡 **สิ่งที่ต้องรู้เกี่ยวกับ Csv.Document**
.
**1. ทุก column จะเป็น text type**
Csv.Document คืนค่าออกมาเป็นตารางข้อมูล (table) ที่ทุกคอลัมน์มีประเภทข้อมูล (data type) เป็นข้อความ (text) ทั้งหมด
ดังนั้นหลังจากแยกวิเคราะห์ (parse) เสร็จแล้วควรใช้ Table.TransformColumnTypes เพื่อแปลงเป็นประเภทข้อมูลที่เหมาะสมกับเนื้อหาจริง
.
เช่น Int64.Type สำหรับตัวเลขจำนวนเต็ม (integer), type number สำหรับตัวเลขทศนิยม (decimal), type date สำหรับข้อมูลวันที่, type logical สำหรับค่าความจริง (true/false)
เพื่อให้สามารถกรองข้อมูล (filter), เรียงลำดับ (sort) และคำนวณผลลัพธ์ได้อย่างถูกต้องตามที่ต้องการ
.
ส่วนตัวผมเคยเจอ bug จากการลืม transform type หลายครั้งเลยครับ 😅 เลยเป็นนิสัยที่จะทำทุกครั้ง
.
**2. Encoding สำคัญมาก (โดยเฉพาะภาษาไทย)**
สำหรับไฟล์ที่มีเนื้อหาเป็นภาษาพิเศษหรือภาษาต่างประเทศควรตรวจสอบรหัสภาษา (encoding) ของไฟล์ต้นทางให้ถูกต้อง
และระบุใน Encoding argument ให้ตรงกันเพื่อป้องกันปัญหาการแสดงผลอักขระผิดพลาด
.
รหัสภาษาที่ใช้บ่อย:
- 65001 สำหรับ UTF-8 ซึ่งเป็นค่าเริ่มต้น (default)
- 874 สำหรับภาษาไทยใน Windows เก่า (Thai Windows)
- 1252 สำหรับภาษายุโรปตะวันตก (Western European)
- 932 สำหรับภาษาญี่ปุ่น Shift-JIS (Japanese Shift-JIS)
- 936 สำหรับภาษาจีนแบบตัวย่อ (Simplified Chinese GBK)
.
**3. Record format อ่านง่ายกว่า**
การใช้รูปแบบ record format อย่างเช่น [Delimiter=";", Encoding=874, ...] จะทำให้โค้ดอ่านเข้าใจได้ง่ายกว่าการส่ง argument แยกกันเป็นหลายตัว
และยังช่วยให้สามารถกำหนดตัวเลือกขั้นสูง (advanced options) ได้ครบทุกตัวพร้อมกัน
เช่น QuoteStyle, CsvStyle, ExtraValues 😎
.
**4. Quoted text ซับซ้อน**
สำหรับข้อมูลที่มีข้อความซับซ้อนที่ครอบด้วย quote (มีตัวแบ่งข้อมูล delimiter หรือการขึ้นบรรทัดใหม่ line break อยู่ภายในข้อความ)
ควรใช้ QuoteStyle=QuoteStyle.Csv และ CsvStyle=CsvStyle.QuoteAfterDelimiter เพื่อให้แยกวิเคราะห์ตามมาตรฐาน CSV อย่างถูกต้องและแม่นยำ
.
**5. Delimiter ที่ใช้บ่อย**
ตัวแบ่งข้อมูล (delimiter) ที่ใช้บ่อยนอกจากเครื่องหมาย comma:
- Semicolon ";" สำหรับไฟล์จากประเทศในยุโรป
- Tab "#(tab)" สำหรับไฟล์รูปแบบ TSV (Tab-Separated Values)
- Pipe "|", colon ":" หรืออักขระใดก็ได้ที่เป็นตัวอักษรเดี่ยว (single character)
.
**6. จัดการ column ไม่สม่ำเสมอ**
ถ้าไฟล์มีจำนวนคอลัมน์ที่ไม่สม่ำเสมอในแต่ละแถว แนะนำให้ใช้ ExtraValues=ExtraValues.Ignore
เพื่อให้ได้ตารางข้อมูลที่มีโครงสร้างสม่ำเสมอ (ละเว้นค่าที่เกินออกไปและเติม null ให้กับค่าที่ขาดหายไป)
ซึ่งจะเหมาะสมกับการแปลงข้อมูลต่อไปใน Power Query และช่วยป้องกันข้อผิดพลาดในขั้นตอนถัดไป
.
ส่วนตัวผมใช้ ExtraValues.Ignore บ่อยมากครับ เพราะข้อมูลจริงมักไม่สมบูรณ์แบบ 💡

## คำถามที่พบบ่อย

**Q: 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 เพื่อให้การประมวลผลมีประสิทธิภาพสูงสุด

**Q: วิธีอ่านไฟล์ 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 เพื่อแปลงประเภทข้อมูลให้ถูกต้องตามปกติ

**Q: ทำไม 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)

**Q: วิธีอ่าน 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 แทน

**Q: จะจัดการ 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 สำหรับงานส่วนใหญ่ครับ เพราะข้อมูลจริงมักมีความไม่สมบูรณ์แบบอยู่แล้ว

**Q: ต้องใช้ 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 ทุกครั้งเลย 😅

**Q: จะจัดการ 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

**Q: ถ้า 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 ก่อนเป็นอันดับแรก 😅

## ฟังก์ชันที่เกี่ยวข้อง

- [Table.PromoteHeaders – เลื่อนแถวแรกเป็นหัวตาราง](https://www.thepexcel.com/functions/power-query/table-functions/table-promoteheaders/)
- [Table.TransformColumnTypes – เปลี่ยนชนิดข้อมูลของคอลัมน์](https://www.thepexcel.com/functions/power-query/table-functions/table-transformcolumntypes/)
- [File.Contents – อ่านข้อมูลจากไฟล์](https://www.thepexcel.com/functions/power-query/accessing-data-functions/file-contents/)
- [Web.Contents – ดึงข้อมูลจากเว็บและ REST API](https://www.thepexcel.com/functions/power-query/accessing-data-functions/web-contents/)
- [Text.Combine – รวมข้อความหลายรายการเป็นข้อความเดียว](https://www.thepexcel.com/functions/power-query/text-functions/text-combine/)
- [Excel.Workbook – อ่านและแยกเนื้อหาไฟล์ Excel ทั้งหมด](https://www.thepexcel.com/functions/power-query/accessing-data-functions/excel-workbook/)
- [Json.Document – แปลง JSON Text เป็น Power Query Record](https://www.thepexcel.com/functions/power-query/accessing-data-functions/json-document/)
- [Table.FromRows – สร้างตารางจากรายการแถว](https://www.thepexcel.com/functions/power-query/table-functions/table-fromrows/)
- [Text.Split – แยกข้อความตามตัวคั่นที่กำหนด](https://www.thepexcel.com/functions/power-query/text-functions/text-split/)
- [Text.FromBinary – แปลง Binary เป็น Text](https://www.thepexcel.com/functions/power-query/text-functions/text-frombinary/)
- [Lines.FromBinary](https://www.thepexcel.com/functions/power-query/lines-functions/lines-frombinary/)

## แหล่งข้อมูลเพิ่มเติม

- [Microsoft Learn: Csv.Document Function Reference](https://learn.microsoft.com/en-us/powerquery-m/csv-document) _(documentation)_
- [Microsoft Learn: ExtraValues.Type Enumeration](https://learn.microsoft.com/en-us/powerquery-m/extravalues-type) _(documentation)_
- [Microsoft Learn: Text Encoding Code Page Identifiers](https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers) _(documentation)_
- [Microsoft Learn: Table.PromoteHeaders Function](https://learn.microsoft.com/en-us/powerquery-m/table-promoteheaders) _(documentation)_
- [Microsoft Learn: Table.TransformColumnTypes Function](https://learn.microsoft.com/en-us/powerquery-m/table-transformcolumntypes) _(documentation)_

---

_Source: [https://www.thepexcel.com/functions/power-query/accessing-data-functions/csv-document/](https://www.thepexcel.com/functions/power-query/accessing-data-functions/csv-document/)_
