DAX fungsi yang ditentukan oleh pengguna (pratinjau)

Nota

DAX fungsi buatan pengguna saat ini dalam tahap pratinjau.

DAX fungsi yang ditentukan pengguna (UDF) memungkinkan Anda mengemas DAX logika dan menggunakannya kembali seperti fungsi lainnya DAX . UDF memperkenalkan kata kunci baru FUNCTION, parameter opsional parameter (skalar, tabel, dan referensi), serta alat bantu pemeriksaan tipe type checking yang membuat penulisan lebih aman dan lebih jelas. Setelah menentukan UDF, Anda dapat menggunakannya dalam ukuran, kolom terhitung, perhitungan visual, atau bahkan fungsi lain yang ditentukan pengguna. Pengguna dapat mempusatkan aturan bisnis, meningkatkan keberlanjutan, dan mengembangkan perhitungan dengan aman dari waktu ke waktu. Fungsi adalah objek model kelas satu yang dapat Anda buat dan kelola dalam DAX tampilan kueri dan tampilan TMDL, dan dapat dilihat di Penjelajah model di bawah simpul Fungsi .

Mengaktifkan fungsi yang ditentukan pengguna

Untuk mencoba UDF di Desktop:

  1. Buka Opsi File > dan pengaturan > Opsi.
  2. Pilih Pratinjau fitur dan periksa DAX fungsi yang ditentukan pengguna.
  3. Pilih OK dan mulai ulang Power BI Desktop.

Menentukan dan mengelola fungsi yang ditentukan pengguna

Ada beberapa lokasi untuk menentukan dan mengelola fungsi:

  • DAX tampilan kueri (DQV). Tentukan dan ubah fungsi di DQV. DQV juga menyertakan menu konteks Kueri Cepat (Evaluasi, Menentukan dan mengevaluasi, serta Menentukan semua fungsi dalam model ini) untuk membantu Anda menguji dan mengelola UDF secara cepat.
  • Tampilan TMDL. UDF juga dapat ditulis dan diedit di TMDL. Tampilan TMDL juga menyertakan Skrip TMDL menu konteks.
  • Penjelajah model. Fungsi baru dapat dibuat dan fungsi yang ada dapat dimodifikasi menggunakan bilah rumus. Fungsi yang ada dapat dilihat di bawah simpul Functions di Penjelajah model.

Saat menentukan UDF, ikuti persyaratan penamaan ini:

Nama fungsi:

  • Harus terstruktur dengan baik dan unik dalam model.
  • Dapat menyertakan titik untuk penamaan ruang lingkup (namespacing) (misalnya Microsoft.PowerBI.MyFunc). Tidak dapat memulai atau mengakhiri periode atau memiliki periode berturut-turut.
  • Selain titik, nama hanya dapat berisi karakter alfanumerik atau garis bawah. Tidak ada spasi atau karakter khusus yang diizinkan.
  • Tidak boleh berkonflik dengan fungsi bawaan atau kata yang dipesan (misalnya, pengukuran, fungsi, definisi) DAX.

Nama parameter:

  • Hanya dapat berisi karakter alfanumerik atau garis bawah. Periode tidak diperbolehkan.
  • Tidak boleh berupa kata yang dicadangkan.

Menggunakan tampilan kueri DAX

Anda dapat menentukan, memperbarui, dan mengevaluasi fungsi yang ditentukan pengguna dalam DAX tampilan kueri. Untuk informasi tambahan tentang DAX tampilan kueri, lihat DAX tampilan kueri.

Formulir umum

DEFINE
    /// Optional description above the function
    /// @param {ParameterType} ParameterName - ParameterDescription
    /// ...
    /// @returns ReturnDescription
    FUNCTION <FunctionName> = ( [ParameterName]: [ParameterType], ... ) => <FunctionBody>

Petunjuk / Saran

Menggunakan tag blok JSDoc, dokumentasikan fungsi Anda dengan deskripsi, nama dan jenis parameter, dan kembalikan informasi untuk membuatnya lebih mudah digunakan. Perhatikan /// untuk deskripsi fungsi. Komentar baris tunggal (//) atau multibaris (/* */) tidak akan muncul dalam deskripsi fungsi IntelliSense.

