Del via


DAX brugerdefinerede funktioner (prøveversion)

Notat

DAX Brugerdefinerede funktioner er i øjeblikket i prøveversion.

DAX brugerdefinerede funktioner (UDF'er) giver dig mulighed for at pakke DAX logik og genbruge den som enhver anden DAX funktion. UDF'er introducerer et nyt FUNCTION nøgleord, valgfrie parametre (skalar, tabel og referencer) og hjælpere til typekontrol , der gør oprettelse sikrere og tydeligere. Når du har defineret en UDF, kan du bruge den i en måling, beregnet kolonne, visuel beregning eller endda andre brugerdefinerede funktioner. Brugere kan centralisere forretningsregler, forbedre vedligeholdelse og udvikle beregninger sikkert over tid. Funktioner er førsteklasses modelobjekter, som du kan oprette og administrere i DAX forespørgselsvisning og TMDL-visning, og de kan ses i Modelsfinder under noden Funktioner .

Aktiver brugerdefinerede funktioner

Sådan prøver du UDF'er i Desktop:

  1. Gå til Filindstillinger > og indstillinger > Indstillinger.
  2. Vælg Forhåndsvisningsfunktioner , og kontroller DAX brugerdefinerede funktioner.
  3. Vælg OK , og genstart Power BI Desktop.

Definer og administrer brugerdefinerede funktioner

Der er flere steder at definere og administrere funktioner:

  • DAX forespørgselsvisning (DQV). Definer og rediger funktioner i DQV. DQV indeholder også genvejsmenuens hurtige forespørgsler (Evaluer, Definer og evaluer og Definer alle funktioner i denne model) for at hjælpe dig med at teste og administrere UDF'er hurtigt.
  • TMDL-visning. UDF'er kan også forfattes og redigeres i TMDL. TMDL-visningen indeholder også kontekstmenuen Script TMDL til.
  • Model udforsker. Nye funktioner kan oprettes, og eksisterende funktioner kan ændres ved hjælp af formelbjælken. Eksisterende funktioner kan ses under noden Funktioner i Modelskandifinder.

Når du definerer en UDF, skal du følge disse navngivningskrav:

Navne på funktioner:

  • Skal være velformet og unik inden for modellen.
  • Kan indeholde punktummer (prikker) for navneafstand (f.eks. Microsoft.PowerBI.MyFunc). Kan ikke starte eller slutte med et punktum eller have fortløbende perioder.
  • Bortset fra punktummer kan navne kun indeholde alfanumeriske tegn eller understregningstegn. Ingen mellemrum eller specialtegn tilladt.
  • Må ikke være i konflikt med indbyggede DAX funktioner eller reserverede ord (f.eks. måle, funktion, definere).

Parameternavne:

  • Kan kun indeholde alfanumeriske tegn eller understregningstegn. Menstruationer er ikke tilladt.
  • Må ikke være et forbeholdt ord.

Brug af DAX forespørgselsvisning

Du kan definere, opdatere og evaluere brugerdefinerede funktioner i DAX forespørgselsvisning. Du kan finde flere oplysninger om DAX forespørgselsvisning i DAX forespørgselsvisning.

Generel formular

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

Tips

Brug JSDoc-bloktags til at dokumentere dine funktioner med beskrivelser, parameternavne og typer, og returner information for at gøre dem lettere at bruge. Bemærk funktionsbeskrivelserne /// for . Kommentarer med en enkelt linje (//) eller flere linjer (/* */) vises ikke i beskrivelser af IntelliSense-funktioner.

Eksempel: Simpel momsfunktion

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

Lagring til modellen

Sådan gemmer du en UDF fra DAX forespørgselsvisning til modellen:

  • Klik på Opdater model med ændringer for at gemme alle UDF'er i forespørgslen.
  • Eller klik på Opdater model: Tilføj ny funktion over den definerede funktion for at gemme en enkelt UDF.

Skærmbillede af DAX forespørgselsvisning i Power BI Desktop, der fremhæver to placeringer, hvor du kan gemme en brugerdefineret funktion. Den første er knappen Opdater model med ændringer øverst i visningen. Den anden er en statuslinje i kodeeditoren med navnet Opdater model: Tilføj ny funktion

Brug af TMDL-visning

Du kan definere og/eller opdatere brugerdefinerede funktioner i TMDL-visningen. For yderligere oplysninger om TMDL-visning, se TMDL-visning.

Generel formular

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

Eksempel: Simpel momsfunktion

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

Lagring til modellen

Klik på knappen Anvend øverst i visningen for at gemme alle UDF'er i scriptet i modellen.

Skærmbillede af TMDL-visning i Power BI Desktop, hvor knappen Anvend øverst i visningen fremhæves. Dette er det sted, hvor du kan gemme en brugerdefineret funktion.

Brug af TMDL-script i et Power BI-projekt

UDF'er er også inkluderet i TMDL-scriptet for den semantiske model, når du bruger et Power BI-projekt. De kan findes i functions.tmdldefinitionsmappen .

Visual Studio Code-skærmbillede af et Power BI-projekt. Stifinder er åben for mappen med semantisk model. 'functions.tmdl' er åben i kodeeditoren. Der vises tre funktioner: CustomerLifetimeValue, AverageOrderValue og AddTax.

Brug af Modelsfinder

Du kan få vist alle brugerdefinerede funktioner i modellen fra Modelsfinder under noden Funktioner . Du kan finde flere oplysninger om Modelsfinder under Modelsfinder.

Panelet Modelsfinder i Power BI Desktop, der viser den udvidede node Funktioner. Der vises tre brugerdefinerede funktioner: AddTax, AverageOrderValue og CustomerLifetimeValue.

I DAX forespørgselsvisning kan du bruge hurtige forespørgsler i højrekliksmenuen i en UDF i Model Explorer til nemt at definere og evaluere funktioner.

Model Explorer-panelet i Power BI Desktop viser den udvidede Funktioner-node. To kontekstmenuer er åbne: den første menu tilbyder hurtige forespørgsler, Omdøb, Slet fra model, Skjul i rapportvisning, Afvis alle, Sammenlæg alle og Udvid alle. Quick Queries er markeret og valgt. Den anden menu er fremhævet og tilbyder hurtige forespørgselsmuligheder Evaluate, Define and evaluate, Define with references and evaluate, Define new function og Define all functions i denne model.

I TMDL-visning kan du trække og slippe funktioner til lærredet eller bruge Script TMDL til at højrekliksmenuen i en UDF i Model Explorer for at generere scripts.

Ruden Modelsfinder i Power BI Desktop viser den udvidede node Funktioner. To genvejsmenuer er åbne: den første menu indeholder Script TMDL til, Omdøb, Slet fra model, Skjul i rapportvisning, Vis alle, Skjul alle og Udvid alle. Script til TMDL er fremhævet og valgt. Den anden menu er fremhævet og tilbyder Script til TMDL-indstillinger, Script-fanen og Udklipsholder.

Brug af DMV'er til at inspicere UDF'er

Du kan inspicere UDF'er i din model ved hjælp af dynamiske administrationsvisninger (DMV'er). Disse visninger giver dig mulighed for at forespørge på oplysninger om funktioner, herunder UDF'er.

