Delen via


DAX door de gebruiker gedefinieerde functies (preview)

Opmerking

DAX door de gebruiker gedefinieerde functies zijn momenteel beschikbaar als preview-versie.

DAX met door de gebruiker gedefinieerde functies (UDF's) kunt u logica verpakken DAX en opnieuw gebruiken zoals elke andere DAX functie. UDF's introduceren een nieuw FUNCTION trefwoord, optionele parameters (scalaire, tabel en verwijzingen) en typecontrolehelpers die het ontwerpen veiliger en duidelijker maken. Nadat u een UDF hebt gedefinieerd, kunt u deze gebruiken in een meting, berekende kolom, visuele berekening of zelfs andere door de gebruiker gedefinieerde functies. Gebruikers kunnen bedrijfsregels centraliseren, de onderhoudbaarheid verbeteren en berekeningen veilig ontwikkelen in de loop van de tijd. Functies zijn eersteklas modelobjecten die u kunt maken en beheren in DAX de queryweergave en TMDL-weergave, en ze kunnen worden weergegeven in Modelverkenner onder het knooppunt Functions .

Door de gebruiker gedefinieerde functies inschakelen

Probeer UDF's op de Desktop:

  1. Ga naar Opties > en instellingen > voor bestanden.
  2. Selecteer Preview-functies en controleer DAX door de gebruiker gedefinieerde functies.
  3. Selecteer OK en start Power BI Desktop opnieuw.

Door de gebruiker gedefinieerde functies definiëren en beheren

Er zijn verschillende locaties voor het definiëren en beheren van functies:

  • DAX queryweergave (DQV). Functies definiëren en wijzigen in DQV. DQV bevat ook contextmenu Snelle queries (evalueren, definiëren en evalueren, en alle functies in dit model definiëren) om u te helpen UDF's snel te testen en beheren.
  • TMDL-weergave. UDF's kunnen ook worden geschreven en bewerkt in TMDL. TMDL-weergave bevat ook contextmenu Script TMDL naar.
  • Modelverkenner. Bestaande functies kunnen worden weergegeven onder het knooppunt Functions in Modelverkenner.

Volg deze naamgevingsvereisten bij het definiëren van een UDF:

Functienamen:

  • Moet goed gevormd en uniek zijn binnen het model.
  • Kan punten bevatten voor naamgeving (bijvoorbeeld Microsoft.PowerBI.MyFunc). Kan niet beginnen of eindigen met een periode of opeenvolgende perioden hebben.
  • Behalve leestekens mogen namen alleen alfanumerieke tekens of onderstrepingstekens bevatten. Er zijn geen spaties of speciale tekens toegestaan.
  • Mag niet conflicteren met ingebouwde DAX functies of gereserveerde woorden (bijvoorbeeld meten, functie, definiëren).

Parameternamen:

  • Mag alleen alfanumerieke tekens of onderstrepingstekens bevatten. Perioden zijn niet toegestaan.
  • Mag geen gereserveerd woord zijn.

Queryweergave gebruiken DAX

U kunt door de gebruiker gedefinieerde functies definiëren, bijwerken en evalueren in DAX de queryweergave. Voor meer informatie over queryweergave DAX, zie queryweergave DAX.

Algemeen formulier

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

Aanbeveling

Gebruiken /// voor functiebeschrijvingen. Opmerkingen met één regel (//) of meerdere regels (/* */) worden niet weergegeven in IntelliSense-functiebeschrijvingen.

Voorbeeld: Eenvoudige belastingfunctie

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

EVALUATE
{ AddTax ( 10 ) }
// Returns 11

Opslaan in het model

Een UDF opslaan vanuit DAX de queryweergave naar het model:

  • Klik op Model bijwerken met wijzigingen om alle UDF's in de query op te slaan.
  • Of klik op Model bijwerken: Voeg een nieuwe functie toe boven de gedefinieerde functie om één UDF op te slaan.

Schermopname van DAX de queryweergave in Power BI Desktop, waarin twee locaties worden gemarkeerd waar u een door de gebruiker gedefinieerde functie kunt opslaan. De eerste is het updatemodel met de knop Wijzigingen boven aan de weergave. De tweede is een statusregel in de code-editor met het label Update-model: Nieuwe functie toevoegen

TMDL-weergave gebruiken

U kunt door de gebruiker gedefinieerde functies definiëren en/of bijwerken in de TMDL-weergave. Voor meer informatie, zie de TMDL-weergave.

Algemeen formulier

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

Voorbeeld: Eenvoudige belastingfunctie

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

Opslaan in het model

Klik boven aan de weergave op de knop Toepassen om alle UDF's in het script op te slaan in het model.

Schermopname van de TMDL-weergave in Power BI Desktop, met de knop Toepassen bovenaan de weergave gemarkeerd. Dit is de locatie waar u een door de gebruiker gedefinieerde functie kunt opslaan.

TMDL-script gebruiken in een Power BI-project

UDF's zijn ook opgenomen in het semantische model TMDL-script wanneer u een Power BI-project gebruikt. Deze zijn te vinden in functions.tmdl binnen de definitiemap.

Schermopname van Een Power BI-project in Visual Studio Code. Explorer is geopend in de semantische modelmap. 'functions.tmdl' is geopend in de code-editor. Er worden drie functies weergegeven: CustomerLifetimeValue, AverageOrderValue en AddTax.

Modelverkenner gebruiken

U kunt alle door de gebruiker gedefinieerde functies in het model bekijken vanuit Modelverkenner onder het knooppunt Functions . Zie Modelverkenner voor meer informatie over Modelverkenner.

Het deelvenster Modelverkenner in Power BI Desktop met het uitgevouwen Functions-knooppunt. Er worden drie door de gebruiker gedefinieerde functies weergegeven: AddTax, AverageOrderValue en CustomerLifetimeValue.

In DAX de queryweergave kunt u snelle query's gebruiken in het snelmenu van een UDF in Modelverkenner om eenvoudig functies te definiëren en te evalueren.

In het deelvenster Modelverkenner in Power BI Desktop wordt het uitgevouwen Functies-knooppunt weergegeven. Er zijn twee contextmenu's geopend: het eerste menu bevat Snelle query's, Naam wijzigen, Verwijderen uit model, Verbergen in rapportweergave, Alles zichtbaar maken, Alles samenvouwen en Alles uitvouwen. Snelle query's is gemarkeerd en geselecteerd. Het tweede menu is gemarkeerd en biedt opties voor Snelle query's zoals Evalueren, Definiëren en evalueren, Nieuwe functie definiëren en Alle functies in dit model definiëren.

In de TMDL-weergave kunt u functies naar het canvas slepen en neerzetten of de functie Script TMDL gebruiken in het contextmenu van een UDF binnen Modelverkenner om scripts te genereren.

In het deelvenster Modelverkenner in Power BI Desktop wordt het uitgevouwen Functions-knooppunt weergegeven. Er zijn twee contextmenu's geopend: het eerste menu biedt Script naar TMDL, Naam wijzigen, Verwijderen uit model, Verbergen in rapportweergave, Alles zichtbaar maken, Alles samenvouwen en Alles uitvouwen. Script naar TMDL is gemarkeerd en geselecteerd. Het tweede menu is gemarkeerd en biedt opties voor Script naar TMDL: Tabblad en Klembord.

DMVs gebruiken om UDFs te inspecteren

U kunt UDF's in uw model inspecteren met dynamische beheerweergaven (DMV's). Met deze weergaven kunt u query's uitvoeren op informatie over functies, waaronder UDF's.

