---
title: List.Generate – สร้าง List แบบวนลูปตามเงื่อนไข (Generator Pattern)
url: https://www.thepexcel.com/functions/power-query/list-functions/list-generate/
type: function-explainer
program: Power Query
syntax: "List.Generate(initial as function, condition as function, next as function, optional selector as nullable function) as list"
date: 2025-12-19
scores:
  popularity: 6
  difficulty: 9
  usefulness: 8
---

# List.Generate – สร้าง List แบบวนลูปตามเงื่อนไข (Generator Pattern)

> สร้าง list แบบ dynamic ด้วย generator pattern (เหมือน while loop)

## คำอธิบาย

List.Generate เป็น generator function ที่สร้าง list โดยเริ่มจากค่าเริ่มต้น (initial) วนลูปตรวจสอบเงื่อนไข (condition) สร้างค่าถัดไป (next) และ transform ผลลัพธ์ด้วย selector (optional) ทำงานคล้าย while loop ในการเขียนโปรแกรม เหมาะสำหรับสร้างลำดับวันที่, pagination API, การคำนวณทบต้น และ pattern ซับซ้อนที่ List.Numbers ทำไม่ได้

## Syntax

```excel
List.Generate(initial as function, condition as function, next as function, optional selector as nullable function) as list
```

**Variant**

```excel
List.Generate(() => initialValue, each conditionExpression, each nextExpression)
```

รูปแบบพื้นฐานโดยไม่ใช้ selector (ผลลัพธ์ = ค่าที่ generate)

**Variant**

```excel
List.Generate(() => initialValue, each conditionExpression, each nextExpression, each selectorExpression)
```

รูปแบบเต็มพร้อม selector เพื่อ transform ค่าผลลัพธ์

## Arguments

| Name | Required | Type | Default | Description |
| --- | --- | --- | --- | --- |
| initial | Yes | function |  | Function ที่กำหนดค่าเริ่มต้น (candidate value แรก) เขียนในรูปแบบ () => value หรือ () => [record] สำหรับเก็บหลายค่า |
| condition | Yes | function |  | Function ที่ตรวจสอบเงื่อนไข รับค่า candidate มาทดสอบ ถ้าผลลัพธ์เป็น true จะเพิ่มค่านั้นใน list และทำรอบต่อ ถ้า false จะหยุดทำงาน เขียนในรูปแบบ each expression (ใช้ _ อ้างอิงค่าปัจจุบัน) |
| next | Yes | function |  | Function สำหรับสร้างค่า candidate ถัดไป รับค่าปัจจุบันที่ผ่านเงื่อนไขแล้ว แล้ว transform เป็นค่าถัดไป เขียนในรูปแบบ each expression (เช่น each _ + 1, each Date.AddDays(_, 1)) |
| selector | No | nullable function | null | Function สำหรับ transform ค่าก่อนเพิ่มใน list ผลลัพธ์ ถ้าไม่ระบุจะใช้ค่าที่ generate ตรงๆ มีประโยชน์เมื่อใช้ record เก็บหลายค่า แต่ต้องการแสดงเฉพาะบางฟิลด์ เขียนในรูปแบบ each expression (เช่น each [fieldName]) |

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

### สร้างลำดับวันที่แบบกำหนดเอง

สร้าง list ของวันที่ตั้งแต่วันเริ่มต้นถึงวันสิ้นสุด เพิ่มทีละ 1 วัน, ทุกสัปดาห์, ทุกเดือน หรือข้าม weekend ตาม logic ที่กำหนด

### Pagination API Loop

เรียก REST API ที่มี pagination โดยวนลูปเรียกทีละหน้า (page 1, 2, 3...) จนกว่า response จะไม่มี nextPageToken หรือ hasMore = false

### คำนวณดอกเบี้ยทบต้น

คำนวณเงินต้นบวกดอกเบี้ยทบต้นแต่ละงวด โดยเริ่มจากเงินต้น คำนวณดอกเบี้ยรอบถัดไปจากยอดรวมก่อนหน้า วนลูปจนครบจำนวนงวดที่กำหนด

### สร้าง Fibonacci Sequence

สร้างลำดับ Fibonacci โดยใช้ record เก็บสองค่าก่อนหน้า (a, b) แล้วคำนวณค่าถัดไปเป็น a + b วนลูปจนถึงขนาดที่ต้องการ

