Author: Sira Ekabut

  • เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข

    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข

    ในบทความนี้เราจะมาใช้ Matrix ช่วยค้นหาข้อมูลตามเงื่อนไขกันครับ ถ้าใครยังไม่ได้อ่าน 2 ตอนก่อนหน้าก็แนะนำให้อ่านก่อนจะได้เข้าใจนะ (โดยเฉพาะตอนที่ 2)

    ค้นหาข้อมูลตามเงื่อนไข

    สมมติเรามี Data แบบนี้ แล้วเราจะหาว่ามีแผนกไหนบ้าง ที่ได้ยอดขายตามที่กำหนด

    สมมติเราอยากจะ Detect เฉพาะยอดขายตั้งแต่ 70 ขึ้นไป ตามเงื่อนไขต่างๆ (ด้วยการฝึกใช้ Matrix) เช่น

    • หาว่าแผนกไหนทำยอดตั้งแต่ 70 ขึ้นไปได้อย่างน้อย 1 เดือน
    • หาว่าแผนกไหนทำยอดตั้งแต่ 70 ขึ้นไปได้อย่างน้อย 2 เดือน
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 1

    การจะหาแบบนั้นได้ เราก็ต้องสร้าง Matrix เงื่อนไขที่ให้ผลลัพธ์เป็น 1,0 ก่อน ดังนี้ (ในวงเล็บจะได้ TRUE/FALSE แล้วพอจับคูณ 1 จะได้ 1,0)

    =(C4:E7>=70)*1
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 2

    ถ้าอยากรู้ว่า Dept แถวไหนบ้างที่ให้ค่าเป็น 1 กี่ตัวตามที่เราต้องการ เราก็ต้องทำการ Sum Total แต่ละแถว ให้ได้ก่อน ว่า Dept ๆ นั้นทำตามเงื่อนไขได้กี่เดือน

    ซึ่งการหา Total แต่ละแถว เราได้เรียนรู้ไปในบทความก่อนหน้าแล้วไง

    ดังนั้นเราลอง SUM แต่ละแถวก่อน ด้วยการเอาไปคูณ Matrix 3×1 ที่เป็นเลข 1 ทั้งหมด ซึ่งคราวนี้ผมจะ Manual Array {1;1;1} ลงไปในสูตรก่อนเพื่อความ Simple ในความเข้าใจ

    =MMULT(G4#,{1;1;1})

    G4# เป็นการอ้างอิง Array ที่ Spill ออกมาทั้งอัน (ถ้าเป็น Excel version เก่า ก็คือ G4:I7 นั่นแหละ)

    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 3

    มียอดขายอย่างน้อยเดือนใดเดือนหนึ่งตั้งแต่ 70 ขึ้นไป

    ถ้าอยากรู้ว่าทำได้อย่างน้อย 1 เดือน ก็เช็คว่า Sum แล้วได้มากกว่าหรือเท่ากับ 1 หรือไม่ แล้วแปลงเป็น 0,1 ซะ ด้วยการคูณ 1 หรือจะใส่ — ข้างหน้าก็ได้ ซึ่งผมจะใส่ — แล้วกันจะได้ดูแล้วไม่งงกับเลข 1 ที่จะใช้เทียบ

    =--(MMULT(G4#,{1;1;1})>=1)
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 4

    ถ้าเขียนรวบทั้งหมดเข้าด้วยกันจะเป็นแบบนี้

    =--(MMULT((C4:E7>=70)*1,{1;1;1})>=1)
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 5

    และถ้าไม่อยากจะ Manual พิมพ์ Matrix 3×1 ที่เป็นเลข 1 แต่เขียนสูตรแบบ Dynamic ตามขนาดของ Data จริงได้ทั้งหมด ก็จะใส่ TRANSPOSE(COLUMN(C4:E7)^0) ลงไปแทน {1;1;1} ก็จะได้แบบนี้

    =--(MMULT((C4:E7>=70)*1,TRANSPOSE(COLUMN(C4:E7)^0))>=1)

    ถ้าอยากรู้ว่าทั้งหมดมีกี่แผนกที่ทำได้ ก็ใช้ SUMPRODUCT หรือ SUM ครอบไป

    =SUMPRODUCT(--(MMULT((C4:E7>=70)*1,TRANSPOSE(COLUMN(C4:E7)^0))>=1))
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 6

    มียอดขายตั้งแต่ 70 ขึ้นไป อย่างน้อย 2 เดือน

    เราก็แค่เปลี่ยนเงื่อนไขเดิมเล็กน้อยจากหาอย่างน้อย 1 เดือน

    =--(MMULT((C4:E7>=70)*1,{1;1;1})>=1)

    เป็นต้องได้อย่างน้อย 2 เดือน

    =--(MMULT((C4:E7>=70)*1,{1;1;1})>=2)

    แค่นั้นก็จบแล้ว

    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 7

    ถ้าอยากดึงชื่อ Dept ออกมาด้วยล่ะ?

    ถ้ามั่นใจว่าผลลัพธ์มี Dept เดียว (หรือต้องการแสดงแค่ Dept แรกสุด)

    ถ้าผลลัพธ์มี Dept เดียวที่ทำได้ตามที่เราต้องการ เช่นในตัวอย่างอันที่สอง เราจะแสดงค่า Dept ออกมาได้ง่ายหน่อย โดยใช้ MATCH หาว่าเลข 1 อยู่ลำดับที่เท่าไหร่ (มันจะเจอ 1 ตัวแรก ซึ่งถ้ามี Dept เดียวจะไม่มีปัญหา) แล้วค่อยใช้ INDEX ถึงชื่อ Dept ตามลำดับที่ MATCH เจอ

    =MATCH(1,--(MMULT((C4:E7>=70)*1,{1;1;1})>=2),0)

    ซึ่งจะได้ว่าเจออยู่ในลำดับที่ 4

    แล้วเราค่อยใช้ INDEX ดึง Dept ออกมา

    =INDEX(B4:B7,MATCH(1,--(MMULT((C4:E7>=70)*1,{1;1;1})>=2),0))

    ถ้าต้องการให้สามารถแสดง Dept หลายชื่อได้

    เช่นในตัวอย่างแรก ที่มี 2 Dept ที่ทำได้ แบบนี้จะใช้ MATCH อย่างเดียวทื่อๆ ไม่ได้แล้ว เพราะมันจะเจอแค่ตัวแรก แต่ถ้าใครมี Office 365 ที่มีฟังก์ชัน Filter ล่ะก็ วิธีนี้จะง่ายกว่า MATCH อีก เช่น

    จากเดิมที่เราทำไว้ว่า

    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 8

    เราก็แค่ใช้ฟังก์ชัน FILTER เอาเฉพาะ Dept ที่ได้ 1 ก็จบเลย

    =FILTER(B4:B7,G4#)
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 9

    และถ้าอยากให้มาแสดงในช่องเดียว คั่นด้วย Comma ก็ใช้ TEXTJOIN ได้อีก เช่น

    =TEXTJOIN(", ",TRUE,FILTER(B4:B7,G4#))
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 10

    และหากอยากจะรวบทุกอย่างเข้าด้วยกัน ไม่ทด 1,0 ออกมาข้างนอก ก็จะเป็นแบบนี้

    =TEXTJOIN(", ",TRUE,FILTER(B4:B7,--(MMULT((C4:E7>=70)*1,TRANSPOSE(COLUMN(C4:E7)^0))>=1)))
    เล่นกับ Matrix ใน Excel ตอนที่ 3 : ค้นหาข้อมูลตามเงื่อนไข 11

    หรือถ้าไม่ใช้ FILTER เราจะใช้ IF มาช่วยก็ได้ (คุณโบ Excel Wizard มาช่วย Comment สูตรให้ประมาณนี้)

    =TEXTJOIN(", ",TRUE,IF(MMULT(N(C4:E7>=70),TRANSPOSE(COLUMN(C4:E7))^0),B4:B7,""))

    ซึ่ง N ก็จะเหมือนกับการเอาไป *1 นั่นแหละ และค่าไหนที่ logical_test ของ IF ออกมาเป็น 0 ก็จะได้ FALSE ซึ่งจะกลายเป็น “” ซึ่งเป็นค่าว่าง ทีนี้ TEXTJOIN สามารถ Skip ค่าว่างได้ ก็เลยสามารถใช้ได้เลยโดยไม่ต้อง FILTER ก็ได้

    สำหรับบทความนี้จบเท่านี้ดีกว่า เพราะเริ่มยากละ 555 เดี๋ยวไว้ดูตัวอย่างอื่นที่น่าสนใจกันอีกในบทความหน้า

  • เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน

    เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน

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

    สมมติเรามีข้อมูลต้นฉบับเป็น Array หรือ Matrix 4×3 ดังนี้ (ก็พิมพ์ลงไปตรงๆ นั่นแหละ) มาดูซิว่าเราจะทำอะไรกับมันได้บ้าง?

    เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน 12

    หาผลรวมแต่ละแถว

    หากอยากจะหาผลรวมแต่ละแถว ปกติแล้วเราก็จะสามารถ SUM แต่ละแถวง่ายๆ ได้เลยเนอะ แต่เพื่อวัตถุประสงค์ในการทำความเข้าใจกับ Matrix ให้มากขึ้น (เพื่อรองรับเคสที่ซับซ้อนขึ้นในอนาคต) เราจะลองมาดูกันว่า ต้องคูณ Matrix ยังไงถึงจะได้ผลรวมแต่ละแถว

    เดิม Matrix นี้เป็น 4×3 ซึ่งถ้าจะได้ผลรวมแถว มันจะต้องออกมาเป็น Matrix ผลลัพธ์ 4×1

    นั่นคือ มันต้องไปคูณกับ Matrix อะไรซักอย่างซึ่งมี 3 แถว 1 คอลัมน์แน่นอนด้วยเหตุผลตามรูปนี้

    เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน 13

    ซึ่งมันจะจับคู่แถวใน Matrix แรกมาคูณกับคอลัมน์แรกของ Matrix ที่สอง ซึ่งเราต้องการทั้งเลข 10, 85, 75 มาบวกกันหมดเลย แสดงว่ามันต้องคูณ 1 ทั้งหมดแน่นอน นั่นคือ Matrix ที่สองต้องเป็นเลข 1 หมดเลย เพื่อที่จะให้เป็น 10*1+ 85*1 + 75*1

    ดังนั้นเขียนสูตรได้ว่า

    =MMULT(B7:D10,F2:F4)
    เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน 14

    ซึ่งถ้าเราไม่อยากจะมาทด Matrix ที่มีเลข 1 แบบนั้น เราก็ต้องสร้างมันขึ้นมา เช่น ใช้เลขประจำ COLUMN ของ Matrix แรกมาทำให้เป็น 1 ด้วยการยกกำลัง 0 แล้ว Transpose เปลี่ยนจากแนวนอน เป็นแนวตั้ง ก็ได้ เช่น

    =MMULT(B7:D10,TRANSPOSE(COLUMN(B7:D10)^0))
    เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน 15

    อธิบายเล็กน้อยเผื่องง

    • =COLUMN(B7:D10) จะได้ {2,3,4}
    • พอจับยกกำลัง 0 จะได้ {1,1,1} ซึ่งเป็น Array แนวนอน (คั่นด้วย Comma แปลว่าคนละ Column)
    • เลย TRANSPOSE ได้ {1;1;1} ซึ่งเป็น Array แนวตั้ง (คั่นด้วย Semi-Colon)
    • จากนั้นมันก็คืออันเดียวกับ F2:F4 ที่เราเขียนแบบ Manual นั่นแหละ

    ต่อไปมาหาผลรวมแต่ละคอลัมน์บ้าง

    ถ้าคิดในทำนองเดียวกันกับอันแรก จะได้ผลลัพธ์เป็น 1 แถวx 3คอลัมน์ มันก็ต้องมี Matrix 1 x 4 มาคูณด้วยข้อมูลต้นฉบับของเรา และมันก็ต้องเป็นเลข 1 หมดเลยด้วย เพราะเราเอาทุกค่าคือ 1*10 + 1*30 + 1*70 +1*30

    และสูตรก็คือ

    =MMULT(A8:D8,F2:H5)
    เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน 16

    และถ้าไม่อยากมาพิมพ์ Matrix 1×4 ที่เป็นเลข 1 ทดไว้ ก็สามารถสร้าง Matrix จำลองในลักษณะคล้ายๆ เดิมได้ว่า

    =MMULT(TRANSPOSE(ROW(F2:H5)^0),F2:H5)

    เพียงแต่เปลี่ยนมาเอาจำนวนแถวของ Matrix Original มาทำให้เป็น 1 ทั้งหมด แล้ว Transpose มาเป็นแนวนอน

    เล่นกับ Matrix ใน Excel ตอนที่ 2 : สรุปข้อมูล Total แต่ละแกน 17

    และนี่ก็เป็นการใช้ Matrix เริ่มมาประยุกต์ทำอะไรที่เกี่ยวกับ Excel โดยตรงมากขึ้น ตอนหน้าจะเริ่มน่าสนใจมากขึ้นแล้ว เช่น ใช้ Matrix ช่วยหาข้อมูลในหลายๆ คอลัมน์เป็นต้น ว่าข้อมูลที่ต้องการอยู่ในแถวไหนบ้าง ^^

  • เล่นกับ Matrix ใน Excel ตอนที่ 1 : ใช้ Matrix แก้สมการ

    เล่นกับ Matrix ใน Excel ตอนที่ 1 : ใช้ Matrix แก้สมการ

    เอาจริงๆ แล้วตั้งแต่เรียนวิชาคณิตศาสตร์มาในสมัย ม.ปลาย ส่วนตัวผมก็แทบไม่เคยได้ใช้เจ้า Matrix เลย และตอนเรียนสมัยเด็กๆ ก็ไม่รู้ด้วยว่าเรียนไปทำไม… (แต่ถ้าเป็นหนัง Matrix นี่ชอบมาก หนังในดวงใจผมเลย 55)

    พอโตมาถึงเพิ่งรู้ว่ามันมีประโยชน์หลากหลายมากๆ และใช้ในหลายๆ สาขา เช่น การ Transform รูปภาพต่างๆ ในวงการ Graphic Design ก็ใช้ Matrix คำนวณทั้งนั้น อีกทั้งการทำพวก AI หรือ Machine Learning ก็ใช้ความรู้ Matrix ด้วยเช่นกัน

    แล้วใน Excel ล่ะ? เราจะใช้ Matrix มาทำอะไรได้บ้าง ในบทความนี้จะใช้ Matrix แก้สมการเส้นตรงหลายตัวแปรซึ่งเป็นเรื่องการคำนวณที่ตรงไปตรงมามากที่สุดอันนึงของการใช้ Matrix เลยล่ะ

    ใช้ Matrix แก้สมการเส้นตรงหลายตัวแปร

    สมมติมีโจทย์เป็นสมการเส้นตรง 3 ตัวแปรว่า

    • 2x + 4y − 3z = 20
    • x + y + z = 10
    • 3y+2z = 19

    ให้หาว่าค่า x, y, z คือเท่าไหร่?

    การจะเข้าใจเรื่องนี้ได้ถ่องแท้ เดี๋ยวผมทบทวนความรู้เรื่องการคูณ Matrix ให้เล็กน้อย

    การคูณ Matrix

    มันคือเอาข้อมูลแนวนอนจาก Matrix ตัวแรก มาคูณกับข้อมูลแนวตั้งของ Matrix ตัวที่สองแล้วหาผลรวม ทำแบบนี้ทีละพิกัดจนครบทุกแถวของ Matrix ตัวแรก และครบทุกคอลัมน์ของ Matrix ตัวที่สอง ทำให้สรุปได้ 2 ประเด็นสำคัญว่า

    • จำนวนคอลัมน์ของ Matrix แรก ต้องเท่ากับจำนวนแถวของ Matrix อันที่สอง (เพราะต้องจับคู่คูณกัน)
    • Matrix ผลลัพธ์จะมีขนาดเท่ากับ จำนวนแถวของ Matrix แรก และมีจำนวนคอลัมน์เท่ากับ Matrix สอง

    แต่โชคดีที่ใน Excel เรามีฟังก์ชันที่ใช้ได้เลย คือ MMULT ซึ่งย่อมาจาก Matrix Multiplication (คูณ Matrix)

    =MMULT(Matrix A, Matrix B)
    =MMULT(B11:D12,G3:H5)

    ** หากเป็น Excel Version เก่าที่ไม่รองรับ Dynamic Array จะต้องลากคลุม 4 ช่องก่อนใส่สูตร แล้วต้องกดเรียกใช้สูตรด้วยคำสั่ง Control+Shift+Enter แทนการกด Enter ธรรมดาด้วย

    เล่นกับ Matrix ใน Excel ตอนที่ 1 : ใช้ Matrix แก้สมการ 18

    เอามาประยุกต์ใช้

    จากสมการข้างบน และความรู้จากวิธีการคูณ Matrix เราสามารถมองได้แบบนี้

    เล่นกับ Matrix ใน Excel ตอนที่ 1 : ใช้ Matrix แก้สมการ 19

    นั่นคือ ถ้าหากว่า Matrix A คูณ Matrix X ได้ Matrix B…
    หากเราต้องการหาว่า Matrix X มีค่าเท่าไหร่? มันก็คือ A Inverse คูณกับ B นั่นเอง (สลับกันไม่ได้นะ เพราะ Matrix ไม่มีคุณสมบัติการสลับที่ของการคูณ)

    ถ้าเป็นคณิตศาสตร์ที่ต้องคำนวณเองก็จะยากหน่อย แต่ถ้าเป็น Excel ก็ง่ายเลย!! เราสามารถหาค่าของ Matrix X ได้แบบนี้

    • การคูณ Matrix จะใช้ MMULT
    • Inverse ของ Matrix A จะใช้ MINVERSE ซึ่งย่อมาจาก Matrix Inverse =MINVERSE(A8:C10)
    • สรุปแล้วรวมเป็น
    =MMULT(MINVERSE(A8:C10),G8:G10)

    ** หากเป็น Excel Version เก่าที่ไม่รองรับ Dynamic Array จะต้องลากคลุม 3 ช่องก่อนใส่สูตร แล้วต้องกดเรียกใช้สูตรด้วยคำสั่ง Control+Shift+Enter แทนการกด Enter ธรรมดาด้วย

    Matrix แก้สมการ

    ซึ่งผลลัพธ์จะออกมาเป็น 3 ค่า ซึ่งก็คือค่าของ x, y, z ตามลำดับ

    Tips : หากไม่ชอบผลลัพธ์ในแนวตั้ง ก็สามารถเอา TRANSPOSE ครอบไปให้เป็นแนวนอนก็ได้ แต่ผมว่าแนวตั้งก็ ok อยู่นะ

    และนี่คือตัวอย่างการใช้ Matrix แบบตรงไปตรงมามากๆ โดยใช้ในการแก้สมการเส้นตรงหลายตัวแปร แต่เดี๋ยวในบทความต่อไปจะให้ดูตัวอย่างการพลิกแพลงเอา MMULT มาทำอะไรแปลกๆ ให้ดูครับ

  • การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม

    การรวมข้อมูลจาก Excel หลายๆ ไฟล์ใน Folder หากข้อมูลแต่ละอันเป็น Table ที่มีหัวตารางเรียบร้อย การรวมจะใช้เครื่องมืออัตโนมัติกด Combine ได้เลย หรือจะใช้สูตร Excel.Workbook รวมได้เลยแบบง่ายๆ ซึ่งรายละเอียดอยู่ใน https://www.thepexcel.com/get-data-from-excel/

    แต่ถ้าข้อมูลในแต่ละชีท ไม่ได้อยู่ในรูปแบบที่เหมาะสม เช่น ต้องมีการ Transform ข้อมูลก่อน ถึงจะเอามา Combine รวมกันได้ แบบนี้จะใช้เครื่องมืออัตโนมัติไม่ได้แล้ว และในชีวิตจริงเราก็มักจะเจอกับข้อมูลแบบนี้ซะด้วย

    พูดง่ายๆ สถานการณ์คือ

    1 Folder มีหลายไฟล์
    1 ไฟล์มีหลาย Sheet
    แต่ละ Sheet มีความเน่า !!

    แนวทางใหม่ ในรูปแบบคลิป

    ในคลิปจะแสดงอีกแนวทางนึง ที่ผมคิดว่าง่ายกว่าเดิมนิดหน่อย ลองดูได้ครับ

    แนวทางจะเป็นแบบนี้ครับ

    1. กด Combine ไฟล์ให้ Excel สร้างฟังก์ชันให้เรา
    2. แก้ Parameter จากแบบ Binary เป็น Any ใน Advanced Editor
    3. แก้ Sample File ให้ชี้ไปที่ตาราง แทนที่จะชี้ไปที่ File
    4. แก้ Transform Sample ไฟล์ ให้ชี้ไปที่ Parameter เฉยๆ
    5. ตอนจะเรียกใช้ฟังก์ชัน ต้องไปเรียกใช้ให้ Input เป็น Table ดังนั้นต้องใช้ Excel.Workbook มาช่วยให้มองเห็น Table ในแต่ละไฟล์ใน Folder ก่อน

    สิ่งที่จะทำในบทความนี้

    เราจะทำการรวมข้อมูลจาก Excel ทุกไฟล์ใน Folder ซึ่งในแต่ละไฟล์มีข้อมูลหลายชีทที่หน้าแบบนี้ ซึ่งแต่ละชีทเป็นรหัสพนักงานขาย และชื่อไฟล์เป็นปีที่ขาย

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 20

    แต่ลองดูข้อมูลในชีทสิ มันอยู่ในรูปแบบที่ไม่ใช่ข้อมูลตาราง Database เลยซักนิด! หัวตารางดันอยู่บรรทัดที่ 5 แถมดันมีรหัสลูกค้าเป็นหัวตารางหลายๆ คอลัมน์อีก ซึ่งทั้งหมดนั้นควรจะมาอยู่ในคอลัมน์เดียวกัน (แปลว่าต้องมีการใช้ unpivot พลิกลงมา) และต้องกำจัดพวก subtotal/total ที่เกินๆ มา และต้องมีการ Fill Down ถมสินค้ามาให้เต็มด้วย ซึ่งจะเห็นว่าต้อง Transform หลายอย่างเลย (แต่ปัญหาหลักคือเรื่องหัวตารางนั่นแหละ)

    ดังนั้นเราจะต้องใช้ฟังก์ชันรับ input ข้อมูลแต่ละชีทที่เน่าๆ มาจัดการดัดแปลงให้เป็น output ที่เรียบร้อยซะก่อนแล้วค่อยเอามารวมกัน ซึ่งเราจะเขียน Query ขึ้นมาแล้วแปลงเป็นฟังก์ชันได้ง่ายๆ ด้วยการใส่ (input)=> เข้าไปใน M Code แต่ว่าวิธีนี้จะทำให้แก้ M Code ด้วย UI ง่ายๆ ไม่ได้…

    จากในบทความ https://www.thepexcel.com/4-steps-function-query/ ผมได้อธิบายวิธีการสร้างฟังก์ชันใน Power Query แบบที่สามารถปรับแก้ Step ด้วย User Interface ง่ายๆ ได้อยู่ ซึ่งในบทความก่อนผมใช้ Parameter ที่เป็นประเภท Text ซึ่งจะเป็นแบบง่าย แต่ในบทความนี้เราจะใช้ Parameter ที่เป็น Table ซึ่งจะยุ่งยากกว่า แต่มีประโยชน์สุดๆ ไปเลยครับ ดังนั้นใครอยากรู้ พลาดไม่ได้เด็ดขาด

    ไฟล์ประกอบ

    โหลดไฟล์ได้ที่นี่

    เริ่มลงมือทำ

    เปิดไฟล์ Excel ใหม่ขึ้นมาแล้ว Get Data from Folder แล้วกด Transform แล้วตั้งชื่อ Query เป็น MyResult ซะ (ถ้าอยากให้ Dynamic ก็ทำ Path เป็น Parameter ซะจะได้เปลี่ยนได้ง่าย แต่ในบทความนี้ผมขี้เกียจทำ 55)

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 21

    จากหลักการ 4 ขั้นตอนที่บอกไปในบทความก่อน ดังนี้

    1. สร้าง New Parameter ขึ้นมา 
    2. เอา Parameter จากข้อ 1 ไปเรียกใช้ใน Query ที่ต้องการจะให้เป็นต้นแบบ 
    3. สร้างฟังก์ชัน (จาก Query ใน Step2)
    4. นำฟังก์ชันไปใช้งาน 

    ในบทความนี้เราก็จะใช้หลักการเดียวกันนั่นแหละ แต่มันจะมีความยุ่งยากเกิดขั้นในขั้นตอนแรกสุด นั่นก็คือการสร้าง Parameter ขึ้นมา เพราะว่าฟังก์ชันของเราคราวนี้เป็นการ Transform ตัวข้อมูลในแต่ละชีทซึ่งมี Data Type เป็น Table หรือตารางนั่นเอง (พูดถึงเรื่อง Data Type ของ PQ ซึ่งเป็นคนละเรื่องกับ Table ของ Excel นะ)

    การที่ Parameter เป็นแบบ Table นั้น ในความเป็นจริงต้องสร้าง Parameter ที่มี Type แบบ Any แต่ถ้าเราเลือก Any ไปตรงๆ ตัวหน้าตา Parameter มันจะไม่ยอมให้ไปต่อ เราก็เลยต้องเลือกหลอกๆ ให้เป็น Binary ก่อน และการจะเลือกแบบ Binary ได้ เราก็ต้องสร้าง Query ที่ชี้ไปที่ตัวไฟล์ Binary ซึ่งก็คือไฟล์ Excel ของเราก่อนอีกทีนึง (เห็นมะว่ายุ่งยากแค่ไหน 555)

    ดังนั้นผมจะขอเพิ่ม Step0 ขึ้นมา นั่นก็คือการเตรียม Sample สำหรับ Parameter ดังนี้

    Step 0 : เตรียม Query สำหรับสร้าง Parameter

    ใน MyResult ให้คลิ๊กขวาที่คำว่า Content แล้ว Remove Other Columns

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 22

    แล้วคลิ๊กขวา Drill Down ลงไปใน Binary อันแรกสุด แล้วลบ Step สุดท้ายออกซะ ให้เหลือเท่านี้ (มันแปลว่าจะอ้างอิงไปที่ไฟล์แรกใน Folder เพราะเป็น index 0)

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 23

    มันจะได้ Query ใหม่ที่อ้างไปถึง Binary ตามที่เราต้องการ ให้เราเปลี่ยนชื่อ Query เป็น MyValue ซะ

    จากนั้นก็กลับไปสู่ Step ปกติได้ละ

    Step 1 : สร้าง New Parameter ขึ้นมา 

    กด Manage Parameter แล้ว New ขึ้นมาใหม่ สมมติชื่อว่า MyPara ซึ่งให้เลือก Type หลอกเป็น Binary ก่อน แล้วเลือก MyValue ไปเป็น Default Value และ Current Value ซะ

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 24

    จากนั้นกด Advanced Editor แล้วให้แก้ Code เปลี่ยนประเภทจาก Binary เป็น Any (เพราะ input ที่เป็น Table ต้องเป็น Any)

    MyPara meta [IsParameterQuery=true, BinaryIdentifier=MySample, Type="Binary", IsParameterQueryRequired=true]
    MyPara meta [IsParameterQuery=true, BinaryIdentifier=MySample, Type="Any", IsParameterQueryRequired=true]

    จากนั้นให้กลับไปใน Query MyValue เพื่อให้อ้างอิงไปที่ Table จริงๆ โดยการ Double Click ที่ตัวไฟล์เพื่อ Drill Down ลงไป (เดิมเราอ้างอิงไปที่ตัวไฟล์)

    จากนั้นเราคลิ๊กขวาที่คอลัมน์ Data แล้ว Remove Other Columns –> แล้วคลิ๊กขวา Drill Down ลงไปใน Table อันแรกสุด

    จากนั้น MyValue ของเราก็จะอ้างอิงไปที่ Table แล้วล่ะ

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 25

    Step 2 : เอา Parameter จากข้อ 1 ไปเรียกใช้ใน Query ที่ต้องการจะให้เป็นต้นแบบ

    เนื่องจาก Parameter เราเป็นข้อมูลที่มี Data Type แบบ Table ดังนั้นเราจะสร้าง Query ต้นแบบขึ้นมาใน Blank Query ใหม่ โดยอ้างอิงไปที่ Parameter ตรงๆ เลย

    แค่เขียนสูตรว่า =MyPara

    จากนั้นตั้งชื่อ Query ว่า MySteps

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 26

    Step 3 : สร้างฟังก์ชัน (จาก Query ใน Step2)

    แค่กดคลิ๊กขวาที่ MySteps แล้วกด Create Function

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 27

    จากนั้นตั้งชื่อว่า MyFunction ก็ได้ (จะเห็นว่าฟังก์ชันนี้มี Parameter คือ MyPara)

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 28

    จากนั้น PQ จะสร้าง Group ของ Query ให้เรา (เพื่อความเรียบร้อยเฉยๆ) และเพื่อให้เรียบร้อยขึ้น ให้เราลาก MyValue ขึ้นไปอยู่ Group MyFunction ด้วย

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 29

    ดัดแปลง MySteps ตามใจชอบ

    จากนั้นให้เราเข้า MySteps เพื่อทำการดัดแปลงข้อมูลตามใจชอบ ซึ่งฟังก์ชันเราจะทำการดัดแปลงตามสิ่งที่เราทำใน MySteps ทั้งหมดกับทุกๆ Sheet ก่อนจะเอามา Combine รวมกันนั่นเอง

    ซึ่งสิ่งที่ผมทำมีดังนี้

    • Remove Top Rows -> 4 แถว
    • Use First Row as Header
    • ลบ Step Change Type ออก เพื่อไม่ให้จำชื่อหัวตาราง (เพราะแต่ละ Table หัวตารางไม่ตรงกัน)
    • Fill Down สินค้า
    • Filter สินค้า not Contain คำว่า Total
    • ลบคอลัมน์ Grand Total ขวาสุดออก
    • เลือกสินค้าและวิธีการชำระเงิน แล้ว Unpivot Other Columns
    • เปลี่ยนชื่อคอลัมน์ Attribute กับ Value เป็น รหัสลูกค้า และ ยอดขาย

    สรุปใน MySteps ได้ออกมาแบบนี้

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 30

    ซึ่งมี M Code ใน Advanced Editor ดังนี้

    let
        Source = MyPara,
        #"Removed Top Rows" = Table.Skip(Source,4),
        #"Promoted Headers" = Table.PromoteHeaders(#"Removed Top Rows", [PromoteAllScalars=true]),
        #"Filled Down" = Table.FillDown(#"Promoted Headers",{"สินค้า"}),
        #"Filtered Rows" = Table.SelectRows(#"Filled Down", each not Text.Contains([สินค้า], "Total")),
        #"Removed Columns" = Table.RemoveColumns(#"Filtered Rows",{"Grand Total"}),
        #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Removed Columns", {"สินค้า", "วิธีการชำระเงิน"}, "Attribute", "Value"),
        #"Renamed Columns" = Table.RenameColumns(#"Unpivoted Other Columns",{{"Attribute", "รหัสลูกค้า"}, {"Value", "ยอดขาย"}})
    in
        #"Renamed Columns"

    Step 4 : นำฟังก์ชันไปใช้งาน 

    เรากลับมาที่ MyResult เพื่อทำการเรียกใช้ฟังก์ชัน MyFunction ที่เพิ่งสร้างขึ้นมา แต่ฟังก์ชันเราต้องการ Input ที่เป็น Table ดังนั้นเราต้องทำการอ่านข้อมูลใน Binary ก่อนโดย Add Custom Column ขึ้นมาแล้วเขียนสูตรดังนี้

    =Excel.Workbook([Content])
    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 31

    จากนั้นเราจะได้คอลัมน์ Custom ขึ้นมา ซึ่งคราวนี้เราต้องการข้อมูลที่เป็นชื่อไฟล์ด้วย ดังนั้นเราจะเก็บคอลัมน์ Custom กับ Name เอาไว้ ดังนั้น Remove Other Column ซะ แล้ว Expand เจ้า Custom ออกมา

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 32

    จะพบว่าข้อมูลจริงที่ยังไม่ได้ Transform ซึ่งเราต้องใช้เป็นตัว Input ของฟังก์ชัน อยู่ใน Data นี่แหละ

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 33

    ดังนั้นเราจะเรียกใช้ฟังก์ชันของเราโดย Invoke Custom Function

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 34

    จะพบว่าจะได้คอลัมน์ MyFunction ใหม่ ที่เป็น Output แบบ Table ที่แปลงข้อมูลเรียบร้อยแล้ว

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 35

    เราต้องการชื่อไฟล์ ชื่อชีท และ Data หลังแปลงแล้ว ดังนั้นเราจะเก็บไว้แค่คอลัมน์ Name, Item และ MyFunction จากนั้น Expand MyFunction ออกมา

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 36

    Extract Name แบบ Before Delimiter จุด เปลี่ยนชื่อคอลัมน์ให้เรียบร้อย และเปลี่ยน Data Type ก็จะได้ดังภาพเป็นอันจบ

    การรวมข้อมูลหลายๆ Sheet จาก Excel หลายๆ ไฟล์ใน Folder แบบที่ต้อง Transform ข้อมูลก่อนรวม 37

    ถ้าอยากจะปรับการ Transform ก่อนจะรวมไฟล์ ก็ไปทำที่ MySteps ได้เลยแบบง่ายๆ นี่แหละคือข้อดีของการสร้าง Function แบบใช้ Parameter จริงจังครับ

    ถ้าใครอ่านแล้วสงสัยตรงไหนก็ถามได้ หรือถ้าอยากดูแบบคลิป vdo ก็มีที่คุณโบ Excel Wizard เคยทำไว้ดังนี้ครับ (อย่างที่บอกในบทความที่แล้วว่าผมเอาเทคนิคนี้มาจากคุณโบนี่แหละ 55)

  • Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX

    ในตอนที่แล้วผมได้พูดถึงเรื่องการทำ Data Model ที่รองรับการแสดงรายงานแบบ Target vs Actual ไปแล้ว แต่ว่าเราแสดงเป็น Target ระดับเดือนอยู่ ซึ่งหากว่าเราอยากจะแสดง ยอดขายที่ละเอียดแต่ละวันด้วย ดังนั้นเราก็จะต้องแจกเป้า หรือ Allocate Target ให้ลงมาถึงที่ระดับวันด้วยนั่นเอง

    อีกประเด็นนึงก็คือ ถึงเราไม่ต้องการจะลงรายละเอียด Target ถึงระดับวัน แต่ถ้าใน Visual ดันดึงข้อมูลระดับวันมา มันก็จะมี Target ทั้งเดือนอยู่ที่วันแรกหมดเลย ซึ่งดูไม่ Make Sense ดังรูป ซึ่งก็อาจจะต้องจัดการอยู่ดี

    ไฟล์ประกอบ

    ใช้ไฟล์จากบทที่แล้วต่อ หรือโหลดอันนี้ได้เลย

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 38

    แนวคิดเบื้องต้นก็คือ เราจะหา Target เฉลี่ยของแต่ละวันให้ได้ก่อน แล้วค่อยเอามาแสดงค่า ขึ้นอยู่กับว่า Filter Context ของ Visual ที่แสดงอยู่มันมีกี่วัน

    คำนวณ Target ระดับวัน

    การจะหา Target เฉลี่ยของแต่ละวันเราจะใช้ DAX คำนวณก็ได้ หรือจะทำตั้งแต่ใน Power Query ก็ได้เช่นกัน แต่เพื่อให้ง่าย เราจะใช้ Power Query ทำ โดยกด Transform Data แล้วเข้าไป Edit Query ของ fTarget ดังนี้

    หาจำนวนวันในเดือน โดยคลิ๊กที่วันที่ แล้วเลือกตามรูป

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 39

    จากนั้นค่อยเอา Target รายเดือน มาหารด้วยจำนวนวันในเดือน

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 40

    จากนั้นเราก็จะได้ Target รายวันมา ซึ่งผมขอตั้งชื่อว่า DailyTarget

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 41

    กด Close & Apply เพื่อ Load ข้อมูลเข้า Data Model

    จากนั้นลองสร้าง Measure ใหม่ โดย SUM ค่าของ Daily Target มาดังนี้

    TotalTargetNew = SUM(fTarget[DailyTarget])

    หากลองลากเข้า Visual ก็จะเป็นดังนี้

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 42

    จะเห็นว่ามันเป็น Target ระดับวันแล้ว แต่มีแค่วันเดียว สิ่งที่เราจะต้องคิดคือเราจะต้องทำให้มันโผล่ขึ้นมาทุกวัน

    เริ่ม Allocate Target

    โดยหลักการคือ เราต้องใช้ DAX ดึงค่า Target จากวันที่ 1 ของแต่ละเดือน มาโปรยลงวันอื่นๆ ด้วย ซึ่งเราจะใช้ CALCULATE ในการเปลี่ยน Filter Context ของวันอื่นๆ ให้กลายเป็นวันที่ 1 ให้หมดเลย ดังนี้

    ThisMonthDailyTarget =
    VAR currentDate =
        FIRSTDATE ( dDate[Date] )
    VAR currentYear =
        YEAR ( currentDate )
    VAR currentMonth =
        MONTH ( currentDate )
    RETURN
        CALCULATE (
            [TotalTargetNew],
            dDate[Date] = DATE ( currentYear, currentMonth, 1 )
        )
    allocate target

    จะเห็นว่าเราสามารถแสดง Target ลงระดับวันได้แล้ว

    แต่ว่า… หากเราเอาแกนเลขวัน DayNum ออกจาก Visual แล้ว ตัว Measure ของเราก็จะผิดทันที เพราะมันก็จะกลายเป็น Target ของวันเดียว แต่ตัว TotalTarget เรายังใช้ได้นี่!

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 43

    เล่นง่าย

    ดังนั้นเราอาจจะสร้าง Measure ตัวใหม่ขึ้นมา เป็นตัวตัดสินว่าจะใช้ Measure ตัวไหนมาแสดงดี ขึ้นกับว่าในรายงานมันแสดง Dimension ละเอียดถึงระดับวันหรือไม่? ดังนี้

    SelectTarget =
    IF ( HASONEVALUE ( dDate[DayNum] ), [ThisMonthDailyTarget], [TotalTarget] )

    ถ้า DayNum ไม่ได้มีค่าเดียว (แสดงว่าไม่ใช่ระดับวัน) เราก็แสดง TotalTarget

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 44

    แต่ถ้า DayNum มีค่าเดียว (แสดงว่าเป็นระดับวัน) เราก็แสดง ThisMonthDailyTarget ได้แล้ว

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 45

    จริงๆ แล้ววิธีข้างบนก็มีปัญหา

    วิธีข้างบนจะใช้ได้ ก็ต้อเมื่อเราเลือกว่าจะแสดงระดับเดือน หรือระดับวันเดียวไปเลย (ไม่ได้เลือกวันที่แค่บางช่วงของเดือน) ซึ่งจะมีปัญหาทันทีหากเลือกวันที่แค่บางช่วง เช่น ดูยอดแค่ 10 วันแรก มันก็ดันเอา Target ทั้งเดือนมาใช้อยู่ดี (เพราะว่ามี DayNum มากกว่า 1 Value เลยไปใช้ระดับ Month) ดังรูป

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 46

    เอาจำนวนวันมาคูณได้มั้ย?

    ดังนั้น ถ้าจะให้เนียนขึ้น เราอาจคิดว่า ThisMonthDailyTarget มาคูณด้วยจำนวนวันใน Filter Context นั้นๆ มากกว่า ซึ่งเราจะใช้ Measure ใหม่แทน SelectTarget ดังนี้

    FinalTarget =
    [ThisMonthDailyTarget] * COUNTROWS ( VALUES ( dDate[Date] ) )
    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 47

    ซึ่งลองไม่ Filter ระดับวัน ผลลัพธ์ก็ไม่ผิดด้วย เพราะมันจะคูณกับจำนวนวันในเดือน จนออกมาถูกต้องเอง

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 48

    แต่มันยังมีจุดบอดที่ตัว Total

    วิธีที่เราคิดข้างบนก็เหมือนจะถูกแล้ว แต่จริงๆ แล้วยังผิดที่ตัวรวมอยู่ เพราะมันดับเอา DailyTarget ของเดือนแรกที่เห็นใน Visual มาคูณจำนวนวันที่เห็นทั้งหมด

    ถ้าจะให้เห็นภาพชัดขึ้น ต้องลองทำให้เห็นข้อมูลแค่ไม่กี่วัน แต่ให้มันข้ามเดือนซะ เช่น

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 49

    จะเห็นว่ายอดรวม 2616129.03 ไม่เท่ากับ 2 เดือนรวมกันนะ ดังนั้นวิธีนี้จึงถือว่ายังไม่ดีเท่าไหร่

    แนวคิดที่ดีที่สุด

    ดังนั้นแนวคิดที่ดีกว่าคือการใช้ DAX สร้างตารางจำลองวันที่แต่ละวันขึ้นมาในช่วง Filter Context นั้นๆ แล้วเรียกเอา ThisMonthDailyTarget มา Sum กันซะ ซึ่งฟังก์ชันที่ทำแบบนั้นได้ก็คือ SUMX นั่นเอง

    ซึ่งพอ SUMX ใช้ผสมกับ Measure [ThisMonthDailyTarget] ก็จะเกิด Context Transition เกิดขึ้นในแต่ละแถวก่อนจะ Sum (ใครไม่เข้าใจลองย้อนไปอ่านเรื่อง Context Transition ได้ที่นี่)

    แบบนี้จะออกมาถูกต้องที่สุด และ Dynamic มากที่สุดด้วยครับ

    FinalTarget2 =
    SUMX ( DISTINCT ( dDate[Date] ), [ThisMonthDailyTarget] )
    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 50

    จะเห็นว่าผลลัพธ์จะถูกเสมอ ไม่ว่าจะเลือก Filter แบบไหนก็ตาม นี่สิวิธีที่ดีที่สุด

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 51

    สรุปแล้วเราก็ใช้แค่ TotalTargetNew (ที่เป็น DailyTarget) , ThisMonthDailyTarget (ที่เป็น DailyTarget แบบ Allocate ลงรายวัน ) และ FinalTarget2 (ที่ใช้ SUMX) เอง ตัวอื่นไม่ใช้ก็ลบไปซะ เช่น SelectTarget, FinalTarget ก็ไม่ใช้แล้ว

    และตัว TotalTarget เราอาจจะอยากใช้กรณีที่อยากเห็น Target ของทั้งเดือนหรือทั้งปี แม้วันที่ยังไม่ครบตามนั้น

    ดังนั้นก็ต้องเพิ่ม Measure %AchieveTarget ใหม่เป็นดังนี้ด้วย

    %AchieveTargetAll = DIVIDE([TotalRevenue],[TotalTarget])
    %AchieveTargetDaily = DIVIDE([TotalRevenue],[FinalTarget2])

    เวลาเราเอามาใช้ใน visual ต่างๆ ค่าที่ได้ก็จะแม่นยำมากที่สุด

    Power BI ตอนที่ 18 : วิธีการกระจายเป้า Allocate Target ด้วย DAX 52

    และนี่ก็คือการ Allocate Target ครับ ซึ่งอาจจะดูยุ่งยากอยู่บ้าง แต่ผมอยากจะลองไล่ Logic ให้ดูว่าทำไมการทำแบบบ้านๆ มันอาจจะผิดยังไงได้บ้าง และแบบที่ดีควรเป็นยังไง ถ้าอ่านแล้วสงสัยยังไงก็ Comment บอกได้นะครับ

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • VDO แฉ! พฤติกรรมแปลกๆ เวลา Filter แล้ว Copy Paste ใน Excel

    VDO แฉ! พฤติกรรมแปลกๆ เวลา Filter แล้ว Copy Paste ใน Excel

    มีวิธีที่ดีกว่าเดิม ในคลิปล่างครับ ^^

  • วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ

    มีคน Inbox มาถามผมว่า จากฐานข้อมูลแบบซ้ายมือ ต้องการ LOOKUP สร้างรายงานผลลัพธ์หน้าตาแบบขวามือ จะทำยังไงดี? (อันนี้เป้นตัวอย่าง Mock up นะ แต่ concept ก็แบบนี้แหละ)

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 53

    เอาจริงๆ ดูเหมือนมันจะเป็นรูปแบบรายงานที่เอาไว้ Print ลงหน้ากระดาษ ซึ่งผมว่าไม่เหมาะกับ Excel เท่าไหร่ ถ้าเป็นผมอาจจะใช้พวก Mail Merge ทำมากกว่า ถ้าใครสนใจลองไปอ่านได้ที่นี่

    แต่ถ้าเราจะใช้ Excel ทำเรื่องแบบนี้จริงๆ มันก็พอจะมีแนวทางอยู่ และผมก็จะค่อยๆ ทำให้ดู ดังนี้

    สร้างผลลัพธ์แบบปกติก่อน

    ก่อนอื่นก็ให้เราใช้ VLOOKUP หรือ INDEX MATCH สร้างผลลัพธ์ที่ link กับ lookup value ที่ต้องการ แต่ให้ผลลัพธ์เรียงเหมือนต้นฉบับให้ได้ก่อน เช่น

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 54

    ช่องสีเหลืองคือเป็นการพิมพ์ลงไปเอง นอกนั้้นเป็นสูตรทั้งหมด

    ช่อง B14 ผมใช้สูตรให้หาว่า TXID ที่ต้องการอยู่บรรทัดไหนของ Table1

    =MATCH(C14,Table1[TXID],0)

    ช่อง C14 ผมเขียนสูตรเพื่อดึงค่าจากคอลัมน์วันที่ออกมาจากแถวที่ Match เจอ แล้วลาก Fil Handle ไปเพื่อ Copy ให้มันเลื่อนไปเอาคอลัมน์อื่นๆ

    =INDEX(Table1[วันที่],$B14)

    เปลี่ยนตำแหน่งผลลัพธ์ตามต้องการ

    จับ Cut -> Paste หรือ Move ลากเพื่อเปลี่ยนตำแหน่งผลลัพธ์ให้อยู่ตำแหน่งที่ต้องการได้เลย (การ cut paste สูตรจะไม่เพี้ยนอยู่แล้ว) และอย่าลืมเปลี่ยน Fomat ช่องวันที่จากเลข 4 หมื่นกว่าให้กลับเป็นวันที่ด้วยนะ (ใครจะตกแต่งสีอะไรก็แล้วแต่เลย)

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 55

    หาแนวทาง Copy Paste

    ทีนี้เราต้องหาทาง copy paste สูตรให้ได้ง่ายๆ เช่น ถ้าสร้างแบบช่องสีเขียวด้านซ้ายได้จะง่ายแล้ว เราแค่ link สูตรจาก C14 ไป A14 แค่นั้นก็พร้อมจะ Copy ยาวลงมาข้างล่างแล้ว

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 56

    แค่ Copy Block B13:J15 ข้างบนไว้ แล้วลากพื้นที่จะ Paste ในคอลัมน์ B ใน B16:B21

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 57

    จากนั้นกด Paste

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 58

    เตรียมสร้างตัวสีเขียวแบบไม่ต้องพิมพ์เอง

    ทีนี้ก็เหลือแค่การสร้างตัวสรเขียวแล้ว ซึ่งทำไม่ยากเลย

    ให้ไป Copy ข้อมูลต้นฉบับในคอลัมน์ TXID ออกมาไว้ซักที่นึง แล้วก็สร้างคอลัมน์เลข running เอาไว้ข้างๆ

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 59

    จากนั้น Copy ตัว Running แล้ว Paste ลงไปข้างล่าง Running เดิมอีก 2 ชุด (เพราะเราจะเว้น 2 บรรทัด)

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 60

    จากนั้นก็ Sort ตัว Running จากน้อยไปมาก มันจะดึงตัวบรรทัดว่างๆ ขึ้นมาติดกับข้างบน

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 61

    แล้วเราค่อย Copy TXID ไปใช้แทนตัวเขียว

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 62

    จากนั้นค่อย copy ผลลัพธ์เราลงมา ก็จะได้ผลลัพธ์ที่ต้องการ จบ!

    วิธี LOOKUP สร้างรายงานหน้าตาแปลกๆ 63
  • วิธี SUM เฉพาะค่าที่เห็นจาก Filter แต่มีเงื่อนไข!

    วิธี SUM เฉพาะค่าที่เห็นจาก Filter แต่มีเงื่อนไข!

    วันนี้เราจะมาดูวิธี SUM เฉพาะที่มองเห็นแบบมีเงื่อนไขกันครับ (Sum Filter with Criteria) ซึ่งเป็นเรื่องที่แปลกดี แต่ก็มีคนถามผมมา เลยเอามาตอบให้ทุกคนพร้อมกันเลย

    หลายคนคงพอจะรู้อยู่บ้างว่า ถ้าเราใช้ฟังก์ชัน SUM ปกติ มันก็จะบวกข้อมูลตัวเลขแค่พื้นที่ในสูตรตรงนั้น โดยไม่สนใจว่าเรา Filter อะไรอยู่หรือไม่

    สมมติข้อมูลก่อน Filter เป็นแบบนี้ ซึ่งรวมจำนวนชิ้นสินค้าทั้งหมดได้ 31 ชิ้น

    วิธี SUM เฉพาะค่าที่เห็นจาก Filter แต่มีเงื่อนไข! 64

    ถ้าเรา Filter ว่าเอาเฉพาะการชำระเงินเป็นเงินสด …จะพบว่า เจ้า SUM ก็จะได้เท่าเดิมอยู่ดี…

    ถ้าจะ SUM เฉพาะสิ่งที่ Filter เห็นอยู่

    แต่ถ้าเราอยากจะ SUM แค่สิ่งที่ Filter อยู่เท่านั้น ต้องใช้ SUBTOTAL หรือไม่ก็ AGGREGATE มาช่วย เช่น

    =SUBTOTAL(9,C5:C14)

    เลข 9 ในสูตร เป็นการเลือกโหมดว่าจะให้ SUBTOTAL สรุปข้อมูลด้วยวิธีไหน? ซึ่ง 9 คือการ SUM นั่นเอง

    =AGGREGATE(9,3,C5:C14)

    ถ้าใช้ AGGREGATE เลข 9 ก็เหมือน SUBTOTAL แต่จะสามารถใส่ Option เพิ่มได้อีกว่าให้มันไม่สนใจอะไรบ้าง ซึ่งเลข 3 คือ ไม่สนแถวที่ซ่อนอยู่ ไม่สน error ไม่สน subtotal และ aggregate ที่ซ้อนอยู่ (พูดง่ายๆ คือ 3 ไม่สนมันทุกอย่างนี่แหละ)

    sum เฉพาะที่มองเห็นจาก filter แต่มีเงื่อนไข

    ถ้าไม่ Filter แต่จะ SUM เฉพาะอาหาร

    ถ้าเราไม่ได้ Filter แต่จะ SUM แค่บางอย่าง แบบนี้เรียกว่า SUM แบบมีเงื่อนไข ซึ่งสามารถทำได้หลายแบบ เช่น

    ใช้ SUMIFS

    =SUMIFS(C5:C14,B5:B14,"อาหาร")

    ซึ่งแปลว่า ให้ SUM พื้นที่ C5:C14 โดยเงื่อนไขคือ B5:B14 เป็นคำว่าอาหาร

    ใช้ SUM แบบ Array

    =SUM((C5:C14)*(B5:B14="อาหาร"))

    หลักการทำงานคือหากลองลากครอบ B5:B14=”อาหาร” แล้วกด F9 จะได้ TRUE/FALSE แบบนี้

    =SUM((C5:C14)*({TRUE;FALSE;FALSE;TRUE;TRUE;FALSE;TRUE;FALSE;TRUE;FALSE}))

    พอ TRUE/FALSE เชื่อมกับเครื่องหมายทางคณิตศาสตร์ มันก็จะกลายเป็น 1 กับ 0 ทำให้ ได้แบบนี้

    =SUM({4;0;0;5;6;0;2;0;4;0})

    ถ้าเป็น Excel ที่ไม่รองรับ Dynamic Array ต้องเขียนสูตรข้างบนแล้วกด Ctrl+Shift+Enter ด้วย จะมีปีกกางอกออกมา ถ้าไม่อยากต้องกด Ctrl+Shift+Enter ก็ให้ใช้ SUMPRODUCT แทน

    ใช้ SUMPRODUCT

    =SUMPRODUCT((C5:C14)*(B5:B14="อาหาร"))
    วิธี SUM เฉพาะค่าที่เห็นจาก Filter แต่มีเงื่อนไข! 65

    ถ้าจะ Filter เงินสด แต่จะ SUM เฉพาะอาหารล่ะ?

    ฟังก์ชันพวก SUMIFS กับ SUMPRODUCT มันก็ดันไม่สนใจ Filter ด้วย เห็นมะว่าได้ 21 เท่าเดิมเลย

    วิธี SUM เฉพาะค่าที่เห็นจาก Filter แต่มีเงื่อนไข! 66

    แล้วเราจะทำไงดี? ลองมั่วหลายๆ แบบดู

    ถ้าเราเอา SUBTOTAL เขียนแบบ Array ล่ะ

    =SUBTOTAL(9,(C5:C14)*(B5:B14="อาหาร"))

    ปรากฏว่ามันไม่ยอมให้กด Enter ด้วยซ้ำ…

    แล้วถ้าลองใช้ AGGREGATE ล่ะ เพราะมันก็สนใจเฉพาะตัวที่มองเห็นได้

    =AGGREGATE(9,7,(C5:C14)*(B5:B14="อาหาร"))

    ก็ดันขึ้น #VALUE! อีก เพราะฟังก์ชันหมายเลข 1-13 ดันไม่รองรับ Array…

    แล้วถ้าเอา SUMPRODUCT ผสม SUBTOTAL ล่ะ!

    =SUMPRODUCT(SUBTOTAL(9,C5:C14)*(B5:B14="อาหาร"))

    คำตอบไม่ Error ด้วย แต่ออกมาได้ 135 ซึ่งผิดเห็นๆ

    เพราะเกิดจาก =SUMPRODUCT(27*{TRUE;FALSE;FALSE;TRUE;TRUE;FALSE;TRUE;FALSE;TRUE;FALSE}) ซึ่งใช้ไม่ได้ เพราะมันดันคำนวณ SUBTOTAL ให้กลายเป็นค่าเดียวก่อนเลย แล้วค่อยมาคูณ กับ 1,0 ของ TRUE/FALSE

    ถ้าเราทำให้ SUBTOTAL มันคิดเลขทีละตัวล่ะ แบบนี้ก็ยังพอมีความหวัง!

    Solution

    วิธีแบบง่ายๆ

    วิธีที่ง่ายคือ เพิ่มคอลัมน์พิเศษที่เอาไว้ดักการ Filter ซะ แล้วเขียนสูตรให้เป็น 1,0 โดยให้เป็น 1 เมื่อมองเห็น ดังนี้

    =SUBTOTAL(3,A5)

    ผมเลือก COUNTA ไปที่ช่อง A5 เพราะคิดว่าช่องนั้นยังไงก็ต้องมีค่าเสมอ ไม่ใช่ช่องว่าง

    วิธี SUM เฉพาะค่าที่เห็นจาก Filter แต่มีเงื่อนไข! 67

    แบบนี้เราก็จะใช้ SUMIFS หรือ SUMPRODUCT ได้แล้ว

    =SUMIFS(C5:C14,B5:B14,"อาหาร",E5:E14,1)
    แค่เพิ่มคอลัมน์พิเศษว่าต้องเป็น 1
    =SUMPRODUCT(C5:C14*(B5:B14="อาหาร")*E5:E14)
    แค่คูณคอลัมน์พิเศษเข้าไป
    วิธี SUM เฉพาะค่าที่เห็นจาก Filter แต่มีเงื่อนไข! 68

    แต่ถ้าไม่เพิมคอลัมน์เอา ก็จะอยากขึ้นเยอะเลย!!

    ผมไปเจอในเว็บ ExcelJet ทำไว้ หลักการคือเค้าใช้ OFFSET ช่วยดึงค่ามาทีละช่องแล้วค่อยส่งให้ SUBTOTAL ทำงานต่อ ซึ่งใครสนใจก็ลองเข้าไปดูได้ครับ https://exceljet.net/formula/count-visible-rows-only-with-critera

    ถ้าเป็นผมทำเองด้วยหลักการคล้ายๆ กันก็จะได้สูตรแบบนี้

    =SUMPRODUCT((B5:B14="อาหาร")*SUBTOTAL(9,OFFSET(C4,ROW(INDIRECT("1:"&ROWS(C5:C14))),0)))

    ซึ่งยากกว่าการเพิ่มคอลัมน์พิเศษเยอะเลยเนอะ

    และนี่ก็คือเทคนิคที่อยากจะแนะนำครับ บางครั้งการเพิ่มคอลัมน์พิเศษเข้าไปก็ช่วยให้สูตรเขียนง่ายขึ้นเยอะเลยนะ และมันก็ไม่ได้แย่อะไรเลยด้วยเปลืองพื้นที่เพิ่มแค่คอลัมน์เดียว แต่เขียนสูตรง่าย และเร็วขึ้นเยอะ

  • Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual

    เนื้อหาตอนนี้คิดว่าเป็นเรื่องที่หลายๆ คนอยากรู้ นั่นก็คือวิธีทำรายงานเทียบเป้าหมาย Target vs Actual โดยที่สามารถจะแสดงข้อมูลใน Visual เดียวกันได้ เทียบได้ว่าค่าจริงต่างจากเป้าหมายเท่าไหร่เป็นต้น

    ไฟล์ประกอบ

    โหลดอันนี้ได้เลย มีไฟล์ Target ให้ด้วยครับ

    หน้าตาของไฟล์ Target ของเราเป็นแบบนี้

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 69

    ถ้าแปลงข้อมูลอันนี้ให้เป็นข้อมูลเชิง Database เราจะสามารถนำไปสร้าง Relationship กับตารางอื่นๆ ใน Data Model ได้

    จะทำ Target vs Actual อะไรได้บ้าง?

    ไฟล์ Target ของเรามีการแบ่งมิติตาม Year Month และ ProductSubCategory ซึ่งเราจะสามารถทำ Target ตามมิติเหล่านี้ได้อย่างแน่นอน รวมถึงมิติที่ใหญ่กว่าซึ่งเกิดจากผลรวมของตัวเหล่านี้ด้วย เช่น ProductCategory ก็จะสามารถทำได้ไปด้วย

    อย่างไรก็ตาม ถ้าหากอยากดูในมิติที่ย่อยลงกว่าเดิม มันขึ้นกับว่ามีวิธี Allocate ค่า Target จากตัวใหญ่ไปตัวย่อยหรือไม่? เช่น ถ้าจะ Allocate ค่าจากรายเดือน เป็นรายวัน ก็น่าจะทำได้ เพราะเอาไปหารจำนวนวันในเดือนก็น่าจะจบ แต่ถ้าจะดู Budget ของสินค้าแต่ละอันเลย จะทำไม่ได้ เพราะไม่มีวิธี Allocate ที่น่าจะดีพอ เป็นต้น

    ผูก Data Model ยังไง?

    Data Model ของเราน่าจะต้องผูกกับ ตารางวันที่ และ ตารางสินค้าอย่างแน่นอน ซึ่งการจะผูกกับตารางวันที่อย่าง dDate ได้จะต้องใช้ Key เชื่อมที่เป็นระดับวันที่ และจะผูกตารางสินค้าซึ่งตอนนี้เรามี dProduct ได้ ก็จะต้องมี Key ระดับ ProductID นี่คือสิ่งที่ต้องรู้ในการผูก Data Model

    สำหรับตารางวันที่ที่ต้องใช้วันเป็นตัวเชื่อม เรายังทำให้ตาราง Target ของเราเพิ่มคอลัมน์วันที่ไปได้ง่ายๆ เช่น เพิ่มให้เป็นวันที่ 1 หรือวันสุดท้ายของแต่ละเดือนไปซะ ก็พอจะเชื่อมได้

    แต่ว่าสินค้า ใน Budget เรามีแต่ SubCategory ไม่มีข้อมูล ProductKey ให้ผูกเลย ทางแก้คือ เราต้องหาทางสร้างคอลัมน์ ProductKey ที่เป็นตัวแทนของ SubCategory นั้นๆ มาให้ได้ เพื่อจะเป็น Key ผูกให้ได้นั่นเอง

    สรุปแล้ว เราจะต้องเพิ่มคอลัมน์ตัวแทน 2 อัน คือ DateKey และ ProductKey ขึ้นมาในตาราง Target ด้วย

    เริ่มสร้างตาราง Target ให้ใช้งานได้จริง

    เริ่มจาก Get Data จาก Excel มา แล้ว Promote Header และ Fill Down ProductSubCategory ซะ จากนั้นลบคอลัมน์ Grand Total ด้านขวาสุดออก

    จากนั้นเลือกคอลัมน์ ProductSubcategory และ Year จากนั้นคลิ๊กขวา Unpivot Other Columns ลงมาซะ

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 70

    เปลี่ยนชื่อคอลัมน์ให้เรียบร้อย

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 71

    สร้าง DateKey

    ทีนี้เราจะสร้างคอลัมน์ใหม่เพื่อให้เป็นวันที่วันแรกของเดือน วิธีที่ง่ายที่สุดคือสร้างคอลัมน์ใหม่ด้วย Column From Example จาก Year และ Month แบบนี้

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 72

    จากนั้นกดเปลี่ยนประเภทข้อมูลให้เป็น Date ซะ (ถ้าไม่ได้ให้กด Using Locale)

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 73

    สร้าง ProductKey

    การจะหา ProductKey มาเป็นตัวแทนของแต่ละ SubCategory วิธีที่ง่ายที่สุดคือสร้าง Query อีกตัวแล้ว Reference ค่าจาก dProduct ออกมาก่อน

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 74

    ทำให้เหลือแค่ ProductKey และ ProductSubcategory โดยเลือก 2 ตัวนี้แล้วกด Remove Other Columns

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 75

    จากนั้นสั่ง Remove Duplicates ที่คอลัมน์ ProductSubcategory ซะ

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 76

    จากนั้นเปลี่ยนชื่อ Query เป็น MapProductKey ซะ แล้วเลือกเอา Enable Load ออกด้วย เพราะเราจะไม่เอาผลลัพธ์ตารางนี้ออกไปยัง Data Model

    จากนั้นกลับไปยัง Target แล้วสั่ง Merge กับ MapProductKey เพื่อจะดึงค่า ProductKey ที่เป็นตัวแทนของแต่ละ ProductSubcategory มายังตาราง Target

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 77

    จากนั้นแตกเอาคอลัมน์ ProductKey ออกมาอันเดียวก็จบ

    เปลี่ยนชื่อ Query ให้เป็น fTarget ซะ แล้วกด Close & Apply

    ทำ Data Model รองรับ Target vs Actual

    จากนั้นก็ผูก Date กับ DateKey เข้าด้วยกันซะ (เพราะชื่อคอลัมน์ไม่ตรงกัน เราเลยต้องทำเอง) สุดท้ายจะได้ Data Model แบบนี้ ซึ่งแปลว่า dDate และ dProduct สามารถ Filter ได้ทั้ง fSales และ fTarget พร้อมๆ กันแล้ว (ดูทิศทางการ Filter จากลูกศร)

    ซึ่ง Model แบบนี้ก็คือ Model ที่มี Fact Table 2 ตาราง (ขึ้นไป) นั่นเอง แต่เป็นแบบที่ไม่ได้ผูกกันเองนะ แต่ผูกผ่าน Dimension Table อื่นๆ เช่น dDate กับ dProduct

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 78

    เริ่มสร้างรายงาน Target vs Actual

    ให้เราสร้าง Measure ที่ชื่อว่า TotalTarget ขึ้นมา โดยใช้สูตรที่ง่ายที่สุดในโลกอย่าง SUM ธรรมดาๆ

    TotalTarget = SUM(fTarget[Target])

    จากนั้นก็สามารลาก TotalTarget เข้า Visual ได้แล้ว และจะเห็นว่าเราสามารถลาก Dimension ที่มีความละเอียดเทียบเท่าหรือใหญ่กว่า Dimension ในตาราง fTarget ได้สบายๆ เช่น ProductCategory นั้นหยาบกว่า สามารถใช้ได้เลย รวมถึง MonthName ที่มีความละเอียดเทียบเท่ากันด้วย

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 79

    และแน่นอนว่าถ้าจะทำคำนวณพวก % Achievement นั้นก็ง่ายเหลือเกิน แค่เอา Actual มาหารด้วย Target

    %AchieveTarget = DIVIDE([TotalRevenue],[TotalTarget])
    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 80

    จากนั้นจะทำ Visual เป็นกราฟแบบไหนก็แล้วแต่คุณแล้ว

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 81

    ซึ่งจะใช้พวก Custom Visual มาช่วยก็ได้กราฟเท่ๆ ไปอีกแบบนึง เช่น อันนี้เป็น Custom Visual ชื่อว่า Bullet Chart by OKViz ครับ ซึ่งทำให้ประหยัดเนื้อที่เรื่อง Target ไปได้เยอะเลย เพราะเหลือแค่ขีดเอง

    Power BI ตอนที่ 17 : วิธีทำรายงานเทียบเป้าหมาย Target vs Actual 82

    เดี๋ยวบทความนี้เราจะขอจบเท่านี้ก่อนดีกว่า (เริ่มยาวละ) ในตอนต่อไปผมจะมาแนะนำวิธี Allocate Target กรณีที่จะดูในมิติที่ย่อยกว่าในตาราง fTarget ที่ทำไว้นะครับ

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function

    ในเนื้อหาตอนที่ 9 ของ Series นี้ ผมได้บอกไปว่าเราสร้าง Date Table ขึ้นมาเพื่อที่จะได้ใช้ฟังก์ชันกลุ่ม Time Intelligence ได้ และในบทความนี้ก็ได้เวลาที่จะไปพูดถึงฟังก์ชันกลุ่ม Time Intelligence ซะทีครับ

    Time Intelligence คืออะไร?

    มันคือฟังก์ชันกลุ่มที่จะช่วยให้เราคำนวณอะไรฉลาดๆ เกี่ยวกับวันที่และเวลาได้ เช่น คำนวณยอดขายสะสมตั้งแต่ต้นปี คำนวณยอดขายเทียบกับปีก่อน เป็นต้น

    เรามาดูตัวอย่างการใช้ฟังก์ชันกลุ่ม Time Intelligence กันดีกว่าว่ามันทำอะไรได้บ้าง และใช้งานยังไง?

    ไฟล์ประกอบ

    ใช้ไฟล์เดิมจากตอนก่อนหน้าได้เลยนะครับ หรือจะใช้อันนี้ก็ได้

    การคำนวณยอดขายสะสมตั้งแต่ต้นปี (Year-To-Date : YTD)

    ก่อนอื่นให้เราสร้าง Visual แบบ Table ใส่ ปี เดือน และ Total Revenue ลงไป (ที่เลือก ปี กับ เดือนมา เพื่อให้เห็นภาพชัดๆ)

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 83

    ถ้าเราอยากได้ยอดขายสะสม วิธีที่ง่ายที่สุดคือใช้ Quick Measure โดยคลิ๊กขวาปุ่ม New Quick Measure ได้เลย

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 84
    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 85

    จากนั้นกด ok ด้านล่าง (ถ้ากดปุ่มไม่ได้เพราะอยู่ล่างเกินไป ให้ย้าย task bar ของ windows ไปด้านขวานะ…)

    เราจะได้ measure ชื่อ TotalRevenue YTD ออกมาที่ซัก Table นึง (กด Search หา Field ชื่อ YTD ง่ายสุด)

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 86

    จากนั้นก็ลากลงมาใน Visual ซะเราก็จะได้ยอด Total Revenue แบบ Year-To-Date

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 87

    และก็ได้สูตรมาว่า

    TotalRevenue YTD = TOTALYTD([TotalRevenue], 'dDate'[Date])

    ซึ่งเจ้า TOTALYTD นี่คือฟังก์ชันสำเร็จรูปที่สามารถเปลี่ยน Filter Context ให้กับ Measure โดยให้มี Filter ช่วงวันที่นับตั้งแต่ต้นปีจนถึงวันล่าสุดที่ถูก Filter ในแต่ละบรรทัดนั้นๆ

    • เช่น เดิม ปี 2011 เดือน 5 มี Filter Context เรื่อง Date ตั้งแต่วันที่ 1/5/2011 – 31/5/2011
    • พอใช้ TOTALYTD มันจะเปลี่ยน Filter Context ไปเป็น 1/1/2011-31/5/2011 ทันที (กลายเป็นสะสม 5 เดือนนั่นเอง)

    และแน่นอนว่ามันก็มี TOTALQTD (Quarter to Date) และ TOTALMTD (Month to Date) ด้วย ลองไปใช้ดูได้

    ซึ่งจริงๆ แล้ว TOTALYTD นั้น เหมือนกับเอา CALCULATE + DATESYTD ดังนี้

    TotalRevenue YTD = 
    TOTALYTD([TotalRevenue], 'dDate'[Date])
    TotalRevenue YTD2 = 
    CALCULATE([TotalRevenue],DATESYTD(dDate[Date]))

    เนื่องจากฟังก์ชัน DATESYTD มีความสามารถในการ Filter เป็นช่วงเวลานับตั้งแต่ต้นปีนั่นเอง

    ทีนี้หลายคนคงสงสัยว่าแล้วจะเรียนรู้การเขียนด้วย CALCULATE ไปทำไม ทั้งๆที่เขียน TOTALYTD ก็ง่ายกว่าตั้งเยอะ ?

    นั่นเป็นเพราะหากใช้ CALCULATE เราสามารถใส่ Filter ได้เรื่อยๆ แต่ TOTALYTD ใส่ Filter ได้ 1 ตัวเท่านั้น ตามวิธีการใช้งานคือ

    TOTALYTD ( <Expression>, <Dates> , [<Filter>] , [<YearEndDate>] )

    แต่ถ้าไม่ได้จะ Filter อะไรเพิ่มเติม ใช้ TOTALYTD ก็ง่ายกว่าจริงๆ นั่นแหละ

    อย่างไรก็ตาม ถ้าเราจะทำการเลื่อนวันแปลกๆ เราก็ต้องย้อนไปสู่ฟังก์ชันพื้นฐานที่ทำได้ทุกอย่างตามใจ แต่อาจจะเขียนได้ยากกว่า ซึ่งเดี๋ยวเราจะลองค่อยๆ แกะว่าฟังก์ชันที่เขียนไว้มันแปลงเป็นอะไรได้บ้าง ที่ให้ผลเหมือนๆ กัน เพื่อที่จะได้สามารถดัดแปลงมาใช้ในเคสซับซ้อนได้ในอนาคต เช่น

    TotalRevenue YTD2 = CALCULATE([TotalRevenue],DATESYTD(dDate[Date]))

    มีค่าเทียบเท่ากับ การเปลี่ยน Filter มาเป็นช่วงเวลาระหว่างวันแรกของปี จนถึงวันสุดท้ายของ Filter Context ปัจจุบัน ซึ่งสามารถเขียนได้ด้วย DATESBETWEEN เป็นต้น

    TotalRevenue YTD3 = 
    VAR currentLastdate = LASTDATE ( dDate[Date] )
    VAR currentYear =  YEAR ( currentLastdate )
    VAR firstdayofYear =  DATE ( currentYear, 1, 1 )
    RETURN
    CALCULATE ( [TotalRevenue],
            DATESBETWEEN ( dDate[Date], firstdayofYear, currentLastdate )
            )

    และถ้าจะไม่ใช้ DATESBETWEEN อีก เราก็อาจจะต้องใช้ FILTER กับ ALL ร่วมกันดังนี้

    TotalRevenue YTD4 = 
    VAR currentLastdate = LASTDATE ( dDate[Date] )
    VAR currentYear =  YEAR ( currentLastdate )
    VAR firstdayofYear =  DATE ( currentYear, 1, 1 )
    RETURN
    CALCULATE ( [TotalRevenue],
            FILTER(ALL(dDate[Date]),dDate[Date]>=firstdayofYear && dDate[Date]<=currentLastdate)
            )

    เทียบหลายๆ วิธี

    แปลว่า 3 ตัวนี้ก็มีค่าเท่ากันทุกประการนั่นเอง

    • DATESYTD(dDate[Date])
    • DATESBETWEEN ( dDate[Date], firstdayofYear, currentLastdate )
    • FILTER(ALL(dDate[Date]),dDate[Date]>=firstdayofYear && dDate[Date]<=currentLastdate)

    เอาล่ะ สำหรับการทำความเข้าใจฟังก์ชันพวก YTD ขอจบเท่านี้ก่อน ลองมาดูอีกกลุ่มนึงคือ การเทียบกับยอดในอีกช่วงเวลาบ้าง

    การคำนวณยอดขายเทียบกับปีก่อน

    เราสามารถใช้ Quick Measure ได้เช่นเดิม โดยเลือกดังนี้

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 88

    มันจะออกมาเป็น

    TotalRevenue YoY% =
    VAR __PREV_YEAR =
        CALCULATE ( [TotalRevenue], DATEADD ( 'dDate'[Date], -1, YEAR ) )
    RETURN
        DIVIDE ( [TotalRevenue] - __PREV_YEAR, __PREV_YEAR )

    ซึ่งจะเป็น % การเปลี่ยนแปลง เทียบกับปีก่อนหน้า ดังนี้

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 89

    แต่ถ้าเราไม่ได้อยากทำเป็น % เทียบ แต่อยากได้ค่ายอดขายของปีก่อนมา เราก็สามารถตัดสูตรให้เหลือแค่นี้ได้

    TotalRevenueLY =
    CALCULATE ( [TotalRevenue], DATEADD ( dDate[Date], -1, YEAR ) )
    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 90

    ซึ่งเจ้า DATEADD มีความสามารถในการเลื่อนวันออกไปตามช่วงเวลาที่ต้องการ ตามหน่วยที่กำหนด ซึ่งเลื่อนได้ทั้งหน่วย DAY MONTH QUARTER YEAR เลยล่ะ เลื่อนย้อนเวลาก็ติดลบ เลื่อนไปข้างหน้าก็เป็นเลขบวก

    Power BI ตอนที่ 16 : เดินทางข้ามเวลาไปกับ Time Intelligence DAX Function 91

    จะว่าไปมันก็ดูคล้ายๆ EDATE ใน Excel เลย แต่ EDATE เลื่อนได้ในหน่วยเดือนเท่านั้น และ DATEADD ให้ผลเป็น Table ซึ่งใช้ใน Filter ของ CALCULATE ได้ แต่ว่า EDATE ให้ผลเป็นค่าตัวเลข (ดังนั้นเราจึงไม่สามารถใช้ EDATE แบบ -12 เดือนในเคสนี้นะ)

    ทีนี้ถ้าเราจะเลื่อนย้อน 1 ปี เพื่อเทียบกับยอดในปีก่อน เราสามารถใช้ฟังก์ชันสำเร็จรูปชื่อ SAMEPERIODLASTYEAR ได้เลย แบบนี้

    TotalRevenueLY2 = CALCULATE([TotalRevenue], SAMEPERIODLASTYEAR(dDate[Date]))

    และถ้าเราจะเขียนแบบ Manual เอง แบบไม่พึ่งพา Time Intelligence มันก็จะประมาณนี้

    TotalRevenueLY3 = 
    VAR currentLastdate = LASTDATE (dDate[Date])
    VAR currentFirstdate = FIRSTDATE(dDate[Date])
    VAR LYLastdate= EDATE(currentLastdate,-12)
    VAR LYFirstdate= EDATE(currentFirstdate,-12)
    RETURN
    CALCULATE ( [TotalRevenue],
            FILTER(ALL(dDate[Date]),dDate[Date]>=LYFirstdate && dDate[Date]<=LYLastdate)
            )

    เทียบหลายๆ วิธี

    แปลว่า 3 ตัวนี้ก็มีค่าเท่ากันทุกประการนั่นเอง

    • SAMEPERIODLASTYEAR(dDate[Date])
    • DATEADD(dDate[Date], -1, YEAR)
    • FILTER(ALL(dDate[Date]),dDate[Date]>=LYFirstdate && dDate[Date]<=LYLastdate)

    ซึ่งแน่นอนว่า SAMEPERIODLASTYEAR นั้นมีความ Flexible น้อยที่สุด แต่ก็เขียนง่ายสุดด้วยนั่นเอง

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report

    เราก็ได้เรียนรู้ความรู้พื้นฐานหลายๆ เรื่องไปแล้ว คราวนี้ขอพักเปลี่ยนหัวข้อมาดูเรื่องที่จะช่วยให้รายงานเรามีลูกเล่นเจ๋งๆ เพิ่มขึ้นด้วยการดึงค่าจาก Slicer มาคำนวณใน Report กันบ้างครับ (พอดีมีคน inbox มาถามด้วยล่ะ 55)

    ไฟล์ประกอบ

    ใช้ไฟล์เดิมจากตอนก่อนหน้าได้เลยนะครับ หรือจะใช้อันนี้ก็ได้

    ก่อนอื่น ลองสร้าง Table หรือ Matrix ขึ้นมาก่อน ลากสรุปผลยอดขายของแต่ละ ProductCategory ประมาณนี้

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 92

    ตัวอย่างการดึงค่าจาก Slicer มาใช้คำนวณใน Visual

    • การปรับตัวเลข TotalRevenue เป็นหน่วยต่างๆ เช่น เลขปกติ หารพัน หารล้าน
    • การปรับสกุลเงิน เช่น BHT USD JPY

    ปรับตัวเลขที่เป็นตัวหาร

    เคสนี้เป็นตัวอย่างที่ Simple ที่สุด เพราะว่าเราจะสร้าง Slicer ที่มีเลข 1 , 1000, 1000000 แค่ 3 ตัว แล้วพอเลือกตัวไหน เราก็จะเอาตัวเลขนั้นมาใช้เป็นตัวหารเลย

    จะมี Slicer ได้ ก็ต้องมีคอลัมน์ก่อน แต่คอลัมน์นี้จะต้องไม่มา Filter ผลลัพธ์ของตารางของเราด้วย ดังนั้นเราจะสร้าง Table ที่แยกออกไปต่างหาก และไม่ต้องผูก Relationship กับตารางอื่นเลย

    ให้ไปกด Enter Data แล้วใส่ประมาณนี้ลงไป

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 93

    แล้วเราก็จะได้ตารางแยกออกมาเดี่ยวๆ ซึ่งเราไม่ต้องไปผูก Relationship กับใครนะ

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 94

    จากนั้นเราลาก Field หัวหาร มาเป็น Slicer แบบ List

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 95

    จากนั้นลองสร้าง Measure เพื่อดึงค่าจาก Field ตัวหารดู ซึ่งฟังก์ชันที่เรารู้จัก และพอใช้ได้ก็คือ VALUES หรือ DISTINCT ก็ได้

    Measureดึงตัวหาร = VALUES('Tableตัวหาร'[ตัวหาร])
    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 96

    มันสามารถดึงค่ามาได้ดีเลย ทีนี้ถ้าเกิดเราสร้าง Measure ใหม่ ให้ TotalRevenue หารด้วย Measure ดึงตัวหาร เราก็จะเปลี่ยนหน่วยได้

    TotalRevenueเปลี่ยนหน่วย = [TotalRevenue]/[Measureดึงตัวหาร]
    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 97

    อย่างไรก็ตาม วิธีที่เราเพิ่งทำไปมันมีจุดอ่อนอยู่ ก็คือ หากคนใช้ Report ดันแกล้งเลือกตัวหารมากกว่า 1 ตัว หรือแม้แต่การ clear การเลือก item ใน slicer ออกไปเลย (จะแปลว่าเลือกทุกตัว) ก็จะทำให้ เจ้า Visual ของเราพังทันที!

    เมื่อกด See Details ก็จะพบว่า มัน Error เพราะว่า Measure ดึงตัวหารมันต้องการค่าเดียว แต่เราดันส่งให้มันหลายค่านั่นเอง…

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 98

    ทางแก้ไขในการดึงค่าจาก Slicer ทำได้หลายแบบ เช่น

    ใช้ IF + COUNTROWS

    TotalRevenueเปลี่ยนหน่วย =
    VAR divider =
        IF (
            COUNTROWS ( VALUES ( 'Tableตัวหาร'[ตัวหาร] ) ) = 1,
            VALUES ( 'Tableตัวหาร'[ตัวหาร] ),
            1
        )
    RETURN
        [TotalRevenue] / divider

    concept คือเช็คจำนวนแถวของ Tableตัวหาร'[ตัวหาร] ซะใช่ 1 แถวรึเปล่า? (ถ้าเลือก Slicer ค่าเดียว มันจะ Filter ตาราง Tableตัวหาร ให้เหลือแค่ 1 Row ซึ่งถ้า COUNTROWS ได้ 1 ก็จะให้ผลลัพธ์เป็น TRUE นั่นเอง

    พอเป็น TRUE เราก็ค่อยให้เอาค่าจากคอลัมน์ Tableตัวหาร'[ตัวหาร] แต่พอไม่ใช่ TRUE เราก็ให้เป็นเลข 1 ไปก่อน ค่าที่ได้จะได้ไม่ Error

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 99

    แต่ถ้าเราไม่อยากเขียนเทียบกับ 1 ให้ยุ่งยาก ก็สามารถใช้อีกฟังก์ชันนึงนั่นก็คือ HASONEVALUE ได้ ถ้าคอลัมน์นั้นมีแค่ค่าเดียว ก็จะได้ผลลัพธ์เป็น TRUE เช่นกัน ตามตัวอย่างข้างล่าง

    ใช้ IF + HASONEVALUE

    TotalRevenueเปลี่ยนหน่วย =
    VAR divider =
        IF (
            HASONEVALUE ( 'Tableตัวหาร'[ตัวหาร] ),
            VALUES ( 'Tableตัวหาร'[ตัวหาร] ),
            1
        )
    RETURN
        [TotalRevenue] / divider

    หรือถ้าขี้เกียจไปกว่านั้นอีก ก็มีฟังก์ชันอีกตัวที่ทำให้สูตรเขียนง่ายขึ้นไปอีก นั่นก็คือ

    SELECTEDVALUE

    SELECTEDVALUE(<columnName>[, <alternateResult>])

    SELECTEDVALUE มีความสามารถในการเช็คว่า <columnName> ที่ระบุ มีค่าเดียวรึเปล่า? ถ้ามีค่าเดียวก็จะให้ผลเป็นค่านั้นเลย แต่ถ้าไม่ได้มีค่าเดียวจะให้ผลเป็น <alternateResult> แทน เช่น

    TotalRevenueเปลี่ยนหน่วย =
    VAR divider =
        SELECTEDVALUE ( 'Tableตัวหาร'[ตัวหาร], 1 )
    RETURN
        [TotalRevenue] / divider
    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 100

    และเพื่อให้อ่านผลได้เนียนขึ้น เราน่าจะต้องใส่หน่วยลงไปด้วย เช่น

    TotalRevenueเปลี่ยนหน่วย =
    VAR divider =
        SELECTEDVALUE ( 'Tableตัวหาร'[ตัวหาร], 1 )
    VAR numResult = [TotalRevenue] / divider
    VAR textResult =
        FORMAT ( numResult, "#,##0.00" )
    RETURN
        SWITCH (
            divider,
            1, numResult,
            1000, textResult & " K",
            1000000, textResult & " M"
        )
    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 101

    การปรับสกุลเงิน

    ให้เราเตรียม Table สกุลเงินที่ต้องการจะเลือกเอาไว้ พร้อมกับตัวเลขอัตราแลกเปลี่ยนเมื่อเทียบกับเงินบาท ( Assume ว่าค่าตัวเลขปัจจุบันที่เราคำนวณอยู่ปกติเป็นสกุลบาทนะ)

    ในบทความนี้ผมจะเอาอัตราแปลกเปลี่ยนมาจากในเว็บ SCB ละกัน test แล้วเร็วดี

    https://www.scb.co.th/th/personal-banking/foreign-exchange-rates.html

    สั่ง Get Data from Web ซะ

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 102

    ที่นี้ Rate ของ JPY มันจะประหลาดตรงที่ว่ามันคิดต่อ 100 เยน ดังนั้นต้องระวังไว้ด้วย

    ผมได้ทำ Query ให้แล้ว แต่ขอไม่อธิบายละเอียด หลักๆ คือเลือกเอาบางคอลัมน์ แล้ว Split เอาตัวย่อกับ Rate ออกมาใช้ เพื่อนๆ สามารถเอา Code นี้ใส่ไว้ใน Advanced Editor ได้เลย

    let
        Source = Web.Page(Web.Contents("https://www.scb.co.th/th/personal-banking/foreign-exchange-rates.html")),
        Data2 = Source{2}[Data],
        #"Changed Type" = Table.TransformColumnTypes(Data2,{{"FOREIGN CURRENCIES", type text}, {"BANK SELLS D/D & T/T", type text}, {"BANK SELLS NOTES", type text}, {"BANK BUYS TT", type text}, {"BANK BUYS EXPORT SIGHT BILL", type text}, {"BANK BUYS T/CHQS. & CHQS.", type text}, {"BANK BUYS NOTES", type text}}),
        #"Removed Other Columns" = Table.SelectColumns(#"Changed Type",{"FOREIGN CURRENCIES", "BANK SELLS NOTES"}),
        #"Removed Top Rows" = Table.Skip(#"Removed Other Columns",2),
        #"Split Column by Delimiter" = Table.SplitColumn(#"Removed Top Rows", "FOREIGN CURRENCIES", Splitter.SplitTextByEachDelimiter({"#(lf)"}, QuoteStyle.Csv, false), {"FOREIGN CURRENCIES.1", "FOREIGN CURRENCIES.2"}),
        #"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"FOREIGN CURRENCIES.1", type text}, {"FOREIGN CURRENCIES.2", type text}}),
        #"Trimmed Text" = Table.TransformColumns(#"Changed Type1",{{"FOREIGN CURRENCIES.1", Text.Trim, type text}, {"FOREIGN CURRENCIES.2", Text.Trim, type text}}),
        #"Renamed Columns" = Table.RenameColumns(#"Trimmed Text",{{"FOREIGN CURRENCIES.1", "FXshort"}, {"FOREIGN CURRENCIES.2", "FXdesc"}, {"BANK SELLS NOTES", "Rate"}}),
        #"Changed Type2" = Table.TransformColumnTypes(#"Renamed Columns",{{"Rate", type number}}),
        #"Replaced Errors" = Table.ReplaceErrorValues(#"Changed Type2", {{"Rate", null}})
    in
        #"Replaced Errors"

    จากนั้นตั้งชื่อ Query ว่า FXRateTable แล้ว Close & Apply ซะ

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 103

    จากนั้นเราจะได้ FXRateTable ออกมาหน้าตาประมาณนี้

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 104

    และใน Data Model ก็ไม่ได้ต้องไปผูก Relationship เช่นเคย

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 105

    จากนั้นเราสร้าง Visual ที่มี Slicer เป็น FXshort ให้กดเลือกสกุลเงินที่ต้องการ (ผมปรับรูปแบบ Orientation ให้เป็น Horizontal เพื่อความสวยงาม)

    จากนั้นสร้าง Measure ชื่อว่า FXRate ด้วยสูตรดังนี้ เพื่อใช้เป็นตัวดึงค่าจาก Slicer นั่นเอง

    FXRate = SELECTEDVALUE(FXRateTable[Rate],1)

    และสร้าง Measure ที่จะแสดง TotalRevenue แบบสกุลเงินอื่นได้ ชื่อว่า TotalRevenueFX

    TotalRevenueFX = 
    VAR currentrate=[FXRate]
    RETURN[TotalRevenue]/currentrate
    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 106

    ทีนี้เราต้องแก้เรื่อง JPY เล็กน้อย เพราะ Rate ที่ให้มามันเป็นการคิดต่อ 100 YEN ไม่ใช่ 1 YEN

    ดังนั้นให้กลับไปแก้ Measure FX Rate ให้เป็นแบบนี้

    FXRate =
    IF (
        SELECTEDVALUE ( FXRateTable[FXshort] ) = "JPY",
        SELECTEDVALUE ( FXRateTable[Rate] ) / 100,
        SELECTEDVALUE ( FXRateTable[Rate], 1 )
    )

    แปลว่าให้เช็คก่อนว่าเลือกมาเป็น JPY รึเปล่า? ถ้าใช่ให้เอา Rate ที่ได้ไปหาร 100 (เพื่อให้เป็น Rate ต่อ 1 YEN) นอกนั้นก็เช็คว่า Rate ที่ได้มีค่าเดียวรึเปล่า? ถ้ามีหลายค่าให้ทำ FXRate ให้เป็น 1 ซะ เพราะแปลว่าไม่ได้เลือกสกุลไหนเลย (หรือเลือกมาหลายอัน) นั่นเอง

    Power BI ตอนที่ 15: วิธีดึงค่าจาก Slicer มาคำนวณใน Report 107

    จากนี้ จะเอาคำว่า Yen มาต่อท้ายตัวเลข คล้ายๆ กับที่เราทำ K กับ M ตอนแปลงหน่วยก็ย่อมได้ แต่ผมขี้เกียจทำแล้วล่ะ เพื่อนๆ ลองไปประยุกต์ทำกันเองนะ แล้วมาบอกด้วยล่ะว่าทำได้รึเปล่า อิอิ

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

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • แผนที่การเรียนรู้  Excel และ Power BI (Skill Map)

    แผนที่การเรียนรู้ Excel และ Power BI (Skill Map)

    เนื่องจาก Excel เป็นโปรแกรมที่ทำได้ครอบจักรวาล มันจึงมีเครื่องมือและฟังก์ชันที่เยอะมาก แถมช่วงหลังๆ ยังมีเครื่องมือใหม่ๆ อย่าง Power Query และ Power BI เพิ่มมาอีก ยิ่งงงเข้าไปใหญ่เลยว่าจะเรียนรู้อะไรก่อนหลังดี

    ถ้าเอาแบบภาพรวมก็ดูรูปนี้ได้

    โครงสร้างหลักสูตรของเทพเอ็กเซล

    เทพเอ็กเซลนำเสนอหลักสูตรอบรมที่ครอบคลุมตั้งแต่ระดับพื้นฐานไปจนถึงระดับสูง พร้อมด้วย Optional Knowledge สำหรับแต่ละหัวข้อเพื่อเสริมสร้างความรู้ในเชิงลึก

    ซึ่งเอาจริงๆ ในส่วนของ Excel เองก็แยกเป็น 2 สายหลักๆ คือ สายเครื่องมือ กับสายเขียนสูตร ดังนี้

    แผนที่การเรียนรู้ Excel และ Power BI (Skill Map) 109

    แต่ถ้าจะเอาแบบละเอียด ผมได้ทำการสรุปแผนที่การเรียนรู้เป็นรูปแบบคล้ายๆ กับแผนที่เส้นทางรถไฟ เพื่อที่ว่าแต่ละคนที่กำลังสนใจเรื่องไหน จะได้พอมีแนวทางในการศึกษาได้ครับ

    แผนที่การเรียนรู้ Excel & Power BI Skill Map 2.0

    Excel Skill Map

    โหลด PDF ได้ที่นี่ , โหลด Excel ได้ที่นี่ (แผนที่นี้ทำด้วยกราฟ Scatter Plot ตามคำแนะนำของ Excel Nana)

    เส้นทางแต่ละสีคือเนื้อหาในคอร์สเรียนของผมครับ ถ้าพื้นฐานคือเริ่มที่ Excel Level Up

    • สีเขียวเข้ม / หนังสือ Excel Level Up
    • สีเขียวอ่อน คือ (เป็นส่วนหนึ่งของ Excel Level Up)
    • สีเขียวฟ้า คือ / หนังสือ Excel Power Up
    • สีแดง คือ / หนังสือจอมเวทเทพเอ็กเซล
    • สีเหลือง คือ
      • สำหรับ Power Pivot จะเรียนคล้าย Power BI แต่เรียนแค่ DAX/Data Model
      • สำหรับ คอร์ส จะเน้นแต่เรื่อง DAX แต่จะลงลึกกว่าคอร์สปกติมาก
    • สีน้ำเงิน คือ เนื้อหาเรื่องกราฟขั้นสูง
    • สีม่วง คือ เนื้อหาเกี่ยวกับ VBA

    อย่างไรก็ตามแผนที่นี้เป็นแค่ Guideline ในความคิดเห็นของผมคนเดียวเท่านั้น เพื่อนๆ อาจมีวิธีหรือแนวทางอื่นที่คิดว่าเหมาะสมกว่าก็ได้นะ คิดเห็นยังไงก็ลอง Comment มาได้ครับ

    Version History

    แผนที่การเรียนรู้ Excel และ Power BI (Skill Map) 110

  • แนะนำคอร์สออนไลน์สำหรับผู้ที่อยาก Level Up ทักษะ Excel

    แนะนำคอร์สออนไลน์สำหรับผู้ที่อยาก Level Up ทักษะ Excel

    เนื่องจากช่วงนี้ COVID-19 ยังคงระบาดอยู่ คอร์สเรียน Excel แบบ Online จึงเป็นวิธีที่น่าสนใจมากขึ้น แต่ผมเองก็มีคอร์สออนไลน์อยู่ในเว็บ SkillLane ด้วยหลายตัว (และจะเพิ่มขึ้นเรื่อยๆ) จึงอยากจะมาแนะนำว่าแต่ละอันสอนอะไร? และเหมาะกับใคร?

    อย่างไรก็ตาม คอร์สของผมใน SkillLane ทุกคอร์สจะเป็นคลิปวีดีโอที่สามารถดูซ้ำกี่รอบก็ได้ ไม่มีวันหมดอายุอยู่แล้วนะครับ

    คอร์สออนไลน์ Excel Level Up : Update 2020

    จุดเด่น

    • รวมเนื้อหาพื้นฐานที่จำเป็นที่สุดของ Excel เข้าไว้ด้วยกันในคอร์สเดียว (12 ชั่วโมงครึ่ง) เช่น
      • ปูพื้นฐานแต่ต้น รวมถึงการจัดการข้อมูลวันที่และเวลา / การจัดการข้อความ
      • เครื่องมือต่างๆ เช่น Sort/Filter, Flash Fill, Conditional Format, Data Validation, Goal Seek
      • สอนแนวคิด แนวทางการเขียนสูตรซ้อนกัน ทำยังไงไม่ให้งง
      • ฟังก์ชันยอดนิยม เช่น IF / VLOOKUP / INDEX / MATCH / SUMIFS
      • การใช้ Table และ Pivot Table เพื่อสร้าง Dashboard
    • จ่ายเงินครั้งเดียวได้คอร์สที่เนื้อหาอัปเดทตลอดชีวิต (ปรับปรุงอย่างน้อยปีละ 1 ครั้ง)
      • คนที่เคยซื้อคอร์ส Excel Level Up Revised ไปแล้ว จะสามารถเข้าไปดูคอร์สใหม่นี้ได้ฟรีเช่นกัน
    • ราคา 1,490 บาท รับรองว่าได้เนื้อหาเน้นๆ ไม่มีน้ำ ตลอด 12 ชั่วโมงครึ่งอย่างแน่นอน

    คอร์สออนไลน์ เทพเรื่องข้อมูล ต้องเก่ง Pivot Table

    จุดเด่น

    • เน้นเรื่องการใช้ Table และ Pivot Table โดยเฉพาะ (เนื้อหาเหมือนกับในคอร์ส Excel Level Up)
    • ราคาย่อมเยาเพียง 490 บาท
    • เรียนจบเร็ว ใช้เวลาน้อยมาก (2 ชั่วโมงครึ่ง) แต่รับรองว่าเก่งขึ้นมาก
    • เหมาะกับการเตรียมตัวเพื่อต่อยอดไปใช้ Power Query และ Power BI ในอนาคตได้

    คอร์สออนไลน์ Excel Power Up 2021 : พลังแห่งข้อมูล สร้างได้ด้วย Power Query

    จุดเด่น

    • คอร์สนี้เป็น version อัปเดทเนื้อหาให้เข้าใจง่ายขึ้นครับ (คนที่เคยลงอันเก่าแล้ว สามารถเข้าเรียนอันนี้ได้ฟรี)
    • เพื่อนๆ ก็จะได้เรียนรู้การใช้เครื่องมือ Power Query ซึ่งมีประโยชน์ในการรวบรวมและดัดแปลงข้อมูลให้อยู่ในรูปแบบที่เหมาะสม ซึ่งมีความสามารถหลักดังนี้
      • ช่วยรวบรวมข้อมูลได้หลายรูปแบบ ทั้ง จากหลายๆ ชีท หลายๆ ไฟล์ หลายๆ format
      • ดัดแปลงข้อมูลให้มีหน้าตาเหมาะต่อการนำไปใช้งานต่อ เช่น เอาไปวิเคราะห์ต่อด้วย PivotTable ปกติหรือ Data Model
      • เวลาจะทำซ้ำ สามารถกด Refresh ปุ่มเดียว แปลว่าเหมาะกับงาน Routine มากๆ
    • Power Query เป็นเครื่องมือที่เป็นส่วนหนึ่งของ Excel Version 2016 ขึ้นไป และมีใน Power BI ด้วย ดังนั้นเรียนรู้ทีเดียวจะใช้ได้ 2 โปรแกรมเลย (ถ้า Excel Version 2013 ขึ้นไปต้องไปโหลด Add-in เพิ่ม)
    • ในคอร์ส Power Query นี้จะเน้นเรื่อง Power Query โดยเฉพาะ ซึ่งจะมีเนื้อหาที่ลงลึกกว่า Section Power Query Editor ที่อยู่ในคอร์ส Power BI นะครับ
    • Scope เนื้อหาในคอร์สนี้จะคล้ายกับหนังสือ Excel Power Up แต่จะมีการยกตัวอย่างการประยุกต์ใช้จริงมากกว่าหนังสือครับ
    • พิเศษ! ช่วงนี้ลดราคาจาก 1590 เหลือ 1,190 เท่านั้น (หมดเขต 19 มีค. 64)

    คอร์สออนไลน์ Powerful Data with Power BI

    จุดเด่น

    • คุณจะได้เรียนรู้เครื่องมือ Power BI ซึ่งเป็นเครื่องมือ Business Intelligent ชั้นยอดจากค่าย Microsoft
    • ใช้ทำ Interactive Dashboard ที่มี Visual หรือกราฟต่างๆ ที่เจ๋งกว่า Excel หลายเท่า
    • มีความสามารถในการแชร์ Dashboard ไปให้คนอื่นใช้ได้ง่าย และมีความปลอดภัยสูง
    • ในคอร์สนี้คุณจะได้เรียนรู้ทั้ง 3 แกนหลักของโปรแกรมนี้ ทั้ง
      • การ Get/Transform Data ด้วย Query Editor (เนื้อหาเทียบเท่าบางส่วนของคอร์ส Power Query) โดยจะเน้นแค่การดัดแปลงข้อมูลเบื้องต้นให้เข้าใจ Concept และแก้ปัญหาทั่วๆ ไปเท่านั้น
      • การทำ Data Model และเขียนสูตร DAX ในระดับที่ใช้งานทั่วไปได้
        • เรียนรู้ Data Model แบบพื้นฐาน และแบบที่รองรับการทำ Data Actual vs Budget ได้
        • สูตร DAX จะสอนนี้ก็จะลงลึกถึง CALCULATE และ Time Intelligent เช่น การคำนวณเทียบยอดในช่วงเดียวกันของปีที่แล้ว เป็นต้น
        • DAX ขั้นสูงจะทำแยกเป็นคอร์สต่างหากอีกอัน ไม่ได้อยู่ในคอร์สนี้ เพราะจะซับซ้อนเกินไป
      • การสร้าง Report ด้วยการสร้างกราฟและปรับแต่ง Visual ต่างๆ รวมถึงการทำให้เกิดความ Interactive มากขึ้น เช่น การปรับ Interaction, การ Drill แบบต่างๆ, Report Tool Tipsเป็นต้น
    • ราคา 2,290 บาท (อัปเดทเนื้อหาให้ฟรีทุกปี)

    คอร์สออนไลน์ : สร้างสูตรมหัศจรรย์ขั้นเทพ ด้วย Array Formula

    จุดเด่น

    • เน้นการเขียนสูตรขั้นสูง และการใช้ Array Formula เหมาะกับคนที่อยากแก้ปัญหาด้วยการใช้สูตร ซึ่งดีตรงที่อัปเดทอัตโนมัติ ไม่ต้อง Refresh แบบ Pivot
    • Scope เนื้อหาของคอร์สนี้เดิมจะคล้ายกับหนังสือจอมเวทเทพเอ็กเซลนะครับ
    • คุณจะเข้าใจการทำงานของ Array Formula อย่างลึกซึ้ง
    • เรียนรู้ Feature ใหม่ของ Excel 365 ที่เรียกว่า Dynamic Array
    • สร้างการคำนวณตามเงื่อนไขได้ตามต้องการ เช่น การคำนวณ PERCENTILE + IF
    • การ Filter ข้อมูล / Lookup ข้อมูลหลายค่า
    • การใช้ Match แบบ Advance เช่น หาค่าตัวสุดท้าย
    • การใช้ SUMPRODUCT, AGGREGATE
    • การสร้าง Dynamic Range ด้วย INDEX
    • การใช้ INDIRECT OFFSET
    • การดัดแปลงหน้าตาโครงสร้างของข้อมูลด้วยสูตร
    • หาว่ามีวันที่ตรงตามเงื่อนไขจำนวนกี่วัน ระหว่างวันเริ่ม-วันจบที่กำหนด
    • การใช้ฟังก์ชัน FREQUENCY
    • การแก้สมการหลายตัวแปรด้วย Matrix
    • การเลียนแบบ Pivot Table ด้วยสูตรแบบ Dynamic Array
    • ราคา 990 บาท

    หากต้องการซื้อหลายคอร์สพร้อมกัน ซื้อแบบคอร์ส Package จะประหยัดกว่า

    สรุปเลือกคอร์สไหนดี?

    ถ้าคุณคิดว่าเป็นคนที่พื้นฐาน Excel ok แล้ว อาจจะขาดแค่เรื่อง Pivot Table หรือคนที่อยากจะมุ่งเตรียมตัวไปใช้ Power Query / Power BI แบบด่วนๆ ผมก็แนะนำคอร์ส นะครับ เพราะเรียนจบเร็วดี (2 ชั่วโมงครึ่ง) แถมประหยัดด้วยแค่ 490 บาทเท่านั้น

    แต่ถ้าคุณอยากได้เนื้อหา Excel แบบครบจริงๆ และอยากรู้เรื่องที่สำคัญให้ครบ ผมก็แนะนำคอร์ส นี่แหละครับ ยิ่งตอนนี้ลดราคาอยู่เหลือแค่ 1,090 เท่านั้นเอง (จาก 1,490) เรียกได้ว่าจ่ายแพงขึ้นอีกนิด แต่ได้เนื้อหาเยอะขึ้นมากเลย (2 ชั่วโมงครึ่งของ Pivot เทียบกับ 12 ชั่วโมงครึ่งของ Excel Level Up)

    • ส่วนนี่แนะนำมากๆ เหมาะกับคนที่ต้องรวบรวมข้อมูลมาวิเคราะห์ และใช้ได้กับทั้ง Excel และ Power BI เลย
    • และถ้าใครอยากทำ Interactive Dashboard แบบเจ๋งๆ ก็แนะนำให้เรียน ครับ รับรองว่าเจ๋งกว่า Excel หลายเท่า
    • ส่วนใครยังหลงรักการเขียนสูตร Excel อยู่ และอยากเทพเรื่องการเขียนสูตร พลาดไม่ได้กับ

    ใครรอคอร์สไหนอยู่ก็ Comment บอกได้นะครับ จะไม่มีในนี้ก็ได้นะ เผื่อผมจะได้ลองทำมาให้เพื่อนๆ ได้เรียนกัน

  • 9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning)

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning)

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

    ตัวอย่างที่ผมชอบมากคือ กรณีของการวิเคราะห์ข้อมูลของนักวิจัยในสมัยสงครามโลก เพื่อที่จะหาว่าจะเพิ่มเกราะป้องกันให้เครื่องบินตรงไหนดี เพื่อให้นักบินมีโอกาสรอดตายมากขึ้น (เพิ่มทั้งลำไม่ไหว เดี๋ยวบินไม่ขึ้นพอดี)

    ซึ่งเค้าได้เก็บข้อมูลจากเครื่องบินที่กลับมาที่ฐานทัพทั้งหมดว่าถูกยิงที่จุดไหนบ้าง?
    ซึ่งก็ได้ดังรูป (จุดแดงคือจุดที่ถูกยิง)

    survivorship bias

    เพื่อนๆ คิดว่าเค้าควรจะติดตั้งเกราะป้องกันเพิ่มตรงบริเวณไหนดีครับ?

    ถ้าคิดเร็วๆ ก็ต้องเพิ่มเกราะตรงจุดที่มีสีแดงเยอะๆ สิ เพราะว่าถูกยิงเยอะบริเวณนั้น…. ใช่มะ?

    แต่การคิดแบบนี้ผิดโดยสิ้นเชิง เพราะจริงๆ แล้วเครื่องบินน่ะมีโอกาสถูกยิงทั้งลำนั่นแหละ แต่ลำที่โดนยิงตรงจุดที่ไม่ใช่สีแดงเนี่ยไม่มีโอกาสรอดกลับมาให้เก็บข้อมูลเหมือนกับกลุ่มนี้

    ดังนั้นแปลว่าสิ่งที่เห็นคือเป็นข้อมูลที่ได้จากผู้รอดชีวิต (Survivor) เท่านั้น ไม่ใช่ข้อมูลที่ครบถ้วนจริงๆ มันถึงมีชื่อเรียก Bias หรือความลำเอียงแบบนี้ว่า “Survivorship Bias” นั่นเอง

    แปลว่าถ้าคิดให้ลึกซึ้งขึ้นไปอีก เราควรเพิ่มเกราะตรงจุดที่ไม่ใช่สีแดงด้วยซ้ำ เพราะเป็นจุดที่โดนยิงแล้วตายเลย ไม่มีโอกาสรอดกลับมา ซึ่งเป็นคนละเรื่องละราวกับการตัดสินใจครั้งแรกเลย ดูสิว่า Bias อันตรายขนาดไหน!!

    ดังนั้นเรามาดูกันดีกว่าว่ามี Bias เกี่ยวกับอะไรบ้าง ซึ่งการแบ่งประเภท Bias ผมได้ทำการจัดกลุ่มในลักษณะที่ผมคิดว่าเหมาะสม โดยพยายามเรียง Bias ตาม Step การทำงาน ตั้งแต่การเก็บข้อมูล การประมวลผล และการตีความผลลัพธ์เลย

    Bias ในขั้นตอนการเก็บข้อมูล

    1. Observer Effect

    ความลำเอียงนี้เกิดขึ้นเมื่อ “ผู้ที่ถูกเก็บข้อมูลทำตัวไม่ปกติเพราะรู้ว่ามีคนคอยจับตาเป็นพิเศษ” เช่น ถ้าพนักงานรู้ว่าทีมตัวเองช่วงนี้กำลังถูก Monitor เค้าก็จะทำตัวดีผิดปกติ ทำให้ผลงานหรือค่าที่วัดได้ “ดูดีเกินจริง”

    หรือแม้แต่การที่ถ้าผู้ถูกวัดต้องเปิดเผยตัวตนว่าได้ให้ความคิดเห็นยังไง ประเมินผลยังไง หรือลงคะแนน Vote แบบไหน ก็อาจจะมีผลต่อการตัดสินใจก็ได้ เพราะการ Vote บางแบบที่ตรงกับใจตนเอง อาจไม่ตรงใจกับเจ้านายที่เฝ้ามองอยู่…

    ทางแก้เบื้องต้นคือ ต้องวัดแบบไม่ให้รู้ตัว หรือ อาจวัดให้นานขึ้น จนไม่สามารถ Fake ไหว (ถ้า Fake นานได้ก็ดีไปอีกแบบ) ถ้าเป็นการ Vote หรือการประเมินผลก็ต้องทำแบบ Anonymous ไม่ให้รู้ว่าใครเป็นผู้ให้คะแนนเป็นต้น

    2. Survivorship Bias

    อันนี้อธิบายไปแล้วในตัวอย่างเครื่องบิน แต่จริงๆ แล้วก็มีอีกหลายเรื่องเลยเช่น การใช้ชัวิตของคนดังที่ลาออกจากมหาลัยแล้วประสบความสำเร็จมากกมาย (ทั้งๆที่ไม่ได้เอาคนที่เรียนไม่จบทั้งหมดมาคิด) การวิเคราะห์ผลดำเนินงานของกองทุนรวมต่างๆ ส่วนใหญ่เราจะเผลอเอากองทุนที่เหลือรอดมาคิดเท่านั้น เพราะกองทุนที่ไม่รอดมันผิดตัวทิ้งไปหมดแล้ว เป็นต้น

    ทางแก้เบื้องต้น คือ อย่าลืมคิดว่า มีอะไรที่เรามองไม่เห็น หรือไม่มีข้อมูลหรือไม่? ทำไมจึงไม่มีข้อมูลนั้น? ซึ่งการไม่มีข้อมูล บางทีก็บอกอะไรได้มากกว่าการที่มีข้อมูลด้วยซ้ำไป…

    3. Selection / Sampling Bias

    อันนี้เกิดจากการที่กลุ่มตัวอย่างที่เราไปเก็บมา ไม่ได้เป็นตัวแทนประชากรที่ดี เช่น อาจเก็บมาเฉพาะกลุ่มที่เราสนใจเท่านั้น หรืออาจมีเหตุการณ์บางอย่างที่ทำให้กลุ่มนึงมาตอบ อีกกลุ่มไม่ตอบ (ก็กลายเป็น Survivorship อีก)

    ถ้าเราวิเคราะห์ค่าจากกลุ่มที่ไม่ใช่ตัวแทนที่ดี ผลที่ได้ก็ย่อมจะไม่สะท้อนประชากรที่แท้จริง

    ดังนั้นทางแก้ก็คือ ต้องสุ่มข้อมูลให้เป็นกลาง เช่น มีประชากรอยู่ 1,000 คน เราสัมภาษณ์ไหวแค่ 100 คน เราอาจเอาชื่อคน 1000 คนมาเรียง

    จากนั้นใส่ฟังก์ชัน RAND ใน Excel เพื่อทำการสุ่มเลข 0-1 (เป็นจุดทศนิยม)
    แล้ว Copy Paste Value ไว้ไม่ให้ค่าเปลี่ยน

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning) 111

    แล้ว Sort เอา 100 คนแรกมาสัมภาษณ์เจาะลึก เป็นต้น

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning) 112

    4. Measurement Bias

    อันนี้เกิดจากการวัดที่ไม่เที่ยงตรง อาจเป็นที่ตัวเครื่องมือวัดไม่เสถียร ทำให้วัดค่าได้แกว่งไปแกว่งมา เมื่อการวัดค่าไม่ได้เรื่อง การวิเคราะห์ในขั้นตอนต่อไปก็ย่อมจะแย่ไปตามกัน ดังที่บอกว่า Garbage-in Garbage-Out นั่นแหละครับ

    วิธีแก้ก็คือ พยายาม Calibrate เครื่องมือด้วย หรือลองวัดกับตัวอย่างเดิมซ้ำๆ ว่าค่าที่ได้แกว่งหรือไม่

    Bias ในขั้นตอนการคำนวณ

    5. Outliers

    การคำนวณด้วยค่าเฉลี่ยเลขคณิต (Mean หรือใน Excel คือ AVERAGE) จะถูกดึงค่าให้เบี้ยวโดยค่าที่น้อยผิดปกติมากๆ หรือ เยอะผิดปกติมากๆ ซึ่งเราเรียกค่าที่น้อยหรือเยอะผิดปกตินี้ว่า Outlier ซึ่งภาษาชาวบ้านเรียกปรากฏการณ์นี้ว่ามีการดึง Mean (ให้เบี้ยวไป) เช่น ในรูปข้างล่าง ค่า Mean เงินเดือนตั้งเกือบแสนเจ็ด ทั้งนี้เพราะดันมีคนเงินเดือนเป็นล้านอยู่ด้วย

    วิธีแก้ก็อาจจะตัด Outlier ก่อนแล้วค่อยคำนวณ หรือจะเปลี่ยนไปใช้ค่ากลางตัวอื่นที่ไม่ได้รับผลจาก Outlier เช่นค่า MEDIAN แทนก็ได้ เพราะว่า MEDIAN จะเอาข้อมูลมาเรียงกันจากน้อยไปมากแล้วดูว่าค่าไหนอยู่ตรงกลาง ซึ่งการทำแบบนี้จะไม่ได้รับผลการฉุดดึงจาก Outlier เลย

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning) 113

    6. Simpson’s Paradox

    เป็นปรากฏการณ์ที่ผลสรุปของกลุ่มย่อย ดันดูขัดแย้งกับผลสรุปในกลุ่มใหญ่กว่า ตัวอย่างเช่นอันนี้

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning) 114

    ถ้าเราได้ข้อมูลแบบนี้มา เราก็คงคิดว่า ผู้หญิงเนี่ยมาสายกว่าผู้ชายเนอะ ดูสิ สายกว่าทั้งสองแผนกเลย แย่จัง!

    แต่ถ้าเรามาดูตัวเลขตัวรวม และดูที่มาจากเลขดิบอาจจะได้ข้อสรุปอีกแบบ

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning) 115

    กลายเป็นว่า พอดูภาพรวมปุ๊ป ผู้ชายดันมี % การมาสายสูงกว่าผู้หญิงตั้งเกือบ 2 เท่า ทั้งๆ ที่ตอนดูแยกแผนก สัดส่วนของผู้หญิงที่มาสายดันมากกว่าตั้งเยอะ!

    ทั้งนี้เพราะว่าเลข 66.67% ที่ดูเยอะ มาจากกลุ่มที่มีแค่ 15 คนเอง แต่ 10% นั่นมาจากตั้ง 500 คน การ Weight จึงเยอะว่า ซึ่งกลับด้านกับของผู้ชายเลย

    นี่แหละความน่ากลัวของการดูข้อมูล หึหึ

    Bias ในขั้นตอนการตีความผลลัพธ์

    7. Correlation bias

    Bias นี้ก็เจอบ่อยมากเลย โดยเฉพาะเวลาคนพยายามหาความสัมพันธ์ระหว่าง 2 ตัวแปร เช่น X กับ Y แล้วเห็นว่ามันมี Correlation กัน คือวิ่งแบบสัมพันกัน รู้ค่า X แล้วสามารถทำนาย Y ได้

    ปัญหาคือ เรามักจะเผลอคิดไปด้วยว่า X จะต้องเป็นสาเหตุทำให้เกิด Y ด้วยก็เลยจะพยายามที่จะเพิ่ม X เพื่อให้ได้ Y มากขึ้น ซึ่งบางทีก็เป็นอย่างนั้นจริง แต่บางทีมันก็ไม่ใช่! (หรือบางที Y นั่นแหละที่ทำให้เกิด X ซึ่งกลับกันเลย)

    เพื่อนๆ เคยได้ยินประโยคนี้มั้ย? “Correlation does not imply Causation” หรือแปลเป็นไทยว่า “มีความสัมพันธ์กันไม่ได้หมายความว่าเป็นเหตุผลซึ่งกันและกัน”

    ถ้าอยากดูตัวอย่าง Correlation ประหลาดๆ ก็ลองเข้าไปดูได้ที่ tylervigen.com นี่เลย

    มันมีลูกเล่นให้เราลองหา Correlation แปลกๆ ด้วยตัวเองได้ด้วย โดยไปที่หน้านี้ เช่น ที่ผมทำอันนี้เป็น Correlation ระหว่างจำนวนคนที่ตายจากการตกเตียง กับ จำนวนเงินที่จ่ายไปกับสัตว์เลี้ยง ซึ่งมี Correlation ตั้ง 94% แน่ะ (หรือว่าจริงๆ สัตว์เลี้ยงคือฆาตกร!!)

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning) 116

    ป.ล. ที่แปลกกว่าคือ มีคนเก็บสถิติการตกเตียงตายด้วยเหรอ…เจ๋งจริงๆ

    ทางแก้ Bias คือ เราต้องหาเหตุผลให้ได้ว่า X มันทำให้ Y เปลี่ยนแปลงได้ยังไง มีกลไกอะไร? อาจต้องทำการทดลองว่าเพิ่ม X ลด X แล้ว Y เปลี่ยนจริงรึเปล่า? และต้องควบคุมการทดลองให้ดีด้วยนะ ไม่ใช่ยังมีตัวแปรปริศนา Z ซ่อนตัวอยู่อีก แบบนั้นการสรุปผลของเราอาจจะผิดก็ได้

    8. Gambler’s Fallacy

    อันนี้มักเกิดขึ้นกับนักเสี่ยงโชค ที่คิดว่าสถิติหรือแนวโน้มบางอย่างในอดีตจะสามารถช่วยให้คาดการณ์เหตุการณ์ในอนาคตได้ ทั้งๆ ที่จริงๆ ไม่ได้เกี่ยวกันเลย

    9 ความลำเอียงหรืออคติที่ต้องระวังเวลาทำงานเกี่ยวกับข้อมูล (Data Bias Warning) 117

    สมมติผมโยนเหรียญปกติ (ไม่ได้โกง) แล้วมันออกหัวไป 5 รอบติดกัน

    ถามว่าตาต่อไป โอกาสออกหัวหรือก้อยจะเยอะกว่ากัน?

    คำตอบคือ ถ้าเหรียญไม่ได้โกง มันก็จะยังมีโอกาสออกหัวอยู่ 50% เช่นเดิมตามปกติ ไม่ได้เกี่ยวอะไรกับที่เคยออกหัวไปแล้ว 5 รอบติดเลย

    9. Confirmation bias

    อันนี้เป็นการพยายามวิเคราะห์หรือสรุปข้อมูลเพื่อให้เข้าทางกับสิ่งที่ตัวเราเองมีความเชื่ออยู่ คือไม่ได้วางใจเป็นกลาง ซึ่งก็ค่อนข้างอันตรายเพราะว่าปกติคนเราก็มักจะเห็นเฉพาะสิ่งที่ตัวเองมองหาอยู่เท่านั้น

    ตัวอย่างอันนึงที่ค่อนข้างน่าสนใจคือ คลิปให้นับว่ามีคนเสื้อขาวส่งบอลกี่ครั้ง?

    คำตอบคือ 15 ครั้ง…

    แต่มีคนเกินครึ่งที่ไม่เห็นคนใส่ชุดกอลิล่าที่เดินผ่านไปในคลิปนี้เลย…

    นั่นเป็นเพราะปกติคนเราจะเห็นเฉพาะสิ่งที่เราสนใจเท่านั้น และเราก็จะ ignore ข้อมูลที่ไม่ได้ตรงกับใจเรา

    ซึ่งเป็นกับทุกเรื่อง เรามักจะรับแต่ข้อมูลที่ Support ความคิดเรา และไม่สนใจข้อมูลของอีกฝ่าย ยิ่งยุคนี้ที่มี Social Media ยิ่งจะได้เห็นแต่ข้อมูลที่ตรงกับเรามากผิดปกติอีก (เพราะเค้าคิดว่าเราน่าจะชอบ) ซึ่งก็ต้องระวังกันไว้ พยายามเปิดใจรับฟังรอบด้านด้วย

    ก่อนจากลา

    วันนี้ผมขอจบบทความเท่านี้ดีกว่า หากเพื่อนๆ มีเรื่อง Bias อะไรน่าสนใจ ก็ Comment บอกกันได้นะครับ

    และถ้าใครชอบบทความแนวนี้ ก็ยังมีเรื่องอื่นๆ อีกตามนี้เลย

  • Power BI ตอนที่ 14:  Context Transition และ พลังแฝงใน Measure

    Power BI ตอนที่ 14: Context Transition และ พลังแฝงใน Measure

    จากในตอนที่แล้วเราได้ทำความรู้จัก CALCULATE กันไปแล้วว่ามันเป็นฟังก์ชันที่เอาไว้เปลี่ยน Filter Context ได้ตามต้องการ ในตอนนี้เราจะมาทำความรู้จักพลังที่แท้จริงของมัน ซึ่งก็คือ

    • CALCULATE สามารถเปลี่ยน Row Context ให้เป็น Filter Context ได้ เรียกว่า Context Transition
    • Measure ทุกตัวมี CALCULATE แฝงอยู่ข้างในเสมอ

    ไฟล์ประกอบ

    ใช้ไฟล์เดิมจากตอนก่อนหน้าได้เลยนะครับ หรือจะใช้อันนี้ก็ได้ ซึ่งเรามี Data Model แบบนี้

    Power BI ตอนที่ 14: Context Transition และ พลังแฝงใน Measure 118

    มาดูเรื่องแรกกันก่อนครับ

    CALCULATE กับ Context Transition

    หากเรานำ CALCULATE ไปใช้ในบริบทที่มี Row Context มันจะเปลี่ยน Row Context นั้นให้กลายเป็น Filter Context … ฟังแล้วไม่เข้าใจเลยซักนิดใช่มั้ยครับ? งั้นมาดูตัวอย่างดีกว่าครับ

    สมมติว่าผมไปที่ Data View แล้วไปที่ Table dStores แล้วสร้างคอลัมน์ใหม์โดยที่ผมอยากจะแสดงยอดขายของแต่ Store ไว้ในคอลัมนี้

    ผมสามารถทำได้โดยกด New Column แล้วใส่สูตรแบบนี้ได้

    StoreRevenue = CALCULATE([TotalRevenue])
    Power BI ตอนที่ 14: Context Transition และ พลังแฝงใน Measure 119

    ผลลัพธ์ที่ได้มันจะใช้ CALCULATE คำนวณ TotalRevenue โดยเปลี่ยน Filter Context ให้เป็นไปตามค่าในแถวเดียวกับมัน

    สมมติว่าเราลองวิเคราะห์ Filter ของบรรทัดแรกจะมีดังนี้

    • StoreKey=1
    • StoreType=Store
    • StoreName=Contoso Seattle No.1 Store
    • Status=On
    • CloseReason=blank
    • EmployeeCount=17
    • SellingAreaSize=462
    • GeographyType=City
    • ContinentName=North America
    • RegionCountryName=United Sates

    พอมัน Filter ตามนี้ก็จะได้ว่า StoreRevenue = 1,615,303.83

    นี่แหละคือการเปลี่ยน Row Context เป็น Filter Context ซึ่งเรียกว่า Context Transition ซึ่งทำให้ผลคำนวณ Revenue แต่ละบรรทัดออกมาไม่เท่ากัน เพราะว่ามันมี Filter ไม่เหมือนกันนั่นเอง

    ระวัง! ถ้าคิดดูให้ดู เวลาเราคำนวณแบบนี้ หากในตารางมีคอลัมน์ที่ Unique ไม่ซ้ำกัน ผลลัพธ์ก็จะไม่มีปัญหา แต่ถ้าในตารางดันมีบรรทัดที่ Duplicate กันทั้งแถว ค่าที่ได้จากการคำนวณจะเบิ้ลทันที

    Measure ทุกตัวมี CALCULATE แฝงอยู่ข้างในเสมอ

    ประเด็นถัดไปก็คือ Measure ทุกตัวมี CALCULATE แฝงอยู่เสมอ อันนี้เข้าใจง่ายครับ

    แปลว่า การเขียนสูตรว่า

    StoreRevenue = CALCULATE([TotalRevenue])

    สามารถเขียนเหลือแค่ Measure ก็ได้ เพราะมันมี CALCUATE อยู่ในตัวอยู่แล้ว เช่น

    StoreRevenue = [TotalRevenue]

    ซึ่งจะได้ผลลัพธ์เท่าเดิมทุกประการ แต่เขียนสั้นลงไปอีก

    Power BI ตอนที่ 14: Context Transition และ พลังแฝงใน Measure 120

    และนี่ก็คือความลับอีก 2 ข้อที่เกี่ยวกับ CALCULATE ครับ จะเห็นว่ามันสั้นๆ ดูเรียบง่าย ไม่มีอะไร แต่พอใช้งานจริง หลายๆ คนอาจลืมนึกถึงเรื่องพวกนี้ ลืมนึกไปว่า Measure มี CALCULATE อยู่ และมันก็จะเกิด Context Transition ด้วย

    เพื่อให้เห็นความสามารถที่ลึกซึ้งมากขึ้น ลองมาดูตัวอย่างการใช้ CALCULATE กับ Row Context ที่น่าสนใจขึ้นดีกว่าครับ

    CALCULATE กับ Row Context ของ Iterator

    สมมติว่าผมอยากจะแสดงยอดขายเฉลี่ยของแต่ละ Store โดยแบ่งตาม Product Category เราจะทำยังไง?

    ก่อนอื่นผมจะต้องทำ Visual ที่มี Product Category อยู่ที่ Row ไว้ก่อน (เพราะเราจะแบ่งตาม Product Category ไง) ดังนี้

    Power BI ตอนที่ 14: Context Transition และ พลังแฝงใน Measure 121

    ทีนี้เราจะทำให้ Values หรือการคำนวณ คำนวณแบบไหนล่ะ? เราอยากได้ยอดขายเฉลี่ย ถ้าเราลาก Total Revenue ลงมา มันก็คือยอดขายรวม หรือถ้าเราลาก Field ยอดขายลงมาแล้วกด Average มันก็คือยอดขายเฉลี่ยแต่ละ Transaction ไม่ใช่ยอดขายเฉลี่ยของแต่ละร้านค้า…

    ทางออกคือ การสร้าง Measure ยอดขายเฉลี่ยของแต่ละร้านขึ้นมา

    Concept คือ เราจะใช้ Iterator เช่น AVERAGEX มาช่วย

    AVERAGEX ( <Table>, <Expression> )

    AVERAGEX จะทำการคำนวณ <Expression> ในแต่ละแถวของ <Table> (เรียกว่า Iterate) จากนั้นจำไว้ในใจ (สร้างตารางจำลอง) พอครบทั้ง Table แล้วก็เอามา Average กันซะ

    สูตรที่จะใช้คือ

    AverageStoreSales = AVERAGEX(DISTINCT(dStores[StoreKey]),[TotalRevenue])

    Table คือ DISTINCT(dStores[StoreKey]) ซึ่งก็คือ Store แต่ละร้านแบบไม่ซ้ำกัน

    Expression คือ [TotalRevenue] ซึ่งคือ Measure และมันมี CALCULATE แฝงอยู่ข้างใน ทำให้เกิด Context Transition ในการคำนวณ [TotalRevenue] ของ StoreKey แต่ละบรรทัดนั่นเอง

    พอคำนวณ TotalRevenue ของแต่ละ StoreKey ได้ก็จับมา Average กันให้เรา จบ.. ได้ผลลัพธ์แบบนี้

    Power BI ตอนที่ 14: Context Transition และ พลังแฝงใน Measure 122

    แต่ละสินค้าก็จะมียอดขายเฉลี่ยต่อร้านไม่เท่ากัน และตรง Total ก็คือยอดขายเฉลี่ยต่อร้านแบบที่ไม่ได้แบ่งตามสินค้า (พูดง่ายๆ ก็คือรวมสินค้าทุกประเภทนั่นแหละ) เลขมันก็เลยเยอะ

    การใช้ CALCULATE ผสมกับพวก SUMX AVERAGEX MAXX RANKX เพื่อแปลง Row Context เป็น Filter Context เป็นอะไรที่ใช้ในชีวิตจริงบ่อยมาก

    จะเห็นว่า TotalRevenue คำนวณจากตาราง fSales ดังนั้นจึงสามารถ Filter จากตารางอื่นได้เมื่อเราใช้ พวก SUMX AVERAGEX MAXX สร้างตารางจำลองขึ้นมา แล้วเกิด Context Transition ขึ้น

    ยกตัวอย่างเช่น

    TotalRevenue เฉลี่ยรายร้านค้า

    AverageStoreRevenue = 
    AVERAGEX(DISTINCT(dStores[StoreKey]),[TotalRevenue])

    TotalRevenue เฉลี่ยราย Category สินค้า

    AvgProductCategoryRevenue = 
    AVERAGEX( DISTINCT(dProduct[ProductCategory]) , [TotalRevenue] )

    TotalProfit ที่มากสุดรายสินค้า

    MaxProductCategoryProfit = 
    MAXX( DISTINCT(dProduct[ProductCategory]) ,[TotalGrossProfit] )

    ซึ่งจะเห็นว่าเราสามารถสร้างมุมมองต่างๆ เพิ่มได้ไม่จำกัด หาก Measure หลักนั้นคำนวณจากข้อมูลซึ่งอยู่ที่ Fact Table แต่ถ้า Measure หลักไม่ได้คำนวณจากคอลัมน์ใน Fact Table จะต้องทำตามในบทความนี้ครับ

    และนี่ก็คือความเจ๋งของการที่เรารู้ DAX ครับ เพราะเป็นเรื่องที่ PivotTable แบบปกติใน Excel ทำไม่ได้เลย ต้องเขียน DAX Measure ใน PowerPivot หรือ Power BI เท่านั้น ^^

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • วิธีสร้างเลข Combination กัน

    วิธีสร้างเลข Combination กัน

    มีคนถามมาว่า ถ้ามีเลข 0, 2, 3, 6, 9 สามารถผสมเป็นเลข 2 Digit ได้แบบไหนบ้าง? ผมว่าน่าสนใจดีเลยเอามาทำบทความให้ครับ วิธีทำที่ผมคิดว่าง่าย ก็คือใช้ Power Query ช่วยทำ ซึ่งมีวิธีทำดังนี้

    เริ่มต้นสร้างเลข Combination

    ก่อนอื่นสร้าง Table ที่มี List ตัวเลขที่ต้องการก่อน

    วิธีสร้างเลข Combination กัน 123

    แล้วก็เอาเข้า Power Query ซะ แล้วเปลี่ยน Data Type เป็น Text เพื่อความยืดหยุ่น (กดแบบ Replace Current)

    จากนั้น Add Custom Column ขึ้นมาแล้วใส่สูตรว่า =1 เพื่อให้ออกมาเป็นเลข 1 ทั้งหมด

    วิธีสร้างเลข Combination กัน 124

    จากนั้นทำการ Merge Query กับตัวเองซะ เลือกตัวเชื่อมเป้นคอลัมน์ที่มีเลข 1 ที่เราสร้างไว้

    วิธีสร้างเลข Combination กัน 125

    กด Expand ผลลัพธ์ออกมา

    วิธีสร้างเลข Combination กัน 126

    จากนั้นเลือกคอลัมน์ Num กับ Num.1 แล้วสั่ง Merge กันซะ จะใส่ตัวคั่นรึเปล่าก็แล้วแต่

    วิธีสร้างเลข Combination กัน 127

    จากนั้นลบ Column Custom ออกไปก็จบละ กด Load เอาผลลัพธ์ออกมาได้เลย

    วิธีสร้างเลข Combination กัน 128

    ลองเปลี่ยนข้อมูลดูได้ ใช้ตัวหนังสือก็ได้

    วิธีสร้างเลข Combination กัน 129
  • 4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query

    ในบทความนี้ผมจะมาแนะนำวิธีสร้าง Function Query ขึ้นใน Power Query ซึ่งไม่ใช่แบบปกติ แต่จะเป็นแบบที่ยังยอมให้เราแก้ไข Step ต่างๆ ใน Function นั้นได้โดยง่าย

    แต่ถ้าใครยังไม่รู้ว่าผมพูดถึงเรื่องอะไร ลองอ่าน recap นี้ดูก่อนเล็กน้อย…

    Recap

    Power Query เป็นเครื่องมือสำหรับการดัดแปลงข้อมูลที่ทรงพลังและใช้ง่ายมากๆ อยากจะทำอะไรก็มีเมนูสำเร็จรูปเอาไว้ให้กดได้เลยโดยแทบไม่ต้องเขียนสูตร แต่ว่าหลายครั้งก็น่าเบื่อเวลาที่เราต้องทำ Step อะไรซ้ำๆ เหมือนเดิมกับหลายๆ Query จะดีกว่ามั้ยถ้าเราทำ Step พวกนั้นเป็นฟังก์ชันแล้วเรียกใช้ได้อย่างง่ายๆ เลย?

    ในหนังสือ Excel Power Up! ที่ผมเขียนไว้ ในบทหลังๆ ก็มีเขียนวิธีที่ทำให้ Query กลายเป็นฟังก์ชันได้ง่ายๆ โดยเปิด Advanced Editor แล้วใส่คำว่า (input1, input2)=> นำหน้า code เดิม

    ซึ่งมันจะเปลี่ยน Query นั้นให้กลายเป็นฟังก์ชันที่มี input 2 ตัวคือ input1 กับ input2 ทันที แต่ข้อเสียคือถ้าจะแก้ต้องมาแก้ใน Advanced Editor ไม่สามารถมี User Interface ง่ายๆ ให้แก้อีกแล้ว

    ในบทความนี้ผมก็เลยจะมาแชร์วิธีสร้าง Function อีกวิธีนึงซึ่งยังสามารถทำให้เราแก้ไขได้ง่ายๆ โดยใช้ User Interface ได้อยู่ โดยที่ผมเห็นวิธีนี้ครั้งแรกมาจากคุณโบแห่ง Excel Wizard ที่ไปตอบในคลิปของ อ. Mike แห่ง Excel is fun

    ผมเห็นว่ามันเป็นประโยชน์มาก เลยขออนุญาตนำเทคนิคนี้มาถ่ายทอดอีกที แต่มีการดัดแปลงเล็กน้อยให้เข้าใจง่ายขึ้น (ล่ะมั๊ง) นะครับ 555

    วิธีใช้ Function Query แบบแก้ไขได้

    หลักการมี 4 ขั้นตอน คือ

    1. สร้าง New Parameter ขึ้นมา โดยจะสร้างกี่ตัวก็ได้ สมมติชื่อ Para1, Para2
    2. เอา Parameter จากข้อ 1 ไปเรียกใช้ใน Query ที่ต้องการจะให้เป็นต้นแบบ (อันนี้ต้อง Manual แก้สูตรนิดนึง) สมมติชื่อ StepQuery ซึ่ง Function ของเราจะทำ Step ตาม Query ตัวนี้เลย
    3. สร้างฟังก์ชัน โดยกดคลิ๊กขวา ที่ StepQuery แล้ว Create Function แล้วตั้งชื่อฟังก์ชันอะไรก็ได้
    4. นำฟังก์ชันไปใช้งาน เช่นเอาไปใช้ใน Query หลัก อาจใช้ผ่าน Invoke Custom Function ก็ได้ง่ายดี

    ซึ่งแบบที่เข้าใจง่ายที่สุดก็คือ Parameter ที่เป็นพวกค่าเดี่ยวๆ เช่น ตัวเลข หรือ ข้อความ เป็นต้น

    ตัวอย่างของการใช้ Parameter แบบนี้แล้วมีประโยชน์มากก็คือ การดึงข้อมูลจากเว็บไซต์ต่างๆ โดยเปลี่ยน URL ไปเรื่อยๆ เช่น การดึงข้อมูลหุ้น เป็นต้น

    ตัวอย่างการสร้าง Function ดึงข้อมูลหุ้นจาก symbol ที่ต้องการ

    สมมติผมต้องการข้อมูลจากเว็บหน้านี้ https://www.set.or.th/set/companyhighlight.do?symbol=SCC

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 130

    ผมก็สามารถสั่ง Get Data From Web ได้ โดยเลือกว่าจะดูด table ในรูป

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 131

    ที่นี้มันจะดูดข้อมูลเข้า Power Query เฉพาะ Symbol นี้อันเดียว

    ให้เปลี่ยนชื่อ Query เป็น StepQuery ซะ เพราะตารางนี้แหละที่เราจะใช้เป็นแม่เแบบของการ Transform Data ซึ่งเราจะ Transform ข้อมูลให้เสร็จไปเลยก็ได้ แต่ผมยังไม่ทำ เพราะไปทีหลังได้

    1. สร้าง Parameter

    ทีนี้ให้เราสร้าง Parameter ขึ้นมา โดยกด Manage Parameter แล้ว New แล้วตั้งชื่อว่า StockSymbol จากนั้นเลือก Type เป็น Text เพราะว่า Parameter นี้คือข้อความ จากนั้นใส่ Current Value เป็น SCC ไปก่อน เพื่อจะได้ดึงค่าจากหุ้น SCC ได้

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 132

    2.เอา Parameter ไปใช้ใน Step Query

    กดตามรูป แล้วไปแก้สูตรของ Source ซะ ให้เปลี่ยนจากข้อความว่า SCC เป็น Parameter ที่ชื่อว่า StockSymbol แทน ซึ่งเชื่อมด้วยเครื่องหมาย &

    = Web.Page(Web.Contents("https://www.set.or.th/set/companyhighlight.do?symbol="&StockSymbol))
    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 133

    พอลองกดกลับมาดู Step หลังๆ ก็ควรจะต้องเห็นว่ายังใช้งานได้อยู่เหมือนเดิม

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 134

    3.สร้างฟังก์ชัน

    จากนั้นคลิ๊กขวาที StepQuery แล้วกด Create Function

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 135

    จากนั้นตั้งชื่อตามใจชอบเช่น GetStockData แล้วกด ok

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 136

    มันจะสร้างฟังก์ชันแล้วผูก Query ให้เราโดยอัตโนมัติ

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 137

    4.นำฟังก์ชันไปใช้งาน

    ทีนี้เราจะลองใช้งานเพื่อดูดหุ้นซัก 5-6 ตัว แต่เนื่องจากเรายังไม่มี List รายชื่อหุ้นเลย ดังนั้นเดี๋ยวไปสร้าง List รายชื่อหุ้นก่อน ซึ่งเราจะสร้างใน Excel ไฟล์นี้แหละ

    ดังนั้นก่อนอื่นให้เรา Close & Load To… -> Only Create Connection เพื่อออกไปยัง Excel ก่อน (ไม่งั้นมันไม่ให้ออกไปสร้าง)

    ให้เราใส่ Data ลงไปตามต้องการ แล้วกดสร้าง Table ชื่อ StockList ซะ

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 138

    จากนั้นกด Get Data From Table/Range เพื่อเอาเข้า Power Query

    จากนั้นกด Add Column -> Invoke Custom Function เพื่อเรียกใช้ฟังก์ชันที่เราสร้างขึ้นมา

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 139

    มันอาจจะมีขึ้นมาเตือนเรื่อง Data Privacy เพราะมีการดึงข้อมูลจาก Local ผสมกับจากแหล่งออนไลน์ ก็ให้กด Continue ไป

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 140

    จุดนี้ถ้าไม่คิดอะไรมาก ติ๊ก Ignore Privacy Level ก็ได้ (มันก็จะไม่แคร์เรื่องข้อมูลรั่วไหลอะไรเลย)

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 141

    จากนั้นมันก็จะดึงข้อมูล Symbol ทุกตัวออกมาเป็น Table ดังรูป เมื่อคลิ๊กแต่ละช่องที่เป็น Table เราก็จะเห็นไส้ในของ Table นั้น

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 142

    ถ้าเรากด Expand ที่มุมขวาบนของคอลัมน์ มันก็จะเอาทุก Table มา Append ต่อแถวกันโดยอัตโนมัติ โดยการ Append ก็จะยึดจากชื่อคอลัมน์ที่เป็นหัวตารางเป็นหลัก

    แต่เนื่องจากหัวตารางไส้ในของเรายังไม่ ok ดังนั้นเราจะกลับไปแก้ StepQuery ให้เรียบร้อยก่อน

    กลับไปแก้ StepQuery (เพราะเราข้ามมา)

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 143

    เอาล่ะ เรากดย้อนหลับมายัง StepQuery เพื่อจัดการตารางให้เรียบร้อยกัน

    ก่อนอื่นจะ Filter เอาบรรทัดที่ไม่เกี่ยวข้องออก นั่นก็คือคอลัมน์แรกจะเอาตัวที่มีคำว่า “สำคัญ” ออกไปซะ

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 144

    ให้ Transpose ตารางลงมาก่อน

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 145

    แล้ว Use First Row as Header ซะ แต่จะลบ Step Change Type ออกเพื่อไม่ให้มันระบุชื่อหัวตารางในสูตร

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 146

    จากนั้นเราอยากใส่ลำดับปีเป็น Y-4, Y-3, Y-2, Y-1, Y-0 ดังนั้นจะกด Add Index Column ใหม่แบบ Custom

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 147

    จากนั้นจะได้เลขเรียง 4,3,2,1,0 ออกมา

    แต่คราวนี้เราจะใส่คำว่า Y- ไว้ข้างหน้า ก็ไปที่ Transform -> Format-> Add Prefix

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 148

    ก็จะได้ผลลัพธ์ตามต้องการ

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 149

    กลับไปดูผลที่ Query หลัก (หลังจากแก้ StepQuery)

    เมื่อกดกลับไปดูที่ StockList ซึ่งเป็น Query หลักของเรา จะเห็นว่าที่เราไปแก้ใน StepQuery นั้นได้สะท้อนออกมายัง Query หลักแล้ว

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 150

    คราวนี้เราก็ Expand ข้อมูลได้อย่างสบายใจแล้ว

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 151

    แค่นี้เราก็จะได้ข้อมูลจากทุก Symbol มารวมกันแล้วครับ

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 152

    ถ้าใครไม่อยากให้ตอน Expand มันระบุชื่อคอลัมน์ ก็สามารถทำตาม Tips ของบทความนี้ได้ เพื่อให้มันอ่านหัวคอลัมน์ใหม่ได้ตลอด

    เช่น เราจะแก้สูตรเป็น

    = Table.ExpandTableColumn(#"Invoked Custom Function", "GetStockData", List.Union(List.Transform(#"Invoked Custom Function"[GetStockData],each Table.ColumnNames(_))))

    ผลลัพธ์ที่ได้จะเหมือนเดิม แต่จะยืดหยุ่นขึ้นกรณีที่ในอนาคตอาจจะมี Field เพิ่มก็จะเห็นทันที

    4 ขั้นตอนในการสร้าง Function Query แบบที่มี UI ให้แก้เล่นได้ใน Power Query 153

    ต่อจากนี้จะเปลี่ยน Datatype ตัวไหนยังไงก็แล้วแต่เลยครับ ผมขอไม่ทำให้ดูแล้วนะ ^^

    ตอนต่อไปคืออะไร?

    ในบทความตอนถัดไป จะเป็นวิธีสร้างฟังก์ชันคล้ายๆ แบบบทความนี้ แต่สร้าง Parameter เป็น Any แทนที่จะเป็น Parameter แค่ Text ธรรมดา เพื่อให้ดึงข้อมูลจาก Table ที่ต้องการได้ ซึ่งจะยากขึ้นอีกเล็กน้อยครับ

    ซึ่งแบบหลังนี้แหละที่คุณโบ Excel Wizard ทำให้ดูในคลิป Excel is fun แต่ถ้าให้ผมอธิบายวิธีนั้นเลย น่าจะงงแน่นอน เลยต้องสอนแบบง่ายก่อนนะ

    แล้วพบกันในตอนต่อไปครับ รับรองว่าเจ๋งมากๆ อีกแล้ววว

  • Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX

    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX

    ในบทความนี้ผมจะมาพูดถึงฟังก์ชัน CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX ที่ถูกออกแบบมาให้ทำหน้าที่ “เปลี่ยน Filter Context” โดยเฉพาะ

    CALCULATE เป็นฟังก์ชันที่หน้าตาดูเรียบง่าย เหมือนไม่มีอะไร แต่ทรงพลังมากๆ ผมว่ามันเทียบได้กับตัวการ์ตูนเอกในเรื่อง One Punch Man ที่ชื่อไซตามะเลยครับ หน้าตาดูไม่เก่งอะไรเลย แต่ต่อยทีเดียวศัตรูตายหมด ดังนั้นอย่าดูถูก CALCULATE เด็ดขาด!!

    ผมกล้าพูดได้เลยว่าใครที่ใช้ Power BI แต่ไม่รู้จัก CALCULATE ก็เหมือนกับยังใช้ Power BI ไม่เป็นอ่ะครับ ดังนั้นมันสำคัญจริงๆ

    บอกเลยว่าตั้งแต่บทนี้ไปเนื้อหาจะเริ่มลึกซึ้งมากขึ้นๆ ดังนั้นความรู้เดิมควรจะแน่นก่อน และควรมีสมาธิในการอ่านดีๆ นะครับ อ่านผ่านๆ ไม่คิดตาม ไม่เข้าใจแน่นอน

    ไฟล์ประกอบ

    ใช้ไฟล์เดิมจากตอนก่อนหน้าได้เลยนะครับ หรือจะใช้อันนี้ก็ได้

    เอาล่ะเราไปเริ่มกันเลย!

    Recap เล็กน้อย

    ความหมายของการเปลี่ยน Filter Context ก็จะคล้ายๆ กับในบทความตอนก่อนหน้านี้ที่ ผมได้พยายามเขียนสูตร ALL เพื่อปลด Filter Context เดิมออกแล้ว Filter สินค้าที่เป็น Class ระดับ Economy เข้าไปอีกที ด้วยสูตรว่า

    FilterEconomyRevenue =
    SUMX (
        FILTER ( ALL ( fSales ), RELATED ( dProduct[ClassName] ) = "Economy" ),
        fSales[SalesQuantity] * RELATED ( dProduct[UnitPrice] )
    )
    

    ถ้าหากเราใช้ CALCULATE ทำ เราสามารถเขียนสูตรสั้นๆ เหลือแค่นี้

    CalculateEconomyRevenue = 
    CALCULATE([TotalRevenue],dProduct[ClassName]="Economy")
    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 154

    จะเห็นว่า CALCULATE นั้นสามารถใช้สูตรที่ทั้งสั้นกว่า และดูน่าจะอ่านเข้าใจง่ายกว่าสูตรยาวๆ นั้นด้วย ดังนั้นเรามาดูกันดีกว่าว่า CALCULATE มีวิธีการใช้งานยังไงกันแน่

    ทำความเข้าใจ CALCULATE

    CALCULATE ( <Expression> , [<Filter1>] , [<Filter2>] , ... )

    CALCULATE นั้นประกอบไปด้วย 2 ส่วนหลักๆ ก็คือ

    • Expression หรือก็คือวิธีการคำนวณ เราจะใส่สูตรคำนวณเอาเองหรือจะอ้างอิง Measure ที่มีอยู่แล้วก็ได้
    • Filter คือ Filter Context ใหม่ที่อยากได้ สามารถใส่ได้หลายตัวโดยคั่นด้วย comma ซึ่งจะเป็นเงื่อนไขแบบ AND
      • สามารถใส่เป็นเงื่อนไขเปรียบเทียบคล้ายๆ กับเงื่อนไขในฟังก์ชัน FILTER ได้เลย
        • เช่น Field เทียบกับค่าอะไรบางอย่าง
        • ซึ่งความหมายคือจะมีการปลด Filter เดิมของ Field นั้นออกด้วย ALL แล้วค่อยใส่ Filter ใหม่ตามที่เราระบุ
      • ความพิเศษคือสามารถอ้างอิง Field จากตารางไหนก็ได้ โดยไม่ต้องใช้ RELATED มาช่วยเลย

    หมายเหตุ : CALCULATE จะประเมิน Filter ก่อน Expression เสมอ

    ฟังดูแล้วอาจจะยังงงๆ งั้นมาดูคำอธิบายของตัวอย่างข้างบนกัน

    CalculateEconomyRevenue = CALCULATE([TotalRevenue],dProduct[ClassName]="Economy")
    • Expression เขียนว่า [TotalRevenue] นั่นคือให้ใช้สูตรวิธีคำนวณของ Measure ที่ชื่อว่า [TotalRevenue] มาคำนวณ
    • Filter เขียนว่า dProduct[ClassName]=”Economy” ความหมายคือ ให้สั่งปลด Filter ของ Field dProduct[ClassName] ออกก่อนด้วย ALL จากนั้นค่อย Filter dProduct[ClassName] ให้เป็น Economy อีกที

    ก่อนจะมีการใช้ CALCULATE

    Total Revenue จะถูก Filter ตามแต่ละ ClassName อย่างที่ผมเคยอธิบายไปในบทแรกๆ ว่าแต่ละจุดของตาราง Pivot นั้นมี Filter Context ที่ไม่เหมือนกันเลย

    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 155

    หลังจากใช้ CALCULATE

    มันปลด Filter ของ ClassName ออกหมด แล้ว Filter เข้าไปใหม่ด้วย ClassName ว่าต้องเท่ากับ Economy ทุกตัวเลยได้ค่าเดียวกันหมดเลยดังรูป

    CALCULATE

    สรุปสั้นๆ นะ

    “CALCULATE จะเปลี่ยน Filter ตามเงื่อนไขที่ระบุ แล้วค่อยคำนวณตามวิธีที่เราระบุ

    โดยที่ถ้าใสเงื่อนไขแบบปกติมาตรฐาน เช่น Field เทียบกับค่าอะไรบางอย่าง มันก็จะปลด Filter เดิมของ Field นั้นๆ ออกไป แล้วค่อยใส่ Filter ใหม่ตามที่เราระบุในส่วน Filter ของ CALCULATE

    จากคำอธิบายข้างบน จริงๆ แล้วสูตร CALCULATE ข้างบน มันคือการเขียนโดยย่อของการเขียนแบบนี้เลยครับ เทียบเท่ากันทุกประการ!!

    CalculateEconomyRevenueFull =
    CALCULATE (
        [TotalRevenue],
        FILTER ( ALL ( dProduct[ClassName] ), dProduct[ClassName] = "Economy" )
    )
    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 156

    ดังนั้นแปลว่า ถ้าผมใส่ Filter ตัวอื่นที่ไม่เคยถูก Filter มาก่อน เช่น StoreType ด้วยสูตรนี้ว่าต้องการ StoreType แบบ Online เท่านั้น

    CalculateOnlineRevenue = 
    CALCULATE([TotalRevenue],dStores[StoreType]="online")

    การทำงานก็ยังคงเป็น Concept เดิม คือ ปลด Filter ด้วย ALL แล้ว Filter เข้าไปด้วยตัวใหม่ที่ระบุ

    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 157

    ผลที่ได้ก็จะเป็นการ Filter เพิ่มจากตัว [TotalRevenue] ปกติ เนื่องจากปลด Filter dStores[StoreType] ก็ไม่ได้มีผลอะไร (เพราะไม่ได้มี Filter ไว้อยู่แล้ว) จากนั้นค่อย Filter dStores[StoreType] ให้เป็น Online

    ทั้งนี้มันต่างจากตอนแรกที่เราสั่ง dProduct[ClassName] = “Economy” ในแง่ที่ว่าอันนั้นการปลด Filter ออกจะเห็นผลที่ชัดเจนเลย เพราะถ้าไม่ปลดออก กรณี Class Name ใน Visual ไม่ใช่ Economy จะต้องได้ค่า Blank เนื่องจาก ไม่มีทางที่จะเป็น Class Name 2 อย่างได้พร้อมกันอยู่แล้ว

    CALCULATE หลายเงื่อนไข

    เงื่อนไขแบบ AND

    ถ้าเราใส่ Filter สองเงื่อนไขคั่นด้วย comma มันจะเป็นเงื่อนไขแบบ AND เลย จะเป็นยังไงมาดูกันครับ

    CalculateOnlineEconomyRevenue =
    CALCULATE (
        [TotalRevenue],
        dProduct[ClassName] = "Economy",
        dStores[StoreType] = "online"
    )
    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 158

    ผลที่ได้จะเป็นการปลด Filter ClassName และ StoreType ออกทั้งหมด และสั่งให้ Filter ClassName เป็น Economy และ StoreType เป็น online นั่นเอง

    และถ้าจะเป็นเงื่อนไขแบบ OR ล่ะ?

    OR Field เดียวกัน ไม่มีปัญหา

    ถ้าเป็นเงื่อนไขแบบ OR แบบอ้างอิง Field เดียวกันเรายังพอใช้เครื่องหมาย || หรือพวก IN มาช่วยได้ดังนี้

    CalculateEconomyRegular =
    CALCULATE (
        [TotalRevenue],
        dProduct[ClassName] = "Economy"
            || dProduct[ClassName] = "Regular"
    )

    หรือ

    CalculateEconomyRegular =
    CALCULATE ( [TotalRevenue], dProduct[ClassName] IN { "Economy", "Regular" } )
    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 159

    OR คนละ Field เริ่มยากละ

    แต่ถ้าเราจะอ้างอิง Field คนละ Field กันแบบ OR มันจะไม่ยอม เช่น

    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 160

    ดังนั้นเราจะใช้ CALCULATE เปล่าๆ ไม่ได้แล้ว ต้องใช้ฟังก์ชันอื่นมาช่วย นั่นก็คือ FILTER กับ ALL มาช่วยนั่นเอง เช่น

    CalculateEconomy_or_Online =
    CALCULATE (
        [TotalRevenue],
        FILTER (
            ALL ( fSales ),
            RELATED ( dProduct[ClassName] ) = "Economy"
                || RELATED ( dStores[StoreType] ) = "online"
        )
    )
    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 161

    สูตรยากกว่า CALCULATE สำเร็จรูปเยอะเลยเนอะ…

    ซึ่งจะเห็นว่าในบางสถานการณ์ ความรู้เรื่อง FILTER และ ALL ที่ผมสอนในบทก่อนๆ ก็จำเป็น ไม่งั้นเราจะเขียนสูตรบางอย่างไม่ได้เลย เพราะ CALCULATE สำเร็จรูปไม่ได้รองรับทุกอย่างไปหมดหรอกครับ

    เราน่าจะพอเห็นภาพการทำงานของ CALCULATE กันแล้ว คราวนี้ลองมาดูกันว่าถ้าใส่ CALCULATE ซ้อนกันจะเกิดอะไรขึ้น

    CALCULATE ซ้อนกัน

    สมมติผมเขียน Measure แบบนี้ ให้ทายว่ามันจะเปลี่ยน Filter ให้กลายเป็นแบบไหน?

    Calculate2X =
    CALCULATE (
        CALCULATE (
            [TotalRevenue],
            dProduct[ClassName] = "Economy",
            dStores[StoreType] = "online"
        ),
        dProduct[ClassName] = "Regular"
    )

    ถ้าดูเผินๆ คนทั่วไปน่าจะคิดว่า มันน่าจะได้เป็น Online และ Regular แต่ในความเป็นจริง Filter ที่หลงเหลือกลับได้เป็น Online และ Economy เหมือนเดิม!!

    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 162

    ทำไมถึงเป็นแบบนั้น? ทั้งๆ ที่การเขียนสูตร 2 ชั้นซ้อนกันมันต้องคำนวณตัวข้างในก่อนสิ ?

    การเขียนสูตร 2 ชั้นจะคำนวณตัวในก่อนนั้นถูกต้องแล้วครับ แต่สาเหตุที่ผลลัพธ์เป็นแบบนี้ก็เพราะ CALCULATE จะประเมิน Filter ก่อน Expression เสมอครับ

    มาดูกันให้ชัดๆ ว่าเกิดอะไรขึ้น

    Calculate2X =
    CALCULATE (
    CALCULATE (
    [TotalRevenue],
    dProduct[ClassName] = "Economy",
    dStores[StoreType] = "online"
    ),
    dProduct[ClassName] = "Regular"
    )

    CALCULATE ตัวข้างใน (สีแดง) จะถูกคำนวณก่อน ซึ่งเดี๋ยวมันจะต้องคิดว่าจะต้องเปลี่ยน Filter ยังไงดี ทำให้มันต้องปลด Filter ClassName และ StoreType ออกให้หมดก่อน ทำให้ dProduct[ClassName] = “Regular” ที่อยู่ในชั้นนอกถูกทำลายไปโดยปริยาย

    จากนั้นมันค่อยใส่ Filter ไปใหม่ว่า ClassName ให้เป็น Economy และ StoreType เป็น online นั่นเอง

    กลายเป็นว่า เวลาใช้ CALCULATE ซ้อนกันหลายชั้น ชั้นในดันได้รับ Priority เรื่อง Filter มากว่านั่นเอง และจะทำลายชั้นนอกตัวที่ซ้ำกันด้านในทิ้งหมดเลย

    เดี๋ยวลองเขียนเงื่อนไขชั้นนอกอีกอันแบบไม่ซ้ำกับข้างในบ้าง

    Calculate2X_v2 =
    CALCULATE (
        CALCULATE (
            [TotalRevenue],
            dProduct[ClassName] = "Economy",
            dStores[StoreType] = "online"
        ),
        dProduct[ClassName] = "Regular",
        dDate[Year] = 2012
    )
    Power BI ตอนที่ 13: CALCULATE ฟังก์ชันที่ทรงพลังที่สุดใน DAX 163

    จะเห็นว่า Filter ที่หลงเหลือก็คือ Online และ Economy และ ปี 2012 เพราะว่าเลขลดลงไปกว่า 2x ปกติ ดังนั้นจะเห็นว่า เงื่อนไข Filter ของ CALCULATE ชั้นนอกไม่ได้ถูกทำลายไปทั้งหมด แต่ถูกทำลายเฉพาะตัวที่ซ้ำกับด้านในเท่านั้น

    หลายคนอาจเริ่มสงสัยแล้วว่า “ในชีวิตจริงใครจะไปเขียน CALCULATE 2 ตัวซ้อนกัน งงจะตายชัก??”

    ครับ มันไม่มีใครตั้งใจเขียนแบบนั้นหรอก แต่เป็นเพราะความลับอีก 2 อย่างต่อจากนี้ต่างหากที่ทำให้เราต้องระวังเรื่องนี้ นั่นก็คือ…

    • CALCULATE สามารถเปลี่ยน Row Context ให้เป็น Filter Context ได้ เรียกว่า Context Transition
    • Measure ทุกตัวมี CALCULATE แฝงอยู่ข้างในเสมอ

    ซึ่งเดี๋ยวผมจะพูดถึง 2 เรื่องนี้ในบทถัดไปครับ ซึ่งบอกเลยว่าเป็น Concept ของ CALCULATE ที่ลึกลับซับซ้อนที่สุดที่คนส่วนใหญ่ล้วนงงไปตามๆ กันเลยล่ะ!!

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน

    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน

    เรื่องของ Table Function ใน DAX นอกจาก FILTER ที่แนะนำไปในบทความที่แล้ว ยังมีที่เราควรจะรู้จักอีก 3 ตัว ก็คือ DISTINCT, VALUES, ALL (และเพื่อนๆ ของมัน)

    เนื่องจากทั้ง 3 ตัวนี้ทำงานคล้ายกันๆ แต่ไม่เหมือนกัน… ดูเผินๆ แล้วจะสับสนได้
    ผมจึงขอทำตารางเปรียบเทียบดังนี้

    ฟังก์ชันรองรับ Table/Col ที่เป็นสูตร (Expression)กรณีใช้กับ Tableกรณีใช้กับคอลัมน์เดียวกรณีใช้กับหลายคอลัมน์
    DISTINCTได้•ได้ Table แบบค่าที่ไม่ซ้ำกัน•ได้ค่าไม่ซ้ำกันในคอลัมน์นั้นทำไม่ได้
    VALUESไม่ได้•ค่า Duplicates ยังอยู่
    •ได้ Blank Row พิเศษ
    •ได้ค่าไม่ซ้ำกันในคอลัมน์นั้น
    •ได้ Blank Row
    พิเศษ
    ทำไม่ได้
    ALLไม่ได้•ค่า Duplicates ยังอยู่
    •ได้ Blank Row พิเศษ
    •เห็นทุกค่าเสมอ
    •ได้ค่าไม่ซ้ำกันในคอลัมน์นั้น
    •ได้ Blank Row พิเศษ
    •เห็นทุกค่าเสมอ
    •ได้ค่าไม่ซ้ำกันเมื่อมองผสมหลายคอลัมน์
    •ได้ Blank Row พิเศษ •เห็นทุกค่าเสมอ

    หมายเหตุ

    • Blank Row พิเศษ จะโผล่มากรณีที่ Relationship ไปเจอข้อมูลเป็น Key ในฝั่ง Many แต่ดันไม่มีใน Key ฝั่ง One (จะมีอธิบายในบทความด้านล่าง)
    • ALLSELECTED = เหมือน All แต่ปลดแค่ Filter ใน Visual นั้นๆ

    ไฟล์ประกอบ

    ใช้ไฟล์เดิมจากตอนก่อนหน้าได้เลยนะครับ หรือจะใช้อันนี้ก็ได้

    สร้าง New Table ใหม่

    เพื่อให้เห็นภาพมากขึ้น เดี๋ยวเราจะสร้างตารางใหม่ที่ชื่อว่า dStoresNew โดยจะเอาให้เหลือเฉพาะ StoreKey ตั้งแต่ 100 ขึ้นไปเท่านั้น (เพื่อตั้งใจสร้างสถานการณ์ให้เจอ Blank Row พิเศษครับ)

    ให้เรา NewTable ขึ้นมาดังนี้

    dStoresNew = FILTER(dStores,dStores[StoreKey]>100)
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 164

    เราจะได้ dStoresNew ที่มี 207 Rows นะครับ

    จากนั้นให้ผูก Relationship กับ Fact ที่เป็น fSales ด้วย

    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 165

    เมื่อเตรียมข้อมูลพร้อมแล้ว มาดูรายละเอียดทีละตัวกันครับ

    DISTINCT

    “จะได้ item แบบไม่ซ้ำกัน”

    DISTINCT ( <ColumnNameOrTableExpr> )

    DISTINCT นั้นจะใช้กับ Table ก็ได้ หรือจะใช้กับ คอลัมน์เดียวก็ได้ จะได้ข้อมูลแบบไม่ซ้ำกัน

    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 166

    *จะเห็นว่า DISTINCT ไม่มี Blank Row พิเศษโผล่ออกมาเหมือนกับ VALUES และ ALL ที่จะแสดงให้เห็นถัดไป

    และสามารถใส่เป็นสูตรได้ด้วย (รองรับ input แบบ Expression) ตัวอย่างเช่น

    DistinctTableExpression = DISTINCT(FILTER(dProduct,dProduct[BrandName]="fabrikam"))
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 167

    VALUES

    มี Blank row พิเศษ โดยถ้าใช้กับคอลัมน์จะได้ item แบบไม่ซ้ำกัน ถ้าใช้กับตารางจะไม่ได้เอาตัวซ้ำออกให้”

    VALUES ( <TableNameOrColumnName> )
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 168

    สังเกตว่าจะได้ Blank Row พิเศษติดมาด้วย ซึ่งจะเกิดขึ้นกรณีที่อีกฝั่งของตารางที่มันอ้างอิง เช่น fSales ดันมี StoreKey ที่ไม่มีในตารางนี้ด้วย (ที่เลข StoreKey <100)

    เจ้า Blank Row พิเศษนี้ถูกสร้างขึ้นมาเพื่อจับคู่กับ key ตัวที่เหลือในฝั่ง fSales ที่หาคู่ใน dStoresNew ไม่ได้นั่นเอง

    ดังนั้นสรุปได้ว่าเวลาใช้งานส่วนใหญ่ จะมองว่าใช้ VALUES กับคอลัมน์จะให้ผลคล้าย DISTINCT แต่ได้ Blank row พิเศษมาด้วย

    และ VALUES ไม่รองรับ Table/Column Expression นะครับ ให้ input เป็นสูตรไม่ได้เลย มันจะไม่ยอม

    ALL

    ALL เป็นตัวที่ผมอยากลงรายละเอียดมากที่สุด เพราะเราจะได้เจอมันค่อนข้างบ่อยเลย

    “การทำงานเหมือน VALUES แต่จะมองเห็นครบทุกค่าเสมอ นอกจากนี้ยังอ้างอิงคอลัมน์อันเดียว หรือ หลายๆ อันก็ได้ (แต่ต้องตารางเดียวกัน)”

    กรณีอ้างอิงทั้งตาราง

    “จะเห็นครบทุกค่า ถ้าใช้กับตารางจะไม่ได้เอาตัวซ้ำออก และก็มี Blank row พิเศษ

    ALL ( TableName )

    เช่น

    AllTable1 = ALL ( dStoresNew )
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 169

    Tips: สังเกตว่า การสร้าง New Table ถือว่าได้ตารางดิบอันใหม่มาเลย จะใช้ ALL ปลด Filter ที่เป็นตัวสร้าง dStoresNew ไม่ได้นะครับ ดังนั้น StoreKey ก็ยังคงมีเฉพาะตั้งแต่เลข 100 อยู่ดี

    กรณีอ้างอิงคอลัมน์ ไม่ว่าจะอันเดียวหรือหลายคอลัมน์

    “จะปลด Filter ออก และได้ combination ที่ไม่ซ้ำกัน แต่มี Blank row พิเศษ

    ALL ( TableName[ColName1])

    ใช้กับคอลัมน์จะได้ Blank Row พิเศษติดมาด้วยเช่นกัน

    All_1Col = ALL(dStoresNew[ContinentName])
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 170
    ALL ( TableName[ColName1], TableName[ColName2] , TableName[ColName3] )

    และถ้าเราใช้ ALL อ้างอิงที่ระดับคอลัมน์ เราจะได้ Combination ของคอลัมน์นั้นๆ แบบไม่ซ้ำกันด้วย แต่ก็จะได้ Blank Row พิเศษติดมาด้วยเช่นกัน

    AllMultiColumn = 
    ALL(dStoresNew[StoreType],dStoresNew[ContinentName],dStoresNew[RegionCountryName])
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 171

    ALLEXCEPT ก็คือเพื่อนของ ALL

    สมมติว่าตาราง MiniTable มีคอลัมน์ชื่อ A,B,C,D,E,F แล้วเราอยากจะปลด FILTER และเลือก combination ทุกคอลัมน์ยกเว้น E กับ F เราสามารถเขียนได้ 2 แบบ คือ

    =ALL(MiniTable[A],MiniTable[B],MiniTable[C],MiniTable[D])

    หรือจะเขียนกลับด้านกันว่าปลดทุกอย่าง ยกเว้น E กับ F ก็ได้ และนั่นคือที่มาของ ALLEXCEPT

    =ALLEXCEPT(MiniTable,MiniTable[E],MiniTable[F])

    จุดเด่นที่สุดของ ALL คือการปลด Filter

    สมมติว่าตารางที่ ALL อ้างอิงอยู่ มีการใส่ Filter เอาไว้ เช่น ใน Report

    จะเห็นว่า ผมสร้าง Measure ตัวใหม่ขึ้นมาคือ AllRevenue โดยเขียนสูตรเหมือน TotalRevenue ทุกอย่างเลย ยกเว้นใส่คำว่า ALL(fSales) แทน fSales เฉยๆ

    TotalRevenue = SUMX(fSales,fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))
    AllRevenue = SUMX(ALL(fSales),fSales[SalesQuantity]* RELATED(dProduct[UnitPrice]))

    ส่งผลให้ผลลัพธ์ที่ได้ ไม่ได้ถูก Filter จากตัวใดๆ เลย (ค่าเลยได้เท่ากับ Total แบบรวมทั้งหมด)

    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 172

    แม้ว่าเรา Filter ปี 2012 เข้าไปด้วย AllRevenue ก็ยังคงไม่เปลี่ยน แต่ TotalRevenue ถูก Filter ได้

    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 173

    หากอยากให้ปลด Filter ออกแค่ใน Visual นั้นๆ ให้ใช้ ALLSELECT แทน ALL ได้ครับ

    AllSelectRevenue = SUMX(ALLSELECTED(fSales),fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 174

    พอคำนวณค่าเหล่านี้ได้ เราจะสร้าง Ratio คล้ายๆ ในบทความที่แล้วก็ได้ครับ แต่อันนี้จะได้เป็น %เทียบกับยอดรวม แต่จะมีความยืดหยุ่นกว่ากด % of Total ธรรมดาๆ เพราะเราสามารถปลด FILTER ออกแบบไหนก็ได้ตามที่ต้องการ ไม่ใช่แค่ปลดที่ตัวที่อยู่ใน Visual อย่างเดียวเหมือนเครื่องมือสำเร็จรูป

    และรูปแบบนึงที่อาจเกิดขึ้นได้ก็คือการปลด Filter ออก แล้ว Filter อีกตัวกลับเข้าไปใหม่

    ตัวอย่างการปลด FILTER ออก แล้ว FILTER อีกตัวกลับเข้าไปใหม่

    เช่น ถ้าเราอยากได้ยอด Revenue ของ Class Economy การ FILTER class=”economy” ลงไปเฉยๆ

    FilterEconomyRevenue = SUMX(FILTER(fSales,RELATED(dProduct[ClassName])="economy"), fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 175

    ผลลัพธ์จะเท่ากับเป็นการ Filter เพิ่มลงไปแบบ AND ใน Filter Context เดิม ทำให้กรณีที่ Row Label มี Class เป็นตัวอื่น เช่น Deluxe จะหลายเป็น Deluxe และ Economy ซึ่งเป็นไปไม่ได้ จึงไม่เหลือผลลัพธ์จากการ Filter เลย

    ดังนั้นถ้าอยากจะได้ Economy Revenue ทุกช่อง จะต้องมีการใช้ ALL มาช่วยปลด Filter ออกไปซะดังนี้

    FilterEconomyRevenue = SUMX(FILTER(ALL(fSales),RELATED(dProduct[ClassName])="economy"), fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))
    Power BI ตอนที่ 12: DISTINCT, VALUES, ALL และผองเพื่อน 176

    เราถึงจะได้ผลลัพธ์ที่ปลด Filter ตาราง fSales ออกให้หมดก่อน จากนั้นค่อย FILTER ให้มี Class เป็น economy อีกทีนึง

    ลักษณะการปลด Filter ออกแล้วใส่ Filter ใหม่ลงไป เรียกได้อีกอย่างว่าเป็นการ “เปลี่ยน Filter Context” ซึ่งเป็นสิ่งที่ต้องทำบ่อยมากในการทำ Report Power BI เจ๋งๆ และมันคือหน้าที่หลักของสุดยอดฟังก์ชันที่ชื่อว่า CALCULATE ซึ่งจริงๆ ฝังความสามารถของ FILTER และ ALL อยู่ข้างในตัวมันเองอีกด้วย!!

    ตอนต่อไปเจอกับ CALCULATE

    CALCULATE ถือได้ว่าเป็นฟังก์ชันที่ลึกลับซับซ้อนและทรงพลังที่สุดอันนึงใน DAX เลยล่ะ ซึ่งเราจะได้เรียนเจ้า CALCULATE นี้ในบทถัดไปแล้วครับ ^^

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • Power BI ตอนที่ 11: เรียนรู้ DAX Table Function – FILTER

    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function – FILTER

    ในซีรีส์ Power BI บทก่อนหน้านี้เราได้เรียนรู้จักสูตร DAX พื้นฐานกันไปแล้ว คราวนี้เรามารู้จักฟังก์ชันกลุ่ม Table Function เพิ่มเติม นั่นก็คือ FILTER, DISTINCT, VALUES, ALL ซึ่งจะช่วยให้เราสามารถเขียนสูตร DAX ที่ซับซ้อนได้มากขึ้นในอนาคตนั่นเอง

    แต่เพื่อไม่ให้มันเยอะเกินไป เดี๋ยวบทความนี้ผมจะพูดถึง FILTER แค่ตัวเดียวก่อน ส่วน ALL, DISTINCT, VALUES และผองเพื่อน จะพูดในตอนถัดไปนะครับ

    ไฟล์ประกอบ

    ใช้ไฟล์เดิมที่ทำมาจากตอนก่อนหน้าได้เลยนะครับ หรือจะใช้อันนี้ก็ได้

    Table Function คืออะไร?

    คำว่า Table Function ก็คือ ฟังก์ชันที่ให้ผลลัพธ์กลับมาเป็น Table หรือตารางนั่นเอง ต้องบอกว่าฟังก์ชันปกติที่เราคุ้นเคยกันก่อนหน้านี้ทุกอัน จะให้คำตอบออกมาเป็นค่าเดียว (เรียกว่า Scalar Value) ไม่ว่าจะเป็นประเภทตัวเลข ตัวหนังสือ logic ก็ตาม ก็จะมีค่าเดียวมาโดยตลอด

    แต่เจ้า Table Function ไม่ใช่แบบนั้น มันดันให้ผลลัพธ์กลับมาเป็นตารางเลย เรามาทำความรู้จักมันทีละตัวกันครับ

    FILTER

    ซึ่งตัวที่น่าจะเห็นหน้าตาเป็นตารางได้ชัดเจนที่สุดก็คือ เจ้า FILTER นี่แหละ เพราะมันจะให้ผลลัพธ์เป็นตารางที่ผ่านการคัดกรองจนเหลือสิ่งที่ต้องการแล้วนั่นเอง (คล้ายๆ กับ FILTER ซึ่งเป็นฟังก์ชันของ Excel 365 เลยเนอะ แต่มันเป็นคนละตัวกันนะครับ อันที่สอนในบทความนี้คือใน DAX)

    วิธีการใช้งานคือ

    FILTER ( <Table>, <FilterExpression> )

    โดยที่ <Table> ก็คือตาราง Original ซึ่งจะเป็นแค่การใส่ชื่อตารางธรรมดาๆ หรือ เป็น Table Function ตัวอื่นก็ยังได้

    ส่วน <FilterExpression> ก็คือเงื่อนไขในการคัดกรอง โดยมันจะต้องเขียนสูตรส่วนนี้ให้ได้ผลลัพธ์เป็น TRUE/FALSE เพื่อคัดกรองเอาเฉพาะตัวที่เป็น TRUE มาแสดง

    สมมติว่า ผมอยากจะ Filter ตาราง dProduct ด้วยสูตร ผมสามารถใช้ฟังก์ชัน FILTER นี้ได้เลย และเพื่อให้เห็นผลลัพธ์ชัดเจนที่สุด ผมจะใช้คำสั่ง New Table เพื่อให้มันออกมาเป็นตารางอีกอันนึงชัดๆ เลย

    ผมใส่สูตรว่า

    myTable = FILTER(dProduct,dProduct[UnitPrice]>200)

    แปลว่า ผมเอาตาราง dProduct มา Filter นะ โดยเงื่อนไขคือ dProduct[UnitPrice]>200 ซึ่งแปลว่า คอลัมน์ UnitPrice มีค่ามากกว่า 200 นั่นเอง

    ซึ่งผลลัพธ์ก็จะออกมาเป็น Table ที่มีจำนวนคอลัมน์เท่ากับ dProduct ทุกประการ แค่มีจำนวนแถวลดลง เพราะมีการคัดกรองตามเงื่อนไขใน <FilterExpression>

    dax filter

    ปล. Power BI มีอัปเดทหน้าตา UI ใหม่นิดหน่อยนะ (ให้เหมือน Ribbon ใน Excel มากขึ้น) หน้าตาเลยแปลกไปจากบทความก่อน

    การอ้างอิงคอลัมน์ที่จะ FILTER

    <FilterExpression> ของ FILTER เนี่ยปกติจะสามารถอ้างอิงคอลัมน์ได้เฉพาะจาก Field ที่อยู่ใน <Table> ที่อ้างถึงเท่านั้น แต่ถ้าอยากจะอ้างอิงข้ามตารางต้องใช้ RELATED มาช่วยนะครับ

    ตัวอย่างการใช้ RELATED ใน FILTER

    หากเราต้องการ Filter fSales ให้เหลือรายการเฉพาะที่มาจากช่องทาง online เท่านั้น แม้ว่าจะไม่มี StoreType ให้เลือกในตารางนี้ตรงๆ เราก็ใช้ RELATED ดึงมามาช่วยได้ครับ

    OnlinefSales = FILTER(fSales,RELATED(dStores[StoreType])="online")
    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function - FILTER 177

    แล้วถ้าจะใส่เงื่อนไขมากกว่า 1 อย่างล่ะ?

    ถ้าสังเกตดูจะเห็นว่า input ที่เป็นเงื่อนไขของ FILTER นั้นมีแค่ตัวเดียว แปลว่าเราไม่สามารถคั่นด้วยเครื่องหมาย , ได้แบบ SUMIFS นะ แปลว่าเราจะต้องใช้เงื่อนไขแบบ AND OR มาช่วยแทนนั่นเอง

    เงื่อนไขแบบ AND

    สามารถใช้ฟังก์ชัน AND(เงื่อนไข1,เงื่อนไข2) ได้ แต่ก็จะได้แค่ 2 เงื่อนไขนี่แหละ

    myTable = FILTER(dProduct,
    AND(dProduct[UnitPrice]>200,dProduct[BrandName]="Litware"))

    แปลว่าเอาที่ Unit Price > 200 และ ฺBrandName เป็น Litware

    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function - FILTER 178

    ถ้าจะใช้มากกว่านี้ให้ใช้เครื่องหมาย && มาช่วยแทน
    เช่น เงื่อนไข1 && เงื่อนไข2 && เงื่อนไข3

    myTable = FILTER(dProduct,
    dProduct[UnitPrice]>200 && dProduct[BrandName]="Litware" && dProduct[ClassName]="Deluxe")

    แปลว่าเอาที่ Unit Price > 200 และ ฺBrandName เป็น Litware และ ClassName เป็น Deluxe

    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function - FILTER 179

    Tips : ถ้าอยากจะเขียน FILTER ซ้อนไปอีกชั้น เพื่อทำเงื่อนไขซ้อนกันแบบ AND ก็ย่อมได้นะ เพราะซ้อนไปเรื่อยๆ ก็แปลว่าต้องผ่านทุกเงื่อนไขนั่นแหละ จึงเป็น AND โดยปริยาย แต่ผมว่ามันอ่านยากเปล่าๆ อย่าทำเลย

    เงื่อนไขแบบ OR

    สามารถใช้ฟังก์ชัน OR(เงื่อนไข1,เงื่อนไข2) ได้ แต่ก็จะได้แค่ 2 เงื่อนไขเช่นกัน

    myTable = FILTER(dProduct,
    OR(dProduct[UnitPrice]>1000, dProduct[BrandName]="Litware"))

    แปลว่าเอาที่ Unit Price > 1000 หรือ BrandName เป็น Litware

    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function - FILTER 180

    ถ้าจะใช้มากกว่านี้ให้ใช้เครื่อบหมาย || มาช่วยแทน
    เช่น เงื่อนไข1 || เงื่อนไข2 || เงื่อนไข3

    myTable = FILTER(dProduct,dProduct[UnitPrice]>1000 || dProduct[BrandName]="Litware" || dProduct[BrandName]="Proseware")

    แปลว่าเอาที่ Unit Price > 1000 หรือ BrandName เป็น Litware หรือ Proseware

    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function - FILTER 181

    แต่ถ้ากรณีจะอ้างอิงค่าใน Field เดียวกันหลายๆ item อย่าง Litware กับ Proseware เราไม่ต้องใช้ OR ก็ได้ แต่หันมาใช้การอ้างอิงเงื่อนไขแบบ field IN {item1, item2} แทนจะง่ายกว่าการเขียนว่า field = item1 ||field = item2 เช่น

    myTable = FILTER(dProduct,dProduct[UnitPrice]>1000 || dProduct[BrandName] IN {"Litware" , "Proseware"} )

    จะได้ผลลัพธ์เหมือนกันทุกประการเลยครับ

    ตัวอย่างทั้งหมดที่ผ่านมายังเป็นการใช้งานพื้นฐานแบบให้เห็นภาพชัดๆ คือลองสร้าง New Table ขึ้นมาเลย แต่ในความเป็นจริงเราสามารถเอา FILTER ไปประกอบกับสูตรอื่นๆ ที่ต้องการ input เป็น Table ได้อีกนะครับ เช่น สร้าง Measure ยอดขายเฉพาะยอดแบบ Online เท่านั้น

    ตัวอย่างการใช้ FILTER ใน Measure

    ผมลองสร้าง New Measure ตัวใหม่ ที่สูตรเหมือน TotalRevenue ทุกอย่าง แค่ส่วนของ Table ใน SUMX เราใช้ FILTER สร้างตารางจำลองขึ้นมาให้เหลือเฉพาะ Transaction ที่มาจากช่องทาง Online เท่านั้น เพื่อที่ผลลัพธ์มันจะได้เอาจำนวน SalesQuantity * UnitPrice เฉพาะ Row ที่มาจากช่องทางออนไลน์ไง

    TotalRevenue = SUMX(fSales,fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))
    TotalOnlineRevenue = SUMX(FILTER(fSales,RELATED(dStores[StoreType])="Online"),
    fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))
    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function - FILTER 182

    พอเรามี Measure 2 ตัวแล้ว เราก็สามารถสร้าง %Portion ที่น่าสนใจได้ เช่น

    Power BI ตอนที่ 11: เรียนรู้ DAX Table Function - FILTER 183

    และนี่ก็เป็นตัวอย่างการใช้ FILTER ครับ เดี๋ยวบทความหน้าเรามาต่อกันที่ ALL, DISTINCT, VALUES และผองเพื่อนกันครับ รับรองว่าลึกซึ้งขึ้นไปอีกครับ

    ทั้งหมดนี้ เพื่อปูทางไปสู่ฟังก์ชันที่ลึกซึ้งที่สุดอันนึงใน DAX นั่นก็คือ CALCULATE ครับ!!

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี

  • เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365

    ผมเชื่อว่าหลายคนที่ใช้ Excel นั้นย่อมเคยต้องการให้ Excel ทำงานจัดการข้อมูลในลักษณะนี้ เช่น

    • คัดกรองข้อมูลให้เหลือสิ่งที่ต้องการเท่านั้น (Filter)
    • จัดเรียงข้องมูลใหม่ตามต้องการ (Sort)
    • ตัดข้อมูลซ้ำออกให้เหลือเฉพาะที่ไม่ซ้ำ (Remove Duplicates)

    ตั้งแต่อดีตที่ผ่านมา จริงๆ Excel ก็มีเครื่องมือที่พร้อมที่จะทำงานเรื่องเหล่านี้อยู่แล้ว ใน Ribbon เครื่องมือ Data เช่น Filter, Sort, Remove Duplicates และผมก็เชื่อว่ามันเป็นเครื่องมือที่หลายๆ คนน่าจะพอใช้กันเป็นอยู่แล้วล่ะ

    อย่างไรก็ตามเครื่องมือเหล่านั้นแม้จะใช้ง่าย แต่ก็มีจุดอ่อนสำคัญคือ มันเป็นเครื่องมือที่ต้องให้เรากดปุ่มสั่งใหม่ทุกครั้ง เช่น จะ Filter แบบไหน Sort ยังไง รวมถึง Remove Duplicates ข้อมูลชุดไหน แปลว่ามันยังต้องมี Step ที่ต้องการมนุษย์มา “ทำงาน Manual” บางอย่างอยู่

    ใน Excel ยุคใหม่ขึ้นมาหน่อย ก็ได้มีเครื่องมือ Power Query เข้ามาช่วยแก้ปัญหานี้ เพราะมันก็ Filter ข้อมูลได้ Sort ได้ Remove Duplicates ได้ (และทำอย่างอื่นได้อีกเยอะแยะ) และที่สำคัญคือ มันกด Refresh เพื่อทำซ้ำ Step ทุกอย่างที่กำหนดไว้ได้! อย่างไรก็ตาม มันก็ยังต้องมี Step การกด Refresh อีกทีนึงอยู่ดี (ยกเว้นใช้ VBA ช่วย)

    ดังนั้นถ้าหากเราต้องการความอัตโนมัติขั้นสุดยอด วิธีที่ทำได้ก็คงหนีไม่พ้น “การเขียนสูตร” ซึ่งบอกเลยว่าการเขียนสูตรเพื่อ Filter/Sort/Remove Duplicates นั้นเคยเป็นเรื่องที่ยากมากกกกกกกกกกๆๆๆๆๆ มาโดยตลอด (คิดดูว่าถ้าจะ Filter ข้อมูลจริงๆ มันก็คล้ายๆ จะต้อง VLOOKUP หรือ INDEX+MATCH นั่นแหละ และปกติสูตรพวกนี้ก็จะเจอแต่ตัวแรกอีก ยากจะตายกว่าจะเอามาครบทุกตัวได้)

    จนกระทั่งมีสูตรชุดใหม่เกิดขึ้นมา เป็นสูตรในกลุ่ม Dynamic Array ซึ่งเป็นความสามารถใหม่ของ Excel 365 ที่จริงๆ มีหลายตัว แต่ผมจะขอแนะนำให้รู้จักแค่ 3 ตัวก่อน นั่นคือ FILTER, SORT และ UNIQUE ครับ

    ** ใครใช้ Excel 365 แล้วยังไม่มี ฟังก์ชัน FILTER, SORT และ UNIQUE ให้ใช้ ลองเช็คดูนะครับว่าอัปเดทเป็น version ล่าสุดรึยัง? วิธีอัปเดทดูได้ที่นี่

    เรามาดูข้อมูลตัวอย่างกัน

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 184

    โหลดข้อมูลตัวอย่างได้ที่นี่

    มาดูการทำงานทีละฟังก์ชันก่อนนะ

    ก่อนอื่นมาดูตัวที่เข้าใจง่ายก่อน นั่นคือ UNIQUE

    UNIQUE เอาไว้คัดมาเฉพาะตัวที่ไม่ซ้ำกัน

    วิธีใช้งานแบบง่ายที่สุดคือ

    =UNIQUE(rangeข้อมูล)

    ซึ่งง่ายมากๆๆๆๆ

    ถ้าไม่มีฟังก์ชัน UNIQUE เราต้องเขียนสูตรผสมฟังก์ชันต่างๆ ออกมายาวเป็นกิโล ที่ทั้งยาวและยาก คนทั่วไปอ่านไม่เข้าใจแน่นอน เช่น ในรูปนี้

    =IFERROR(INDEX($B$2:$B$15,MATCH(0,COUNTIFS($I$2:I2,$B$2:$B$15),0)),"")
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 185

    แต่พอมี UNIQUE แล้ว เหลือแค่นี้ =UNIQUE(B2:B15) !!

    ผลลัพธ์จะได้ข้อมูลแบบไม่ซ้ำกันเลย แบบนี้ และผลลัพธ์จะงอกออกมาเท่ากับจำนวนข้อมูลด้วย

    ถ้ามีสินค้าเพิ่มขึ้นในข้อมูลดิบ เช่น ผมเพิ่มเจลล้างมือลงไป ผลลัพธ์ของ UNIQUE ก็จะเพิ่มมาทันที!!

    Dynamic Array กับการงอกผลลัพธ์แบบ Spill

    การที่ผลลัพธ์งอกอัตโนมัติแบบนี้ มีศัพท์เทคนิคเรียกว่า Spill นะครับ ซึ่งเป็น Concept ใหม่ของ Array Formula ใน Excel 365 ที่เรียกว่า “Dynamic Array” โดยที่สูตรจะอยู่ช่องซ้ายบนของพื้นที่ที่ Spill เท่านั้น (คล้ายๆ Merge Cell) ถ้าคลิ๊กที่ช่องอื่นสูตรจะเป็นสีเทา

    =UNIQUE(E2:E15)
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 186

    โดยถ้าพื้นที่ที่จะงอกมีข้อมูลอื่นขวางอยู่มันจะขึ้น Spill Error ว่า #SPILL! แบบนี้

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 187

    กลับมาดูเรื่อง UNIQUE ต่อกัน

    การใช้งานแบบเต็มความสามารถของ UNIQUE คือ

    =UNIQUE(array, [by_col] , [exactly_once] )
    • array คือ range ข้อมูลต้นฉบับ
    • [by_col] ถ้าเป็น TRUE คือจะคิด Unique by column คือจะกำจัดตัวซ้ำที่อยู่ในแถวเดียวกันออก (ซึ่งปกติค่านี้จะเป็น FALSE คือ ให้เอาที่ซ้ำกันในคอลัมน์เดียวกันออก) ซึ่งผมว่าแทบไม่ค่อยได้ใช้หรอก
    • ส่วน [exactly_once] ถ้าใส่เป็น TRUE คือจะคัดให้เหลือเฉพาะข้อมูลที่โผล่มาครั้งเดียวใน Data Source เท่านั้น อันนี้เดี๋ยวลองกับวันที่ให้ดู (ปกติอันนี้จะเป็น FALSE)
    =UNIQUE(B2:B15,FALSE,TRUE)
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 188

    ผลลัพธ์ออกมาเป็น 4 หมื่นกว่าๆ เพราะยังไม่ได้ปรับ Number Format ดังนั้นให้ลากครอบแล้วปรับ Number Format ให้เป็น Date ซะ (เลือกพื้นที่เผื่อเอาลงมาเยอะๆก็ได้)

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 189

    สังเกตว่าไม่มีวันที่ 1/2/2020 และ 7/2/2020 เพราะมันไม่ได้มีแค่ตัวเดียว

    SORT เอาไว้เรียงข้อมูลตามที่ต้องการ

    แบบง่ายสุดก็คือ

    =SORT(range ข้อมูล)

    เช่น

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 190

    แต่การใช้งานแบบเต็มความสามารถ คือ

    =SORT(array, [sort_index], [sort_order], [by_col])
    • array คือ range ข้อมูลต้นฉบับ
    • [sort_index] คือ จะเรียงตามคอลัมน์ที่เท่าไหร่ (ปกติเรียงตามคอลัมน์แรก)
    • [sort_order] ถ้าเป็น 1 คือ น้อยไปมาก ส่วน -1 คือ มากไปน้อย (ปกติจะเป็น 1)
    • [by_col] คือ ถ้าเป็น TRUE คือจะเรียงตามแนวนอน (ปกติเป็น FALSE) อันนี้ไม่ค่อยได้ใช้อีกนั่นแหละ

    ตัวอย่างเช่น

    ถ้าผม Sort ทั้งพื้นที่เหลือง แต่ให้เรียงตามคอลัมน์ที่ 3 ของพื้นที่เหลือง (ก็คือ ลูกค้า) ก็จะได้ดังนี้

    =SORT(A2:D15,3,1)
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 191

    FILTER เอาไว้คัดเลือกให้เหลือเฉพาะสิ่งที่ต้องการ

    =FILTER(array,include,[if_empty])
    • array คือ range ข้อมูลต้นฉบับที่จะนำมา Filter
    • include คือ range ของเงื่อนไขโดยจะเอาเฉพาะค่าที่เป็น TRUE มาแสดง (สามารถใส่ condition ใน Range ที่ไม่อยู่ใน array ได้)
    • [if_empty] คือ ถ้าไม่มีผลลัพธ์เหลือเลยจะให้ขึ้นว่าอะไร

    ตัวอย่างเช่น

    =FILTER(C2:E15,D2:D15="sales ค","ไม่มีข้อมูล")
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 192

    array คือพื้นที่สีเหลือง

    include เขียนว่า D2:D15=”sales ค” ซึ่งจริงๆ ถ้า Highlight แล้วกด F9 ดูจะได้เป็นค่า TRUE/FALSE ดังนี้

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 193

    เจ้าฟังก์ชัน FILTER นี่จะเอาเฉพาะรายการที่เป็น TRUE มาเท่านั้น ก็เลยได้แค่ item อันที่ 2 กับ 11 นั่นเอง

    ถ้าจะ Filter หลายเงื่อนไข เราต้องรู้จักว่า การเอาเงื่อนไขคูณกัน จะเป็นเงื่อนไขเป็น AND (TRUE * TRUE ได้ 1 นอกนั้นเป็น 0)

    เช่น ถ้าอยากได้เฉพาะรายการของ sales ก และ อาหาร เท่านั้น ก็เขียนได้ว่า

    =FILTER(C2:E15,(D2:D15="sales ก")*(E2:E15="อาหาร"))
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 194

    ใช้ฟังก์ชันผสมผสานกัน

    ความโดดเด่นของวิธีการเขียนสูตรใน Excel เมื่อเทียบกับวิธีอื่นๆ คือเราสามารถใช้ฟังก์ชันหลายอันผสมกันได้ และฟังก์ชันขี้โกงเหล่านี้ก็ใช้ผสมกันได้แน่นอน

    ตัวอย่างเช่น ถ้าผมใช้ UNIQUE กับ SORT ซ้อนกันจะได้แบบนี้

    การเขียนฟังก์ชันซ้อนกันในสูตรเดียว

    การเขียน

    =SORT(UNIQUE(D2:D15))

    เป็นการเขียนฟังก์ชันซ้อนกันในสูตรเดียว เหมาะกับคนที่เขียนสูตรคล่องๆ แล้ว

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 195

    การเขียนฟังก์ชันแยก Cell กัน แต่อ้างอิงข้อมูลที่ Spill

    อย่างไรก็ตามถ้าเราต้องการเขียน UNIQUE ก่อน แล้วค่อย SORT แยกออกมาต่างหาก ก็สามารถทำได้ โดยการอ้างอิงไปที่ช่องซ้ายบนของพื้นที่ Spill แล้วตามด้วยเครื่องหมาย# เพื่อให้ Excel เข้าใจว่าเป็นการอ้างอิงตัวที่ Spill ทั้งชุด ไม่ได้อ้างอิงแค่ Cell เดียว เช่น

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 196

    เดี๋ยวลองผสมกัน 3 ตัวเลย

    ใส่ Filter เลือก sales ก ก่อน

    ที่ K8 =FILTER(E2:F15,D2:D15=K3)
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 197

    จากนั้นใส่ Sort ให้เรียงจากน้อยไปมาก ตามชื่อสินค้า

    ที่ K8 =SORT(FILTER(E2:F15,D2:D15=K3))
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 198

    Tips : ถ้ารู้สึกยังไม่ถูกใจ เพราะราคายังไม่เรียงด้วย แปลว่าต้อง Sort หลาย Step ซึ่งจริงๆใช้ฟังก์ชัน SORTBY จะง่ายกว่า แต่ผมยังไม่ได้สอน 555 ไม่เป็นไร ใช้ SORT ก็ทำได้แต่ต้องใส่ซ้อนกัน เช่น SORT index 2 ก่อน แล้วค่อย Sort index 1 ครอบทีหลังดังนี้

    ที่ K8 =SORT(SORT(FILTER(E2:F15,D2:D15=K3),2),1)
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 199

    จากนั้นใส่ UNIQUE เพื่อกำจัดตัวซ้ำ

    ที่ K8 =UNIQUE(SORT(SORT(FILTER(E2:F15,D2:D15=K3),2),1))
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 200

    ลองเปลี่ยน sales ก เป็นคนอื่นบ้าง เช่น sales ค

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 201

    ตัวอย่างการพลิกแพลงสูตร

    ซึ่งหากเรามีความรู้เรื่องฟังก์ชันอื่นๆ ด้วย เราก็สามารถทำอะไรที่พลิกแพลงได้กว่านี้มาก

    ตัวอย่างการสร้าง Dropdown List ที่มี Item เพิ่มตามข้อมูลที่เปลี่ยนไป

    ให้เราเขียน Dynamic Array ทิ้งไว้ แล้วค่อยอ้างอิงเข้าไปใน Data Validation

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 202

    หากอยากให้สามารถเห็นข้อมูลใหม่ที่อาจเพิ่มในอนาคตได้

    ก็ทำให้ตารางเป็น Table ซะสิ เพราะความสามารถที่เด่นที่สุดของ Table คือการขยายอาณาเขตตัวเองได้เวลามีข้อมูลเพิ่มด้านขวาหรือด้านล่าง

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 203

    ตัวอย่าง เลียนแบบ Pivot Table แบบมีทั้ง Row และ Column

    เช่นสามารถได้ตารางที่ใกล้เคียง Pivot Table เลย โดยในนี้เพิ่มฟังก์ชัน TRANSPOSE ที่เอาไว้พลิกสลับแนวนอนเป็นแนวตั้ง และมีการใช้ SUMIFS มาช่วย โดยระบุ Criteria แบบ Array เป็นตัวที่ Spill

    ที่ M5 : =SORT(UNIQUE(C2:C15))
    ที่ N4 : =TRANSPOSE(SORT(UNIQUE(E2:E15)))
    ที่ N5 : =SUMIFS(H2:H15,C2:C15,M5#,E2:E15,N4#,D2:D15,M1)
    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 204

    ตัวอย่าง เลียนแบบ Pivot Table แบบมี row 2 ชั้น

    โดยเลือกมาบางคอลัมน์ด้วย CHOOSE ผสม Array Constant และหาผลสรุปด้วย SUMIFS ผสมกับเลือก Criteria บางส่วนของที่ Spill ด้วย INDEX

    เปลี่ยนสูตรยากให้เป็นสูตรกล้วยๆ ด้วย Dynamic Array ใน Excel 365 205
    ที่ K5 : =SORT(FILTER(CHOOSE({1,2},C2:C15,E2:E15,H2:H15),D2:D15=K1))
    ที่ M5 : =SUMIFS(H2:H15,C2:C15,INDEX(K5#,0,1),E2:E15,INDEX(K5#,0,2),D2:D15,K1)

    สรุป

    เป็นอย่างไรบ้างกับฟังก์ชันใหม่ของ Excel 365 ? ถึงมันจะดูยากไปบ้างเมื่อเทียบกับการใช้ Pivot Table แต่ว่าสิ่งที่ได้กลับมาคือความอัตโนมัติแบบสุดๆ นั่นเอง

    และถ้าย้อนกลับไปตอนไม่มีฟังก์ชันพวกนี้ให้ใช้ สูตร Array Formula จะยากกว่านี้หลายสิบเท่า เผลอๆ ต้องเขียนสูตรยาวหลายบรรทัด กว่าจะได้คำตอบที่เทียบเท่ากับสูตร Dynamic Array บรรทัดเดียว

    ดังนั้นลองเลือกดว่าจะลองหัดใช้สูตรใหม่นี้หรือไม่ และถ้าจะใช้ ประเด็นที่ต้องพิจารณาคือ หากสิ่งไฟล์ไปให้คนอื่นที่มี Excel Version เก่า ก็จะเปิดไฟล์มาแล้ว Error นะ ดังนั้นระวังให้ดีด้วยนะครับ *o*

  • เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?)

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?)

    “มาเลิกใช้ Merge Cell กันเถอะ!” นี่คือความในใจที่อยากจะตะโกนบอกคนใช้ Excel ทุกคนเลย 555

    แต่ผมไม่ได้มาห้ามเฉยๆ นะ เพราะในบทความผมมีวิธีหลีกเลี่ยงที่พอจะช่วยลดปัญหาของ Merge Cell มาบอกด้วยล่ะ

    หากผมจะบอกว่า “การ Merge Cell คือต้นกำเนิดของความเลวร้ายทั้งปวงใน Excel” มันอาจจะดูแรงเกินไปนิด แต่มันก็ใกล้เคียงล่ะ มาดูกันว่าทำไม…

    ปัญหาของการ Merge Cell

    หากเรามีการใช้ Merge Cell ที่ตัวข้อมูลดิบที่เป็น Input จะพบว่ามันก่อให้เกิดปัญหามากมาย

    Merge Cell
    • Merge แบบหัวตาราง 2 ชั้น (กรอบชมพูในรูปบน)
      • ทำให้เลือก Sort/Filter หัวตารางลำบาก ต้องเลือกทั้งแถวที่สองแล้วกด Filter เอาถึงจะเลือกหัวตารางชั้นล่างได้ ซึ่งยุ่งยากมาก
        เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 206
      • เอาข้อมูลเข้าไปวิเคราะห์ใน Pivot Table ก็ไม่ได้อีก (เพราะถือว่ามีชื่อ Field ว่าง)
        เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 207
    • การ Merge ที่ Data ข้างใน (กรอบแดงในรูปบน) จะทำให้
      • ไม่สามารถ Sort/Filter ข้อมูลที่มีการ Merge Cell ได้เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 208
    • Copy Paste ข้อมูลลงบน Merge Cell โดยที่ขนาดไม่เท่าเดิมก็ไม่ได้
      เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 209
    • แถมยังเป็นการเว้นช่องว่างเอาไว้ในฐานที่มนุษย์เข้าใจแต่คอมพิวเตอร์ไม่เข้าใจ (Computer เข้าใจว่าข้อมูลอยู่ที่ช่องซ้ายบนเท่านั้น นอกนั้นเป็นช่องว่าง)
    • เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 210
    • การเขียนสูตรเพื่อเลือกข้อมูลช่องที่ถูก Merge แต่ไม่ใช่ช่องซ้ายบนก็ยากอีก

    ทำไมคนยังใช้ Merge Cell?

    จะเห็นว่าปัญหามากมายนั้นเกิดจากการใช้ Merge Cells แต่ทำไมคนถึงใช้มันอีกล่ะ??

    คำตอบที่ผมพบจากการสอบถามเพื่อนๆ ในเพจ สามารถสรุปเหตุผลได้สั้นๆ ก็คือ เป็น “เพราะมันสวยดี”

    ผมขอบอกเลยว่า ความงามที่ทำให้เกิดปัญหาตามมานั้น ย่อมไม่ใช่ความงามที่แท้ ดังนั้นผมขอแนะนำให้หลีกเลี่ยงการ Merge Cell ถ้าไม่จำเป็นจริงๆ

    ผมเชื่อว่า คนที่ใช้ Merge Cell ส่วนใหญ่ไม่รู้ด้วยว่ามันจะส่งผลให้มีปัญหาในอนาคตแค่ไหน เพราะอาจจะไม่ค่อยเข้าใจการใช้ Sort/Filter/Table/Pivot Table

    ทำไม Excel ถึงไม่ยอมให้เรา Sort/Filter/Pivot ข้อมูลที่ Merge?

    ต้องเข้าใจด้วยว่าการที่เรา Merge ข้อมูลมันไม่ได้กระจายไปทุกช่อง แต่มันอยู่ที่ช่องซ้ายบนสุดแค่ช่องเดียว ดังนั้นช่องอื่นจะถือว่าเป็นช่องว่างทั้งหมด พอเป็นแบบนั้น มันก็เลยไม่อยากให้เรา Filter ยังไงล่ะ เดี๋ยวเข้าใจผิด

    เวลาพูดว่าอย่า Merge Cell ที่ห้ามจริงๆ หมายถึงตัว Data Input ไม่ใช่ Report Output

    หลักการที่ถูกต้องคือ แยกข้อมูลส่วน Input กับ Output ออกจากกันซะ ส่วน Input ที่เป็นข้อมูลดิบ ให้ทำให้อยู่ในลักษณะ Database ให้มากที่สุด (แต่ถ้ากรอกไม่ไหวจริงๆ ก็ใช้ Power Query ช่วย Fill Down/Unpivot แปลงหน้าตาได้ ถ้าทำเป็น) ส่วน Output ถ้าอยากจะ Merge ก็แล้วแต่ ไม่มีใครว่า (ยกเว้นวันจะต้องไปเป็น input ของชาวบ้านอีกที)

    แปลว่า ถ้าเราจะ Merge เพื่อความสวยงาม ให้ทำที่ Output ซึ่งก็คือตัว Report ไม่ใช่ Input ที่เป็นแหล่งข้อมูลดิบ

    วิธีที่พอจะช่วยหลีกเลี่ยง Merge Cell (ถ้ายังอยากทำ)

    กรณีจะ Merge แนวนอน ให้ใช้ Center Across Selection แทน

    เทคนิคนี้เป็นตัวที่สามารถสร้างผลลัพธ์ที่หน้าตาจะเหมือนกับ Merge Cell มากๆ (แต่ใช้รวม cell ได้แต่แนวนอน ใช้รวมแนวตั้งไม่ได้) มันคือการจัด Format ให้กับข้อมูลในแนวนอน โดยให้ข้อความมาอยู่ตรงกลางของพื้นที่ที่เลือกได้

    ดังนั้นหากคุณต้องการจะ Merge Cell แค่แถวเดียว ให้เปลี่ยนมาใช้ Center Across Selection จะดีกว่ากันมากๆ เลย

    วิธีทำก็แค่เลือกข้อมูล แบบที่ยังไม่ต้องMerge

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 211

    จากนั้นก็คลิ๊กขวา Format Cell หรือกด Ctrl+1 ก็ได้

    จากนั้นเลือก Alignment -> Horizontal : Center Across Selection

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 212

    ผลที่ได้จะเหมือนกับการ Merge Cell เลย แต่ Cell ไม่ได้ Merge (เห็นมะว่ายังคลิ๊กเลือก cell แยกกันได้) ส่วนข้อมูลจริงจะยังคงอยู่ที่ช่องซ้ายสุดของพื้นที่ช่องเดียวเหมือนเดิม

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 213

    ดังนั้นสรุปว่าถ้าจะ Merge Cell แนวนอนจริงๆ ก็ให้ใช้ Center Across Selection แทนนะ แต่ถ้าเลือกได้จริงๆ ก็อย่าไปทำมันเลยทั้งคู่นั่นแหละ ให้พิมพ์ข้อมูลให้ครบทุกช่องดีกว่า เพราะอย่างที่บอกไปว่าการ Merge ข้อมูลมันไม่ได้อยู่ครบทุกช่อง ไอ้เจ้า Center Across Selection ก็มีข้อมูลอยู่แต่ช่องซ้ายสุดเหมือนกัน เดี๋ยวก็มีปัญหาอีก

    กรณีจะ Merge แนวตั้ง ให้พิมพ์ให้ครบทุกช่องเถอะ ไม่มีทางเลือก

    การ Merge แนวตั้ง ใช้ Center Across Selection ไม่ได้นะ และไม่น่าจะมีวิธีที่ดีไปกว่านี้แล้วล่ะ เสียใจด้วย

    กรณี Merge หัวตาราง พอมีทางช่วยได้

    กรณีที่เรามีหัวตาราง 2 ชั้น มันทำให้ใช้ PivotTable ไม่ได้โดยสิ้นเชิง ดังนั้นวิธีแก้ที่ดีที่สุดคือ ทำหัวตารางให้มีแค่ชั้นเดียวพอ

    ซึ่งถ้ารู้สึกว่าหัวตารางชั้นเดียวมันไม่สวยงาม งั้นก็ทำทั้งสองแบบ แต่เอาหัวตารางสองชั้นย้ายไปอยู่ข้างบนสิ เช่น เขียนสูตรเอาสองบรรทัดเชื่อมข้อความกันซะแบบนี้ ให้เหลือหัวตารางบรรทัดเดียว

    และอย่าลืมทำลายข้อมูลที่ Merge อยู่ให้หมด (วิธีกำจัด Merge Cell ที่ง่ายที่สุดคือเลือกคลุมทั้งหมด แล้วกดปุ่ม Merge Cell อีกรอบ มันจะปลดออกหมดเลย) แล้วกรอกให้ครบทุกช่องซะ อย่าปล่อยว่างเลยและตัวสรุปรวมท้ายตารางให้ลบทิ้งไปก่อนทั้งบรรทัดเลย

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 214

    จากนั้น Copy Paste Value ซะแล้วแก้บางคอลัมน์ที่อ่านไม่รู้เรื่องให้ถูกต้อง (ตัวที่ Merge ทั้งหลาย)

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 215

    จากนั้นพอจะใช้งานจริง แล้วค่อยเลือกที่ช่อง C3 แล้วสั่ง Freeze Pane ซะแบบนี้

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 216

    พอ Scroll Mouse ลงมา ไอ้ส่วนหัวตารางสองชั้นสวยๆ ของเราก็จะยังอยู่

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 217

    แต่วิธีนี้เราจะได้ความสามารถของการ Sort/Filter กลับคือนมา และยังสามารถทำข้อมูลเป็น Table และใช้ PivotTable ได้ด้วย ทั้งนี้เพราะเราสร้างหัวตาราง 1 บรรทัดให้อยู่ติดกับตัวข้อมูลไว้แล้วนั่นเอง

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 218

    เอายังไงกับตัวสรุปรวมท้ายตาราง

    หากเราต้องการสรุปข้อมูลจริงๆ ควรจะใช้ Pivot Table ทำมากกว่าการมาเขียนสูตรเอาท้ายตาราง แต่ถ้าต้องการให้มีการสรุปข้อมูลอยู่ที่ท้ายตารางจริงๆ ผมแนะนำให้ใช้ความสามารถของ Table ครับ

    ก่อนอื่นให้เลือกข้อมูลช่องใดช่องหนึ่งแล้วกด Insert->Table หรือ Ctrl+T เพื่อแปลงข้อมูลเป็น Table ซะ ซึ่งตอนแรกมันจะยังไม่มีตัวสรุปท้ายตารางให้

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 219

    ถ้าอยากให้มีสรุปท้ายตาราง แค่ติ๊กเลือก Total Row ตามรูป ก็จะมีบรรทัดสรุปโผล่มา

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 220

    จากนั้นเราสามารถเลือกแต่ละคอลัมน์ได้ว่าจะให้สรุปด้วยวิธีไหน เช่น SUM COUNT AVERAGE MAX MIN

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 221

    เราได้ตารางที่หน้าตาไม่ได้แย่เลย มีหัวตาราง 2 ชั้นเหมือนเดิม มีบรรทัดสรุป แค่เนื้อในต้องพิมพ์ให้ครบทุกช่องเท่านั้นเอง เพื่อที่จะได้ Sort/Filter/Pivot ได้ตามปกติครับ

    เลิกใช้ Merge Cell กันเถอะ (แล้วจะให้ทำยังไงแทน?) 222

    และทั้งหมดนี้ก็คือเทคนิค ที่พอจะช่วยหลีกเลี่ยงการทำ Merge Cell ได้นะครับ ถ้าทำตามนี้รับรองว่าชีวิตดีขึ้นแน่นอน ^^

  • ฐานข้อมูลตำบล อำเภอ จังหวัด รหัสไปรษณีย์ ของประเทศไทย V3: ข้อมูลสมบูรณ์มากขึ้น

    ฐานข้อมูลตำบล อำเภอ จังหวัด รหัสไปรษณีย์ ของประเทศไทย V3: ข้อมูลสมบูรณ์มากขึ้น

    สืบเนื่องจากที่ผมได้พยายามทำ “ฐานข้อมูลส่วนกลาง” หรือที่ผมจะเรียกว่า “Common Database” ที่หลายๆ คนก็น่าจะอยากใช้เหมือนกัน เช่น ฐานข้อมูลตำบล อำเภอ จังหวัด ภาค ทั้งภาษาไทยและภาษาอังกฤษ เพื่อที่เพื่อนๆ จะได้ไม่ต้องมาเสียเวลาทำเหมือนผมอีก

    ตอนนี้ผมทำเสร็จแล้วในระดับนึง คือ ได้ ภาค จังหวัด อำเภอ ตำบล แบบที่เรียกได้ว่าครบถ้วนที่สุดอันนึงในโลก internet แล้วล่ะ 555 (ถ้าไม่นับ Wikipedia นะ ) ก็เลยจะเอามาแจกเพื่อนๆ ให้ลองเอาไปใช้ดูก่อน ( ตอนนี้เพิ่งเพิ่มรหัสไปรษณีย์ไปให้แล้วนะ เมื่อ 17 Mar 2020)

    ที่บอกว่าครบถ้วน เพราะผมมีการ crosscheck หลาย source มากๆ ถ้าอันไหนไม่ตรงกันจะเปิด wiki ดูทีละเขต ทีละอำเภอเลย (รายละเอียดของ source อยู่ในไฟล์นะ) ที่ต้อง cross check เพราะไม่มีแหล่งใดถูกต้องสมบูรณ์เลย ขนาดว่าของราชบัณฑิตยังมีชื่อไทยผิดพลาดหลายจุด (ทำให้อังกฤษผิดตาม)

    เหมือน wikipedia จะอัปเดทสุด ถูกต้องที่สุด แต่ข้อมูลแยกเป็นชิ้นๆ ไม่เห็นภาพรวม ผมเลยอาสาทำ database อันนี้ขึ้นมาให้

    เอาล่ะ ใครอยากโหลดฐานข้อมูลที่ผมทำไว้ก็เข้าไปได้ที่

    Download ฐานข้อมูลตำบล

    ฐานข้อมูลตำบล อำเภอ จังหวัด รหัสไปรษณีย์ ของประเทศไทย V3: ข้อมูลสมบูรณ์มากขึ้น 223

    Version History

    • 16/3/2020 version 1 – ไฟล์ตั้งต้น มีตำบล อำเภอ จังหวัด ทั้งไทยและอังกฤษ
    • 17/3/2020 version 2 – เพิ่มเรื่องรหัสไปรษณีย์ / แก้ชื่อภาษาอังกฤษของ ต.โคกกะเทียม เป็น Khok Kathiam
    • 7/11/2021 version 3 – แก้ข้อมูลชื่อตำบลภาษาอังกฤษของอุบลราชธานีเลื่อน / แก้ชื่อ eng สมุทรปราการ กับ พังงา ตาม ISO 3166-2:TH แก้ชื่อ โพนพิสัย, กัลยาณิวัฒนา / แก้ district id เวียงเก่าเป็น 4029 / แก้ post code เฝ้าไร่

    ปล. เพื่อนๆ สามารถเอาข้อมูลนี้ไปใช้ได้เลย ไม่ต้องขออนุญาตผมนะครับ

    ปล. 2แน่นอนว่าฐานข้อมูลที่ผมทำมันไม่ใช่ database official อะไรทั้งสิ้น ดังนี้ใครเจอที่ผิดช่วยแจ้งที่ inbox เพจ เทพเอ็กเซลด้วย https://www.facebook.com/thepexcel/

    ปล. 3 พวกข้อมูลอื่นๆ ที่มีหลายคนขอมากันเยอะๆ เช่น Latitude Longitude จริงๆ ก็มีแล้วล่ะ แต่ยังไม่ค่อยสมบูรณ์ ก็เลยขอเวลาจัดการข้อมูลให้ดีกว่านี้ก่อนค่อยเอามาปล่อยต่ออีกทีนะครับ

  • สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code

    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code

    จากที่ผมได้เคยอธิบายไปว่า Date Table มีความสำคัญต่อการทำ Data Model เป็นอย่างยิ่ง โดยเฉพาะการใช้ฟังก์ชัน Date Intelligence ยิ่งจำเป็นต้องใช้ Date Table เลยล่ะ

    แปลว่า Data Model ของทุกคนควรมี Date Table ซึ่งกลายเป็นเรื่องที่ทุกๆ คนต้องทำเหมือนๆ กันหมด

    ดังนั้นจะดีกว่ามั้ย ถ้าเราสามารถมีสูตรสำเร็จรูปอะไรซักอย่าง ที่สามารถ Copy Paste ไปใช้สร้าง Date Table ได้เลย? และนั่นคือที่มาของบทความนี้ครับ

    ทีนี้การสร้าง Date Table นั้นทำได้ 2 วิธี คือใช้ DAX กับใช้ M Code ของ Power Query เรามาดูแต่ละวิธีกันครับ

    สร้าง Date Table ด้วย DAX

    แค่กด New Table ใน Power BI แล้วใส่ code นี้ลงไป

    dDateTable = 
    VAR MyCalendar=CALENDARAUTO()
    
    RETURN
    
    ADDCOLUMNS (MyCalendar,
    "Year",YEAR([Date]),
    "Quarter","Q" & QUARTER([Date]),
    "Month",MONTH([Date]),
    "Day",DAY([Date]),
    "MonthName",FORMAT([Date],"mmmm"),
    "YearMonth",FORMAT([Date],"yyyy-mm"),
    "YearMonthName",FORMAT([Date],"yyyy-mmm"),
    "WeekDayNum",WEEKDAY([Date],2),
    "WeekDayName",FORMAT([Date],"dddd"),
    "DateText",FORMAT([Date],"yyyy-mm-dd"),
    "Start of Month",EOMONTH([Date],-1)+1,
    "End of Month",EOMONTH([Date],0)
    )

    โดยที่ตาราง fSales มีข้อมูลรายการวันที่สั่งซื้อสินค้าอยู่ในคอลัมน์ OrderDate

    ดังนั้นให้เปลี่ยนคอลัมน์วันที่ ที่จะใช้อ้างอิงได้จาก fSales[OrderDate] เป็นวันที่ใน Table ของคุณจริงๆ ได้เลย

    Tips: ผมมีการ comment ใส่ startYear และ endYear อีก 2 แบบไว้ (ถ้าจะใช้ก็เอา — ข้างหน้าออกเพื่อ uncomment)

    • แบบทางเลือก1 เอาไว้พิมพ์ปีที่ต้องการเริ่มและจบเอาเอง โดยที่ไม่ขึ้นกับ Field Data จริง
    • แบบทางเลือก2 (ที่ยาวๆ) ซึ่งไว้เทียบ Field วันที่กรณีมีมากกว่า 1 Field ด้วย

    แค่นี้ก็จะได้ Date Table มาใช้งานแล้วล่ะ

    Date Table

    ถ้าใครจะเพิ่มคอลัมน์อีก ก็กด Add Column แล้วใส่สูตรตามปกติต่อไปได้เรื่อยๆ นะครับ เช่น วันแรก วันสุดท้ายของเดือน จำนวนวันในเดือนเป็นต้น

    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 224
    FirstDateofMonth = STARTOFMONTH(dDate[Date])
    LastDateofMonth = ENDOFMONTH(dDate[Date])
    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 225
    NumDaysinMonth = DATEDIFF(dDate[FirstDateofMonth],dDate[LastDateofMonth],DAY)+1

    หรือจะใช้ว่า

    NumDaysinMonth = INT(dDate[LastDateofMonth]-dDate[FirstDateofMonth]+1)

    ก็ได้

    สร้าง Date Table ด้วย Power Query M Code

    ให้เราสร้าง Blank Query (กด Get Data -> Blank Query) ขึ้นมาและใส่ Code นี้ลงไปใน Advanced Editor (กด View->Advanced Editor)

    Edit : 23/3/2021 แก้ไข DayCount อันเดิมใส่วันขาดไป 1 วัน

    (StartDate as date, EndDate as date) as table =>
    let
    displayRegion="en-GB",
    //displayRegion="th-TH",
    //StartDate=#date(2017, 1, 1),
    //EndDate=#date(2019,12,31),
    DayCount = Duration.Days(Duration.From(EndDate - StartDate))+1,
    Source = List.Dates(StartDate,DayCount,#duration(1,0,0,0)),
    #"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "Date"}}),
        #"Changed Type" = Table.TransformColumnTypes(#"Renamed Columns",{{"Date", type date}}),
    #"Inserted Year" = Table.AddColumn(#"Changed Type", "Year", each Date.Year([Date]), Int64.Type),
    #"Inserted Quarter" = Table.AddColumn(#"Inserted Year", "Quarter", each "Q"& Text.From(Date.QuarterOfYear([Date])), type text),
    #"Inserted Month" = Table.AddColumn(#"Inserted Quarter", "Month", each Date.Month([Date]), Int64.Type),
    #"Inserted Month Name" = Table.AddColumn(#"Inserted Month", "Month Name", each Date.ToText([Date],"MMMM",displayRegion), type text),
    #"Inserted Day" = Table.AddColumn(#"Inserted Month Name", "Day", each Date.Day([Date]), Int64.Type),
    #"Inserted Day of Week" = Table.AddColumn(#"Inserted Day", "Day of Week", each Date.DayOfWeek([Date],1)+1, Int64.Type),
    #"Added YearMonthNum" = Table.AddColumn(#"Inserted Day of Week", "YearMonthNum", each Date.ToText([Date],"yyyyMM",displayRegion)),
    #"Added YearMonthText" = Table.AddColumn(#"Added YearMonthNum", "YearMonthText", each Date.ToText([Date],"yyyy-MMM",displayRegion))
    in
        #"Added YearMonthText"

    Tips: สังเกตว่าใน code มีการระบุรูปแบบ region ได้ ซึ่งผมใส่เป็น displayRegion=”en-GB” ไว้ ซึ่งจะเป็นภาษาอังกฤษครับ ถ้าจะให้เป็นภาษาไทยสามารถ uncomment // เปลี่ยน displayRegion=”th-TH” ได้นะครับ

    แล้วตั้งชื่อ Query ตามต้องการ เช่น CreateDateTable

    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 226

    ผลลัพธ์ออกมาจะเป็น Function Query ให้เราใส่ Parameter วันเริ่มกับวันจบ (กดรูปปฏิทินได้นะ)

    ถ้าใส่แล้วกด invoke จะได้ตารางออกมาดังนี้

    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 227

    แปลว่าถ้าอยากให้ตารางนี้ Dynamic ได้จะต้องไปแก้สูตรจาก

    = CreateDateTable(#date(2018, 1, 1), #date(2020, 12, 31))

    ให้เป็น

    = CreateDateTable(วันเริ่มต้น, วันสิ้นสุด)

    โดยอาจ Link สูตรวันเริ่มต้นจากการไป Date Start of Year ของซัก Field วันที่นึง เช่น

    วันเริ่มต้น= 
    Date.StartOfYear(List.Min(fSales[OrderDate]))
    วันสิ้นสุด=
    Date.EndOfYear(List.Max(fSales[OrderDate]))

    โดยที่ตาราง fSales มีข้อมูลรายการวันที่สั่งซื้อสินค้าอยู่

    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 228

    แค่นี้เราก็จะได้ Date Table มาใช้ และยังคง Add อะไรเพิ่มได้อีกเช่นกัน โดยคลิกที่คอลัมน์ Date และไปที่ Add Column –> Date

    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 229

    เช่น ผมจะใส่จำนวนวันในเดือน ก็กดปุ่มได้เลยแบบชิลๆ ไม่ต้องใส่สูตรอะไรทั้งนั้น

    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 230
    สูตรสำเร็จรูปสำหรับสร้าง Date Table ด้วย DAX และ Power Query M Code 231

    เท่านี้เราก็สามารถสร้าง Date Table ได้ทั้ง 2 วิธีแล้ว และก็ยังเพิ่มคอลัมน์ได้ตามที่ต้องการด้วย

    ว่าแต่เพื่อนๆ ชอบแบบไหนมากกว่ากันครับ ^^

  • วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query

    วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query

    ปกติเวลาเราสั่งให้ Power Query รวมทุกไฟล์ใน Folder เดียวกัน แม้มันจะเอาข้อมูลรวมกันได้ แต่ก็อาจจะมีปัญหาเรื่องชื่อคอลัมน์ได้ในอนาคต

    สาเหตุเพราะ มันมีการระบุชื่อคอลัมน์ที่แตกออกมาอย่างชัดเจนในสูตร M Code ทำให้ หากในอนาคตมีคอลัมน์เพิ่มขึ้นหรือลดลง ก็จะมีปัญหาทันที (อย่างเช่นที่ผมบอกไว้ในหนังสือ Excel Power Up ว่า เมื่อไหร่ก็ตามที่มีการระบุชื่อคอลัมน์ในสูตร M Code นั้น จะอันตรายต่อการ Refresh ทันที)

    ลองทำดู

    โหลดไฟล์ประกอบได้ที่นี่

    ตัวอย่างเช่น ผมสั่งรวมข้อมูลจาก Folder ที่ชื่อ MyFolder และสร้าง Custom Column ดังนี้ เพื่อดึงข้อมูลจาก Excel ด้วยสูตรว่า

    =Excel.Workbook([Content],true)
    วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query 232

    ผมแตกคอลัมน์ Custom ออกมาจะได้ดังนี้

    วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query 233

    เดี๋ยวผมลบคอลัมน์ที่ไม่ใช้ทิ้งก่อน โดยจะเก็บแค่ ชื่อไฟล์ ชื่อ Item และ Data ไว้ โดยเลือกที่จะเอา แล้วสั่ง Remove Other Columns ซะ

    วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query 234

    ปัญหาเรื่องชื่อคอลัมน์ เกิดขึ้นตอน Expand Data

    พอเรากด Expand Data ออกมา จะพบว่าสูตรที่ได้มีการระบุชื่อคอลัมน์ออกมาโต้งๆ เลย ว่า

    = Table.ExpandTableColumn(#"Removed Other Columns", "Data", {"วันที่", "ลูกค้า", "สินค้า", "ราคาต่อชิ้น", "จำนวนชิ้น", "วิธีการชำระเงิน"}, {"วันที่", "ลูกค้า", "สินค้า", "ราคาต่อชิ้น", "จำนวนชิ้น", "วิธีการชำระเงิน"})
    วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query 235

    ถ้าเป็นแบบนี้ หากในข้อมูลต้นฉบับบางคอลัมน์หายไป หรือมีคอลัมน์เพิ่มเข้ามา จะมีปัญหาทันที!!

    ลองเพิ่ม/ลดคอลัมน์ดู

    จะพบว่าถ้าเพิ่มคอลัมน์ เช่น ยอดขาย มันจะไม่ถูดดึงมาด้วย (เพราะสูตรไม่ได้ระบุคอลัมน์นั้น)

    ถ้าลบคอลัมน์ซักอันนึง เช่น ผมเอาวิธีการชำระเงินออกออกจากทุกไฟล์ มันก็จะยังมีคอลัมน์ค้างอยู่เป็น null อย่างงั้นเลย (เพราะสูตรมีการระบุคอลัมน์นั้น)

    วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query 236

    ถ้าปล่อยให้เป็นแบบนี้ การอัปเดทข้อมูลจะยากเกินไป

    แก้ปัญหาโดยแก้ M Code เล็กน้อย

    เราสามารถทำให้ชื่อ Column มีความ Dynamic ยืดได้หนดได้ โดยต้องแก้บางส่วนของ Code เดิมอันนี้

    = Table.ExpandTableColumn(#"Removed Other Columns", "Data", {"วันที่", "ลูกค้า", "สินค้า", "ราคาต่อชิ้น", "จำนวนชิ้น", "วิธีการชำระเงิน"}, {"วันที่", "ลูกค้า", "สินค้า", "ราคาต่อชิ้น", "จำนวนชิ้น", "วิธีการชำระเงิน"})

    จะเห็นว่า สีแดง มันคือ List ของชื่อคอลัมน์ทั้งหมด

    = Table.ExpandTableColumn(#"Removed Other Columns", "Data", List ของชื่อคอลัมน์)

    ซึ่ง List ของชื่อคอลัมน์เกิดจากการรวมชื่อคอลัมน์ทุก Table ดังนี้

    List.Union(List.Transform(#"Removed Other Columns"[Data],each Table.ColumnNames(_)))

    หลักการคือ เราจะใช้สูตร List.Transform โดยใช้ Table.ColumnNames(_) กับทุกๆ Table เพื่อให้แต่ละ Table คืนค่ามาเป็น List ของหัวตารางใน Table นั้นๆ จากนั้นใช้ List.Union มารวม item ทุกตัวเข้าด้วยกัน

    ใครอยากรู้ว่าทำไมสูตรนี้ถึงได้ผล สามารถอ่านได้ที่นี่ https://www.thepexcel.com/m-code-power-query-03-list/

    สรุปแล้วเราจะแก้สูตรเป็นดังนี้

    = Table.ExpandTableColumn(#"Removed Other Columns", "Data", List.Union(List.Transform(#"Removed Other Columns"[Data],each Table.ColumnNames(_))))

    เราก็จะได้ Column ที่ Expand ได้แบบ Dynamic สุดๆ เจ๋งป่ะ!

    วิธีรวมไฟล์ใน Folder แบบไม่มีปัญหาเรื่องชื่อคอลัมน์ใน Power Query 237

    ผมมั่นใจว่าถ้าเพื่อนๆ ใช้วิธีที่ผมบอกนี้ ตอนอัปเดทข้อมูลชีวิตจะง่ายขึ้นเยอะเลยครับ

    สุดท้าย อย่าเผลอไปกด Auto Detect Data Type นะครับ เดี๋ยวมันก็จะระบุชื่อคอลัมน์อีก ให้ทำเฉพาะคอลัมน์ที่จำเป็นเท่านั้น เช่น ตัวเลข วันที่ เวลา เป็นต้น

  • การใช้ Power Query จัดการข้อมูลที่มีหัวตาราง 2 ชั้น

    การใช้ Power Query จัดการข้อมูลที่มีหัวตาราง 2 ชั้น

    ปัญหาข้อมูลเน่าแบบ classic อันนึงเลยก็คือ ได้ข้อมูลเชิง Report มา และดันใส่หัวตาราง 2 ชั้นมาด้วย ทำให้ใช้ Unpivot ตรงๆ ไม่ได้

    คราวนี้จะทำยังไงดี มาดูกันครับ

    Download ข้อมูลที่มีหัวตาราง 2 ชั้นได้ที่เว็บสำนักงานสถิติแห่งชาติ

    จำนวนนักเรียน นิสิต นักศึกษาในระบบโรงเรียน ในสถานศึกษาของรัฐบาลและเอกชน จำแนกตามระดับการศึกษา และชั้น ปีการศึกษา 2556 – 2560

    หรือ http://statbbi.nso.go.th/staticreport/Page/sector/TH/report/sector_03_3_TH_.xlsx

    หลักๆ การจัดการข้อมูลใน Power Query จะมีแนวทางดังนี้

    ข้อมูลอยู่ในรูปแบบ Report ยังไม่ใช่ข้อมูลเชิง Database

    • ติดข้อมูลอื่นที่ไม่เกี่ยวมา เช่น header/footer -> filter, remove col, remove top/bottom rows
    • ข้อมูลเว้นว่างแบบละไว้ในฐานที่เข้าใจ -> fill down
    • ข้อมูล error -> replace error
    • ข้อมูลมีตัว Subtotal ติดมาด้วย -> หาทาง filter ออก
    • คอลัมน์เดียวกันปนมาหลายเรื่อง -> conditional column -> หาทาง filter ออก
    • หัวตาราง crosstab เชิง Report (เรื่องเดียวมีหลายคอลัมน์) -> Unpivot
    • หัวตาราง 2 ชั้น -> Transpose -> Fill Down -> Merge -> Unpivot

    ข้อมูลมีหลายตาราง

    • ข้อมูลแบบเดียวกัน เลยอยากเอามาต่อแถวกัน เช่น เป็นคนละช่วงเวลา คนละสินค้า -> Append
    • เป็นข้อมูลที่เกี่ยวข้องกัน อยากเอามาต่อคอลัมน์กัน เช่น ตารางจำนวนประชากรรายจังหวัด vs จำนวนอาชญากรรมรายจังหวัด -> Merge / Data Model

    เอาล่ะ มาเริ่มกันเลย

    ผมทำเป็นคลิปไว้แล้ว ลองเปิดดูได้เลยนะครับ

  • เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query

    หากคุณกำลังเจอข้อมูลเน่าเฟะ อย่าเพิ่งสิ้นหวัง…

    ทำอย่างไรเมื่อเจอข้อมูลที่อยู่ในรูปแบบที่แย่และไม่ ok เอาซะเลย และดันมีความจำเป็นต้องแก้ด้วย Power Query ซะด้วยสิ

    ในบทความนี้เราจะมาเผชิญความเน่าเฟะไปด้วยกันครับ

    เตือนไว้ก่อนว่าบทความนี้ยาวหน่อยและมีหลายขั้นตอน ซึ่งเป็นเรื่องปกติที่การกำจัดข้อมูลที่เน่าเฟะนั้นต้องใช้เวลา ดังนั้นอย่าเพิ่งท้อถอยนะครับ รับรองว่าจะได้ความรู้ดีๆ กลับไปแน่นอน

    ข้อมูลเน่าเฟะที่ได้มา

    สมมติว่าเราได้ข้อมูลหุ้นในตลาด SET100 ทุกตัวหน้าตาแบบนี้มา ซึ่งผมใช้ Python ดึงมารวมกันแบบไม่ได้ Clean ดีๆ ตั้งแต่แรก (จะได้มาฝึกทำใน Power Query ไง 555)

    ซึ่งดาวน์โหลดไฟล์ได้ที่นี่ (Google Drive / GitHub)

    ความยาก1 มี Topic แทรกอยู่ระหว่างบรรทัดอยู่เป็นระยะๆ เช่น ทรัพย์สินรวม หนี้สินรวม

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 238

    ความยาก2 จำนวนตัวเลขต่อ 1 Topic มี 4 ตัวบ้าง 5 ตัวบ้าง ไม่แน่นอน
    ซึ่งความเป็นจริงคือข้อมูลย้อนหลังจนถึงปีปัจจุบัน Y-4, Y-3, Y-2, Y-1, Y0 ซึ่งบาง Topic มี 4 บาง Topic มี 5

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 239

    หน้าตาผลลัพธ์ที่ต้องการ

    ผลลัพธ์ที่อยากได้ เราอยากเอา Topic ทั้งหมดขึ้นเป็นหัวตารางไล่ไปทางด้านขวา และหุ้นตัวนึง 1 บรรทัดคือข้อมูล 1 ปี ดังนั้นถ้ามีทั้งหมด 5 ปี หุ้นตัวนึงจะมี 5 บรรทัด

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 240

    เริ่มกำจัดความเน่าเฟะ

    สร้าง Topic แยกออกมาให้ได้

    หลังจากสั่ง Get Data from Table/Range เพื่อเอาข้อมูลเข้าสู่ Power Query

    ก่อนอื่น เราต้องคิดว่า ถ้าเราอยากเอา Topic ไปทำเป็นหัวตาราง เราต้องสั่ง Pivot เอา Topic ขึ้นไป

    และการจะทำ Pivot ได้ ก็ต้องมีคอลัมน์ Topic ขึ้นมาโดยเฉพาะซะก่อน โดย Topic จะต้องถมค่าแบบนี้ให้ได้

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 241

    การจะถมค่าได้ เราต้องเอาหัว Topic แต่ละบรรทัดมาให้ได้ก่อน แล้วค่อย Fill Down ลงมา

    แล้วการจะได้หัว Topic มาเราก็ต้องรู้ให้ได้ว่าอันไหนคือหัว Topic อันไหนไม่ใช่

    จากที่ลองไล่ดูแล้ว การจะได้หัว Topic มา น่าจะต้องดูว่าข้อมูลเป็นข้อความรึเปล่า? ถ้าเป็นข้อความน่าจะเป็นหัว Topic

    ข้อมูลในคอลัมน์ Data จริงๆ มันก็เป็นข้อความหมดแหละ แค่เป็นตัวที่หน้าตาแบบข้อความจริงๆ กับข้อความที่หน้าตาเหมือนตัวเลข ดังนั้นเราจะลองบังคับขืนใจให้มันเป็นตัวเลขดูว่ามันยอมมั้ย? ถ้ายอมแสดงว่าหน้าตามันเป็นตัวเลขได้

    ดังนั้นเราจะสั่ง Duplicate Column Data ออกมาอันนึงก่อน โดยคลิ๊กขวาที่คอลัมน์ Data แล้ว Duplicate Column จากนั้นสั่งแปลงเป็น Decimal Number ซะ

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 242

    จะพบว่าอันไหนพอจะแปลงเป็นตัวเลขได้ มันก็จัดให้เรียบร้อย อะไรที่ทำไม่ได้ก็ค้างเป็น Error

    ถ้าไล่ดูจะเห็นว่ายังมีประเด็นค้างอยู่อีก 2 ตัว คือ วันที่ กับค่า N/A

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 243

    เนื่องจากค่า N/A ยังไงก็ใช้ไม่ได้ ดังนั้นผมจะย้อน Step กลับไปก่อนจะ Duplicated Column แล้วสั่ง Replace Value (Insert Step) แล้วทำให้ N/A ให้เป็น null ซะ

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 244

    จากนั้นสั่ง Duplicate คอลัมน์ Data ออกมา เพื่อจัดการแปลงเป็นวันที่ซะ โดยใช้ Using Locale เป็น Thai (เพราะวันที่ที่เป็น text นั้นเป็นรูปแบบไทย)

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 245

    จะเห็นว่ามันออกมาเป็นวันที่ได้แล้ว แต่ว่าดันติดวันที่เกินๆ มาด้วย (ด้วยความฉลาดที่มากเกินไป ดันมองว่าทศนิยมบางตัวเป็นวันที่ได้ 555)

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 246

    เพื่อให้จัดการค่าง่ายขึ้นผมจะ Replace Error ใน Data-Copy และ Data-Copy.1 ด้วย null ทั้งหมด

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 247

    จากนั้นผมสั่ง Conditional Column เพื่อให้เลือกเอา Data ให้เหลือคอลัมน์เดียว นั่นคือ ได้ Data Copy ว่าง ให้เอาจาก Data-Copy.1 แทน

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 248

    จะได้แบบนี้ ซึ่งดีขึ้นมาก

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 249

    ดังนั้นบรรทัดที่ยังเป็น null ในคอลัมน์ NumData จะตรงกับ Topic ที่อยากได้ในคอลัมน์ Data พอดีเลย ดังนั้นเราจะใช้ Conditional Column ได้

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 250

    สุดท้ายจะได้แบบนี้

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 251

    คราวนี้เราก็ Fill Down คอลัมน์ Topic ได้

    จากนั้นเลือกเก็บไว้แค่คอลัมน์ Symbol, Topic และ NumData พอ ด้วยการคลิ๊กเลือก 3 คอลัมน์ที่ต้องการแล้ว Remove Other Column

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 252

    จากนั้นเราสามารถ Filter เอาบรรทัด null ใน NumData ทิ้งได้เลย

    แต่จากการตรวจดู Data พบว่า บาง Topic ดันมี 4 ตัวบ้าง 5 ตัวบ้าง (ซึ่งไม่แปลก เพราะบางค่าของปีล่าสุดจะยังไม่มี) แต่ดันมี Topic ที่มี 3 ตัวด้วย! ซึ่งน่าจะเกิดจากการที่เดิมเป็น N/A แล้วผมสั่งให้เป็น Null

    กลับไปแก้ไข Step เก่าให้รัดกุมขึ้น

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 253

    ดังนั้นการ Replace ให้ N/A เป็น null ก่อนหน้านี้อาจไม่ใช่วิธีที่ดีแล้ว ดังนั้นเราจะไปแก้ให้ Replace N/A เป็นเลขซักตัวนึงที่เรามั่นใจว่าไม่มีทางใช่ข้อมูลจริงดีกว่า เช่น -99999

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 254

    คราวนี้เราจะได้บรรทัดกลับมาครบตามที่ควรจะเป็นแล้ว (และเรียงถูกต้องตาม sequence เดิม)

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 255

    แล้วเราค่อย Replace -99999 ของเราด้วย null ใหม่อีกที

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 256

    สร้างเลข Running ตาม Topic

    คราวนี้เราต้องการจะสร้างเลข Running 1,2,3,4,5 ตาม Topic แต่ละตัว (โดยบางตัวอาจมี 4, บางตัวอาจมี 5)

    ถ้าเรากด Add Index คอลัมน์ตรงๆ มันจะไม่ Reset ใหม่ตาม Topic แต่เราจะได้ Code ออกมาตามนี้

    = Table.AddIndexColumn(#"Replaced Value1", "Index", 1, 1)
    = Table.AddIndexColumn(ชื่อ Table ,ชื่อคอลัมน์,เลขตั้งต้น,เพิ่มทีละ)

    ซึ่งเดี๋ยวเราจะจำเอาไว้เลียนแบบตอนทำเรื่อง Group by ต่อไป

    เพื่อให้เราสามารถ Add Index เฉพาะกลุ่มได้ ดังนั้นเราจะใช้ Group By แบบ All Row มาช่วย ดังนี้

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 257

    เราจะได้ผลลัพธ์ออกมาเป็น Table ซึ่งถ้าคลิ๊กดูจะเป็น Table ที่มีครบทุกคอลัมน์เลย แต่มีการ Group ให้เหลือตามที่เรา Group By เท่านั้น

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 258

    ซึ่งที่เราจะทำคือเราจะ Add Index คอลัมน์ โดยการใส่ Custom Function แบบนี้

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 259
    =Table.AddIndexColumn(ชื่อ Table ,ชื่อคอลัมน์,เลขตั้งต้น,เพิ่มทีละ)
    =Table.AddIndexColumn([Data],"running",1,1)

    ซึ่งในคอลัมน์ NewData เราจะได้ Table ใหม่ ซึ่งมีคอลัมน์ running เพิ่มขึ้นมา

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 260

    แต่ถ้าเราอยากให้ไล่จาก -4,-3,-2,-1,0 แทน 0,1,2,3,4 ก็ต้องแก้สูตรเป็น

    =Table.AddIndexColumn([Data],"running",-4,1)
    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 261

    คราวนี้เราจะลบคอลัมน์ Data ทิ้ง เพราะไม่ใช้แล้ว

    หลังจากนั้นกด Expand คอลัมน์ NewData ออกมาโดยเอาแค่ NumData กับ Running ดังรูป

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 262
    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 263

    เราจะสั่ง Pivot คอลัมน์ Topic ไปเป็นหัวตาราง แต่ว่าข้อมูลมันจะยัง Sum ไม่ได้เพราะยังไม่ได้เปลี่ยน NumData ให้เป็นตัวเลข

    ดังนั้นให้เปลี่ยนประเภทข้อมูล NumData ให้เป็นตัวเลขก่อนครับ (ถึงจะเลือกการ Sum ใน Step ถัดไปได้)

    จากนั้นค่อยเลือกคอลัมน์ Topic แล้วสั่ง Pivot Column

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 264

    ผลลัพธ์จะออกมาเป็นแบบที่อยากได้แล้ว

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 265

    ความเน่าเฟะที่ยังหลงเหลือ

    แต่ถ้าตรวจดูความเรียบร้อย ดันมีคอลัมน์งอกเกินมา ซึ่งเป็นผลมาจาก Symbol บางตัว

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 266

    ดังนั้นต้องย้อน Step กลับไปดูว่าพลาดตรงไหน

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 267

    จะพบว่า ดันมี Text จำพวก N/A ที่เราตั้งใจแปลงเป็น -99999 แต่ดันมี Text อื่นอีก เช่น N.A. และ –

    ดังนั้นเราต้องย้อน Step กลับไป Replace Value ให้ N.A. และ – เป็น -99999 ด้วย (แบบ Insert Step นะ)

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 268

    จากนั้นก็ Replace – ด้วย -99999 อีกที แต่ให้ติ๊กว่าต้องเจอแบบ Entire Cell Content ด้วยนะ ไม่งั้นมันแทนเครื่องหมายติดลบด้วยซวยเลย

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 269

    ถ้าเรากลับไปดู Step สุดท้าย จะพบว่าคอลัมน์ที่งอกเกินมาได้หายไปแล้ว

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 270

    จัดการวันที่

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 271

    เหลือปัญหาสุดท้ายคือ Data Type ของวันที่งบการเงิน แค่กดเปลี่ยน Data Type เป็น Date ก็จบเลย เพราะเลขเป็น 4 หมื่นกว่าอยู่แล้ว

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 272

    แก้คอลัมน์ Running ให้เป็น Year

    เดิม Running เราเป็น -4,-3,-2… สมมติว่าเราจะทำให้เป็น Y-4, Y-3, Y-2 ก็ทำได้

    ให้ไปที่คอลัมน์ Running -> Transform -> Format -> Add Prefix แล้วใส่คำว่า Y

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 273

    จากนั้นเปลี่ยนชื่อคอลัมน์เป็น Year ซะก็จบละ

    จบแล้ว สำเร็จ!!

    ในที่สุด เราก็ได้ฐานข้อมูลที่ต้องการแล้ว ดังนั้นกด Close & Load to.. ออกมาเป็น Table หรือจะเอาเข้า Pivot Table เลยก็ย่อมได้

    เทคนิคการเผชิญหน้ากับข้อมูลเน่าเฟะด้วย Power Query 274

    เป็นอย่างไรบ้างกับการต่อสู้อันยาวนานกับข้อมูลขยะอันเน่าเฟะ อาจมีขั้นตอนเยอะซักหน่อย แต่คิดว่าเป็นประโยชน์กับทุกคนแน่นอนครับ ใครสงสัยตรงไนก็ post ถามได้เลยนะครับ

  • ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic

    ในตอนนี้เราจะมาแนะนำแหล่งเรียนรู้ แหล่งฝึกฝน Logic เพื่อที่พวกเราจะได้มีโอกาสฝึกคิดมากขึ้น เป็นการเพิ่ม Exp ด้าน Logic นั่นเอง ซึ่งเป็นตอนต่อของเนื้อหาสองตอนก่อน คือ

    • ในตอนแรกเป็นการเกริ่นนำว่า Logic เป็นเรื่องที่พัฒนาได้ แค่ยอมรับและฝึกฝนในลำดับที่เหมาะสมกับความสามารถตนเอง และค่อยพัฒนาไปเจอแบบที่ซับซ้อนมากขึ้นเรื่อยๆ
    • ในตอน 2 เป็นการใช้ Logic กับ Excel ซึ่งจริงๆ จะเห็นว่าไม่ได้ใช้ความรู้ Logic ที่ซับซ้อนเท่าในวิชาคณิตศาสตร์ (ที่ต้องพิสูจน์ความสมเหตุสมผล) แต่ใช้แค่พวก AND, OR อะไรมากกว่า (แต่อาจต้องใช้ Systems Thinking หรือความรู้เชิงระบบเพิ่มเติมอีก ซึ่งจะพูดถึงในอนาคต)

    เอาล่ะเพื่อไม่ให้เสียเวลา เรามาเริ่มดูแหล่งเรียนรู้เรื่อง Logic กันดีกว่า

    รวมแหล่งฝึกฝน Logic

    เกมแนว Puzzle ต่างๆ (เล่นคนเดียว)

    ผมขอไล่จากที่ดูง่ายไปยากละกันนะครับ (Judgement ส่วนตัวนะ อย่าซีเรียส)

    ปริศนาแนว Logic Grid Puzzle

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 275

    เกมแนวนี้มักจะให้ข้อมูลเป็น Hint มาว่า ใครทำอะไร/ใครคู่กับอะไร? แต่จะให้แบบไม่ครบสมบูรณ์ เราต้องปะติดปะต่อเหตุการณ์แล้วทำการตัด choice ที่เป็นไปไม่ได้ออก จนกว่าจะเจอคำตอบที่ต้องการ

    ตัวอย่างแบบง่ายๆ เช่น

    มีคน 4 คน คือ นาย A, B, C, D และมีสัตว์เลี้ยงทั้งหมด 4 ประเภท คือ แมว, หมา, ปลา, นก โดยที่มีคำใบ้ (Hint) คือ

    1. สัตว์เลี้ยงของนาย A บินไม่ได้
    2. สัตว์เลี้ยงของ C และ D มี 4 ขา
    3. สัตว์เลี้ยงของ D ไม่เห่า

    โจทย์ต้องการให้หาว่า : ใครคือเจ้าของสัตว์เลี้ยงประเภทไหน?

    ซึ่งถ้าเราพิจารณาจาก Hint เฉยๆ จะพบว่าข้อมูลมันไม่เป็นระเบียบ อาจจะอ่านแล้วงง จับต้นชนปลายไม่ถูก แต่ว่าหากเรานำข้อมูลที่ได้จาก Hint มาใส่ตารางที่ออกแบบมาดีๆ เกมแนวนี้จะง่ายขึ้นมากๆ

    เราอาจเริ่มโดยใส่สัญลักษณ์เพื่อให้เห็นภาพมากขึ้น เช่น N คือแน่ใจว่าไม่ใช่, Y=แน่ใจว่าใช่

    ชื่อคน\สัตว์เลี้ยงแมวหมาปลานก
    AN (Hint1)
    B
    CN (Hint2)N (Hint2)
    DN (Hint3)N (Hint2)N (Hint2)

    พอเราใส่แบบข้างบนเราก็จะเริ่มไล่ใส่ข้อมูลเพิ่มได้ว่า D ต้องมีสัตว์เลี้ยงเป็นแมวแน่นอน เป็นตัวอื่นในแถวแนวนอนเดียวกันเป็น N หมดแล้ว ทำให้สามารถใส่ N ในแนวตั้งทั้งหมดในคอลัมน์แมวได้ด้วย

    ชื่อคน\สัตว์เลี้ยงแมวหมาปลานก
    AN (step1)N
    BN (step1)
    CN (step1)NN
    DY (step1)NNN

    ไล่ต่ออีก… ไปเรื่อยๆ จนครบ

    ชื่อคน\สัตว์เลี้ยงแมวหมาปลานก
    AN (step1)N (step2)Y (step3)N
    BN (step1)N (step2)N (step3)Y (step4)
    CN (step1)Y (step2)NN
    DY (step1)NNN

    สรุป

    ชื่อคน\สัตว์เลี้ยงแมวหมาปลานก
    AY
    BY
    CY
    DY

    กรอบความคิด (Framework) ที่ดีช่วยได้มาก

    ดังนั้นจะเห็นว่าถ้ามีระบบหรือกรอบความคิด (Framework) ที่ดี มันก็ช่วยให้เราหาคำตอบได้ง่ายขึ้นเยอะ ซึ่งผมคิดว่าเป็นเทคนิคที่สำคัญอย่างนึงเลยครับในชีวิตจริงของเราเลยล่ะครับ ^^

    ถ้าเจอโจทย์ในชีวิตจริง ก็พยายามหา Framework หรือวาดตารางออกมา โดยจับคู่ทุกมิติให้ครบ เราจะได้คิดให้ครบทุกกรณี เช่นมี 4 เรื่อง ก็ต้องจับคู่ได้ =COMBIN(4,2) = 6 แบบ

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 276

    เกมแนวนี้ส่วนตัวผมขอแนะนำ https://www.brainzilla.com/logic/logic-grid/ เพราะเว็บนี้ออกแบบการเล่นให้ง่ายขึ้นมาก เพราะเมื่อเรากดติ๊กว่ามั่นใจว่าถูกในช่องแล้วมันจะ auto ตัดตัวที่ไม่ใช่ทิ้งในแถวและคอลัมน์เดียวกันให้ด้วย

    Minesweeper

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 277

    ในสมัยก่อนเครื่อง Computer ทุกเครื่องจะมีเกม Minesweeper ซึ่งต้องหาว่าระเบิดอยู่ตรงไหน ซึ่งผมว่าก็ฝึก logic การตัด choice ได้ดีเลยครับ แต่ Minesweeper มันต้องอาศัยโชคอยู่นิดๆ ในบางจังหวะนะ 555

    เดี๋ยวนี้เหมือนจะไม่มีลงมากับเครื่องแล้ว ดังนั้น ใครสนใจก็เล่นได้ที่นี่ http://minesweeperonline.com/

    เกมแนวหา Sequence ที่ถูกต้อง

    เกมแนวนี้ต้องคิด Sequence ที่ถูกต้องในการแก้ปัญหา ยกตัวอย่างเช่น

    เกม Tower of Hanoi

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 278

    เป็นเกมที่ต้องย้าย Disc ไปยังแท่นที่สามให้ได้ โดยมีกติกาว่า เราไม่สามารถเอา Disc ใหญ่วางบน Disc เล็กได้ มันจึงต้อคิดให้ดีว่าจะย้าย Disc ยังไงก่อนหลัง

    ผมแนะนำให้เล่นที่นี่ครับ มีความยากหลายระดับ https://www.transum.org/Maths/Investigation/Tower_Of_Hanoi/

    (ปล. ในเว็บเดียวกันมี Puzzle อีกเพียบเลย https://www.transum.org/Software/Puzzles/)

    Sudoku

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 279

    Sudoku เป็นเกม Puzzle ยอดฮิต ที่ให้เราใส่เลข 1-9 ลงไปในช่องสี่เหลี่ยม
    โดยมีกติกาว่าห้ามมีเลขซ้ำกันในแถว ในคอลัมน์ และในบล๊อคย่อย 3×3

    ดังนั้นหลักการคือพยายามหาตัวที่มั่นใจที่สุดใส่ลงไปให้ได้ก่อน แล้วก็จะมีข้อมูลมากขึ้นจนสามารถตัด choice ของตัวเลขได้เอง

    เว็บที่แนะนำก็นี่เลย https://sudoku.com/ ดีตรงที่ถ้าเรายังไม่มั่นใจ มีเครื่องมือให้ทดเลขเอาไว้ก่อนได้ด้วย (กดตรง Note) ซึ่งการทดจะทำให้แก้ปริศนาได้ง่ายขึ้นเยอะ

    เกมกระดาน (แข่งกัน)

    Chess (หมากรุก)

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 280

    Chess หรือ หมากรุก เป็นเกมกระดานแบบสู้กัน 2 คนที่เป็นที่นิยมมากๆ โดยที่แต่ละฝ่ายมีหมากหรือตัวเดินหลายตัว แต่ละตัวมีความสามารถแตกต่างกัน จุดมุ่งหมายคือหาทางกิน King หรือขุนของอีกฝ่ายนึงให้ได้นั่นเอง

    หมากรุกมีหลาย version เพราะแต่ละประเทศอาจมีกติกาของตัวเอง เช่น ของไทยเราก็มีหมากรุกไทยด้วย แต่แบบที่เป็นที่นิยมสุดๆ ในโลกก็ต้องหนีไม่พ้นหมากรุกสากลอย่างแน่นอน

    ส่วนตัวแล้วผมคิดว่าการฝึกหมากรุก ไม่ได้ฝึก Logic โดยตรง แต่เป็นการฝึกการคิดในเชิงกลยุทธ์หรือ Strategic Thinking มากกว่า เพราะต้องคิดในเชิงว่า ถ้าเราทำแบบนี้ อีกฝ่ายจะตอบโต้ยังไงด้วย แต่มันก็ช่วยเรื่อง Logic ได้บ้างแหละและสนุกดีด้วย

    เว็บที่แนะนำคืออันนี้ https://www.chess.com/ เพราะมีครบตั้งแต่โหมดเล่นคนเดียว เล่นออนไลน์ และถ้ายังเล่นไม่เป็นก็มี Tutorial สอน

    รวมถึงมี Puzzle ให้แก้ด้วยด้วย (ตรง Puzzle นี่แหละที่พอจะช่วยฝึก logic ได้)

    สำหรับคนที่อยากเล่นหมากรุกไทยมากกว่า ก็มีแฟนเพจแนะนำเว็บนี้มาครับ https://www.playok.com/th/makruk/

    Go (โกะ/หมากล้อม)

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 281

    หากว่าหมากรุกคือบอร์ดเกมยอดฮิตแล้ว อีกเกมนึงที่ฮิตและโด่งดังมากในลำดับถัดไปก็คือ Go (โกะ) หรือหมากล้อมนั่นเอง

    หมากล้อมเป็นเกมที่กำเนิดมาจากประเทศจีนหลายพันปีก่อน และได้แพร่หลายไปยังเกาหลีและญี่ปุ่น และสุดท้ายก็แพร่หลายไปทั่วโลกในที่สุด

    หมากล้อมเป็นเกมที่มีตัวหมากแค่แบบเดียว (ไม่เหมือนหมากรุกที่มีหลายแบบ) และมีกติกาที่เรียบง่ายและจำง่ายกว่าหมากรุก แต่กลับเป็นเกมที่มีความลึกซึ้งและซับซ้อนมากๆ

    หมากล้อมเป็นเกมที่ลึกซึ้งมาก จนเรามักจะเห็นนักปราชญ์ในหนังจีนกำลังภายในสู้กันด้วยหมากล้อมอยู่เสมอๆ เลยล่ะ และการ์ตูนยอดฮิตอย่างฮิคารุเซียนโกะก็เป็นอีกเรื่องที่จุดกระแสโกะให้โด่งดังขึ้นมามากขึ้นด้วย

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 282

    ในสมัยก่อนการจะเขียนโปรแกรม Computer ให้เล่นหมากล้อมเก่งนี่ยากมากๆ (ยากและซับซ้อนกว่าหมากรุกเยอะ) เพราะกระดานโกะเป็นกระดานสี่เหลี่ยมจตุรัสที่มีเส้นอยู่ด้านละ 19 เส้นตัดกันเป็น 361 จุด แล้วผู้เล่นสามารถลงหมากที่จุดตัดไหนก็ได้ ดังนั้นมันจึงมีทางเดินที่เป็นไปได้มากมายมหาศาล

    จะว่าไปแล้วผมเองก็ไม่แน่ใจว่าโกะ มันฝึก Logic ด้วยรึเปล่า (หรือฝึกอย่างอื่นมากกว่า?) ซึ่งผมดันเล่นโกะไม่เก่งด้วยสิ ใครที่เล่นโกะบ่อยๆ ฝากช่วย Comment หน่อยนะครับว่ามันฝึกอะไรให้เราได้บ้าง แต่ที่แน่ๆ ผผมว่าคนเล่นโกะเก่งๆ เนี่ยมีดูฉลาดเอามากๆ เลยล่ะ ^^

    สำหรับเว็บที่แนะนำคืออันนี้ครับ https://online-go.com/ ซึ่งมีทั้งให้เล่น และมีสอนเล่นและก็ยังมี Puzzle ให้ฝึกคิดด้วย

    ป.ล. เมื่อปี 2015 ที่ผ่านมา Computer ชื่อ AlphaGo เพิ่งจะสามารถเอาชนะแชมป์โลกที่เป็นมนุษย์ได้ด้วยแนวทางการคิดแบบ Deep Learning (Machine Learning แบบนึงที่เลียนแบบ Concept การคิดของสมองมนุษย์) ซึ่งคอมพิวเตอร์ได้ฝึกโกะด้วยการเรียนรู้จากข้อมูลหมากตัวอย่างจนเก่งในระดับนึง และสุดท้ายก็แข่งกับตัวเองด้วยจำนวนตามหาศาลในเวลาอันรวดเร็วจนเก่งขึ้นเรื่อยๆ สุดท้ายก็แซงมนุษย์ที่เก่งที่สุดในโลกได้ในที่สุด (ในขณะที่ฝั่งหมากรุกนั้น Computer สามารถชนะมนุษย์ได้ตั้งแต่ปี 1996 แล้ว เพราะมันไม่ลึกซึ้งเท่า จึงเขียนโปรแกรมให้คิดดักได้ทุกทางอย่างง่ายๆ เลย)

    เกมที่ Excel Wizard เล่น

    ใครยังไม่จุใจ ลองไปหาเกมที่คุณ Bo แห่ง Excel Wizard แนะนำก็ได้ครับ ตามนี้เลย

    ทำอย่างไรเราถึงจะมี Logic ดีขึ้น? ตอนที่ 3 : แหล่งฝึกฝน Logic 283
  • Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น

    ในบทความนี้เราจะมาเรียนรู้การใช้ DAX เบื้องต้นกันครับ เดี๋ยวจะสอนแบบที่ว่า ไม่เคยใช้ DAX เลยก็สามารถเข้าใจได้นะ ก่อนอื่นเรามาลองดู Data ของตารางหลัก นั่นก็คือ fSales กันก่อนครับ

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 284

    เกิดอะไรขึ้นเมื่อลาก Field ตัวเลขลง Visual

    สิ่งที่เราควรรู้คือ เราสามารถลาก Field ที่เป็นตัวเลข (สังเกตว่าที่ Field มีสัญลักษณ์ Sigma อยู่) อย่างเช่น SalesQuantity ลง Visual ได้เลย และเราก็สามารถเลือกวิธีสรุปข้อมูลได้เช่นจะให้ Sum, Count, Average, Max, Min หรือแม้แต่ Distinct Count

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 285

    เวลาใน Values เรากดที่ลูกศรลงของ SalesQuantity ก็จะเห็นวิธีสรุปที่เลือกได้มากมายดังนี้

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 286

    ค่า Default ของการลากข้อมูลตัวเลขลงมาก็คือการ Sum แต่เราสามารถเปลี่ยนวิธีการสรุปข้อมูลได้ตาม Choice ที่เห็นในรูปข้างบน (เช่นเดียวกับใน PivotTable ของ Excel นั่นแหละ)

    ทั้งหมดที่ทำข้างบนนี้ เป็นสิ่งที่ไม่ควรทำ!

    การลาก Field ลงมาที่ Visual ตรงๆ เพื่อให้เกิดการสรุปแบบอัตโนมัติแบบนี้ เป็นการสร้าง Measure แบบที่เรียกว่า Implicit Measure ซึ่งเป็นสิ่งที่กูรูเรื่อง DAX บอกว่าเป็นสิ่งที่ไม่ควรทำ โดยที่เค้าแนะนำให้เราตั้งใจสร้าง Measure โดยเขียนสูตรการคำนวณขึ้นมาเองด้วย DAX จะดีกว่า

    ข้อดีของการสร้าง Measure ขึ้นมาเอง

    • Number format ติดตัวอยู่ที่ Measure
    • ชื่อไม่สับสน (ปกติถ้าลากด้วยวิธีการ Sum มันจะใช้ชื่อ Field มาให้เลย โดยที่ไม่มีคำว่า Sum โผล่มาด้วย ทำให้อาจจะสับสนได้ว่ามันสรุปด้วยวิธีไหน)
    • เขียนการคำนวณที่ซับซ้อนได้
    • เวลาเอาเข้า Power BI Service แล้วไม่มีปัญหากับการกด Analyze in Excel

    ดังนั้น มาเริ่มสร้าง Measure (Explicit Measure) กันเถอะ!!

    คำนวณ Total Sales Quantity

    การสร้าง Measure ขึ้นมาใหม่ ให้กดปุ่ม New Measure

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 287

    แล้วเขียนสูตรในรูปแบบ

    ชื่อMeasure=สูตรของMeasure

    Tips : หากเราอยู่ที่ Table ไหนแล้วกดสร้าง Measure ขึ้นมา Measure ก็จะถือว่ามีที่อยู่ใน Table นั้น (เรียกว่า Home Table) แต่เราสามารถย้าย Measure ไปอยู่ที่ Table ไหนก็ได้ (คือการเปลี่ยน Home Table) โดยที่จริงๆ แล้วไม่ได้มีผลเรื่องการคำนวณอะไรทั้งสิ้น

    การที่จะได้ Total Sales Quantity ซึ่งก็คือจำนวนชิ้นของสินค้าที่ขายได้ทั้งหมด เราก็ต้องเอาข้อมูลในคอลัมน์ SalesQuantity มาสรุปด้วยวิธี SUM จริงมั้ยครับ? ดังนั้นสูตรใน Measure นี้ก็คือการ SUM ง่ายๆ ธรรมดาๆ เลย

    TotalSalesQuantity=SUM(fSales[SalesQuantity])

    Tips : จำได้มั้ยว่าเราควรจะอ้างอิงคอลัมน์ด้วย ชื่อตาราง[ชื่อคอลัมน์]

    ใส่ Number Format ให้กับ Measure

    ข้อดีนึงของการสร้าง Measure ก็คือ เราสามารถกำหนด Number Format ฝังไว้กับ Measure ไว้เลย

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 288

    ไม่ว่าจะลาก Measure นั้นลงไปที่ Visual ใดก็ตาม เราก็จะได้ Number format นั้นไปเลย โดยไม่ต้องมานั่งเปลี่ยนใหม่ทุกครั้ง

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 289

    ดังนั้นแม้มันจะเป็นการคำนวณง่ายๆ โง่ๆ อย่าง SUM ก็ทำ Explicit Measure ให้เป็นนิสัยเถอะครับ ^^

    คำนวณ Total Revenue

    บอกลา VLOOKUP

    ต่อไปสมมติว่าเราอยากจะคำนวณยอดขาย สิ่งที่เราต้องทำคือเอา SalesQuantity มาคูณกับ UnitPrice ในแต่ละแถว

    แต่ปัญหาก็คือ Unit Price มันดันอยู่อีกตารางนึง ซึ่งถ้าเป็น Excel เราคงต้องใช้สูตรแนว VLOOKUP ดึงข้อมูลมาก่อนใช่มะ?

    แต่ใน DAX เราสามารถสร้าง New Column แล้วใช้ฟังก์ชันที่ชื่อว่า RELATED ดึงข้อมูลจากอีกตารางนึงมาได้เลย ข้อแม้คือต้องผูก Relationship แล้วเท่านั้น (และต้อง active ด้วย) ซึ่งวิธีเขียนสูตรมันง่ายมากกว่า VLOOKUP หลายร้อยเท่า เพราะแค่เลือกว่าต้องการข้อมูลในคอลัมน์ไหนแค่นั้นเอง (ห๊ะ!)

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 290

    นี่ไง เราได้ผลลัพธ์มาอย่างง่ายดาย แบบเรียบรู้ด้วยเวลาไม่ถึง 10 วินาที (ตอนเรียน VLOOKUP ครั้งแรกยากขนาดไหนคิดดู)

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 291

    แบบนี้ถ้าอยากได้ยอดขายต่อ 1 แถว ก็สร้าง New Column ขึ้นมาด้วยสูตรว่า

    LineRevenue = fSales[SalesQuantity]*fSales[UnitPrice]
    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 292

    และถ้าอยากได้ Total Revenue เราก็สามารถเอา LineRevenue มา SUM กันได้ ดังนั้นเราจะสร้าง New Measure ได้ว่า

    TotalRevenue = SUM(fSales[LineRevenue])

    เริ่มรู้จัก Row Context

    ก่อนหน้านี้ผมได้มีการพูดถึง Filter Context ไว้ว่า แม้วิธีสรุปจะเหมือนกัน (Measure เหมือนกัน) แต่สามารถแสดงค่าผลลัพธ์ใน Visual ต่างกัน เพราะมี Filter Context หรือวิธีการ Filter ข้อมูลก่อนที่จะคำนวณ Measure ที่ต่างกัน

    ในทำนองเดียวกัน ถ้าเราสังเกตผลลัพธ์แต่ละบรรทัดของ LineRevenue ก็จะเห็นว่าผลลัพธ์ออกมาต่างกัน ทั้งๆ ที่สูตรเขียนเหมือนกันแท้ๆ

    เหตุการณ์นี้เกิดขึ้นได้เพราะว่าตอนคำนวณมันมี Row Context อยู่ ซึ่งเป็นตัวที่บ่งบอกว่าตัวมันกำลังคำนวณข้อมูลที่ Row ไหนอยู่ มันจึงรู้ว่า สูตร fSales[SalesQuantity] นั้นให้อ้างอิงจากข้อมูลที่อยู่ในแถวของตัวเองเท่านั้น ซึ่งการคำนวณมันจะทำซ้ำๆ ทีละแถวจนกว่าจะครบทุกแถวในตาราง (การทำซ้ำ เรียกว่า Iterate) ซึ่งเราจะเห็นพฤติกรรมนี้ในสูตรอย่าง SUMX ด้วย

    สำหรับ Row Context ในเบื้องต้นนี้ไม่น่าจะงงอะไร เพราะมันคล้ายกับการที่เราเขียนสูตรใน Table ของ Excel มากๆ เลย จนคิดว่ามันไม่ได้มีอะไรพิสดารในการที่จะรู้ว่ากำลังคำนวณ Row ไหนอยู่ แต่เดี๋ยวพอเราเจอ Concept ที่ซับซ้อนขึ้นอย่าง SUMX และ CALCULATE เราจะได้เห็นความสำคัญของมันจริงๆ อีกทีนึงครับ

    New Column หรือ New Measure ?

    ถึงจุดนี้หลายคนอาจจะเริ่มสงสัยแล้วว่าเมื่อไหร่ต้อง New Column เมื่อไหร่ถึงจะ New Measure??

    หลักการคือ

    • ถ้าจะสร้างให้มีคอลัมน์เพิ่มมาจริงๆ ในตารางก็ต้อง New Column ซึ่ง New Column จะถูกสร้างให้มีตัวตนอยู่จริงๆ ในตารางของเรา และมักถูกใช้ใน Visual ได้ในฐานะ Category ในแกนต่างๆ ด้วย
    • ถ้าเราต้องการสร้างผลสรุป (เหมือนตอนลากเข้าไปสรุปใน PivotTable ด้วย Sum) เราก็จะใช้ Measure ซึ่ง Measure จะไม่มีตัวตนจนกว่าเราจะลากลงไปใน Visual

    ความต่างในเชิง Performance

    • การที่ New Column ถูกสร้างให้มีตัวตนจริงๆ ซึ่งเกิดการคำนวณขึ้นตอนที่ Refresh Data (ซึ่งเป็นขั้นตอนสร้าง Data Model) ซึ่งกิน Memory และ Disk Space จริงๆ
    • ส่วน Measure จะถูกคำนวณตอนที่ User ใช้งาน Report แล้วกดโน่นนี่นั่น ซึ่งจะทำให้ Filter Context เปลี่ยนไป ก็จะต้องมีการคำนวณใหม่

    แปลว่ามันคือการเลือก ว่าจะช้าตอนกด Refresh และเปลือง ram+space (ก็สร้าง Column) หรือจะช้าตอน User กดเล่น Report นิดหน่อย (สร้าง Measure)

    ซึ่งโดยทั่วไปเค้าจะคิดกันว่า ถ้าสร้าง Measure ได้ก็สร้าง Measure ไป เพราะมันคำนวณเร็วมาก จะได้ไม่เปลือง Ram และ Space (ลองดูก็ได้ครับ มันไม่ได้ช้าอะไรเลยตอนกดเล่น)

    สร้าง Measure TotalRevenue ตรงๆ โดยไม่ต้องมีคอลัมน์ช่วยเลยก็ได้

    ในความเป็นจริงแล้วเราสามารถสร้าง Measure TotalRevenue ที่คำนวณการ Sum LineRevenue โดยไม่ต้องมี UnitPrice และ LineRevenue เลยก็ได้

    ทั้งนี้เราจะใช้ฟังก์ชัน SUMX มาช่วย ซึ่งมีหลักการทำงานดัง slide นี้

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 293

    หรือพูดอีกอย่างได้ว่า ก็คือ SUMX สามารถจำลองการคำนวณอะไรก็ได้โดยทดไว้ในหัวมัน โดยที่มันจะสร้างการคำนวณ <expression> ในแต่ละแถวของตาราง <table>* (ตรงนี้แหละคือ Row Context ที่มันรู้ว่าต้องวิ่งคำนวณ iterate ซ้ำๆ ในแต่ละแถวของ Table ไหนจนครบตาราง) จากนั้นก็เอาผลลัพธ์ในแต่ละแถวที่ทดไว้ทั้งหมดมา SUM กัน (เพราะเราใช้ SUMX)

    *ซึ่ง<table> นี่ในอนาคตเราจะได้เรียนรู้ว่า มันสามารถระบุเป็นตารางที่ไม่ได้มีอยู่จริงใน Data Model ก็ได้ เพราะเราจะใช้ DAX สร้างตารางด้วยสูตรเช่น FILTER, DISTINCT, ALL, CALCULATETABLE ได้

    เช่นจำลอง fSales[SalesQuantity]*fSales[UnitPrice] แต่ละแถวของตาราง fSales

    TotalRevenueSUMX =
    SUMX ( fSales, fSales[SalesQuantity] * fSales[UnitPrice] )

    และไหนๆ ก็ไหนๆ แล้ว เราสามารถเขียน RELATED ในส่วนของ Expression ของ SUMX เพื่อที่จะได้ไม่ต้องสร้างคอลัมน์ fSales[UnitPrice] ด้วยซ้ำ (จะได้ไม่เปลืองที่) จะได้ว่า

    TotalRevenueSUMX =
    SUMX(fSales,fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))

    ซึ่งค่าที่ได้จะออกมาเท่ากับ TotalRevenue ตัวเดิมที่เราทำไว้เป๊ะเลยครับ

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 294

    ลบ Column และ Measure ที่ไม่จำเป็นซะ

    ดังนั้นแปลว่า ใน fSales เราไม่จำเป็นต้องมีคอลัมน์ UnitPrice กับ LineRevenue อีกต่อไป ก็สามารถคลิ๊กขวา Delete ทิ้งได้เลย

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 295

    ซึ่งพอกดลบคอลัมน์แล้ว Measure TotalRevenue ที่เคยอ้างอิงถึงคอลัมน์เหล่านั้นก็จะพังตามไปด้วย (ไม่แปลก) ก็ให้ลบ Measure เดิมทิ้งไปด้วยเช่นกันนะ

    สร้าง Total Cost of Goods Sold

    ในทำนองเดียวกับ TotalRevenueSUMX เราก็สามารถคำนวณ Total Cost of Goods Sold ได้ด้วย concept เดียวกันเลย แค่เปลี่ยนจาก UnitPrice เป็น UnitCost เอง

    จะได้ว่า

    TotalCOGS = 
    SUMX(fSales,fSales[SalesQuantity]*RELATED(dProduct[UnitCost]))

    สร้าง TotalGrossProfit

    Total Gross Profit เกิดจาก Total Revenue ลบด้วย Total Cost of Goods Sold ดังนั้นก็สามารถเขียนสูตรง่ายๆ โดยอ้างอิง Measure เดิมที่มีอยู่แล้วได้เลยว่า

    TotalGrossProfit = [TotalRevenueSUMX]-[TotalCOGS]

    Tips : จำได้มั้ยว่า ถ้าอ้างอิง Measure ให้ระบุแค่ [ชื่อmeasure] ไม่ต้องใส่ชื่อ Table นะ ตรงนี้ให้ทำเป็นนิสัยเลย เดี๋ยวมันจะส่งผลในอนาคตอย่างมากตอนเรียนเรื่อง CALCULATE ครับ

    เปลี่ยนชื่อ Measure ก็ไม่ทำให้สูตรพังนะ

    ชื่อ Measure เดิม TotalRevenueSUMX มันดูทุเรศไปหน่อย ให้เราคลิ๊กขวา Rename เป็น TotalRevenue เฉยๆ แหละดีกว่า ซึ่งพอทำแล้วสูตรทั้งหมดก็ยังใช้ได้อยู่นะครับ

    โดยสูตร TotalGrossProfit = [TotalRevenueSUMX]-[TotalCOGS]
    จะกลายเป็น TotalGrossProfit = [TotalRevenue]-[TotalCOGS] ให้เองเลย

    สร้าง Gross Profit Margin

    ทีนี้เราจะมาคำนวณว่ากำไรที่ได้มันเป็นกี่ % เมื่อเทียบกับยอดขาย สิ่งที่เราจะทำก็คือเอา TotalGrossProfit มาหารด้วย TotalRevenue ซึ่งเขียนได้ว่า

    GrossProfitMargin=[TotalGrossProfit]/[TotalRevenue]

    จริงมั้ยครับ?

    แต่ใน DAX มีฟังก์ชันการหารโดยเฉพาะชื่อว่า DEVIDE ซึ่งดีกว่าการหารตรงๆ ที่มันดัก Error กรณีตัวส่วนเป็น 0 ให้แล้วด้วย ดังนั้นเราจะเขียนแบบนี้เลย

    GrossProfitMargin = DIVIDE([TotalGrossProfit],[TotalRevenue])

    จากนั้นอย่าลืมปรับ Format เป็น % ด้วยล่ะ ผลลัพธ์ใน Visual จะได้เห็นเลขเป็น % ไปด้วย

    Power BI ตอนที่ 10: เรียนรู้ DAX เบื้องต้น 296

    สรุป DAX เบื้องต้น

    สรุปแล้ว สุดท้ายที่เราทำในบทนี้คือการสร้าง Measure ขึ้นมา 5 ตัว ดังนี้

    TotalSalesQuantity=SUM(fSales[SalesQuantity])
    TotalRevenue=SUMX(fSales,fSales[SalesQuantity]*RELATED(dProduct[UnitPrice]))
    TotalCOGS =SUMX(fSales,fSales[SalesQuantity]*RELATED(dProduct[UnitCost]))
    TotalGrossProfit = [TotalRevenue]-[TotalCOGS]
    GrossProfitMargin = DIVIDE([TotalGrossProfit],[TotalRevenue])

    ซึ่งทั้งหมดนี้คือ Measure ล้วนๆ ที่ไม่ต้องการคอลัมน์พิเศษอะไรเลยด้วยซ้ำ

    สำหรับ DAX เบื้องต้นของบทความนี้ก็ขอจบเพียงเท่านี้ เดี๋ยวต่อไปเราจะเริ่มรู้จัก พวก CALCULATE, FILTER, ALL ที่จะสามารถเปลี่ยน Filter Context ได้ ซึ่งใกล้จะได้เห็นพลังของสูตรแบบ DAX ที่แท้จริงแล้วล่ะ!

    สารบัญ Series Power BI

    ใครสนใจอยากเรียนเป็นคลิปวีดีโอ ผมมี