U kunt de functie INFO.FUNCTIONS gebruiken om de UDFs in het model te inspecteren. Als u het resultaat alleen wilt beperken tot UDF's, geeft u de ORIGIN parameter op als 2.

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

Deze query retourneert een tabel met alle UDF's die zich momenteel in het model bevinden, inclusief hun naam, beschrijving en bijbehorende metagegevens.

Een door de gebruiker gedefinieerde functie gebruiken

Zodra een UDF is gedefinieerd en opgeslagen in het model, kunt u deze aanroepen vanuit metingen, berekende kolommen, visuele berekeningen en andere UDF's. Dit werkt hetzelfde als het aanroepen van ingebouwde DAX functies.

Een UDF aanroepen in een meting

Gebruik een UDF in een meting om herbruikbare logica toe te passen met volledige filtercontext.

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

De voorbeeldmeting wordt weergegeven in de onderstaande tabel:

Tabel met totale verkoop en totale omzet met belasting. Totale omzet met belasting is gemarkeerd. Het deelvenster Visualisaties is geopend. Totale omzet met belasting is gemarkeerd in het veld Kolommen.

Een UDF aanroepen in een berekende kolom

UDF's kunnen worden gebruikt in een berekende kolom om herbruikbare logica toe te passen op elke rij in een tabel.

