แชร์ผ่าน


DAX ฟังก์ชันที่ผู้ใช้กําหนดเอง (พรีวิว)

Note

DAXฟังก์ชันที่ผู้ใช้กําหนดเองอยู่ในการแสดงตัวอย่าง

DAXฟังก์ชันที่ผู้ใช้กําหนดเอง (UDF) ช่วยให้คุณจัดแพ็กเกจDAXตรรกะและนํากลับมาใช้ใหม่ได้เหมือนกับฟังก์ชันอื่นๆDAX FUNCTION แนะนําคีย์เวิร์ดใหม่ พารามิเตอร์เสริม (สเกลาร์ ตาราง และการอ้างอิง) และตัวช่วยตรวจสอบประเภทที่ทําให้การเขียนปลอดภัยและชัดเจนยิ่งขึ้น หลังจากที่คุณกําหนด UDF แล้ว คุณสามารถใช้ในหน่วยวัดคอลัมน์จากการคํานวณการคํานวณด้วยภาพ หรือแม้แต่ฟังก์ชันอื่นๆ ที่ผู้ใช้กําหนดเอง ผู้ใช้สามารถรวมศูนย์กฎทางธุรกิจ ปรับปรุงการบํารุงรักษา และพัฒนาการคํานวณได้อย่างปลอดภัยเมื่อเวลาผ่านไป ฟังก์ชันเป็นออบเจ็กต์โมเดลชั้นหนึ่งที่คุณสามารถสร้างและจัดการในDAXมุมมองคิวรีและมุมมอง TMDL และสามารถดูได้ใน Model explorer ภายใต้โหนดฟังก์ชัน

เปิดใช้งานฟังก์ชันที่ผู้ใช้กําหนดเอง

เมื่อต้องการลองใช้ UDF ในเดสก์ท็อป:

  1. ไปที่ตัวเลือกไฟล์>และตัวเลือกการตั้งค่า>
  2. เลือก แสดงตัวอย่างคุณสมบัติ และตรวจสอบDAXฟังก์ชันที่ผู้ใช้กําหนดเอง
  3. เลือก ตกลง และ รีสตาร์ท Power BI Desktop

กําหนดและจัดการฟังก์ชันที่ผู้ใช้กําหนด

มีหลายตําแหน่งในการกําหนดและจัดการฟังก์ชัน:

  • DAX มุมมองคิวรี (DQV) กําหนดและแก้ไขฟังก์ชันใน DQV DQV ยังมีการ สืบค้นด่วน ในเมนูบริบท (ประเมิน กําหนดและประเมิน และกําหนดฟังก์ชันทั้งหมดในโมเดลนี้) เพื่อช่วยให้คุณทดสอบและจัดการ UDF ได้อย่างรวดเร็ว
  • มุมมอง TMDL UDF ยังสามารถเขียนและแก้ไขใน TMDL ได้อีกด้วย มุมมอง TMDL ยังมีเมนูบริบท สคริปต์ TMDL ไป
  • ตัวสํารวจโมเดล ฟังก์ชันที่มีอยู่สามารถดูได้ภายใต้โหนด ฟังก์ชัน ใน Model explorer

เมื่อกําหนด UDF โปรดปฏิบัติตามข้อกําหนดการตั้งชื่อเหล่านี้:

ชื่อฟังก์ชัน:

  • ต้องมีรูปแบบที่ดีและมีเอกลักษณ์เฉพาะตัวภายในแบบจําลอง
  • สามารถรวมจุด (จุด) สําหรับการเว้นวรรคชื่อ (เช่น Microsoft.PowerBI.MyFunc) ไม่สามารถเริ่มต้นหรือลงท้ายด้วยจุดหรือมีช่วงเวลาติดต่อกัน
  • นอกเหนือจากจุดแล้ว ชื่อสามารถมีได้เฉพาะอักขระที่เป็นตัวอักษรและตัวเลขหรือขีดล่างเท่านั้น ไม่อนุญาตให้เว้นวรรคหรืออักขระพิเศษ
  • ต้องไม่ขัดแย้งกับฟังก์ชันในตัว DAX หรือคําที่สงวนไว้ (เช่น measure, function, define)

ชื่อพารามิเตอร์:

  • สามารถมีได้เฉพาะอักขระที่เป็นตัวอักษรและตัวเลขหรือขีดล่างเท่านั้น ไม่อนุญาตให้มีช่วงเวลา
  • ต้องไม่เป็นคําที่สงวนไว้

การใช้ DAX มุมมองคิวรี

คุณสามารถกําหนด อัปเดต และประเมินฟังก์ชันที่ผู้ใช้กําหนดเองใน DAX มุมมองคิวรี สําหรับข้อมูลเพิ่มเติมเกี่ยวกับDAXมุมมองคิวรี ให้ดูที่DAXมุมมองคิวรี

แบบฟอร์มทั่วไป