Du kan bruge INFORMATIONEN. USERDEFINEDFUNCTIONS funktionen til at inspicere UDF'erne i modellen. Denne funktion returnerer fuld metadata og kræver skrivetilladelse.

EVALUATE INFO.USERDEFINEDFUNCTIONS()

Alternativt kan du bruge INFO. FUNCTIONS-funktionen returnerer UDF-navne og begrænset metadata.

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

Brug af en brugerdefineret funktion

Når en UDF er defineret og gemt i modellen, kan du kalde den fra målinger, beregnede kolonner, visuelle beregninger og andre UDF'er. Dette fungerer på samme måde som at kalde indbyggede DAX funktioner.

Kaldelse af en UDF i en foranstaltning

Brug en UDF i en måling til at anvende genanvendelig logik med fuld filterkontekst.

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

Eksempelmålingen er vist i nedenstående tabel:

Tabel, der viser Samlet salg og Samlet salg med moms. Samlet salg med moms er fremhævet. Ruden Visualiseringer er åben. Samlet salg med moms er fremhævet i feltet Kolonner.

Kald en UDF i en beregnet kolonne

UDF'er kan bruges i en beregnet kolonne til at anvende genanvendelig logik på hver række i en tabel.

Notat

Når du bruger en UDF i en beregnet kolonne, skal du sikre dig, at funktionen returnerer en skalar af en ensartet type. Se Parametre for at få flere oplysninger. Hvis det er nødvendigt, kan du konvertere resultatet til den ønskede type ved hjælp af CONVERT eller lignende funktioner.

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