Opmerking

Wanneer u een UDF in een berekende kolom gebruikt, moet u ervoor zorgen dat de functie een scalaire waarde van een consistent type retourneert. Zie Parameters voor meer informatie. Converteer indien nodig het resultaat naar het gewenste type met behulp van CONVERT of vergelijkbare functies.

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

We kunnen deze voorbeeldmeting zien die in de onderstaande tabel wordt gebruikt:

Tabel met verkoopbedrag en verkoopbedrag inclusief belasting. Verkoopbedrag inclusief belasting is gemarkeerd. Het deelvenster visualisaties is geopend. Verkoopbedrag inclusief belasting is gemarkeerd in het veld kolommen.

Een UDF aanroepen in een visuele berekening

U kunt UDF's in een visuele berekening gebruiken om logica rechtstreeks op de visual toe te passen. Zie Visuele berekeningen voor meer informatie over visuele berekeningen.

Opmerking

Visuele berekeningen worden alleen uitgevoerd op velden die aanwezig zijn in de visual. Ze hebben geen toegang tot modelobjecten die geen deel uitmaken van de visual en u kunt in deze context geen modelobjecten (zoals kolommen of metingen) doorgeven aan een UDF.

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

We kunnen deze voorbeeldmeting zien in de onderstaande tabel:

In de bewerkingsmodus voor visuele berekeningen. Tabel met verkoopbedrag en verkoopbedrag met belasting. Verkoopbedrag met belasting is gemarkeerd. Visuele berekeningsformule voor verkoopbedrag met belasting is gemarkeerd.

Een UDF aanroepen in een andere UDF

U kunt UDF's nesten door een functie vanuit een andere functie aan te roepen. In dit voorbeeld definiëren we onze eenvoudige AddTax UDF en roepen we deze aan in een andere 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

Parameterwaarden

DAX UDF's kunnen nul of meer parameters accepteren. Wanneer u parameters voor een UDF definieert, kunt u desgewenst typehints opgeven voor elke parameter:

  • Type: welk type waarde de parameter accepteert (AnyVal, Scalar, Tableof AnyRef).
  • Subtype (alleen voor scalaire typen): het specifieke scalaire gegevenstype (Variant, Int64, DecimalDouble, , String, , DateTime, of BooleanNumeric).
  • ParameterMode: wanneer het argument wordt geëvalueerd (val of expr).

Typehints staan in de vorm: [type] [subtype] [parameterMode]

U kunt alle, sommige of geen van deze type hints voor elke parameter opnemen om uw functies veiliger en voorspelbaarder te maken op oproepsites. Als u alles weglaat en alleen de parameternaam schrijft, gedraagt het zich zoals AnyVal val, wat betekent dat het argument onmiddellijk wordt geëvalueerd tijdens het aanroepen. Dit is handig voor eenvoudige functies.

Typologie

Type definieert de categorie van het argument dat uw parameter accepteert en of deze wordt doorgegeven als een waarde of een expressie.