DEFINE
    /// Optional description above the function
    FUNCTION <FunctionName> = ( [ParameterName]: [ParameterType], ... ) => <FunctionBody>

เคล็ดลับ

ใช้สําหรับ /// คําอธิบายฟังก์ชัน ข้อคิดเห็นบรรทัดเดียว (//) หรือหลายบรรทัด (/* */) จะไม่ปรากฏในคําอธิบายฟังก์ชัน IntelliSense

ตัวอย่าง: ฟังก์ชันภาษีอย่างง่าย

DEFINE
    /// AddTax takes in amount and returns amount including tax
    FUNCTION AddTax = 
        ( amount : NUMERIC ) =>
            amount * 1.1

EVALUATE
{ AddTax ( 10 ) }
// Returns 11

บันทึกลงในโมเดล

เมื่อต้องการบันทึก UDF จาก DAX มุมมองคิวรีไปยังแบบจําลอง:

  • คลิก อัปเดตแบบจําลองด้วยการเปลี่ยนแปลง เพื่อบันทึก UDF ทั้งหมดในคิวรี
  • หรือคลิก อัปเดตโมเดล: เพิ่มฟังก์ชันใหม่ เหนือฟังก์ชันที่กําหนดไว้เพื่อบันทึก UDF เดียว

สกรีนช็อตของ DAX มุมมองคิวรีใน Power BI Desktop โดยเน้นตําแหน่งที่ตั้งสองตําแหน่งที่คุณสามารถบันทึกฟังก์ชันที่ผู้ใช้กําหนดได้ ปุ่มแรกคือปุ่มอัปเดตแบบจําลองที่มีการเปลี่ยนแปลงที่ด้านบนของมุมมอง รายการที่สองคือบรรทัดสถานะในตัวแก้ไขโค้ดที่มีป้ายกํากับว่าอัปเดตแบบจําลอง: เพิ่มฟังก์ชันใหม่

การใช้มุมมอง TMDL

คุณสามารถกําหนดและ/หรืออัพเดตฟังก์ชันที่ผู้ใช้กําหนดในมุมมอง TMDL สําหรับข้อมูลเพิ่มเติมเกี่ยวกับมุมมอง TMDL โปรดดู มุมมอง TMDL

แบบฟอร์มทั่วไป

createOrReplace
    /// Optional description above the function
    function <FunctionName> = ( [ParameterName]: [ParameterType], ... ) => <FunctionBody>

ตัวอย่าง: ฟังก์ชันภาษีอย่างง่าย

createOrReplace
    /// AddTax takes in amount and returns amount including tax
    function AddTax = 
        (amount : NUMERIC) =>
            amount * 1.1

บันทึกลงในโมเดล

คลิกปุ่ม นําไปใช้ ที่ด้านบนของมุมมองเพื่อบันทึก UDF ทั้งหมดในสคริปต์ไปยังโมเดล

สกรีนช็อตของมุมมอง TMDL ใน Power BI Desktop โดยเน้นปุ่ม นําไปใช้ ที่ด้านบนของมุมมอง นี่คือตําแหน่งที่คุณสามารถบันทึกฟังก์ชันที่ผู้ใช้กําหนดได้

การใช้สคริปต์ TMDL ในโครงการ Power BI

UDF ยังรวมอยู่ในสคริปต์ TMDL แบบจําลองความหมายเมื่อใช้โครงการ Power BI สามารถพบได้ในfunctions.tmdlโฟลเดอร์คําจํากัดความ

ภาพหน้าจอ Visual Studio Code ของโครงการ Power BI Explorer เปิดไปยังโฟลเดอร์แบบจําลองความหมาย 'functions.tmdl' เปิดอยู่ในโปรแกรมแก้ไขโค้ด ฟังก์ชันสามฟังก์ชันจะปรากฏขึ้น: CustomerLifetimeValue, AverageOrderValue และ AddTax

การใช้ตัวสํารวจแบบจําลอง

คุณสามารถดูฟังก์ชันที่ผู้ใช้กําหนดทั้งหมดในแบบจําลองได้จาก Model explorer ภายใต้โหนด ฟังก์ชัน สําหรับข้อมูลเพิ่มเติมเกี่ยวกับ Model explorer โปรดดู ตัวสํารวจแบบจําลอง

แผงตัวสํารวจแบบจําลองใน Power BI Desktop ที่แสดงโหนดฟังก์ชันที่ขยาย ฟังก์ชันที่ผู้ใช้กําหนดเองสามฟังก์ชันจะแสดงรายการ: AddTax, AverageOrderValue และ CustomerLifetimeValue

ใน DAX มุมมองคิวรี คุณสามารถใช้ คิวรีด่วน ในเมนูคลิกขวาของ UDF ภายใน Model explorer เพื่อกําหนดและประเมินฟังก์ชันได้อย่างง่ายดาย