Vi kan se dette eksempel på måling brugt i tabellen nedenfor:

Tabel, der viser Salgsbeløb og Salgsbeløb med moms. Salgsbeløb med moms er fremhævet. Ruden Visualiseringer er åben. Salgsbeløb med moms er fremhævet i feltet Kolonner.

Kald en UDF i en visuel beregning

Du kan bruge UDF'er i en visualiseringsberegning til at anvende logik direkte på visualiseringen. Du kan finde flere oplysninger om visuelle beregninger under Visuelle beregninger.

Notat

Visuelle beregninger fungerer kun på felter, der findes i visualiseringen. De kan ikke få adgang til modelobjekter, der ikke er en del af visualiseringen, og du kan ikke overføre modelobjekter (f.eks. kolonner eller målinger, der ikke er i visualiseringen) til en UDF i denne kontekst.

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

Vi kan se dette eksempel på måling i nedenstående tabel:

I redigeringstilstand for visuel beregning. Tabel, der viser Salgsbeløb og Salgsbeløb med moms. Salgsbeløb med moms er fremhævet. Visuel beregningsformel for salgsbeløb med moms er fremhævet.

Kald en UDF i en anden UDF

Du kan indlejre UDF'er ved at kalde en funktion fra en anden. I dette eksempel definerer vi vores simple AddTax UDF og kalder det i en anden 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

Parametre

DAX UDF'er kan acceptere nul eller flere parametre. Når du definerer parametre for en UDF, kan du vælge at angive typetip for hver parameter:

  • Type: hvilken type værdi parameteren accepterer (AnyVal, Scalar, Table, , AnyRefCalendarRef, , ColumnRef, , eller TableRefMeasureRef ).
  • Undertype (kun for skalartype): den specifikke skalardatatype (Variant, Int64, Decimal, Double, StringDateTimeBoolean, eller ).Numeric
  • ParameterMode: Når argumentet evalueres (val eller expr).

Typetip er i formen: [type] [subtype] [parameterMode]

Du kan medtage alle, nogle eller ingen af disse typetip for hver parameter for at gøre dine funktioner sikrere og mere forudsigelige på opkaldssteder. Hvis du udelader alt og bare skriver parameternavnet, opfører det sig som AnyVal val, hvilket betyder, at argumentet evalueres med det samme på kaldstidspunktet. Dette er nyttigt til enkle funktioner.

Type

Type definerer den kategori af argumenter, som parameteren accepterer, og om den overføres som en værdi eller et udtryk.

Der er to typefamilier i DAX UDF-parametre: værdityper og udtrykstyper:

  • Værdityper: Dette argument evalueres med det samme (ivrig evaluering), når funktionen kaldes, og den resulterende værdi overføres til funktionen.
    • AnyVal: Accepterer en skalar eller en tabel. Dette er standarden, hvis du udelader type for en parameter.
    • Scalar: Accepterer en skalarværdi (kan desuden tilføje en undertype).
    • Table: Accepterer en tabel.
  • Udtrykstyper: Dette argument overfører et ikke-evalueret udtryk (doven evaluering). Funktionen bestemmer, hvornår og i hvilken sammenhæng den skal evalueres. Dette er nødvendigt for referenceparametre og nyttigt, når du har brug for at kontrollere filterkonteksten (f.eks. indeni CALCULATE). expr Typer kan være referencer til en kolonne, tabel, kalender eller måling.
    • AnyRef: Accepterer enhver reference. Det svarer til ikke at specificere en udtrykstype.
    • CalendarRef: Accepterer en henvisning til en kalender.
    • ColumnRef: Accepterer en reference til en kolonne.
    • MeasureRef: Accepterer en henvisning til et mål.
    • TableRef: Accepterer en reference til en tabel.