Er zijn twee typefamilies in DAX UDF-parameters: waardetypen en expressietypen:

  • Waardetypen: dit argument wordt onmiddellijk geëvalueerd (gretige evaluatie) wanneer de functie wordt aangeroepen en de resulterende waarde wordt doorgegeven aan de functie.
    • AnyVal: accepteert een scalaire waarde of een tabel. Dit is de standaardinstelling als u het type voor een parameter weglaat.
    • Scalar: Accepteert een scalaire waarde (kan ook een subtype toevoegen).
    • Table: Accepteert een tabel.
  • Expressietypen: dit argument geeft een niet-geëvalueerde expressie door (luie evaluatie). De functie bepaalt wanneer en in welke context deze moet worden geëvalueerd. Dit is vereist voor referentieparameters en handig wanneer u filtercontext wilt beheren (bijvoorbeeld binnen CALCULATE). expr typen kunnen verwijzingen zijn naar een kolom, tabel, agenda of meting.
    • AnyRef: Accepteert een verwijzing (een kolom, tabel, agenda of meting).

Onderdeeltype

Met subtype kunt u een specifiek Scalar gegevenstype definiëren. Als u een subtype definieert, hoeft u de parameter niet expliciet te definiëren als een Scalar type. Dit wordt automatisch aangenomen.

Subtypen zijn:

  • Variant: accepteert alle scalaire waarden.
  • Int64: accepteert een geheel getal.
  • Decimal: Accepteert een decimale waarde met vaste precisie (zoals Valuta).
  • Double: Accepteert een decimale komma met drijvende komma.
  • String: Accepteert tekst.
  • DateTime: Accepteert datum/tijd.
  • Boolean: accepteert TRUE/FALSE.
  • Numeric: Accepteert een numerieke waarde (Int64of DecimalDouble subtypen)

ParameterMode

ParameterMode bepaalt wanneer en waar de parameterexpressie wordt geëvalueerd. Dit zijn:

  • val (gretige evaluatie): de expressie wordt eenmaal geëvalueerd voordat u de functie aanroept. De resulterende waarde wordt vervolgens doorgegeven aan de functie. Dit is gebruikelijk voor eenvoudige scalaire invoer of tabelinvoer. Dit is de standaardinstelling als u parameterMode weglaat voor een parameter.
  • expr (luie evaluatie): de expressie wordt geëvalueerd in de functie, mogelijk in een andere context (bijvoorbeeld rijcontext of filtercontext) en mogelijk meerdere keren als er meerdere keren naar wordt verwezen of binnen iteraties. Dit is vereist voor referentieparameters en is handig wanneer u de evaluatiecontext wilt beheren.

Het Scalar type kan of val of expr gebruiken. Gebruik val deze optie als u wilt dat de scalaire waarde eenmaal wordt geëvalueerd in de context van de aanroeper. Gebruik expr deze optie als u de evaluatie wilt uitstellen en mogelijk context in de functie wilt toepassen. Zie Voorbeeld: Tabelparameter als voorbeeld.

Het AnyRef type moet zijn expr als verwijzingen (kolommen, tabellen, metingen, enzovoort) moeten worden geëvalueerd in de context van de functie.

Voorbeeld: Typecasting

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

Hierbij wordt gebruikgemaakt van een Scalar type, Int64 subtype en val parameterMode voor voorspelbare afronding en coercion van tekst-naar-getal, en om ervoor te zorgen dat expressies gretig worden geëvalueerd. U kunt dit ook bereiken door alleen het Int64 subtype op te halen, zoals te zien is in het onderstaande voorbeeld. Niet-numerieke tekenreeksen resulteren in een fout.

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

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

Voorbeeld: Tabelparameter (waarde versus expressie)

Om te illustreren hoe de UDF parameterMode de filtercontext beïnvloedt, zijn er twee functies die beide de rijen in de tabel 'Sales' tellen. Beide gebruiken CALCULATETABLE(t, ALL('Date')) als onderdeel van hun structuur, maar één parameter wordt gedeclareerd als een val (vroege evaluatie) en de andere als expr (uitgestelde evaluatie):

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 retourneert alleen het aantal verkopen voor FY2020. De tabel Verkoop wordt al gefilterd op het jaar voordat u de functie invoert, dus ALL('Date') binnen de functie heeft geen effect.