บานหน้าต่างตัวสํารวจแบบจําลองใน Power BI Desktop แสดงโหนดฟังก์ชันที่ขยาย เมนูบริบทสองเมนูเปิดอยู่: เมนูแรกมี คิวรีด่วน เปลี่ยนชื่อ ลบออกจากแบบจําลอง ซ่อนในมุมมองรายงาน เลิกซ่อนทั้งหมด ยุบทั้งหมด และ ขยายทั้งหมด คิวรีด่วนจะถูกเน้นและเลือก เมนูที่สองถูกเน้นและมีตัวเลือกการสืบค้นด่วน ประเมิน กําหนดและประเมิน กําหนดฟังก์ชันใหม่ และกําหนดฟังก์ชันทั้งหมดในโมเดลนี้

ใน มุมมอง TMDL คุณสามารถ ลากและวาง ฟังก์ชันลงในพื้นที่ทํางาน หรือใช้ สคริปต์ TMDL ใน เมนูคลิกขวาของ UDF ภายใน Model explorer เพื่อสร้างสคริปต์

บานหน้าต่างตัวสํารวจแบบจําลองใน Power BI Desktop แสดงโหนดฟังก์ชันที่ขยาย เมนูบริบทสองเมนูเปิดอยู่: เมนูแรกให้ Script TMDL to, เปลี่ยนชื่อ, ลบออกจากแบบจําลอง, ซ่อนในมุมมองรายงาน, เลิกซ่อนทั้งหมด, ยุบทั้งหมด และ ขยายทั้งหมด สคริปต์เป็น TMDL ถูกไฮไลต์และเลือก เมนูที่สองถูกเน้นและเสนอตัวเลือกสคริปต์เป็น TMDL แท็บสคริปต์และคลิปบอร์ด

การใช้ DMV เพื่อตรวจสอบ UDF

คุณสามารถตรวจสอบ UDF ในโมเดลของคุณโดยใช้ มุมมองการจัดการแบบไดนามิก (DMV) มุมมองเหล่านี้ช่วยให้คุณสามารถสอบถามข้อมูลเกี่ยวกับฟังก์ชัน รวมถึง UDF

คุณสามารถใช้ INFO ฟังก์ชัน FUNCTIONS เพื่อตรวจสอบ UDF ในโมเดล หากต้องการจํากัดผลลัพธ์ไว้ที่ UDF เท่านั้น ให้ระบุORIGINพารามิเตอร์เป็น2

EVALUATE INFO.FUNCTIONS("ORIGIN", "2")

คิวรีนี้ส่งคืนตารางของ UDF ทั้งหมดที่อยู่ในแบบจําลองในปัจจุบัน รวมถึงชื่อ คําอธิบาย และข้อมูลเมตาที่เกี่ยวข้อง

การใช้ฟังก์ชันที่ผู้ใช้กําหนดเอง

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

การเรียก UDF ในหน่วยวัด

ใช้ UDF ในหน่วยวัดเพื่อใช้ตรรกะที่นํากลับมาใช้ใหม่ได้กับบริบทตัวกรองแบบเต็ม

Total Sales with Tax = AddTax ( [Total Sales] )

ตัวอย่างการวัดผลแสดงในตารางด้านล่าง:

ตารางแสดงยอดขายรวมและยอดขายรวมรวมพร้อมภาษี ยอดขายรวมพร้อมภาษีจะถูกเน้น บานหน้าต่างการแสดงภาพเปิดอยู่ ยอดขายรวมพร้อมภาษี จะถูกเน้นในฟิลด์ คอลัมน์ อย่างดี

การเรียก UDF ในคอลัมน์จากการคํานวณ

สามารถใช้ UDF ในคอลัมน์จากการคํานวณเพื่อใช้ตรรกะที่นํากลับมาใช้ใหม่ได้กับทุกแถวในตาราง

Note

เมื่อใช้ UDF ในคอลัมน์จากการคํานวณ ตรวจสอบให้แน่ใจว่าฟังก์ชันส่งกลับสเกลาร์ของชนิดที่สอดคล้องกัน ดู พารามิเตอร์ สําหรับข้อมูลเพิ่มเติม หากจําเป็น ให้แปลงผลลัพธ์เป็นประเภทที่ต้องการโดยใช้ CONVERT ฟังก์ชันหรือฟังก์ชันที่คล้ายกัน

Sales Amount with Tax = CONVERT ( AddTax ( 'Sales'[Sales Amount] ), CURRENCY )

เราสามารถดูตัวอย่างการวัดผลนี้ที่ใช้ในตารางด้านล่าง:

ตารางแสดงยอดขายและยอดขายพร้อมภาษี ยอดขายพร้อมภาษีจะถูกเน้น บานหน้าต่างการแสดงภาพเปิดอยู่ ยอดขายพร้อมภาษี จะถูกเน้นในฟิลด์ คอลัมน์ อย่างดี

การเรียก UDF ในการคํานวณด้วยภาพ

คุณสามารถใช้ UDF ในการคํานวณด้วยวิชวลเพื่อใช้ตรรกะโดยตรงกับวิชวล สําหรับข้อมูลเพิ่มเติมเกี่ยวกับการคํานวณด้วยภาพ โปรดดู การคํานวณด้วยภาพ