Værdityper (AnyVal, Scalar, Table) understøtter implicit typecasting. Udtrykstyper (AnyRef, CalendarRef, ColumnRef, MeasureRef, ) TableRefgør det ikke.

Undertype

Undertype giver dig mulighed for at definere en bestemt Scalar datatype. Hvis du definerer en undertype, behøver du ikke eksplicit at definere parameteren som en Scalar type, dette antages automatisk.

Undertyper er:

  • Variant: Accepterer enhver skalar.
  • Int64: Accepterer en hel numner.
  • Decimal: Accepterer en decimal med fast præcision (f.eks. Valuta eller Penge).
  • Double: Accepterer et flydende decimaltal.
  • String: Accepterer tekst.
  • DateTime: Accepterer dato/klokkeslæt.
  • Boolean: Accepterer TRUE/FALSE.
  • Numeric: Accepterer alle numeriske værdier (Int64, Decimaleller Double undertyper)

Parameter-tilstand

ParameterMode styrer, hvornår og hvor parameterudtrykket evalueres. Disse er:

  • val (ivrig evaluering): Udtrykket evalueres én gang, før funktionen påberåbes. Den resulterende værdi overføres derefter til funktionen. Dette er almindeligt for simple skalar- eller tabelinput. Dette er standarden, hvis du udelader parameterMode for en parameter.
  • expr (doven evaluering): Udtrykket evalueres inde i funktionen, potentielt i en anden kontekst (f.eks. rækkekontekst eller filterkontekst) og muligvis flere gange, hvis der refereres til det flere gange eller i iterationer. Dette er påkrævet for referenceparametre og nyttigt, når du har brug for at kontrollere evalueringskonteksten.

Typen Scalar kan bruge enten val eller expr. Bruges val , når du vil have skalaren evalueret én gang i opkalderens kontekst. Bruges expr , når du vil udskyde evalueringen og eventuelt anvende kontekst i funktionen. Se Eksempel: Tabelparameter som et eksempel.

Udtrykstyperne (AnyRef, ColumnRef, osv.) skal være expr som dens referencer (kolonner, tabeller, mål osv.) skal evalueres i funktionens kontekst.

Følgende tabel opsummerer den effektive/tilladte parameterMode:

Type ParameterMode ikke specificeret ParameterMode: val ParameterMode: expr
(ikke specificeret) / AnyVal val val expr
Scalar, Table val val expr
AnyRef expr Ikke tilladt expr
CalendarRef, , ColumnRefMeasureRef,TableRef expr Ikke tilladt expr

Eksempel: Type støbning

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

Dette bruger en Scalar type, Int64 subtype og val parameterMode til forudsigelig afrunding og tekst-til-nummer-tvang samt til at sikre, at alle udtryk evalueres ivrigt. Du kan også opnå dette ved blot at inkludere Int64 undertypen som vist i eksemplet nedenfor. Ikke-numeriske strenge vil resultere i en fejl.

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

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

Eksempel: Tabelparameter (værdi vs. udtryk)

For at illustrere, hvordan UDF parameterMode påvirker filterkonteksten, skal du overveje to funktioner, der begge tæller rækker i tabellen 'Salg'. Begge bruger CALCULATETABLE(t, ALL('Date')) i deres kroppe, men den ene parameter er erklæret som en val (ivrig evaluering) og den anden som expr (doven evaluering):

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 returnerer kun optællingen af salg for regnskabsåret 2020. Tabellen 'Salg' er allerede filtreret efter året før indtastning af funktionen, så ALL('Date') inde i funktionen har ingen effekt.