Contoh: Fungsi pajak sederhana

DEFINE
    /// AddTax takes in amount and returns amount including tax
    /// @param {NUMERIC} amount - The pre-tax value to which tax will be applied
    /// @returns The amount including 10% tax
    FUNCTION AddTax = 
        ( amount : NUMERIC ) =>
            amount * 1.1

EVALUATE
{ AddTax ( 10 ) }
// Returns 11

Menyimpan ke dalam model

Untuk menyimpan UDF dari DAX tampilan kueri ke model:

  • Klik Perbarui model dengan perubahan untuk menyimpan semua UDF dalam kueri.
  • Atau klik Perbarui model: Tambahkan fungsi baru di atas fungsi yang ditentukan untuk menyimpan satu UDF.

DAX Cuplikan layar tampilan kueri di Power BI Desktop, menyoroti dua lokasi tempat Anda bisa menyimpan fungsi yang ditentukan pengguna. Yang pertama adalah tombol Perbarui model dengan perubahan di bagian atas tampilan. Yang kedua adalah baris status di editor kode berlabel Model pembaruan: Tambahkan fungsi baru

Menggunakan tampilan TMDL

Anda dapat menentukan dan/atau memperbarui fungsi yang ditentukan pengguna dalam tampilan TMDL. Untuk informasi tambahan tentang tampilan TMDL, lihat tampilan TMDL.

Formulir umum

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

Contoh: Fungsi pajak sederhana

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

Menyimpan ke dalam model

Klik tombol Terapkan di bagian atas tampilan untuk menyimpan semua UDF dalam skrip ke model.

Cuplikan layar tampilan TMDL di Power BI Desktop, menyoroti tombol Terapkan di bagian atas tampilan. Ini adalah lokasi tempat Anda dapat menyimpan fungsi yang ditentukan pengguna.

Menggunakan skrip TMDL dalam Proyek Power BI

UDF juga disertakan dalam skrip TMDL model semantik saat menggunakan proyek Power BI. Mereka dapat ditemukan di dalam functions.tmdl folder definisi .

Cuplikan layar Visual Studio Code dari proyek Power BI. Explorer terbuka untuk folder model semantik. 'functions.tmdl' terbuka di editor kode. Tiga fungsi ditampilkan: CustomerLifetimeValue, AverageOrderValue, dan AddTax.

Menggunakan penjelajah Model

Anda dapat melihat semua fungsi yang ditentukan pengguna dalam model dari Penjelajah model di bawah simpul Functions . Untuk informasi tambahan tentang Penjelajah model, lihat Penjelajah model.

Panel penjelajah model di Power BI Desktop memperlihatkan simpul Fungsi yang diperluas. Tiga fungsi yang ditentukan pengguna tercantum: AddTax, AverageOrderValue, dan CustomerLifetimeValue.

Dalam DAX tampilan kueri, Anda bisa menggunakan Kueri cepat di menu klik kanan UDF dalam penjelajah Model untuk menentukan dan mengevaluasi fungsi dengan mudah.

Panel penjelajah model di Power BI Desktop menampilkan simpul Fungsi yang diperluas. Dua menu konteks terbuka: menu pertama menyediakan Kueri cepat, Ganti Nama, Hapus dari model, Sembunyikan dalam tampilan laporan, Munculkan semua, Ciutkan semua, dan Perluas semua. Kueri cepat disorot dan dipilih. Menu kedua disorot dan menawarkan opsi Kueri cepat Mengevaluasi, Menentukan dan mengevaluasi, Menentukan dengan referensi dan mengevaluasi, Menentukan fungsi baru, dan Menentukan semua fungsi dalam model ini.

Dalam tampilan TMDL, Anda dapat menyeret dan meletakkan fungsi ke kanvas atau menggunakan Script TMDL ke di menu klik kanan UDF dalam penjelajah Model untuk menghasilkan skrip.