Note

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

Sales Amount with Tax = AddTax ( [Sales Amount] )

เราสามารถดูตัวอย่างการวัดนี้ได้ในตารางด้านล่าง:

ในโหมดแก้ไขการคํานวณด้วยภาพ ตารางแสดงยอดขายและยอดขายพร้อมภาษี ยอดขายพร้อมภาษีจะถูกเน้น สูตรการคํานวณด้วยภาพสําหรับยอดขายที่มีภาษีจะถูกเน้น

การเรียก UDF ใน UDF อื่น

คุณสามารถซ้อน UDF ได้โดยการเรียกฟังก์ชันจากฟังก์ชันอื่น ในตัวอย่างนี้เรากําหนด UDF อย่างง่าย AddTax ของเราและเรียกมันใน UDF AddTaxAndDiscountอื่น .

DEFINE
    /// AddTax takes in amount and returns amount including tax
    FUNCTION AddTax = 
        ( amount : NUMERIC ) =>
            amount * 1.1

	FUNCTION AddTaxAndDiscount = 
        (
			amount : NUMERIC,
			discount : NUMERIC
		) =>
		    AddTax ( amount - discount )

EVALUATE
{ AddTaxAndDiscount ( 10, 2 ) }
// Returns 8.8

พารามิเตอร์

DAX UDF สามารถรับพารามิเตอร์เป็นศูนย์หรือมากกว่า เมื่อคุณกําหนดพารามิเตอร์สําหรับ UDF คุณสามารถเลือกระบุคําใบ้ชนิดสําหรับแต่ละพารามิเตอร์ได้:

  • ชนิด: ชนิดของค่าที่พารามิเตอร์ยอมรับ (AnyVal, Scalar, Tableหรือ AnyRef)
  • ชนิดย่อย (สําหรับชนิดสเกลาร์เท่านั้น): ชนิดข้อมูลสเกลาเฉพาะ (Variant, , Int64, DecimalDouble, StringDateTimeBooleanหรือ )Numeric
  • ParameterMode: เมื่อมีการประเมินอาร์กิวเมนต์ (val หรือ expr)

คําแนะนําประเภทอยู่ในรูปแบบ: [type] [subtype] [parameterMode]

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

ประเภท

ชนิด จะกําหนดประเภทของอาร์กิวเมนต์ที่พารามิเตอร์ของคุณยอมรับ และไม่ว่าจะส่งผ่านเป็นค่าหรือนิพจน์

มีตระกูลชนิดสองชนิดใน DAX พารามิเตอร์ UDF: ชนิดค่า และ ชนิดนิพจน์:

  • ประเภทค่า: อาร์กิวเมนต์นี้จะได้รับ การประเมินทันที (การประเมินอย่างกระตือรือร้น) เมื่อมีการเรียกใช้ฟังก์ชันและค่าผลลัพธ์จะถูกส่งผ่านไปยังฟังก์ชัน
    • AnyVal: ยอมรับสเกลาร์หรือตาราง นี่เป็นค่าเริ่มต้นถ้าคุณละเว้น type สําหรับพารามิเตอร์
    • Scalar: ยอมรับค่าสเกลาร์ (สามารถเพิ่มชนิดย่อยเพิ่มเติมได้)
    • Table: ยอมรับตาราง
  • ชนิดนิพจน์: อาร์กิวเมนต์นี้ส่งนิ พจน์ที่ยังไม่ได้ประเมิน (การประเมินแบบขี้เกียจ) ฟังก์ชันจะตัดสินใจว่าจะประเมินเมื่อใดและในบริบทใด สิ่งนี้จําเป็นสําหรับพารามิเตอร์อ้างอิงและมีประโยชน์เมื่อคุณต้องการควบคุมบริบทตัวกรอง (เช่น ภายใน CALCULATE) expr ชนิดสามารถอ้างอิงไปยังคอลัมน์ ตาราง ปฏิทิน หรือหน่วยวัด
    • AnyRef: ยอมรับการอ้างอิง (คอลัมน์ ตาราง ปฏิทิน หรือหน่วยวัด)

ประเภทย่อย

ชนิดย่อยช่วยให้คุณสามารถกําหนดชนิดข้อมูลเฉพาะ Scalar ได้ ถ้าคุณกําหนดชนิดย่อย คุณไม่จําเป็นต้องกําหนดพารามิเตอร์เป็น Scalar ชนิดอย่างชัดเจน

ประเภทย่อยคือ:

  • Variant: ยอมรับสเกลาร์ใด ๆ
  • Int64: ยอมรับทั้งตัวเลข
  • Decimal: ยอมรับทศนิยมที่มีความแม่นยําคงที่ (เช่น สกุลเงินหรือเงิน)
  • Double: ยอมรับทศนิยมทศนิยมทศนิยม
  • String: ยอมรับข้อความ
  • DateTime: ยอมรับวันที่/เวลา
  • Boolean: ยอมรับ TRUE/FALSE.
  • Numeric: ยอมรับค่าตัวเลข (Int64, Decimalหรือ Double ชนิดย่อย)