### Recursive Data Collection

ดึงข้อมูลแบบ recursive เช่น folder structure ที่มี subfolder หลายชั้น หรือ organization hierarchy ที่ต้อง drill down จนถึง leaf node

## ตัวอย่าง

### 1. ตัวอย่างที่ 1: นับถอยหลังจาก 10 ถึง 1

```excel
let
    Countdown = List.Generate(
        () => 10,              // เริ่มที่ 10
        each _ > 0,            // ทำต่อเมื่อ > 0
        each _ - 1             // ลดค่าลงทีละ 1
    )
in
    Countdown
```

**ผลลัพธ์:** `{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}`

เริ่มต้นด้วยค่า 10 จาก initial function, ตรวจสอบเงื่อนไข each _ > 0 (ค่าปัจจุบันมากกว่า 0) ถ้าเป็น true ก็เพิ่มค่านั้นใน list แล้วใช้ next function (each _ - 1) ลดค่าลงทีละ 1 วนลูปจนกว่าค่าจะเป็น 0 (เงื่อนไขเป็น false) จึงหยุดและได้ list ตัวเลข 10-1

### 2. ตัวอย่างที่ 2: สร้างลำดับวันที่ 1-7 มกราคม 2025

```excel
let
    StartDate = #date(2025, 1, 1),
    EndDate = #date(2025, 1, 7),
    DateList = List.Generate(
        () => StartDate,                        // เริ่มที่ 1 ม.ค.
        each _ <= EndDate,                      // ทำต่อถ้า <= 7 ม.ค.
        each Date.AddDays(_, 1)                 // เพิ่มวันทีละ 1
    )
in
    DateList
```

**ผลลัพธ์:** `{2025-01-01, 2025-01-02, 2025-01-03, 2025-01-04, 2025-01-05, 2025-01-06, 2025-01-07}`

สร้าง list ของวันที่โดยเริ่มจาก 1 มกราคม 2025 ใช้ Date.AddDays เพิ่มวันทีละ 1 ในแต่ละรอบ วนลูปจนกว่าวันที่จะเกิน 7 มกราคม 2025 วิธีนี้ใช้ได้กับช่วงวันที่ใดๆ เพียงเปลี่ยน StartDate และ EndDate

### 3. ตัวอย่างที่ 3: สร้างตัวเลขคี่ 1, 3, 5, 7, 9

```excel
let
    OddNumbers = List.Generate(
        () => 1,               // เริ่มที่ 1
        each _ < 10,           // ทำต่อถ้า < 10
        each _ + 2             // เพิ่มทีละ 2
    )
in
    OddNumbers
```

**ผลลัพธ์:** `{1, 3, 5, 7, 9}`

สร้างลำดับตัวเลขคี่โดยเริ่มที่ 1 แล้วเพิ่มทีละ 2 (1+2=3, 3+2=5, ...) วนลูปจนกว่าค่าจะถึง 9 (รอบถัดไปจะเป็น 11 ซึ่ง >= 10 จึงหยุด) ถ้าต้องการเลขคู่ให้เริ่มที่ 0 หรือ 2 แทน

### 4. ตัวอย่างที่ 4: ใช้ Record เก็บหลายค่า พร้อม Selector

```excel
let
    Result = List.Generate(
        () => [Counter = 1, DoubleValue = 2],     // เริ่มด้วย record
        each [Counter] <= 5,                      // ทำต่อถ้า Counter <= 5
        each [                                    // สร้าง record ถัดไป
            Counter = [Counter] + 1,
            DoubleValue = [Counter] * 2
        ],
        each [DoubleValue]                        // เลือกแสดงเฉพาะ DoubleValue
    )
in
    Result
```

**ผลลัพธ์:** `{2, 4, 6, 8, 10}`

ใช้ record structure เพื่อเก็บสองค่าพร้อมกัน: Counter สำหรับนับรอบ และ DoubleValue สำหรับค่าที่ต้องการจริง ในแต่ละรอบจะเพิ่ม Counter ขึ้น 1 และคำนวณ DoubleValue = Counter * 2 แต่เนื่องจากมี selector (each [DoubleValue]) จึงแสดงเฉพาะค่า DoubleValue ในผลลัพธ์ วิธีนี้เหมาะกับ logic ที่ซับซ้อนต้องเก็บ state หลายตัว