Panel penjelajah model di Power BI Desktop menampilkan simpul Fungsi yang diperluas. Dua menu konteks terbuka: menu pertama menyediakan Skrip ke TMDL, Ganti Nama, Hapus dari model, Sembunyikan dalam tampilan laporan, Munculkan semua, Ciutkan semua, dan Perluas semua. Skrip ke TMDL disorot dan dipilih. Menu kedua disorot dan menawarkan opsi Skrip ke TMDL: Tab Skrip dan Clipboard.

Menggunakan DMV untuk memeriksa UDF

Anda dapat memeriksa UDF dalam model Anda menggunakan Tampilan Manajemen Dinamis (DMV). Tampilan ini memungkinkan Anda mengkueri informasi tentang fungsi, termasuk UDF.

Anda dapat menggunakan INFO.USERDEFINEDFUNCTIONS untuk memeriksa UDF dalam model. Fungsi ini mengembalikan metadata penuh dan memerlukan izin tulis.

EVALUATE INFO.USERDEFINEDFUNCTIONS()

Atau, Anda dapat menggunakan fungsi INFO.FUNCTIONS untuk mengembalikan nama UDF dan metadata terbatas.

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

Menggunakan fungsi yang ditentukan pengguna

Setelah UDF ditentukan dan disimpan ke model, Anda dapat memanggilnya dari pengukuran, kolom terhitung, perhitungan visual, dan UDF lainnya. Ini berfungsi sama dengan memanggil fungsi bawaan DAX .

Memanggil UDF dalam sebuah metrik

Gunakan UDF dalam ukuran untuk menerapkan logika yang dapat digunakan kembali dengan konteks filter penuh.

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

Contoh pengukuran diperlihatkan dalam tabel di bawah ini:

Tabel memperlihatkan Total Penjualan dan Total Penjualan dengan Pajak. Total Penjualan dengan Pajak disorot. Panel visualisasi terbuka. Total Penjualan dengan Pajak disorot di bidang Kolom dengan baik.

Memanggil UDF dalam kolom terhitung

UDF dapat digunakan dalam kolom terhitung untuk menerapkan logika yang dapat digunakan kembali ke setiap baris dalam tabel.

Nota

Saat menggunakan UDF dalam kolom terhitung, pastikan fungsi mengembalikan skalar dari jenis yang konsisten. Lihat Parameter untuk informasi selengkapnya. Jika diperlukan, konversikan hasilnya ke jenis yang diinginkan menggunakan CONVERT atau fungsi serupa.

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

Kita dapat melihat contoh pengukuran ini yang digunakan dalam tabel di bawah ini:

Tabel memperlihatkan Jumlah Penjualan dan Jumlah Penjualan dengan Pajak. Jumlah Penjualan dengan Pajak disorot. Panel visualisasi terbuka. Jumlah Penjualan dengan Pajak disorot di bidang Kolom dengan baik.

Memanggil UDF dalam perhitungan visual

Anda dapat menggunakan UDF dalam perhitungan visual untuk menerapkan logika langsung ke visual. Untuk informasi tambahan tentang penghitungan visual, lihat Perhitungan Visual.

Nota

Perhitungan visual hanya beroperasi pada bidang yang ada di visual. Mereka tidak dapat mengakses objek model yang bukan bagian dari visual, dan Anda tidak dapat meneruskan objek model (seperti kolom atau pengukuran yang tidak ada dalam visual) ke dalam UDF dalam konteks ini.

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

Kita dapat melihat contoh pengukuran ini dalam tabel di bawah ini:

Dalam mode edit perhitungan visual. Tabel memperlihatkan Jumlah Penjualan dan Jumlah Penjualan dengan Pajak. Jumlah Penjualan dengan Pajak disorot. Rumus perhitungan visual untuk jumlah Penjualan dengan Pajak disorot.

Memanggil UDF di UDF lain

Anda dapat menumpuk UDF dengan memanggil fungsi dari fungsi lain. Dalam contoh ini kami mendefinisikan UDF sederhana AddTax kami dan memanggilnya dalam UDF lain, 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