โหมดพารามิเตอร์

ParameterMode ควบคุมเวลาและตําแหน่งที่นิพจน์พารามิเตอร์จะถูกประเมิน ต่อไปนี้คือ:

  • val (การประเมินอย่างกระตือรือร้น): นิพจน์จะได้รับการประเมินหนึ่งครั้งก่อนที่จะเรียกใช้ฟังก์ชัน ค่าผลลัพธ์จะถูกส่งผ่านไปยังฟังก์ชัน นี่เป็นเรื่องปกติสําหรับอินพุตสเกลาร์หรือตารางอย่างง่าย นี่เป็นค่าเริ่มต้นถ้าคุณละเว้น parameterMode สําหรับพารามิเตอร์
  • expr (การประเมินแบบขี้เกียจ): นิพจน์จะได้รับการประเมินภายในฟังก์ชัน ซึ่งอาจอยู่ในบริบทที่แตกต่างกัน (เช่น บริบทของแถวหรือบริบทตัวกรอง) และอาจหลายครั้งหากอ้างอิงหลายครั้งหรือภายในการทําซ้ํา สิ่งนี้จําเป็นสําหรับพารามิเตอร์อ้างอิงและมีประโยชน์เมื่อคุณต้องการควบคุมบริบทการประเมิน

Scalarประเภทสามารถใช้อย่างใดอย่างหนึ่งvalหรือ expr. ใช้ val เมื่อคุณต้องการให้สเกลาได้รับการประเมินหนึ่งครั้งในบริบทของผู้โทร ใช้ expr เมื่อคุณต้องการเลื่อนการประเมินและอาจใช้บริบทภายในฟังก์ชัน ดู ตัวอย่าง: พารามิเตอร์ตาราง เป็นตัวอย่าง

AnyRefชนิดต้องเป็นexprข้อมูลอ้างอิง (คอลัมน์ ตาราง หน่วยวัด ฯลฯ) ที่ต้องได้รับการประเมินในบริบทของฟังก์ชัน

ตัวอย่าง: การแคสต์ประเภท

DEFINE
    /// returns x cast to an Int64
    FUNCTION CastToInt = (
            x : SCALAR INT64 VAL
        ) =>
        x

EVALUATE
{ CastToInt ( 3.4 ), CastToInt ( 3.5 ), CastToInt ( "5" ) }
// returns 3, 4, 5

สิ่งนี้ใช้ Scalar type, Int64 subtype และ val parameterMode สําหรับการปัดเศษที่คาดเดาได้และการบีบบังคับข้อความเป็นตัวเลข ตลอดจนทําให้แน่ใจว่านิพจน์ใดๆ จะได้รับการประเมินอย่างกระตือรือร้น คุณยังสามารถทําสิ่งนี้ได้โดยการรวม Int64 ประเภทย่อยตามที่เห็นในตัวอย่างด้านล่าง สตริงที่ไม่ใช่ตัวเลขจะส่งผลให้เกิดข้อผิดพลาด

DEFINE
    /// returns x as an Int64
    FUNCTION CastToInt = (
            x : INT64
        ) =>
        x

EVALUATE
{ CastToInt ( 3.4 ), CastToInt ( 3.5 ), CastToInt ( "5" ) }
// returns 3, 4, 5

ตัวอย่าง: พารามิเตอร์ตาราง (ค่าเทียบกับนิพจน์)

เพื่อแสดงให้เห็นว่า UDF parameterMode ส่งผลต่อบริบทตัวกรองอย่างไร ให้พิจารณาฟังก์ชันสองฟังก์ชันที่ทั้งคู่นับแถวในตาราง 'ยอดขาย' ทั้งสองใช้ใน CALCULATETABLE(t, ALL('Date')) ร่างกาย แต่พารามิเตอร์หนึ่งถูกประกาศเป็น val (การประเมินที่กระตือรือร้น) และอีกตัวหนึ่งเป็น expr (การประเมินแบบขี้เกียจ):

DEFINE
    /// Table val: receives a materialized table, context can't be changed
    FUNCTION CountRowsNow = (
            t : TABLE VAL
        ) =>
        COUNTROWS ( CALCULATETABLE ( t, ALL ( 'Date' ) ) )
    
    /// Table expr: receives an unevaluated expression, context CAN be changed
    FUNCTION CountRowsLater = (
            t : TABLE EXPR
        ) =>
        COUNTROWS ( CALCULATETABLE ( t, ALL ( 'Date' ) ) )

EVALUATE
{
    CALCULATE ( CountRowsNow ( 'Sales' ), 'Date'[Fiscal Year] = "FY2020" ),
    CALCULATE ( CountRowsLater ( 'Sales' ), 'Date'[Fiscal Year] = "FY2020" )
}
// returns 84285, 121253