### 5. ตัวอย่างที่ 5: Fibonacci Sequence (10 ตัวแรก)

```excel
let
    Fibonacci = List.Generate(
        () => [a = 0, b = 1, result = 0],         // เริ่มด้วย 0, 1
        each [result] < 10,                       // สร้าง 10 ตัวแรก (นับด้วย result)
        each [                                    // คำนวณค่าถัดไป
            a = [b],
            b = [a] + [b],
            result = [result] + 1
        ],
        each [a]                                  // เลือกแสดงค่า a
    )
in
    Fibonacci
```

**ผลลัพธ์:** `{0, 1, 1, 2, 3, 5, 8, 13, 21, 34}`

สร้าง Fibonacci sequence โดยใช้ record เก็บสามค่า: a (ค่าปัจจุบัน), b (ค่าถัดไป), result (ตัวนับ) ในแต่ละรอบจะเลื่อนค่า a = b และคำนวณ b ใหม่จาก a + b ตัวนับ result ใช้ควบคุมจำนวนรอบ selector (each [a]) เลือกแสดงเฉพาะค่า a ซึ่งเป็นลำดับ Fibonacci ที่ต้องการ

### 6. ตัวอย่างที่ 6: API Pagination Pattern (จำลอง)

```excel
let
    AllPages = List.Generate(
        () => [PageNumber = 1, HasMore = true],   // เริ่มหน้า 1
        each [HasMore] = true,                    // ทำต่อถ้ายังมีหน้าถัดไป
        each [                                    // จำลองการเรียก API
            PageNumber = [PageNumber] + 1,
            HasMore = [PageNumber] < 5            // มี 5 หน้าทั้งหมด
        ],
        each "Page " & Text.From([PageNumber])   // สร้าง label
    )
in
    AllPages
```

**ผลลัพธ์:** `{"Page 1", "Page 2", "Page 3", "Page 4", "Page 5"}`

จำลอง pattern การเรียก API แบบ pagination โดยใช้ record เก็บ PageNumber (หมายเลขหน้า) และ HasMore (มีหน้าถัดไปหรือไม่) ในการใช้งานจริงจะเรียก Web.Contents ใน next function และตรวจสอบ response ว่ามี nextPageToken หรือ hasMore field หรือไม่ ถ้ามีก็ทำต่อ ถ้าไม่มีก็หยุด ตัวอย่างนี้จำลองโดยให้หยุดที่หน้า 5

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

List.Generate เป็นหนึ่งในฟังก์ชันที่ทรงพลังที่สุดของ Power Query แต่ต้องระวังเรื่อง infinite loop หากเงื่อนไข condition ไม่ถูกต้อง ควรทดสอบกับข้อมูลขนาดเล็กก่อนเพื่อให้มั่นใจว่า logic ทำงานถูกต้องและหยุดได้ตามที่ตั้งใจ นอกจากนี้หาก logic ซับซ้อนมากควรเขียน comment ไว้ในโค้ดเพื่อให้เข้าใจง่ายในอนาคต สำหรับการใช้งานกับ API pagination แนะนำให้ศึกษา error handling ด้วย try...otherwise เพื่อจัดการกรณีที่ API response ผิดปกติ

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

**Q: List.Generate ต่างจาก List.Numbers อย่างไร?**

List.Numbers สร้างลำดับตัวเลขตาม pattern คงที่ (start, count, increment) เหมาะกับลำดับเลขเรียงง่ายๆ เช่น {1, 2, 3} หรือ {0, 10, 20, 30} แต่ List.Generate ให้คุณควบคุม logic การสร้างค่าได้เองทั้งหมดผ่าน function parameters ทำให้สร้าง pattern ซับซ้อนได้ เช่น Fibonacci, compound growth, หรือ conditional sequence ที่ List.Numbers ทำไม่ได้

**Q: ทำไม List.Generate ถึงต้องใช้ () => value แทนที่จะเป็น value ตรงๆ?**