CountRowsLater returnerer optællingen af salg for alle år. Funktionen modtager et ikke-evalueret tabeludtryk og evaluerer det under ALL('Date'), hvilket fjerner filteret for eksterne år.

Kontrol af type

Typekontrol i UDF'er kan udføres med nye og eksisterende typekontrolfunktioner, som du kan kalde inde i din funktionstekst for at bekræfte runtime-typen af beståede parametre. Dette gør det muligt for UDF'er at bruge kontekstkontrol, validere parametre på forhånd, normalisere input før beregning.

Notat

For expr parameterMode-parametre udføres typekontrol, når der refereres til parameteren i funktionsteksten (ikke på funktionskaldstidspunktet).

Tilgængelige funktioner til typekontrol

UDF'er kan bruge følgende funktioner til at teste skalarværdier. Hver returnering TRUE/FALSE afhænger af, om den angivne værdi er af den pågældende type.

Kategori Functions
Numeric ERTAL,ISNUMBER
Dobbelt ISDOUBLE
Heltal ISINT64, HELTAL
Decimaltal ERDECIMAL,ERVALUTA
String ISSTRING,ISTEXT
Boolean ISBOOLSKISLOGICAL
Dato og klokkeslæt ERDATOKLOKKESLÆT

Eksempel: Kontrollér, om parameteren er en streng

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

Dette forhindrer fejl og giver dig mulighed for at bestemme, hvordan ikke-strenginput skal håndteres i funktionen (i dette eksempel returnerer BLANK).

Eksempel: Accepter flere parametertyper

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"

Dette eksempel viser, hvordan du bruger typekontrol i UDF'er til sikkert at acceptere flere inputtyper og returnere et enkelt, forudsigeligt resultat. GetCurrencyName tager et argument, currency, som enten kan være en heltal valutanøgle eller en tekstvalutakode. Funktionen kontrollerer argumenttypen med ISINT64. Hvis inputtet er et heltal, kaldes den hjælperen GetCurrencyNameByKey , der slår valutanavnet op baseret på valutanøglen. Hvis inputtet ikke er et heltal, kaldes den hjælperen GetCurrencyNameByCode , der slår valutanavnet op baseret på valutakoden.

Nyttige informationsfunktioner

Følgende informationsfunktioner er nyttige ved udgivelse af UDF'er:

  • TABLEOF: Returnerer den fulde tabel tilknyttet en given kolonne, mål eller kalender.
  • NAMEOF: Returnerer navnet på en tabel, kolonne, mål eller kalender som en tekststreng

Eksempel: En MODEX-funktion

Følgende eksempel viser en grundlæggende implementering af en MODEX-funktion, der returnerer de hyppigst forekommende værdi(er) af et udtryk, evalueret over en tabel. Den bruges TABLEOF til automatisk at løse den korrekte tabel ud fra den givne reference.

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] )

Definer flere funktioner på én gang

UDF'er giver dig mulighed for at definere flere funktioner i en enkelt forespørgsel eller script, hvilket gør det nemt at organisere genanvendelig logik. Dette er især nyttigt, når du vil indkapsle relaterede beregninger eller hjælperutiner sammen. Funktioner kan evalueres sammen eller hver for sig.

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

Avanceret eksempel: Fleksibel valutaomregning

For at vise, hvordan DAX UDF'er kan håndtere mere kompleks logik, vil vi se på et valutaomregningsscenarie. I dette eksempel bruges typekontrol og indlejrede funktioner til at konvertere et bestemt beløb til en målvaluta ved hjælp af enten gennemsnits- eller dagskursen for en given dato.

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