Parameter-parameternya

DAX UDF dapat menerima parameter nol atau lebih. Saat menentukan parameter untuk UDF, Anda dapat secara opsional menentukan petunjuk jenis untuk setiap parameter:

  • Jenis: jenis nilai apa yang diterima parameter (AnyVal, , Scalar, Table, AnyRefCalendarRef, ColumnRef, MeasureRef atau TableRef).
  • Subjenis (hanya untuk jenis skalar): jenis data skalar tertentu (Variant, Int64, Decimal, Double, String, DateTime, Boolean, atau Numeric).
  • ParameterMode: ketika argumen dievaluasi (val atau expr).

Petunjuk jenis ada dalam formulir: [type] [subtype] [parameterMode]

Anda dapat menyertakan semua, beberapa, atau tidak satu pun dari petunjuk jenis ini untuk setiap parameter agar fungsi Anda lebih aman dan lebih dapat diprediksi di situs panggilan. Jika Anda menghilangkan semuanya dan hanya menulis nama parameter, maka akan berperilaku seperti AnyVal val, yang berarti argumen dievaluasi segera saat waktu pemanggilan. Ini berguna untuk fungsi sederhana.

Tipe

Jenis menentukan kategori argumen yang diterima parameter Anda dan apakah itu diteruskan sebagai nilai atau ekspresi.

Ada dua jenis keluarga dalam DAX parameter UDF: jenis nilai dan jenis ekspresi:

  • Jenis nilai: argumen ini dievaluasi segera (evaluasi bersemangat) ketika fungsi dipanggil dan nilai yang dihasilkan diteruskan ke fungsi.
    • AnyVal: Menerima skalar atau tabel. Ini adalah default jika Anda tidak menentukan jenis untuk parameter.
    • Scalar: Menerima nilai skalar (juga dapat menambahkan subjenis).
    • Table: Menerima tabel.
  • Jenis ekspresi: argumen ini melewati ekspresi yang tidak dievaluasi (evaluasi malas). Fungsi memutuskan kapan dan dalam konteks apa untuk mengevaluasinya. Ini diperlukan untuk parameter referensi dan berguna ketika Anda perlu mengontrol konteks filter (misalnya di dalam CALCULATE). expr jenis dapat menjadi referensi ke kolom, tabel, kalender, atau pengukuran.
    • AnyRef: Menerima referensi apa pun. Ini setara dengan tidak menentukan jenis ekspresi.
    • CalendarRef: Menerima referensi ke kalender.
    • ColumnRef: Menerima referensi ke kolom.
    • MeasureRef: Menerima referensi ke ukuran.
    • TableRef: Menerima referensi ke tabel.

Jenis nilai (AnyVal, Scalar, Table) mendukung casting tipe implisit. Jenis ekspresi (AnyRef, CalendarRef, ColumnRef, MeasureRef, TableRef) tidak melakukan hal tersebut.

Subtipe

Subjenis memungkinkan Anda menentukan jenis data tertentu Scalar . Jika Anda menentukan subjenis, Anda tidak perlu secara eksplisit menentukan parameter sebagai Scalar jenis, ini secara otomatis diasumsikan.

Subjenis adalah:

  • Variant: Menerima skalar apa pun.
  • Int64: Menerima bilangan bulat.
  • Decimal: Menerima desimal presisi tetap (seperti Mata Uang).
  • Double: Menerima bilangan desimal floating-point.
  • String: Menerima teks.
  • DateTime: Menerima tanggal/waktu.
  • Boolean: Menerima TRUE/FALSE.
  • Numeric: Menerima nilai numerik apa pun (Int64, Decimal, atau Double subjenis)

ParameterMode