CountRowsLater retourneert het aantal verkopen voor alle jaren. De functie ontvangt een niet-geëvalueerde tabelexpressie en evalueert deze onder ALL('Date'), waarbij het externe jaarfilter wordt verwijderd.

Typecontrole

Typecontrole in UDF's kan worden uitgevoerd met nieuwe en bestaande typecontrolefuncties die u in de hoofdtekst van uw functie kunt aanroepen om het runtimetype van doorgegeven parameters te bevestigen. Hierdoor kunnen UDF's contextbeheer gebruiken, parameters vooraf valideren, invoer normaliseren vóór de berekening.

Opmerking

Voor expr parameterMode-parameters worden typecontroles uitgevoerd wanneer naar de parameter wordt verwezen in de hoofdtekst van de functie (niet tijdens het aanroepen van de functie).

Beschikbare functies voor typecontrole

UDF's kunnen de volgende functies gebruiken om scalaire waarden te testen. Elk resultaat TRUE/FALSE is afhankelijk van of de opgegeven waarde van dat type is.

Categorie Functions
Numeric ISNUMERIC, ISNUMBER
Double ISDOUBLE
Geheel getal ISINT64, ISINTEGER
Decimal ISDECIMAL, ISCURRENCY
Snaar / Touwtje ISSTRING, ISTEXT
Booleaan ISBOOLEAN, ISLOGICAL
Datum en tijd ISDATETIME

Voorbeeld: Controleren of de parameter een tekenreeks is

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

Hiermee voorkomt u fouten en kunt u bepalen hoe u invoer van niet-tekenreeksen in de functie kunt verwerken (in dit voorbeeld wordt geretourneerd BLANK).

Voorbeeld: Meerdere parametertypen accepteren

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"

In dit voorbeeld ziet u hoe u typecontrole in UDF's gebruikt om veilig meerdere invoertypen te accepteren en één voorspelbaar resultaat te retourneren. GetCurrencyName gebruikt één argument, currencydat een valutasleutel voor een geheel getal of een code voor een tekstvaluta kan zijn. De functie controleert het argumenttype met ISINT64. Als de invoer een geheel getal is, wordt de helper GetCurrencyNameByKey aanroepen die de valutanaam opzoekt op basis van de valutasleutel. Als de invoer geen geheel getal is, wordt de helper GetCurrencyNameByCode aanroepen die de valutanaam opzoekt op basis van de valutacode.

Meerdere functies tegelijk definiëren

Met UDF's kunt u verschillende functies definiëren in één query of script, zodat u eenvoudig herbruikbare logica kunt ordenen. Dit is vooral handig als u gerelateerde berekeningen of helperroutines samen wilt inkapselen. Functies kunnen samen of afzonderlijk worden geëvalueerd.

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

Geavanceerd voorbeeld: Flexibele valutaconversie

Om te laten zien hoe DAX UDF's complexere logica kunnen verwerken, kijken we naar een valutaconversiescenario. In dit voorbeeld worden typecontrole en geneste functies gebruikt om een bepaald bedrag te converteren naar een doelvaluta naar keuze met behulp van de gemiddelde wisselkoers of de slotkoers voor een specifieke datum.

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

De ConvertToCurrency functie accepteert flexibele invoertypen voor zowel valuta als datum. Gebruikers kunnen een valutasleutel of datumsleutel rechtstreeks opgeven of een valutacode of standaarddatumwaarde opgeven. De functie controleert het type invoer en verwerkt deze dienovereenkomstig: als pCurrency dit een geheel getal is, wordt deze beschouwd als een valutasleutel. Anders wordt door de functie uitgegaan van een valutacode en wordt geprobeerd de bijbehorende sleutel op te lossen. pDate volgt een vergelijkbaar patroon, als het een geheel getal is, wordt het beschouwd als een datumsleutel; anders wordt ervan uitgegaan dat de functie een standaarddatumwaarde is en wordt geconverteerd naar een datumsleutel met behulp van de ConvertDateToDateKey helperfunctie. Als de functie een geldige exchnage-rente niet kan bepalen, wordt het bericht 'geen wisselkoers beschikbaar' geretourneerd.

