List.Generate เป็น generator function ที่สร้าง list โดยเริ่มจากค่าเริ่มต้น (initial) วนลูปตรวจสอบเงื่อนไข (condition) สร้างค่าถัดไป (next) และ transform ผลลัพธ์ด้วย selector (optional) ทำงานคล้าย while loop ในการเขียนโปรแกรม เหมาะสำหรับสร้างลำดับวันที่, pagination API, การคำนวณทบต้น และ pattern ซับซ้อนที่ List.Numbers ทำไม่ได้
| อาร์กิวเมนต์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
| initial | function | Function ที่กำหนดค่าเริ่มต้น (candidate value แรก) เขียนในรูปแบบ () => value หรือ () => [record] สำหรับเก็บหลายค่า | |
| condition | function | Function ที่ตรวจสอบเงื่อนไข รับค่า candidate มาทดสอบ ถ้าผลลัพธ์เป็น true จะเพิ่มค่านั้นใน list และทำรอบต่อ ถ้า false จะหยุดทำงาน เขียนในรูปแบบ each expression (ใช้ _ อ้างอิงค่าปัจจุบัน) | |
| next | function | Function สำหรับสร้างค่า candidate ถัดไป รับค่าปัจจุบันที่ผ่านเงื่อนไขแล้ว แล้ว transform เป็นค่าถัดไป เขียนในรูปแบบ each expression (เช่น each _ + 1, each Date.AddDays(_, 1)) | |
| [selector]ไม่บังคับ | nullable function | null | Function สำหรับ transform ค่าก่อนเพิ่มใน list ผลลัพธ์ ถ้าไม่ระบุจะใช้ค่าที่ generate ตรงๆ มีประโยชน์เมื่อใช้ record เก็บหลายค่า แต่ต้องการแสดงเฉพาะบางฟิลด์ เขียนในรูปแบบ each expression (เช่น each [fieldName]) |
[ ] = อาร์กิวเมนต์ที่ไม่บังคับ
ฟังก์ชัน List.Generate ใน Power Query เป็นเครื่องมือสำหรับสร้าง list แบบ dynamic โดยใช้ generator pattern ซึ่งคล้ายกับการวนลูป while loop ในภาษาโปรแกรมมิ่ง ฟังก์ชันนี้ทำงานโดยเริ่มจากค่าเริ่มต้น (initial value) แล้ววนลูปตรวจสอบเงื่อนไข (condition) และสร้างค่าถัดไป (next value) จนกว่าเงื่อนไขจะเป็นเท็จ
ฟังก์ชันนี้มีประโยชน์อย่างมากในการสร้างข้อมูลที่มี pattern ซับซ้อน เช่น การสร้างลำดับวันที่ระหว่างช่วงเวลา การเรียก API แบบ pagination ที่ต้องวนลูปหลายหน้า หรือการคำนวณแบบทบต้นที่ค่าแต่ละรอบขึ้นอยู่กับค่าก่อนหน้า โดย List.Generate สามารถทำงานกับ record structure เพื่อเก็บสถานะหลายตัวแปรพร้อมกันได้
จุดเด่นของ List.Generate คือความยืดหยุ่นสูง เพราะคุณสามารถกำหนด logic การทำงานได้เองทั้งหมดผ่าน 4 function parameters ซึ่งแตกต่างจาก List.Numbers หรือ List.Dates ที่มี pattern การสร้างค่าแบบตายตัว นอกจากนี้ยังมี optional selector parameter ที่ช่วยให้คุณ transform ค่าผลลัพธ์ก่อนส่งออกมาได้อีกด้วย
สร้าง list ของวันที่ตั้งแต่วันเริ่มต้นถึงวันสิ้นสุด เพิ่มทีละ 1 วัน, ทุกสัปดาห์, ทุกเดือน หรือข้าม weekend ตาม logic ที่กำหนด
เรียก REST API ที่มี pagination โดยวนลูปเรียกทีละหน้า (page 1, 2, 3…) จนกว่า response จะไม่มี nextPageToken หรือ hasMore = false
คำนวณเงินต้นบวกดอกเบี้ยทบต้นแต่ละงวด โดยเริ่มจากเงินต้น คำนวณดอกเบี้ยรอบถัดไปจากยอดรวมก่อนหน้า วนลูปจนครบจำนวนงวดที่กำหนด
สร้างลำดับ Fibonacci โดยใช้ record เก็บสองค่าก่อนหน้า (a, b) แล้วคำนวณค่าถัดไปเป็น a + b วนลูปจนถึงขนาดที่ต้องการ
ดึงข้อมูลแบบ recursive เช่น folder structure ที่มี subfolder หลายชั้น หรือ organization hierarchy ที่ต้อง drill down จนถึง leaf node
เริ่มต้นด้วยค่า 10 จาก initial function, ตรวจสอบเงื่อนไข each _ > 0 (ค่าปัจจุบันมากกว่า 0) ถ้าเป็น true ก็เพิ่มค่านั้นใน list แล้วใช้ next function (each _ – 1) ลดค่าลงทีละ 1 วนลูปจนกว่าค่าจะเป็น 0 (เงื่อนไขเป็น false) จึงหยุดและได้ list ตัวเลข 10-1
สร้าง list ของวันที่โดยเริ่มจาก 1 มกราคม 2025 ใช้ Date.AddDays เพิ่มวันทีละ 1 ในแต่ละรอบ วนลูปจนกว่าวันที่จะเกิน 7 มกราคม 2025 วิธีนี้ใช้ได้กับช่วงวันที่ใดๆ เพียงเปลี่ยน StartDate และ EndDate
สร้างลำดับตัวเลขคี่โดยเริ่มที่ 1 แล้วเพิ่มทีละ 2 (1+2=3, 3+2=5, …) วนลูปจนกว่าค่าจะถึง 9 (รอบถัดไปจะเป็น 11 ซึ่ง >= 10 จึงหยุด) ถ้าต้องการเลขคู่ให้เริ่มที่ 0 หรือ 2 แทน
ใช้ record structure เพื่อเก็บสองค่าพร้อมกัน: Counter สำหรับนับรอบ และ DoubleValue สำหรับค่าที่ต้องการจริง ในแต่ละรอบจะเพิ่ม Counter ขึ้น 1 และคำนวณ DoubleValue = Counter * 2 แต่เนื่องจากมี selector (each [DoubleValue]) จึงแสดงเฉพาะค่า DoubleValue ในผลลัพธ์ วิธีนี้เหมาะกับ logic ที่ซับซ้อนต้องเก็บ state หลายตัว
สร้าง Fibonacci sequence โดยใช้ record เก็บสามค่า: a (ค่าปัจจุบัน), b (ค่าถัดไป), result (ตัวนับ) ในแต่ละรอบจะเลื่อนค่า a = b และคำนวณ b ใหม่จาก a + b ตัวนับ result ใช้ควบคุมจำนวนรอบ selector (each [a]) เลือกแสดงเฉพาะค่า a ซึ่งเป็นลำดับ Fibonacci ที่ต้องการ
จำลอง pattern การเรียก API แบบ pagination โดยใช้ record เก็บ PageNumber (หมายเลขหน้า) และ HasMore (มีหน้าถัดไปหรือไม่) ในการใช้งานจริงจะเรียก Web.Contents ใน next function และตรวจสอบ response ว่ามี nextPageToken หรือ hasMore field หรือไม่ ถ้ามีก็ทำต่อ ถ้าไม่มีก็หยุด ตัวอย่างนี้จำลองโดยให้หยุดที่หน้า 5
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 ทำไม่ได้
เพราะ List.Generate ต้องการ function type สำหรับทุก parameter ไม่ใช่แค่ค่าตายตัว () => value เป็น syntax ของ anonymous function ใน M language ที่ไม่รับ parameter และ return ค่าคงที่ วิธีนี้ทำให้ Power Query สามารถเรียก function เมื่อต้องการได้ แทนที่จะ evaluate ค่าตั้งแต่ตอนเริ่ม ซึ่งสอดคล้องกับ lazy evaluation pattern ของ Power Query
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
Selector ช่วยให้คุณ transform ค่าก่อนเพิ่มเข้า list ผลลัพธ์ มีประโยชน์มากเมื่อใช้ record structure เก็บหลายค่า (เช่น [x = 1, y = 2]) แต่ต้องการแสดงเฉพาะบางฟิลด์ (เช่น each [y] จะได้เฉพาะค่า y) หรือต้องการคำนวณค่าใหม่จากหลายฟิลด์ (เช่น each [Price] * [Quantity]) ถ้าไม่ระบุ selector จะใช้ค่าที่ generate ตรงๆ
Power Query ไม่มี hard limit สำหรับจำนวนรอบของ List.Generate แต่ถ้าวนลูปเกินไปจะทำให้ performance ช้าและอาจเกิด memory issue ดังนั้นควรมีเงื่อนไข (condition function) ที่รับประกันได้ว่าจะหยุดในที่สุด หลีกเลี่ยง infinite loop โดยตรวจสอบให้มั่นใจว่าค่า candidate จะทำให้เงื่อนไขเป็น false ได้ในที่สุด เช่นใช้ counter หรือเช็คค่า null
ใช้ 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.Generate จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง
List.Accumulate เป็นฟังก์ชันสำหรับการวนลูปผ่านแต่ละ element ใน list พร้อมทั้งเก็บสถานะสะสมไว้ตลอดการทำงาน
.
โดยจะเริ่มต้นจากค่าเริ่มต้นที่กำหนด (seed value) และในแต่ละรอบของการวนลูป ฟังก์ชันจะส่งค่าสถานะปัจจุบัน (current state) พร้อมกับ element ปัจจุบันเข้าไปใน accumulator function ที่คุณกำหนดขึ้นมา เพื่อคำนวณและสร้างสถานะใหม่สำหรับรอบถัดไป
.
เมื่อวนลูปครบทุก element แล้ว ฟังก์ชันจะคืนค่าสถานะสุดท้ายกลับมา เหมาะสำหรับการคำนวณยอดสะสม (running totals) การรวมแบบกำหนดเอง (custom aggregations) และการสร้างรูปแบบ For-Next loop pattern ใน M language ครับ
สร้าง List ของวันที่เรียงกัน
List.Numbers สร้าง List ของตัวเลขเรียงกันตามค่าเริ่มต้น จำนวน และการเพิ่มค่า
List.Random สร้างรายการของตัวเลขสุ่มจำนวนที่ระบุ ใช้สำหรับการสุ่มตัวอย่าง การทดลอง และการสร้างข้อมูลทดสอบ
List.Repeat จะคืน List ใหม่ที่ประกอบด้วยสมาชิกทั้งหมดของ List ต้นฉบับที่ถูกทำซ้ำกัน 'count' ครั้ง โดยเรียงต่อกันไปตามลำดับเดิม
List.Transform ใช้สำหรับสร้างลิสต์ใหม่โดยนำฟังก์ชันไปประมวลผลแต่ละตัวในลิสต์เดิม
Comments
อีเมลของคุณจะไม่ถูกเผยแพร่