ParameterMode mengontrol kapan dan di mana ekspresi parameter dievaluasi. Ini adalah:

  • val (Evaluasi bersemangat): Ekspresi dievaluasi sekali sebelum memanggil fungsi. Nilai yang dihasilkan kemudian diteruskan ke fungsi . Ini umum untuk input skalar atau tabel sederhana. Ini adalah default jika Anda menghilangkan parameterMode untuk parameter.
  • expr (evaluasi malas): Ekspresi dievaluasi di dalam fungsi, berpotensi dalam konteks yang berbeda (misalnya konteks baris atau konteks filter) dan bisa dievaluasi beberapa kali jika direferensikan beberapa kali atau berada di dalam iterasi. Ini diperlukan untuk parameter referensi dan berguna saat Anda perlu mengontrol konteks evaluasi.

Jenis Scalar dapat menggunakan baik val maupun expr. Gunakan val saat Anda ingin skalar dievaluasi sekali dalam konteks pemanggil. Gunakan expr saat Anda ingin menungguhkan evaluasi dan mungkin menerapkan konteks di dalam fungsi. Lihat Contoh: Parameter tabel sebagai contoh.

Jenis ekspresi (AnyRef, ColumnRef, dll) harus expr sebagai referensinya (kolom, tabel, pengukuran, dll.) perlu dievaluasi dalam konteks fungsi.

Tabel berikut meringkas parameterMode yang efektif atau diizinkan:

Tipe ParameterMode tidak ditentukan ParameterMode: val ParameterMode: expr
(Tidak Ditentukan) / AnyVal val val expr
Scalar, Table val val expr
AnyRef expr Tidak diizinkan expr
CalendarRef,ColumnRef,MeasureRef,TableRef expr Tidak diizinkan expr

Contoh: Konversi tipe data

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

Ini menggunakan Scalar jenis, Int64 subjenis, dan val parameterMode untuk pembulatan yang dapat diprediksi dan paksa teks ke angka, serta memastikan ekspresi apa pun dievaluasi segera. Anda juga dapat mencapai ini hanya dengan menyertakan Int64 subjenis seperti yang terlihat dalam contoh di bawah ini. String non-numerik akan mengakibatkan kesalahan.

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

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

Contoh: Parameter tabel (nilai vs ekspresi)

Untuk mengilustrasikan bagaimana parameterMode UDF memengaruhi konteks filter, pertimbangkan dua fungsi yang keduanya menghitung baris dalam tabel 'Penjualan'. Keduanya menggunakan CALCULATETABLE(t, ALL('Date')) dalam tubuh mereka, tetapi satu parameter dinyatakan sebagai val (evaluasi bersemangat) dan yang lainnya sebagai expr (evaluasi malas):

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 mengembalikan jumlah penjualan hanya untuk FY2020. Tabel 'Penjualan' sudah difilter menurut tahun sebelum memasuki fungsi, sehingga ALL('Date') di dalam fungsi tidak berpengaruh.

CountRowsLater mengembalikan jumlah penjualan untuk semua tahun. Fungsi menerima ekspresi tabel yang tidak dievaluasi dan mengevaluasinya di bawah ALL('Date'), menghapus filter tahun eksternal.

Pemeriksaan jenis

Pengecekan jenis dalam UDF dapat dilakukan dengan fungsi pemeriksaan jenis yang baru maupun yang sudah ada, yang dapat Anda panggil di dalam badan fungsi Anda untuk mengonfirmasi jenis waktu proses dari parameter yang diteruskan. Ini memungkinkan UDF menggunakan kontrol konteks, memvalidasi parameter di depan, menormalkan input sebelum perhitungan.

Nota

Untuk expr parameter ParameterMode, pemeriksaan jenis terjadi ketika parameter dirujuk dalam isi fungsi (bukan pada waktu panggilan fungsi).

Fungsi pemeriksaan jenis yang tersedia

UDF dapat menggunakan fungsi berikut untuk menguji nilai skalar. Setiap pengembalian TRUE/FALSE tergantung pada apakah nilai yang disediakan adalah jenis tersebut.

Kategori Functions
Numeric ISNUMERIC, ISNUMBER
Double ISDOUBLE
Bilangan bulat ISINT64, ISINTEGER
Decimal ISDECIMAL, ISCURRENCY
String ISSTRING, ISTEXT
Boolean ISBOOLEAN, ISLOGICAL
Tanggal dan Waktu ISDATETIME