CountRowsNow ส่งคืนจํานวนยอดขายสําหรับปีงบประมาณ 2020 เท่านั้น ตาราง 'ยอดขาย' ถูกกรองตามปีก่อนเข้าสู่ฟังก์ชัน ดังนั้น ALL('Date') ภายในฟังก์ชันจึงไม่มีผล

CountRowsLater ส่งกลับจํานวนยอดขายสําหรับทุกปี ฟังก์ชันจะได้รับนิพจน์ตารางที่ยังไม่ได้ประเมินและประเมินภายใต้ ALL('Date')ลบตัวกรองปีภายนอก

การตรวจสอบประเภท

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

Note

สําหรับ expr พารามิเตอร์ parameterMode การตรวจสอบชนิดจะเกิดขึ้นเมื่อมีการอ้างอิงพารามิเตอร์ในเนื้อหาฟังก์ชัน (ไม่ใช่ในเวลาเรียกใช้ฟังก์ชัน)

ฟังก์ชั่นการตรวจสอบประเภทที่ใช้ได้

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

ประเภท ฟังก์ชัน
ตัวเลข ISNUMERICISNUMBER
คู่ ISDOUBLE
จำนวนเต็ม ISINT64, ISINTEGER
ทศนิยม ISDECIMAL,ISCURRENCY
สตริง ไอสตริงISTEXT
แบบบูลีน ไอสบูลีนISLOGICAL
วันที่และเวลา ISDATETIME

ตัวอย่าง: ตรวจสอบว่าพารามิเตอร์เป็นสตริงหรือไม่

DEFINE
    /// Returns the length of a string, or BLANK if not a string
    FUNCTION StringLength = (
            s
        ) =>
        IF ( ISSTRING ( s ), LEN ( s ), BLANK () )

EVALUATE
{ StringLength ( "hello" ), StringLength ( 123 ) }
// Returns: 5, BLANK

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

ตัวอย่าง: ยอมรับพารามิเตอร์หลายชนิด

DEFINE
    /// Helper 1: get currency name by int64 key
    FUNCTION GetCurrencyNameByKey = (
            k : INT64
        ) =>
        LOOKUPVALUE ( 'Currency'[Currency], 'Currency'[CurrencyKey], k )
    
    /// Helper 2: get currency name by string code
    FUNCTION GetCurrencyNameByCode = (
            code : STRING
        ) =>
        LOOKUPVALUE ( 'Currency'[Currency], 'Currency'[Code], code )
    
    /// Accepts key (int64) or code (string) and returns the currency name
    FUNCTION GetCurrencyName = (
            currency
        ) =>
        IF (
            ISINT64 ( currency ),
            GetCurrencyNameByKey ( currency ),
            GetCurrencyNameByCode ( currency )
        )

EVALUATE
{ GetCurrencyName ( 36 ), GetCurrencyName ( "USD" ) }
// returns "Euro", "US Dollar"

ตัวอย่างนี้แสดงวิธีใช้การตรวจสอบชนิดใน UDF เพื่อยอมรับอินพุตหลายชนิดอย่างปลอดภัยและส่งคืนผลลัพธ์เดียวที่คาดเดาได้ GetCurrencyName ใช้อาร์กิวเมนต์หนึ่งอาร์กิวเมนต์ currencyซึ่งอาจเป็นคีย์สกุลเงินจํานวนเต็มหรือรหัสสกุลเงินข้อความก็ได้ ฟังก์ชันจะตรวจสอบประเภทอาร์กิวเมนต์ด้วยISINT64 ถ้าอินพุตเป็นจํานวนเต็ม จะเรียกตัวช่วย GetCurrencyNameByKey ที่ค้นหาชื่อสกุลเงินตามคีย์สกุลเงิน ถ้าอินพุตไม่ใช่จํานวนเต็ม จะเรียกตัวช่วย GetCurrencyNameByCode ที่ค้นหาชื่อสกุลเงินตามรหัสสกุลเงิน

กําหนดหลายฟังก์ชันพร้อมกัน

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

DEFINE
    /// Multiplies two numbers
    FUNCTION Multiply = (
            a,
            b
        ) =>
        a * b

    /// Adds two numbers and 1
    FUNCTION AddOne = (
            x,
            y
        ) =>
        x + y + 1

    /// Returns a random integer between 10 and 100
    FUNCTION RandomInt = () =>
        RANDBETWEEN ( 10, 100 )

EVALUATE
{ Multiply ( 3, 5 ), AddOne ( 1, 2 ), RandomInt () }
// returns 15, 4, 98

ตัวอย่างขั้นสูง: การแปลงสกุลเงินที่ยืดหยุ่น

