Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Uwaga / Notatka
DAX Funkcje zdefiniowane przez użytkownika są obecnie dostępne w wersji zapoznawczej.
DAX Funkcje zdefiniowane przez użytkownika (UDF) umożliwiają pakowanie DAX logiki i ponowne używanie jej tak jak każda inna DAX funkcja. Funkcje zdefiniowane przez użytkownika wprowadzają nowe FUNCTION słowo kluczowe, opcjonalne parametry (skalarne, tablicowe i referencyjne) oraz narzędzia pomocnicze dla sprawdzania typów, które sprawiają, że tworzenie jest bezpieczniejsze i jaśniejsze. Po zdefiniowaniu UDF można ją używać w miarze, kolumnie obliczeniowej, obliczeniach wizualnych lub nawet innych funkcjach zdefiniowanych przez użytkownika. Użytkownicy mogą centralizować reguły biznesowe, zwiększać łatwość konserwacji i bezpiecznie rozwijać obliczenia w czasie. Funkcje to obiekty modelu pierwszej klasy, którymi można tworzyć w widoku zapytań i widoku TMDL oraz zarządzać nimiDAX. Można je wyświetlić w Eksploratorze modeli w węźle Funkcje.
Włączanie funkcji zdefiniowanych przez użytkownika
Aby wypróbować funkcje zdefiniowane przez użytkownika w programie Desktop:
- Przejdź do pozycji Opcje pliku > i opcje ustawień>.
- Wybierz pozycję Funkcje w wersji zapoznawczej i sprawdź DAX funkcje zdefiniowane przez użytkownika.
- Wybierz przycisk OK i uruchom ponownie program Power BI Desktop.
Definiowanie funkcji zdefiniowanych przez użytkownika i zarządzanie nimi
Istnieje kilka lokalizacji do definiowania funkcji i zarządzania nimi:
- DAX widok zapytania (DQV). Definiowanie i modyfikowanie funkcji w DQV. Funkcja DQV zawiera również menu kontekstowe Szybkie zapytania (Ocena, Definiowanie i ocenianie oraz Definiowanie wszystkich funkcji w tym modelu), które ułatwiają szybkie testowanie funkcji zdefiniowanych przez użytkownika i zarządzanie nimi.
- Widok TMDL. Funkcje UDF można również tworzyć i edytować w TMDL. Widok TMDL zawiera również pozycję menu kontekstowego Skrypt TMDL do.
- Eksplorator modelu. Istniejące funkcje można wyświetlić w węźle Funkcje w Eksploratorze modeli.
Podczas definiowania funkcji zdefiniowanej przez użytkownika (UDF) należy przestrzegać następujących wytycznych dotyczących nazewnictwa:
Nazwy funkcji:
- Musi być dobrze sformułowany i unikatowy w modelu.
- Może zawierać kropki (kropki) w celu nadania nazw (np. Microsoft.PowerBI.MyFunc). Nie można rozpocząć ani zakończyć kropką lub mieć kolejnych okresów.
- Oprócz kropek nazwy mogą zawierać tylko znaki alfanumeryczne lub znak podkreślenia. Spacje ani znaki specjalne nie są dozwolone.
- Nie może powodować konfliktu z wbudowanymi DAX funkcjami ani słowami zarezerwowanymi (np. miarą, funkcją, definiowaniem).
Nazwy parametrów:
- Może zawierać tylko znaki alfanumeryczne lub podkreślenia. Okresy są niedozwolone.
- Nie może być słowem zastrzeżonym.
Korzystanie z DAX widoku zapytania
W widoku zapytania można definiować, aktualizować i oceniać funkcje DAX zdefiniowane przez użytkownika. Aby uzyskać dodatkowe informacje na DAX temat widoku zapytania, zobacz DAX widok zapytania.
Formularz ogólny
DEFINE
/// Optional description above the function
FUNCTION <FunctionName> = ( [ParameterName]: [ParameterType], ... ) => <FunctionBody>
Wskazówka
Użyj /// do opisów funkcji. Komentarze jednowierszowe (//) lub wielowierszowe (/* */) nie będą wyświetlane w opisach funkcji IntelliSense.
Przykład: Prosta funkcja podatkowa
DEFINE
/// AddTax takes in amount and returns amount including tax
FUNCTION AddTax =
( amount : NUMERIC ) =>
amount * 1.1
EVALUATE
{ AddTax ( 10 ) }
// Returns 11
Zapisywanie do modelu
Aby zapisać funkcję zdefiniowaną przez użytkownika z DAX widoku zapytań do modelu:
- Kliknij Aktualizuj model ze zmianami, aby zapisać wszystkie funkcje UDF w zapytania.
- Możesz też kliknąć pozycję Aktualizuj model: Dodaj nową funkcję powyżej zdefiniowanej funkcji, aby zapisać pojedynczą funkcję zdefiniowaną przez użytkownika.
Korzystanie z widoku TMDL
W widoku TMDL można definiować i/lub aktualizować funkcje zdefiniowane przez użytkownika. Aby uzyskać dodatkowe informacje na temat widoku TMDL, zobacz widok TMDL.
Formularz ogólny
createOrReplace
/// Optional description above the function
function <FunctionName> = ( [ParameterName]: [ParameterType], ... ) => <FunctionBody>
Przykład: Prosta funkcja podatkowa
createOrReplace
/// AddTax takes in amount and returns amount including tax
function AddTax =
(amount : NUMERIC) =>
amount * 1.1
Zapisywanie do modelu
Kliknij przycisk Zastosuj na górze widoku, aby zapisać wszystkie UDF-y z skryptu do modelu.
Używanie skryptu TMDL w projekcie usługi Power BI
Funkcje UDF są również uwzględniane w skrypcie TMDL modelu semantycznego podczas korzystania z projektu Power BI. Można je znaleźć w functions.tmdl folderze definicji .
Korzystanie z eksploratora modelu
Wszystkie funkcje zdefiniowane przez użytkownika można wyświetlić w modelu z poziomu Eksploratora modeli w węźle Funkcje . Aby uzyskać dodatkowe informacje na temat Eksploratora modeli, zobacz Eksplorator modeli.
W DAX widoku zapytania można użyć szybkich zapytań w menu kontekstowym (prawym przyciskiem myszy) funkcji UDF w Eksploratorze modeli, aby łatwo definiować i oceniać funkcje.
W widoku TMDL można przeciągać i upuszczać funkcje na kanwie lub użyć opcji generowania skryptu TMDL w menu po kliknięciu prawym przyciskiem myszy na funkcję zdefiniowaną przez użytkownika w Eksploratorze modeli, aby wygenerować skrypty.
Używanie widoków DMV do sprawdzania funkcji zdefiniowanych przez użytkownika
Funkcje zdefiniowane przez użytkownika można sprawdzić w modelu, korzystając z Dynamicznych Widoków Zarządzania (DMVs). Te widoki umożliwiają wykonywanie zapytań dotyczących funkcji, w tym funkcji zdefiniowanych przez użytkownika.
Możesz użyć funkcji INFO.FUNCTIONS do sprawdzenia UDF-ów w modelu. Aby ograniczyć wynik tylko do funkcji zdefiniowanych przez użytkownika, należy podać parametr ORIGIN jako 2.
EVALUATE INFO.FUNCTIONS("ORIGIN", "2")
To zapytanie zwraca tabelę wszystkich funkcji zdefiniowanych przez użytkownika aktualnie w modelu, w tym ich nazwę, opis i skojarzone metadane.
Korzystanie z funkcji zdefiniowanej przez użytkownika
Po zdefiniowaniu i zapisaniu funkcji zdefiniowanej przez użytkownika (UDF) w modelu, można ją wywołać z miar, kolumn obliczeniowych, obliczeń wizualnych oraz innych funkcji zdefiniowanych przez użytkownika. Działa to tak samo jak wywoływanie wbudowanych DAX funkcji.
Wywoływanie funkcji zdefiniowanej przez użytkownika w miarze
Użyj UDF w mierze, aby zastosować logikę z pełnym kontekstem filtru.
Total Sales with Tax = AddTax ( [Total Sales] )
Przykładowa miara jest pokazana w poniższej tabeli:
Wywoływanie UDF (funkcji zdefiniowanej przez użytkownika) w kolumnie obliczeniowej
Funkcje zdefiniowane przez użytkownika (UDF) mogą być używane w kolumnie obliczeniowej w celu zastosowania logiki wielokrotnego użytku do każdego wiersza w tabeli.
Uwaga / Notatka
W przypadku korzystania z funkcji zdefiniowanej przez użytkownika w kolumnie obliczeniowej upewnij się, że funkcja zwraca skalar spójnego typu. Aby uzyskać więcej informacji, zobacz Parametry . W razie potrzeby przekonwertuj wynik na żądany typ przy użyciu CONVERT lub podobnych funkcji.
Sales Amount with Tax = CONVERT ( AddTax ( 'Sales'[Sales Amount] ), CURRENCY )
Poniższa przykładowa miara jest używana w poniższej tabeli:
Wywoływanie funkcji zdefiniowanej przez użytkownika w obliczeniach wizualnych
Funkcje UDF można użyć w wizualnych obliczeniach, aby zastosować logikę bezpośrednio w wizualizacji. Aby uzyskać dodatkowe informacje na temat obliczeń wizualnych, zobacz Obliczenia wizualne.
Uwaga / Notatka
Obliczenia wizualne działają tylko na polach znajdujących się w wizualizacji. Nie mogą oni uzyskać dostępu do obiektów modelu, które nie są częścią wizualizacji. Przekazywanie obiektów modelu (takich jak kolumny lub miary niewchodzące w skład wizualizacji) do funkcji zdefiniowanej przez użytkownika w tym kontekście jest niedozwolone.
Sales Amount with Tax = AddTax ( [Sales Amount] )
Poniższa przykładowa miara jest widoczna w poniższej tabeli:
Wywoływanie funkcji zdefiniowanej przez użytkownika w innej funkcji zdefiniowanej przez użytkownika
Funkcje zdefiniowane przez użytkownika można zagnieżdżać, wywołując jedną funkcję w ramach innej. W tym przykładzie definiujemy naszą prostą AddTax UDF i wywołujemy ją w innym 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
Parametry
DAX Funkcje zdefiniowane przez użytkownika mogą akceptować zero lub więcej parametrów. Podczas definiowania parametrów dla funkcji zdefiniowanej przez użytkownika można opcjonalnie określić wskazówki dotyczące typu dla każdego parametru:
-
Typ: jakiego typu wartość przyjmuje parametr (
AnyVal,Scalar, ,TablelubAnyRef). -
Podtyp (tylko dla typu skalarowego): określony typ danych skalarnych (
Variant,Int64,DecimalDoubleStringDateTimeBooleanlub ).Numeric -
ParameterMode: kiedy argument jest oceniany (
vallubexpr).
Wskazówki dotyczące typów są w postaci: [type] [subtype] [parameterMode]
Możesz uwzględnić wszystkie, niektóre lub żadne z tych wskazówek typu dla każdego parametru, aby funkcje były bezpieczniejsze i bardziej przewidywalne w lokacjach wywołań. Jeśli pominiesz wszystko i po prostu napisz nazwę parametru zachowuje się jako AnyVal val, co oznacza, że argument jest obliczany natychmiast w czasie wywołania. Jest to przydatne w przypadku prostych funkcji.
Typ
Typ definiuje kategorię argumentu, który akceptuje parametr i czy jest przekazywany jako wartość , czy wyrażenie.
Istnieją dwie rodziny typów w DAX parametrach UDF: typy wartości i typy wyrażeń:
-
Typy wartości: ten argument jest obliczany natychmiast (gorliwe obliczanie) w momencie wywołania funkcji, a wynikowa wartość jest przekazywana do funkcji.
-
AnyVal: akceptuje wartość skalarną lub tabelę. Jest to ustawienie domyślne, jeśli pominięto typ parametru. -
Scalar: akceptuje wartość skalarną (może dodatkowo dodać podtyp). -
Table: akceptuje tabelę.
-
-
Typy wyrażeń: ten argument przekazuje niewartościowane wyrażenie (leniwe wyliczanie). Funkcja decyduje, kiedy i w jakim kontekście należy ją ocenić. Jest to wymagane w przypadku parametrów referencyjnych i przydatne, gdy trzeba kontrolować kontekst filtra (np. wewnątrz CALCULATE elementu).
exprtypy mogą być odwołaniami do kolumny, tabeli, kalendarza lub miary.-
AnyRef: Przyjmuje odniesienie (kolumna, tabela, kalendarz lub miara).
-
Podtyp
Podtyp umożliwia zdefiniowanie określonego Scalar typu danych. Jeśli zdefiniujesz podtyp, nie musisz jawnie definiować parametru jako Scalar typu, przyjmuje się to automatycznie.
Podtypy to:
-
Variant: akceptuje wszelkie skalarne. -
Int64: akceptuje liczbę całkowitą. -
Decimal: akceptuje wartość dziesiętną o stałej precyzji (na przykład Waluta lub Pieniądze). -
Double: akceptuje liczbę zmiennoprzecinkową. -
String: akceptuje tekst. -
DateTime: akceptuje datę/godzinę. -
Boolean: akceptuje TRUE/FALSE. -
Numeric: akceptuje dowolną wartość liczbową (Int64,DecimallubDoublepodtypy)
ParametrMode
ParametrMode określa, kiedy i gdzie wyrażenie parametru jest oceniane. Są to:
-
val(eager evaluation): Wyrażenie jest oceniane raz przed wywołaniem funkcji. Wynikowa wartość jest następnie przekazywana do funkcji. Jest to typowe dla prostych danych wejściowych skalarnych lub wejściowych tabeli. Jest to ustawienie domyślne, jeśli pominięto parametr parameterMode dla parametru. -
expr(ocena leniwa): Wyrażenie jest obliczane wewnątrz funkcji, potencjalnie w innym kontekście (np. kontekście wiersza lub kontekście filtru) i ewentualnie wielokrotnie, jeśli jest do niego odwoływane wiele razy lub wewnątrz iteracji. Jest to wymagane w przypadku parametrów referencyjnych i przydatnych, gdy trzeba kontrolować kontekst oceny.
Typ Scalar może używać elementu val lub expr. Użyj val jeśli chcesz, aby skalar był obliczony raz w kontekście obiektu wywołującego. Użyj expr , gdy chcesz odroczyć wykonanie i ewentualnie zastosować kontekst wewnątrz funkcji. Zobacz Przykład: parametr tabeli jako przykład.
Typ AnyRef musi być expr, ponieważ jego odwołania (kolumny, tabele, miary itp.) muszą być oceniane w kontekście funkcji.
Przykład: rzutowanie typu
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
To używa typu Scalar, podtypu Int64 i trybuParametru val do przewidywalnego zaokrąglania i konwersji tekstu na liczbę, a także zapewnienia, że wszystkie wyrażenia są oceniane natychmiast. Można to również osiągnąć, dołączając tylko podtyp Int64, jak pokazano w poniższym przykładzie. Ciągi znaków nie będących liczbami spowodują błąd.
DEFINE
/// returns x as an Int64
FUNCTION CastToInt = (
x : INT64
) =>
x
EVALUATE
{ CastToInt ( 3.4 ), CastToInt ( 3.5 ), CastToInt ( "5" ) }
// returns 3, 4, 5
Przykład: Parametr tabeli (wartość a wyrażenie)
Aby zilustrować, jak parameterMode w UDF wpływa na kontekst filtru, rozważ dwie funkcje, które obie zliczają wiersze w tabeli "Sales". Oba używają CALCULATETABLE(t, ALL('Date')) w swoich ciałach, ale jeden parametr jest zadeklarowany jako val (chętna ocena) i drugi jako expr (leniwe obliczanie):
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 zwraca liczbę transakcji sprzedaży tylko dla roku fiskalnego 2020. Tabela "Sales" jest już filtrowana według roku przed wprowadzeniem funkcji, więc ALL('Date') wewnątrz funkcji nie ma żadnego wpływu.
Funkcja CountRowsLater zwraca liczbę sprzedaży ze wszystkich lat. Funkcja przyjmuje niewyrażone wyrażenie tabelowe i ocenia je w kontekście ALL('Date'), usuwając zewnętrzny filtr roku.
Sprawdzanie typów
Sprawdzanie typów w UDF-ach można wykonywać przy użyciu nowych i istniejących funkcji sprawdzania typów, które można wywołać wewnątrz treści funkcji, aby potwierdzić typ przekazywanych parametrów. Dzięki temu funkcje UDF mogą korzystać z kontroli kontekstu, weryfikować parametry z wyprzedzeniem oraz normalizować dane wejściowe przed obliczeniami.
Uwaga / Notatka
W przypadku expr parametrów parameterMode sprawdzanie typu występuje, gdy parametr jest przywoływał w treści funkcji (a nie w czasie wywołania funkcji).
Dostępne funkcje sprawdzania typów
UDF mogą używać następujących funkcji do testowania wartości skalarnych. Każdy zwracany TRUE/FALSE zależy od tego, czy podana wartość jest tego typu.
| Kategoria | Functions |
|---|---|
| Numeric | ISNUMERIC, ISNUMBER |
| Double | ISDOUBLE |
| Liczba całkowita | ISINT64, ISINTEGER |
| Decimal | ISDECIMAL, ISCURRENCY |
| Sznurek | ISSTRING, ISTEXT |
| logiczny | ISBOOLEAN, ISLOGICAL |
| Data i godzina | ISDATETIME |
Przykład: Sprawdzanie, czy parametr jest ciągiem
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
Zapobiega to błędom i pozwala zdecydować, jak obsługiwać dane wejściowe inne niż ciągi w funkcji (w tym przykładzie funkcja zwraca wartość BLANK).
Przykład: Akceptowanie wielu typów parametrów
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"
W tym przykładzie pokazano, jak używać sprawdzania typów w funkcjach zdefiniowanych przez użytkownika, aby bezpiecznie akceptować wiele typów danych wejściowych i zwracać jeden, przewidywalny wynik.
GetCurrencyName przyjmuje jeden argument , currencyktóry może być kluczem waluty całkowitej lub kodem waluty tekstowej. Funkcja sprawdza typ argumentu za pomocą polecenia ISINT64. Jeśli dane wejściowe są liczbą całkowitą, wywołuje pomocnika GetCurrencyNameByKey , który wyszukuje nazwę waluty na podstawie klucza waluty. Jeśli dane wejściowe nie są liczbą całkowitą, wywołuje pomocnika GetCurrencyNameByCode , który wyszukuje nazwę waluty na podstawie kodu waluty.
Definiowanie wielu funkcji jednocześnie
Funkcje zdefiniowane przez użytkownika umożliwiają definiowanie kilku funkcji w jednym zapytaniu lub skrypcie, co ułatwia uporządkowanie logiki do wielokrotnego użytku. Jest to szczególnie przydatne, gdy chcesz grupować powiązane obliczenia lub procedury pomocnicze. Funkcje można oceniać razem lub indywidualnie.
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
Zaawansowany przykład: elastyczna konwersja walut
Aby pokazać, jak funkcje zdefiniowane przez użytkownika (UDF) mogą obsługiwać bardziej złożoną logikę, przyjrzymy się scenariuszowi konwersji waluty. W tym przykładzie użyto sprawdzania typów i zagnieżdżonych funkcji, aby przeliczyć daną kwotę na walutę docelową przy użyciu średniego lub całodobowego kursu wymiany dla określonej daty.
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
Funkcja ConvertToCurrency akceptuje elastyczne typy danych wejściowych zarówno dla waluty, jak i daty. Użytkownicy mogą podać klucz waluty lub klucz daty bezpośrednio albo podać kod waluty lub standardową wartość daty. Funkcja sprawdza typ poszczególnych danych wejściowych i odpowiednio je obsługuje: jeśli pCurrency jest liczbą całkowitą, jest traktowana jako klucz waluty; w przeciwnym razie funkcja przyjmuje kod waluty i próbuje rozpoznać odpowiedni klucz.
pDate jest zgodny z podobnym wzorcem, jeśli jest liczbą całkowitą, jest traktowany jako klucz daty; w przeciwnym razie funkcja zakłada, że jest to standardowa wartość daty i jest konwertowana na klucz daty przy użyciu ConvertDateToDateKey funkcji pomocnika. Jeśli funkcja nie może określić prawidłowego kursu wymiany, zwraca komunikat "brak dostępnego kursu wymiany".
Tej logiki można następnie użyć do zdefiniowania miary, takiej jak Total Sales in Local Currency (Łączna sprzedaż w walucie lokalnej).
Total Sales in Local Currency =
ConvertToCurrency (
SELECTEDVALUE ( 'Currency'[Code] ),
SELECTEDVALUE ( 'Date'[DateKey] ),
TRUE,
[Total Sales]
)
Można to opcjonalnie sparować z ciągiem formatu dynamicznego , aby wyświetlić wynik w odpowiednim formacie waluty.
CALCULATE (
MAX ( 'Currency'[Format String] ),
'Currency'[Code] == SELECTEDVALUE ( 'Currency'[Code] )
)
Przykładowy wynik można zobaczyć na poniższym zrzucie ekranu.
Uwagi i ograniczenia
Funkcje zdefiniowane przez użytkownika są obecnie w wersji zapoznawczej, a w wersji zapoznawczej należy pamiętać o następujących zagadnieniach i ograniczeniach:
Ogólne:
- Nie można tworzyć ani modelować DAX funkcji zdefiniowanych przez użytkownika w usłudze.
- Nie można ukrywać/odkrywać funkcji definiowanej przez użytkownika w modelu.
- Nie można umieścić funkcji zdefiniowanych przez użytkownika w folderach widoku.
- Brak przycisku „utwórz funkcję” na wstążce.
- Nie można łączyć UDF z tłumaczeniami.
- Funkcje zdefiniowane przez użytkownika (UDF) nie są obsługiwane w modelach bez tabel.
Tworzenie funkcji zdefiniowanej przez użytkownika:
- Rekursja lub rekursja wzajemna nie jest obsługiwana.
- Przeciążenie funkcji nie jest obsługiwane.
- Jawne typy zwracane nie są obsługiwane.
Parametry funkcji zdefiniowanej przez użytkownika:
- Parametry opcjonalne nie są obsługiwane.
- Opisy parametrów nie są obsługiwane.
- Funkcje definiowane przez użytkownika nie mogą zwracać wartości
enum. Wbudowane funkcje, które akceptują wartościenumjako parametry swoich funkcji, nie będą mogły używać UDF w tym kontekście. - Nieprzypisane parametry dla podpowiedzi typu
exprnie są oceniane.
Obsługa funkcji IntelliSense:
- Chociaż funkcje zdefiniowane przez użytkownika mogą być używane w modelach z bezpośrednim połączeniem lub w modelach złożonych, nie ma wsparcia dla IntelliSense.
- Chociaż funkcje UDF mogą być używane w obliczeniach wizualnych, pasek formuły obliczeń wizualnych nie obsługuje funkcji IntelliSense dla UDF.
- Widok TMDL nie obsługuje prawidłowej funkcji IntelliSense dla funkcji UDF.
Znane usterki
Obecnie znane są następujące problemy i mogą mieć wpływ na funkcjonalność:
- Odwołania do obiektu modelu tabelarycznego (np. miara, tabela, kolumna) w UDF nie są automatycznie aktualizowane po zmianie nazwy tych obiektów. Jeśli zmienisz nazwę obiektu, od którego zależy funkcja UDF, treść funkcji będzie nadal zawierać starą nazwę. Aby zaktualizować wszystkie odwołania do obiektu o zmienionej nazwie, należy ręcznie edytować wyrażenie UDF.
- Niektóre zaawansowane scenariusze obejmujące funkcje zdefiniowane przez użytkownika mogą powodować niespójności w analizatorze. Na przykład użytkownicy mogą zobaczyć czerwone podkreślenia lub błędy walidacji podczas przekazywania kolumn jako
exprparametrów lub przy użyciu niekwalifikowanych odwołań do kolumn.