Contoh: Periksa apakah parameter adalah string

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

Ini mencegah kesalahan dan memungkinkan Anda memutuskan cara menangani input non-string ke dalam fungsi (dalam contoh ini, mengembalikan BLANK).

Contoh: Menerima beberapa jenis parameter

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"

Contoh ini menunjukkan cara menggunakan pemeriksaan jenis di UDF untuk menerima beberapa jenis input dengan aman dan mengembalikan satu hasil yang dapat diprediksi. GetCurrencyName mengambil satu argumen, currency, yang dapat berupa kunci mata uang seluruh angka atau kode mata uang teks. Fungsi memeriksa jenis argumen dengan ISINT64. Jika input adalah bilangan bulat, input memanggil pembantu GetCurrencyNameByKey yang mencari nama mata uang berdasarkan kunci mata uang. Jika input bukan bilangan bulat, input memanggil pembantu GetCurrencyNameByCode yang mencari nama mata uang berdasarkan kode mata uang.

Fungsi informasi yang berguna

Fungsi informasi berikut berguna saat menulis UDF:

  • TABLEOF: Mengembalikan tabel lengkap yang terkait dengan kolom, pengukuran, atau kalender tertentu.
  • NAMEOF: Mengembalikan nama tabel, kolom, pengukuran, atau kalender sebagai string teks

Contoh: Fungsi MODEX

Contoh berikut menunjukkan implementasi dasar fungsi MODEX yang mengembalikan nilai ekspresi yang paling sering muncul yang dievaluasi atas tabel. Menggunakan TABLEOF untuk secara otomatis menyelesaikan tabel yang benar dari referensi yang diberikan.

DEFINE
    FUNCTION MODEX = (
            e : ANYREF
        ) =>
        VAR newTable =
            ADDCOLUMNS ( TABLEOF ( e ), "expr", e )
        VAR freqTable =
            GROUPBY ( newTable, [expr], "count", SUMX ( CURRENTGROUP (), 1 ) )
        VAR maxCount =
            MAXX ( freqTable, [count] )
        VAR topResults =
            FILTER ( freqTable, [count] = maxCount )
        RETURN
            SELECTCOLUMNS ( topResults, "expr", [expr] )

EVALUATE
MODEX ( [Total Sales] )

Tentukan beberapa fungsi sekaligus

UDF memungkinkan Anda menentukan beberapa fungsi dalam satu kueri atau skrip, sehingga memudahkan untuk mengatur logika yang dapat digunakan kembali. Ini sangat berguna ketika Anda ingin merangkum perhitungan terkait atau rutinitas pembantu bersama-sama. Fungsi dapat dievaluasi bersama-sama atau secara individual.

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

Contoh lanjutan: Konversi mata uang fleksibel

Untuk menunjukkan bagaimana DAX UDF dapat menangani logika yang lebih kompleks, kita akan melihat skenario konversi mata uang. Contoh ini menggunakan pemeriksaan jenis dan fungsi berlapis untuk mengonversi jumlah tertentu menjadi mata uang target menggunakan nilai tukar rata-rata atau akhir hari untuk tanggal tertentu.

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

Fungsi ini ConvertToCurrency menerima jenis input yang fleksibel untuk mata uang dan tanggal. Pengguna dapat memberikan kunci mata uang atau kunci tanggal secara langsung atau menyediakan kode mata uang atau nilai tanggal standar. Fungsi ini memeriksa jenis setiap input dan menanganinya dengan sesuai: jika pCurrency merupakan bilangan bujur, fungsi diperlakukan sebagai kunci mata uang; jika tidak, fungsi mengasumsikan kode mata uang dan mencoba menyelesaikan kunci yang sesuai. pDate mengikuti pola serupa, jika merupakan bilangan bulat, diperlakukan sebagai kunci tanggal; jika tidak, fungsi mengasumsikan sebagai nilai tanggal standar dan dikonversi ke kunci tanggal menggunakan fungsi pembantu ConvertDateToDateKey. Jika fungsi tidak dapat menentukan nilai tukar yang valid, maka itu akan mengembalikan pesan "tidak ada nilai tukar yang tersedia".