เพราะ List.Generate ต้องการ function type สำหรับทุก parameter ไม่ใช่แค่ค่าตายตัว () => value เป็น syntax ของ anonymous function ใน M language ที่ไม่รับ parameter และ return ค่าคงที่ วิธีนี้ทำให้ Power Query สามารถเรียก function เมื่อต้องการได้ แทนที่จะ evaluate ค่าตั้งแต่ตอนเริ่ม ซึ่งสอดคล้องกับ lazy evaluation pattern ของ Power Query

**Q: each _ หมายถึงอะไร และใช้เมื่อไหร่?**

each เป็น shorthand syntax ของ M language สำหรับเขียน anonymous function ที่รับ parameter เดียว โดย _ คือ placeholder แทนค่า parameter นั้น เช่น each _ > 0 เทียบเท่ากับ (x) => x > 0 ใช้ each กับ condition, next, และ selector parameters ของ List.Generate เพราะ function เหล่านี้รับค่า candidate หรือ item เดียวเป็น input ส่วน initial ใช้ () => value เพราะไม่รับ parameter

**Q: Selector parameter มีประโยชน์อย่างไร?**

Selector ช่วยให้คุณ transform ค่าก่อนเพิ่มเข้า list ผลลัพธ์ มีประโยชน์มากเมื่อใช้ record structure เก็บหลายค่า (เช่น [x = 1, y = 2]) แต่ต้องการแสดงเฉพาะบางฟิลด์ (เช่น each [y] จะได้เฉพาะค่า y) หรือต้องการคำนวณค่าใหม่จากหลายฟิลด์ (เช่น each [Price] * [Quantity]) ถ้าไม่ระบุ selector จะใช้ค่าที่ generate ตรงๆ

**Q: List.Generate มีข้อจำกัดเรื่องจำนวนรอบไหม?**

Power Query ไม่มี hard limit สำหรับจำนวนรอบของ List.Generate แต่ถ้าวนลูปเกินไปจะทำให้ performance ช้าและอาจเกิด memory issue ดังนั้นควรมีเงื่อนไข (condition function) ที่รับประกันได้ว่าจะหยุดในที่สุด หลีกเลี่ยง infinite loop โดยตรวจสอบให้มั่นใจว่าค่า candidate จะทำให้เงื่อนไขเป็น false ได้ในที่สุด เช่นใช้ counter หรือเช็คค่า null

**Q: สามารถใช้ List.Generate กับ API pagination จริงๆ ได้อย่างไร?**

ใช้ record เก็บ URL หรือ pageToken พร้อมกับข้อมูลที่ดึงมา เช่น () => [url = "api.com/data?page=1", data = {}] ใน next function เรียก Web.Contents กับ URL ปัจจุบัน parse response เพื่อหา nextPageUrl และ append data ที่ได้เข้า list ใน condition ตรวจสอบว่า nextPageUrl มีค่าหรือไม่ (each [nextPageUrl]  null) ใน selector ดึงเฉพาะ data ออกมา (each [data]) แล้วใช้ List.Combine รวมทุกหน้าเป็น table เดียว

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

- [List.Accumulate – วนลูปสะสมค่าด้วย Accumulator Pattern](https://www.thepexcel.com/functions/power-query/list-functions/list-accumulate/)
- [List.Numbers – สร้างลำดับตัวเลข](https://www.thepexcel.com/functions/power-query/list-functions/list-numbers/)
- [List.Dates – สร้างรายการวันที่](https://www.thepexcel.com/functions/power-query/list-functions/list-dates/)
- [List.Repeat – ทำซ้ำ List หลายครั้ง](https://www.thepexcel.com/functions/power-query/list-functions/list-repeat/)
- [List.Transform – แปลงค่าในลิสต์แต่ละตัว](https://www.thepexcel.com/functions/power-query/list-functions/list-transform/)

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

- [Microsoft Learn: List.Generate](https://learn.microsoft.com/en-us/powerquery-m/list-generate) _(documentation)_
- [PowerQuery.how: List.Generate Guide](https://powerquery.how/list-generate/) _(guide)_
- [Microsoft Learn: Understanding Power Query M formula language](https://learn.microsoft.com/en-us/powerquery-m/understanding-power-query-m) _(documentation)_

---

_Source: [https://www.thepexcel.com/functions/power-query/list-functions/list-generate/](https://www.thepexcel.com/functions/power-query/list-functions/list-generate/)_