Deze logica kan vervolgens worden gebruikt om een meting te definiëren, zoals Totale verkoop in lokale valuta.

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

Dit kan eventueel worden gekoppeld aan een tekenreeks voor dynamische notatie om het resultaat weer te geven in de juiste valutanotatie.

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

In de onderstaande schermopname ziet u een voorbeeldresultaat.

Tabel met volledige datum, valuta, totale verkoop in lokale valuta en totale verkoop.

Overwegingen en beperkingen

Door de gebruiker gedefinieerde functies zijn momenteel in preview en tijdens de preview moet u rekening houden met de volgende overwegingen en beperkingen:

Algemeen:

  • Kan DAX UDF's niet maken of modelleren in Service.

  • Kan een UDF niet verbergen of zichtbaar maken in het model.

  • UDF's kunnen niet in weergavemappen worden geplaatst.

  • Er is geen knop 'functie maken' op het lint.

  • UDF's kunnen niet worden gecombineerd met vertalingen.

  • UDF's worden niet ondersteund in modellen zonder tabellen.

  • Geen snelle query 'definiëren met verwijzingen' in DAX de queryweergave.

  • Object-Level Security (OLS) wordt niet overgedragen naar functies of vise versa. Denk bijvoorbeeld aan de volgende functie F die verwijst naar beveiligde meting MyMeasure:

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

    wanneer de MyMeasure beveiliging wordt beveiligd met behulp van beveiliging op objectniveau, wordt functie F niet automatisch beveiligd. Als F wordt uitgevoerd onder een identiteit zonder toegang tot MyMeasure, doet F alsof niet bestaat. Het is raadzaam om te voorkomen dat beveiligde objecten in functienamen en beschrijvingen worden weergegeven.

Een UDF definiëren:

  • Recursie of wederzijdse recursie wordt niet ondersteund.
  • Overbelasting van functies wordt niet ondersteund.
  • Expliciete retourtypen worden niet ondersteund.

UDF-parameters:

  • Optionele parameters worden niet ondersteund.
  • Parameterbeschrijvingen worden niet ondersteund.
  • UDF's kunnen geen enum waarde retourneren. Ingebouwde functies die waarden accepteren enum als hun functieparameters, kunnen in die context geen UDF's gebruiken.
  • Niet-afhankelijke parameters van het type hint expr worden niet geëvalueerd.

Ondersteuning voor IntelliSense:

  • Hoewel UDF's kunnen worden gebruikt in live connect- of samengestelde modellen, is er geen IntelliSense-ondersteuning.
  • Hoewel UDF's kunnen worden gebruikt in visuele berekeningen, heeft de formulebalk voor visuele berekeningen geen IntelliSense-ondersteuning voor UDF's.
  • De TMDL-weergave beschikt niet over de juiste IntelliSense-ondersteuning voor UDF's.

Bekende bugs

De volgende problemen zijn momenteel bekend en kunnen van invloed zijn op de functionaliteit:

  • Verwijzingen naar een tabellair modelobject (bijvoorbeeld meting, tabel, kolom) in een UDF worden niet automatisch bijgewerkt wanneer de naam van deze objecten wordt gewijzigd. Als u de naam van een object wijzigt waarop een UDF afhankelijk is, bevat de hoofdtekst van de functie nog steeds de oude naam. U moet de UDF-expressie handmatig bewerken om alle verwijzingen naar het hernoemde object bij te werken.
  • Bepaalde geavanceerde scenario's met betrekking tot UDF's kunnen leiden tot inconsistenties van parser. Gebruikers kunnen bijvoorbeeld rode onderstrepingen of validatiefouten zien bij het doorgeven van kolommen als expr parameters of het gebruik van niet-gekwalificeerde kolomverwijzingen.