Logika ini kemudian dapat digunakan untuk menentukan ukuran seperti Total Penjualan dalam Mata Uang Lokal.

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

Ini dapat dipasangkan secara opsional dengan string format dinamis untuk menampilkan hasil dalam format mata uang yang sesuai.

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

Contoh hasil dapat dilihat pada cuplikan layar di bawah ini.

Tabel memperlihatkan Tanggal Penuh, Mata Uang, Total Penjualan dalam Mata Uang Lokal, dan Total Penjualan.

Pertimbangan dan keterbatasan

Fungsi yang ditentukan pengguna saat ini dalam pratinjau, dan selama pratinjau, perlu diketahui pertimbangan dan batasan berikut:

Umum:

  • Tidak dapat membuat atau memodelkan DAX UDF di dalam Layanan.

  • Tidak dapat menyembunyikan/menampilkan UDF dalam model.

  • Tidak dapat menempatkan UDF dalam folder tampilan.

  • Tidak ada tombol 'buat fungsi' di pita.

  • Tidak dapat menggabungkan UDF dengan terjemahan.

  • UDF tidak didukung dalam model tanpa tabel.

  • Object-Level Security (OLS) tidak ditransfer ke fungsi atau sebaliknya. Misalnya, pertimbangkan fungsi F berikut yang mengacu pada ukuran MyMeasureaman :

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

    MyMeasure ketika diamankan menggunakan keamanan tingkat objek, fungsi F tidak diamankan secara otomatis. Jika F berjalan di bawah identitas tanpa akses ke MyMeasure, itu bertindak seolah-olah MyMeasure tidak ada. Sebaiknya hindari mengungkapkan objek aman dalam nama dan deskripsi fungsi.

  • Perbaikan rumus dan perhitungan dependensi didukung, dengan batasan yang diketahui di sekitar nama yang tidak memenuhi syarat. Karena nama yang tidak memenuhi syarat ditafsirkan sebagai referensi pengukuran, nama tersebut tidak dapat diperbaiki atau disertakan dalam pelacakan dependensi dengan andal saat dimaksudkan untuk merujuk ke kolom. Nama yang tidak memenuhi syarat adalah referensi objek yang tidak menyertakan awalan tabel.

  • CalendarRef, ColumnRef, MeasureRef dan TableRef petunjuk tipe mungkin tidak diterima di seluruh situs pemanggilan fungsi saat kita sedang dalam tahap pratinjau. Pengguna dapat mundur ke AnyRef.

Menentukan UDF:

  • Rekursi atau rekursi bersama tidak didukung.
  • Kelebihan beban fungsi tidak didukung.
  • Jenis pengembalian eksplisit tidak didukung.

Parameter UDF:

  • Parameter opsional tidak didukung.
  • Deskripsi parameter tidak didukung.
  • UDF tidak dapat mengembalikan enum nilai. Fungsi bawaan yang menerima enum nilai sebagai parameter fungsinya tidak akan dapat menggunakan UDF dalam konteks tersebut.
  • Parameter petunjuk jenis expr yang tidak terikat tidak dievaluasi.

Dukungan IntelliSense:

  • Meskipun UDF dapat digunakan dalam model koneksi langsung atau komposit, tidak ada dukungan IntelliSense.
  • Meskipun UDF dapat digunakan dalam perhitungan visual, bilah rumus perhitungan visual tidak memiliki dukungan IntelliSense untuk UDF.
  • Tampilan TMDL memiliki dukungan IntelliSense terbatas untuk UDF.

Bug yang diketahui

Masalah berikut saat ini diketahui dan dapat memengaruhi fungsionalitas:

  • Skenario lanjutan tertentu yang melibatkan UDF dapat mengakibatkan inkonsistensi pengurai. Misalnya, pengguna mungkin melihat garis bawah merah atau kesalahan validasi saat meneruskan kolom sebagai expr parameter atau menggunakan referensi kolom yang tidak memenuhi syarat.