เพื่อแสดงให้เห็นว่า UDF สามารถจัดการกับตรรกะที่ซับซ้อนมากขึ้นได้อย่างไร DAX เราจะดูสถานการณ์การแปลงสกุลเงิน ตัวอย่างนี้ใช้การตรวจสอบประเภทและฟังก์ชันที่ซ้อนกันเพื่อแปลงจํานวนเงินที่กําหนดเป็นสกุลเงินเป้าหมายโดยใช้อัตราแลกเปลี่ยนเฉลี่ยหรือสิ้นวันสําหรับวันที่ที่กําหนด

createOrReplace
	function ConvertDateToDateKey =  
		( 
			pDate: scalar variant 
		) => 
		YEAR ( pDate ) * 10000 + MONTH ( pDate ) * 100 + DAY ( pDate ) 
	
	function ConvertToCurrency = 
		( 
			pCurrency:scalar variant, 
			pDate: scalar variant, 
			pUseAverageRate: scalar boolean, 
			pAmount: scalar decimal 
		) => 
		var CurrencyKey = 
			EVALUATEANDLOG ( 
				IF ( 
					ISINT64 ( pCurrency ), 
					pCurrency, 
					CALCULATE ( 
						MAX ( 'Currency'[CurrencyKey] ), 
						'Currency'[Code] == pCurrency 
					) 
				) 
				, "CurrencyKey" 
			) 

		var DateKey = 
			EVALUATEANDLOG ( 
				SWITCH ( 
					TRUE, 
					ISINT64 ( pDate ), pDate, 
					ConvertDateToDateKey ( pDate ) 
				) 
				, "DateKey" 
			) 

		var ExchangeRate = 
			EVALUATEANDLOG ( 
				IF ( 
					pUseAverageRate, 
					CALCULATE ( 
						MAX ( 'Currency Rate'[Average Rate] ), 
						'Currency Rate'[DateKey] == DateKey, 
						'Currency Rate'[CurrencyKey] == CurrencyKey 
					), 
					CALCULATE ( 
					MAX ( 'Currency Rate'[End Of Day Rate] ), 
						'Currency Rate'[DateKey] == DateKey, 
						'Currency Rate'[CurrencyKey] == CurrencyKey 
					) 
				) 
				, "ExchangeRate" 
			) 

		var Result = 
			IF ( 
				ISBLANK ( pCurrency ) || ISBLANK ( pDate ) || ISBLANK ( pAmount ), 
				BLANK (), 
				IF ( 
					ISBLANK ( ExchangeRate ) , 
					"no exchange rate available", 
					ExchangeRate * pAmount 
				) 
			) 

		RETURN Result

ฟังก์ชันนี้ ConvertToCurrency ยอมรับประเภทการป้อนข้อมูลที่ยืดหยุ่นสําหรับทั้งสกุลเงินและวันที่ ผู้ใช้สามารถระบุคีย์สกุลเงินหรือคีย์วันที่ได้โดยตรง หรือระบุรหัสสกุลเงินหรือค่าวันที่มาตรฐาน ฟังก์ชันจะตรวจสอบประเภทของอินพุตแต่ละรายการและจัดการตามนั้น: หาก pCurrency เป็นจํานวนเต็ม จะถือว่าเป็นคีย์สกุลเงิน มิฉะนั้น ฟังก์ชันจะถือว่าเป็นรหัสสกุลเงินและพยายามแก้ไขคีย์ที่เกี่ยวข้อง pDate ทําตามรูปแบบที่คล้ายกันหากเป็นจํานวนเต็มจะถือว่าเป็นคีย์วันที่ มิฉะนั้นฟังก์ชันจะถือว่าเป็นค่าวันที่มาตรฐานและถูกแปลงเป็นคีย์วันที่โดยใช้ ConvertDateToDateKey ฟังก์ชันตัวช่วย หากฟังก์ชันไม่สามารถกําหนดอัตราแลกเปลี่ยนที่ถูกต้องได้ จะส่งคืนข้อความ "ไม่มีอัตราแลกเปลี่ยน"

ตรรกะนี้สามารถใช้เพื่อกําหนดหน่วยวัด เช่น ยอดขายรวมในสกุลเงินท้องถิ่น

Total Sales in Local Currency = 
ConvertToCurrency (
    SELECTEDVALUE ( 'Currency'[Code] ),
    SELECTEDVALUE ( 'Date'[DateKey] ),
    TRUE,
    [Total Sales]
)

ซึ่งสามารถเลือกจับคู่กับ สตริงรูปแบบไดนามิก เพื่อแสดงผลลัพธ์ในรูปแบบสกุลเงินที่เหมาะสม

CALCULATE (
    MAX ( 'Currency'[Format String] ),
    'Currency'[Code] == SELECTEDVALUE ( 'Currency'[Code] )
)

ตัวอย่างผลลัพธ์สามารถดูได้ในภาพหน้าจอด้านล่าง

ตารางแสดงวันที่เต็ม สกุลเงิน ยอดขายรวมในสกุลเงินท้องถิ่น และยอดขายรวม

ข้อควรพิจารณาและข้อจำกัด