Funktionen ConvertToCurrency accepterer fleksible inputtyper for både valuta og dato. Brugere kan angive enten en valutanøgle eller datonøgle direkte eller angive en valutakode eller standarddatoværdi. Funktionen kontrollerer typen af hvert input og håndterer det i overensstemmelse hermed: Hvis pCurrency det er et helt tal, behandles det som en valutanøgle; ellers antager funktionen en valutakode og forsøger at løse den tilsvarende nøgle. pDate følger et lignende mønster, hvis det er et helt tal, behandles det som en datonøgle; Ellers antager funktionen, at det er en standarddatoværdi og konverteres til en datonøgle ved hjælp af hjælpefunktionen ConvertDateToDateKey . Hvis funktionen ikke kan bestemme en gyldig ekschnagekurs, returnerer den meddelelsen "ingen valutakurs tilgængelig".

Denne logik kan derefter bruges til at definere en måling som f.eks. Samlet salg i lokal valuta.

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

Dette kan eventuelt parres med en dynamisk formatstreng for at få vist resultatet i det relevante valutaformat.

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

Et eksempel på et resultat kan ses på skærmbilledet nedenfor.

Tabel, der viser Fuld dato, Valuta, Samlet salg i lokal valuta og Samlet salg.

Overvejelser og begrænsninger

Brugerdefinerede funktioner er i øjeblikket i prøveversion, og under prøveversionen skal du være opmærksom på følgende overvejelser og begrænsninger:

Generel:

  • Kan ikke oprette eller modellere DAX UDF'er i Service.

  • Kan ikke skjule/vise en UDF i modellen.

  • Kan ikke placere UDF'er i visningsmapper.

  • Ingen 'opret funktion'-knap på båndet.

  • Kan ikke kombinere UDF'er med oversættelser.

  • UDF'er understøttes ikke i modeller uden tabeller.

  • Object-Level Security (OLS) overføres ikke til funktioner eller omvendt. For eksempel, betragt følgende funktion F , der refererer til sikret mål MyMeasure:

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

    når sikringen MyMeasure sikres ved hjælp af objektniveau-sikkerhed, sikres funktion F ikke automatisk. Hvis F kører under en identitet uden adgang til MyMeasure, opfører den sig, som om MyMeasure ikke eksisterer. Vi anbefaler at undgå at afsløre sikre objekter i funktionsnavne og beskrivelser.

  • Formler-fixering og afhængighedsberegning understøttes, med en kendt begrænsning omkring ukvalificerede navne. Fordi ukvalificerede navne fortolkes som målreferencer, kan de ikke pålideligt fastgøres eller inkluderes i afhængighedssporing, når de er beregnet til at referere til kolonner. Et ukvalificeret navn er en objektreference, der ikke indeholder et tabelpræfiks.

  • CalendarRef, ColumnRef, MeasureRef og TableRef typehints accepteres måske ikke på alle funktionskaldssteder, mens vi er i forhåndsvisning. Brugeren kan falde tilbage til AnyRef.

Definition af en UDF:

  • Rekursion eller gensidig rekursion understøttes ikke.
  • Overbelastning af funktioner understøttes ikke.
  • Eksplicitte returtyper understøttes ikke.

UDF-parametre:

  • Valgfrie parametre understøttes ikke.
  • Parameterbeskrivelser understøttes ikke.
  • UDF'er kan ikke returnere en enum værdi. Indbyggede funktioner, der accepterer enum værdier som deres funktionsparametre, kan ikke bruge UDF'er i denne sammenhæng.
  • Ubundne parametre af typen tip expr evalueres ikke.

IntelliSense-understøttelse:

  • Selvom UDF'er kan bruges i live connect- eller kompositmodeller, er der ingen IntelliSense-understøttelse.
  • Selvom UDF'er kan bruges i visuelle beregninger, har formellinjen for visuelle beregninger ikke IntelliSense-understøttelse af UDF'er.
  • TMDL View har begrænset IntelliSense-understøttelse af UDF'er.

Kendte fejl

Følgende problemer er i øjeblikket kendte og kan påvirke funktionaliteten:

  • Visse avancerede scenarier, der involverer UDF'er, kan resultere i parser-uoverensstemmelser. Brugere kan f.eks. se røde understregninger eller valideringsfejl, når de overfører kolonner som expr parametre eller bruger ukvalificerede kolonnereferencer.