ฟังก์ชันที่ผู้ใช้กําหนดเองอยู่ในการแสดงตัวอย่าง และในระหว่างการแสดงตัวอย่าง โปรดทราบข้อควรพิจารณาและข้อจํากัดต่อไปนี้:

ทั่วไป:

  • ไม่สามารถเขียนหรือสร้างแบบจําลอง DAX UDF ในบริการได้

  • ไม่สามารถซ่อน/เลิกซ่อน UDF ในโมเดลได้

  • ไม่สามารถใส่ UDF ในโฟลเดอร์ที่แสดงผลได้

  • ไม่มีปุ่ม 'สร้างฟังก์ชัน' ใน Ribbon

  • ไม่สามารถรวม UDF กับการแปลได้

  • UDF ไม่ได้รับการสนับสนุนในรุ่นที่ไม่มีตาราง

  • ไม่มีคิวรีด่วน 'กําหนดด้วยการอ้างอิง' ใน DAX มุมมองคิวรี

  • Object-Level Security (OLS) จะไม่ถ่ายโอนไปยังฟังก์ชันหรือในทางกลับกัน ตัวอย่างเช่น พิจารณาฟังก์ชัน F ต่อไปนี้ที่อ้างถึงการวัดที่ปลอดภัย MyMeasure:

    function F = () => [MyMeasure] + 42
    

    เมื่อมีการ MyMeasure รักษาความปลอดภัยโดยใช้การรักษาความปลอดภัยระดับวัตถุ ฟังก์ชัน F จะไม่ได้รับการรักษาความปลอดภัยโดยอัตโนมัติ หาก F ทํางานภายใต้ข้อมูลประจําตัวโดยไม่มีการเข้าถึง MyMeasureมันจะทําหน้าที่ราวกับว่า MyMeasure ไม่มีอยู่จริง เราขอแนะนําให้หลีกเลี่ยงการเปิดเผยวัตถุที่ปลอดภัยในชื่อฟังก์ชันและคําอธิบาย

การกําหนด UDF:

  • ไม่รองรับการเรียกซ้ําหรือการเรียกซ้ําร่วมกัน
  • ไม่รองรับการโอเวอร์โหลดฟังก์ชัน
  • ไม่รองรับชนิดการส่งคืนที่ชัดเจน

พารามิเตอร์ UDF:

  • ไม่รองรับพารามิเตอร์เพิ่มเติม
  • ไม่รองรับคําอธิบายพารามิเตอร์
  • UDF ไม่สามารถส่งคืน enum ค่าได้ ฟังก์ชันที่มีอยู่แล้วภายในที่ยอมรับ enum ค่าเป็นพารามิเตอร์ฟังก์ชันจะไม่สามารถใช้ UDF ในบริบทนั้นได้
  • พารามิเตอร์ที่ไม่ถูกผูกของคําใบ้ expr ชนิดจะไม่ถูกประเมิน

รองรับ IntelliSense:

  • แม้ว่า UDF จะสามารถใช้ในการเชื่อมต่อสดหรือโมเดลคอมโพสิตได้ แต่ก็ไม่รองรับ IntelliSense
  • แม้ว่า UDF จะสามารถใช้ในการคํานวณด้วยภาพ แต่แถบสูตรการคํานวณด้วยภาพไม่มีการสนับสนุน IntelliSense สําหรับ UDF
  • มุมมอง TMDL ไม่มีการสนับสนุน IntelliSense ที่เหมาะสมสําหรับ UDF

ข้อบกพร่องที่ทราบ

ปัญหาต่อไปนี้เป็นที่ทราบกันดีในขณะนี้และอาจส่งผลกระทบต่อฟังก์ชันการทํางาน:

  • การอ้างอิงไปยังวัตถุแบบจําลองแบบตาราง (เช่น หน่วยวัด ตาราง คอลัมน์) ใน UDF จะไม่ได้รับการอัปเดตโดยอัตโนมัติเมื่อมีการเปลี่ยนชื่อวัตถุเหล่านั้น ถ้าคุณเปลี่ยนชื่อวัตถุที่ UDF ขึ้นอยู่กับ เนื้อหาของฟังก์ชันจะยังคงมีชื่อเก่าอยู่ คุณต้องแก้ไขนิพจน์ UDF ด้วยตนเองเพื่อปรับปรุงการอ้างอิงทั้งหมดไปยังวัตถุที่เปลี่ยนชื่อ
  • สถานการณ์ขั้นสูงบางอย่างที่เกี่ยวข้องกับ UDF อาจส่งผลให้ตัวแยกวิเคราะห์ไม่สอดคล้องกัน ตัวอย่างเช่น ผู้ใช้อาจเห็นขีดเส้นใต้สีแดงหรือข้อผิดพลาดในการตรวจสอบความถูกต้องเมื่อส่งคอลัมน์เป็น expr พารามิเตอร์หรือใช้การอ้างอิงคอลัมน์ที่ไม่มีเงื่อนไข