Share via


Introductie

Overzicht

Microsoft Power Query biedt een krachtige ervaring voor het ophalen van gegevens die veel functies omvat. Een kernmogelijkheid van Power Query is het filteren en combineren van gegevens uit een of meer van een uitgebreide verzameling ondersteunde gegevensbronnen. Dergelijke gegevens mashup wordt uitgedrukt met behulp van de Power Query-formuletaal (informeel bekend als 'M'). Power Query sluit M-documenten in in een breed scala aan Microsoft-producten, waaronder Excel, Power BI, Analysis Services en Dataverse, om herhaalbare mashup van gegevens mogelijk te maken.

Dit document bevat de specificatie voor M. Na een korte inleiding die gericht is op het bouwen van een eerste intuïtieve en vertrouwdheid met de taal, beslaat het document de taal precies in verschillende progressieve stappen:

  1. De lexicale structuur definieert de set teksten die lexical geldig zijn.

  2. Waarden, expressies, omgevingen en variabelen, id's en het evaluatiemodel vormen de basisconcepten van de taal.

  3. De gedetailleerde specificatie van waarden, zowel primitieve als gestructureerde, definieert het doeldomein van de taal.

  4. Waarden hebben typen, zelf een speciaal soort waarde, die beide de fundamentele soorten waarden karakteriseren en aanvullende metagegevens bevatten die specifiek zijn voor de vormen van gestructureerde waarden.

  5. De set operators in M definieert welke soorten expressies kunnen worden gevormd.

  6. Functies, een ander soort speciale waarden, bieden de basis voor een uitgebreide standaardbibliotheek voor M en maken het toevoegen van nieuwe abstracties mogelijk.

  7. Er kunnen fouten optreden bij het toepassen van operators of functies tijdens de evaluatie van expressies. Hoewel fouten geen waarden zijn, zijn er manieren om fouten af te handelen die fouten weer toewijzen aan waarden.

  8. Met expressies kunt u hulpdefinities invoeren die worden gebruikt voor het opbouwen van complexe expressies in kleinere stappen.

  9. Als expressies voorwaardelijke evaluatie ondersteunen.

  10. Secties bieden een eenvoudig modulariteitsmechanisme. (Secties worden nog niet gebruikt door Power Query.)

  11. Ten slotte verzamelt een geconsolideerde grammatica de grammaticafragmenten van alle andere secties van dit document in één volledige definitie.

Voor computertaal theoristen: de formuletaal die in dit document is opgegeven, is een voornamelijk pure, hogere volgorde, dynamisch getypte, gedeeltelijk luie functionele taal.

Expressies en waarden

De centrale constructie in M is de expressie. Een expressie kan worden geëvalueerd (berekend), wat één waarde oplevert.

Hoewel veel waarden letterlijk als een expressie kunnen worden geschreven, is een waarde geen expressie. De expressie 1 evalueert bijvoorbeeld naar de waarde 1; de expressies 1+1 evalueren naar de waarde 2. Dit onderscheid is subtiel, maar belangrijk. Expressies zijn recepten voor evaluatie; waarden zijn de resultaten van de evaluatie.

In de volgende voorbeelden ziet u de verschillende soorten waarden die beschikbaar zijn in M. Als conventie wordt een waarde geschreven met behulp van de letterlijke vorm waarin deze worden weergegeven in een expressie die alleen die waarde evalueert. (Houd er rekening mee dat het // begin van een opmerking aangeeft die verdergaat naar het einde van de regel.)

  • Een primitieve waarde is een enkele waarde, zoals een getal, logische waarde, tekst of null. Een null-waarde kan worden gebruikt om aan te geven dat er geen gegevens zijn.

    123                  // A number
    true                 // A logical
    "abc"                // A text
    null                 // null value
    
  • Een lijstwaarde is een geordende reeks waarden. M ondersteunt oneindige lijsten, maar als ze als letterlijk zijn geschreven, hebben lijsten een vaste lengte. De accoladetekens { en } geven het begin en einde van een lijst aan.

    {123, true, "A"}     // list containing a number, a logical, and 
                          //     a text 
    {1, 2, 3}            // list of three numbers 
    
  • Een record is een set velden. Een veld is een naam-waardepaar waarbij de naam een tekstwaarde is die uniek is binnen de record van het veld. Met de letterlijke syntaxis voor recordwaarden kunnen de namen zonder aanhalingstekens worden geschreven, een formulier dat ook wel id's wordt genoemd. Hieronder ziet u een record met drie velden met de naam "A", "B" en "C", met waarden 1, 2en 3.

    [ 
          A = 1,  
          B = 2,  
          C = 3 
    ]
    
  • Een tabel is een set waarden die zijn ingedeeld in kolommen (die worden aangeduid met de naam) en rijen. Er is geen letterlijke syntaxis voor het maken van een tabel, maar er zijn verschillende standaardfuncties die kunnen worden gebruikt om tabellen te maken op basis van lijsten of records.

    Bijvoorbeeld:

    #table( {"A", "B"}, { {1, 2}, {3, 4} } ) 
    

    Hiermee maakt u een tabel met de volgende shape:

    Image of an example table in the M formula language.

  • Een functie is een waarde die, wanneer deze wordt aangeroepen met argumenten, een nieuwe waarde produceert. Een functie wordt geschreven door de parameters van de functie tussen haakjes weer te geven, gevolgd door het symbool 'naar', =>gevolgd door de expressie die de functie definieert. Deze expressie verwijst doorgaans naar de parameters (op naam).

    (x, y) => (x + y) / 2`
    

Beoordeling

Het evaluatiemodel van de M-taal wordt gemodelleerd na het evaluatiemodel dat vaak wordt gevonden in spreadsheets, waarbij de volgorde van de berekening kan worden bepaald op basis van afhankelijkheden tussen de formules in de cellen.

Als u formules hebt geschreven in een spreadsheet zoals Excel, herkent u mogelijk de formules aan de linkerkant in de waarden aan de rechterkant wanneer deze worden berekend:

Image of the formulas on the right resulting in the values on the left.

In M kunnen delen van een expressie verwijzen naar andere delen van de expressie op naam en het evaluatieproces bepaalt automatisch de volgorde waarin naar expressies wordt verwezen.

U kunt een record gebruiken om een expressie te produceren die gelijk is aan het vorige spreadsheetvoorbeeld. Wanneer u de waarde van een veld initialiseert, kunt u als volgt verwijzen naar andere velden in de record met behulp van de naam van het veld:

[  
    A1 = A2 * 2,  
    A2 = A3 + 1,  
    A3 = 1  
]

De bovenstaande expressie is gelijk aan het volgende (in dat beide waarden als resultaat geven):

[  
    A1 = 4,  
    A2 = 2,  
    A3 = 1  
]

Records kunnen worden opgenomen in of genest in andere records. U kunt de opzoekoperator ([]) gebruiken om toegang te krijgen tot de velden van een record op naam. De volgende record bevat bijvoorbeeld een veld Sales met een record en een veld met de naam Total die toegang heeft tot de FirstHalf en SecondHalf velden van de Sales record:

[  
    Sales = [ FirstHalf = 1000, SecondHalf = 1100 ], 
    Total = Sales[FirstHalf] + Sales[SecondHalf] 
]

De bovenstaande expressie is gelijk aan het volgende wanneer deze wordt geëvalueerd:

[  
    Sales = [ FirstHalf = 1000, SecondHalf = 1100 ], 
    Total = 2100 
]

Records kunnen ook worden opgenomen in lijsten. U kunt de positionele indexoperator ({}) gebruiken om toegang te krijgen tot een item in een lijst door de bijbehorende numerieke index. De waarden in een lijst worden aangeduid met behulp van een op nul gebaseerde index vanaf het begin van de lijst. De indexen 0 worden 1 bijvoorbeeld gebruikt om te verwijzen naar de eerste en tweede items in de onderstaande lijst:

[ 
    Sales =  
        {  
            [  
                Year = 2007,  
                FirstHalf = 1000,  
                SecondHalf = 1100, 
                Total = FirstHalf + SecondHalf // 2100 
            ], 
            [  
                Year = 2008,  
                FirstHalf = 1200,  
                SecondHalf = 1300, 
                Total = FirstHalf + SecondHalf // 2500 
            ]  
        }, 
    TotalSales = Sales{0}[Total] + Sales{1}[Total] // 4600 
]

Lijst- en recordlidexpressies (en laat expressies) worden geëvalueerd met behulp van luie evaluatie. Dit betekent dat ze alleen worden geëvalueerd als dat nodig is. Alle andere expressies worden geëvalueerd met behulp van gretige evaluatie, wat betekent dat ze onmiddellijk worden geëvalueerd wanneer ze tijdens het evaluatieproces worden aangetroffen. Een goede manier om hier rekening mee te houden is dat het evalueren van een lijst- of recordexpressie een lijst- of recordwaarde retourneert die zelf onthoudt hoe de lijstitems of recordvelden moeten worden berekend, wanneer dit wordt aangevraagd (door opzoek- of indexoperators).

Functies

In M is een functie een toewijzing van een set invoerwaarden aan één uitvoerwaarde. Een functie wordt geschreven door eerst de vereiste set invoerwaarden (de parameters voor de functie) een naam te geven en vervolgens een expressie op te geven waarmee het resultaat van de functie wordt berekend met behulp van deze invoerwaarden (de hoofdtekst van de functie) na het gaat-naar=> () symbool. Bijvoorbeeld:

(x) => x + 1                    // function that adds one to a value 
(x, y) =>  x + y                // function that adds two values

Een functie is een waarde, net als een getal of een tekstwaarde. In het volgende voorbeeld ziet u een functie die de waarde is van een veld Toevoegen dat vervolgens wordt aangeroepen of uitgevoerd vanuit verschillende andere velden. Wanneer een functie wordt aangeroepen, wordt een set waarden opgegeven die logisch worden vervangen door de vereiste set invoerwaarden in de hoofdtekstexpressie van de functie.

[ 
    Add = (x, y) => x + y,
    OnePlusOne = Add(1, 1),     // 2 
    OnePlusTwo = Add(1, 2)      // 3
]

Bibliotheek

M bevat een algemene set definities die beschikbaar zijn voor gebruik vanuit een expressie die de standaardbibliotheek wordt genoemd, of een bibliotheek kortom. Deze definities bestaan uit een set benoemde waarden. De namen van waarden die door een bibliotheek worden geleverd, zijn beschikbaar voor gebruik binnen een expressie zonder expliciet door de expressie te zijn gedefinieerd. Bijvoorbeeld:

Number.E                        // Euler's number e (2.7182...) 
Text.PositionOf("Hello", "ll")  // 2

Operatoren

M bevat een set operators die kunnen worden gebruikt in expressies. Operators worden toegepast op operanden om symbolische expressies te vormen. In de expressie 1 + 2 zijn bijvoorbeeld de getallen 1 en 2 operanden en is de operator de operator voor optellen (+).

De betekenis van een operator kan variëren, afhankelijk van wat voor soort waarden de operanden zijn. De plus-operator kan bijvoorbeeld worden gebruikt met andere soorten waarden naast getallen:

1 + 2                   // numeric addition: 3 
#time(12,23,0) + #duration(0,0,2,0) 
                        // time arithmetic: #time(12,25,0)

Een ander voorbeeld van een operator met operand-afhankelijke betekenis is de combinatieoperator (&):

"A" & "BC"              // text concatenation: "ABC" 
{1} & {2, 3}            // list concatenation: {1, 2, 3} 
[ a = 1 ] & [ b = 2 ]   // record merge: [ a = 1, b = 2 ]

Houd er rekening mee dat sommige operators niet alle combinaties van waarden ondersteunen. Bijvoorbeeld:

1 + "2"  // error: adding number and text isn't supported

Expressies die, wanneer deze worden geëvalueerd, niet-gedefinieerde operatorvoorwaarden tegenkomen, resulteren in fouten.

Metagegevens

Metagegevens zijn informatie over een waarde die is gekoppeld aan een waarde. Metagegevens worden weergegeven als een recordwaarde, een metagegevensrecord genoemd. De velden van een metagegevensrecord kunnen worden gebruikt om de metagegevens voor een waarde op te slaan.

Elke waarde heeft een metagegevensrecord. Als de waarde van de metagegevensrecord niet is opgegeven, is de metagegevensrecord leeg (bevat geen velden).

Metagegevensrecords bieden een manier om aanvullende informatie te koppelen aan elk soort waarde op een onopvallende manier. Als u een metagegevensrecord aan een waarde wilt koppelen, wordt de waarde of het gedrag ervan niet gewijzigd.

Een metagegevensrecordwaarde y is gekoppeld aan een bestaande waarde x met behulp van de syntaxis x meta y. De volgende code koppelt bijvoorbeeld een metagegevensrecord aan Rating en Tags velden aan de tekstwaarde "Mozart":

"Mozart" meta [ Rating = 5, Tags = {"Classical"} ]

Voor waarden die al een niet-lege metagegevensrecord bevatten, is het resultaat van het toepassen van meta die de recordsamenvoeging van de bestaande en de nieuwe metagegevensrecord berekenen. De volgende twee expressies zijn bijvoorbeeld gelijk aan elkaar en aan de vorige expressie:

("Mozart" meta [ Rating = 5 ]) meta [ Tags = {"Classical"} ] 
"Mozart" meta ([ Rating = 5 ] & [ Tags = {"Classical"} ])

Een metagegevensrecord kan worden geopend voor een bepaalde waarde met behulp van de functie Value.Metadata . In het volgende voorbeeld heeft de expressie in het ComposerRating veld toegang tot de metagegevensrecord van de waarde in het Composer veld en wordt vervolgens het Rating veld van de metagegevensrecord geopend.

[ 
    Composer = "Mozart" meta [ Rating = 5, Tags = {"Classical"} ], 
    ComposerRating = Value.Metadata(Composer)[Rating] // 5
]

Expressie toestaan

Veel van de voorbeelden die tot nu toe worden weergegeven, bevatten alle letterlijke waarden van de expressie in het resultaat van de expressie. Met de let expressie kan een set waarden worden berekend, toegewezen namen worden berekend en vervolgens worden gebruikt in een volgende expressie die volgt op de in. In ons voorbeeld van verkoopgegevens kunt u bijvoorbeeld het volgende doen:

let 
    Sales2007 =  
        [  
            Year = 2007,  
            FirstHalf = 1000,  
            SecondHalf = 1100, 
            Total = FirstHalf + SecondHalf // 2100 
        ], 
    Sales2008 =  
        [  
            Year = 2008,  
            FirstHalf = 1200,  
            SecondHalf = 1300, 
            Total = FirstHalf + SecondHalf // 2500 
        ] 
  in Sales2007[Total] + Sales2008[Total] // 4600

Het resultaat van de bovenstaande expressie is een getalwaarde (4600) die wordt berekend van de waarden die zijn gebonden aan de namen Sales2007 en Sales2008.

If-expressie

De if expressie selecteert tussen twee expressies op basis van een logische voorwaarde. Bijvoorbeeld:

if 2 > 1 then
    2 + 2
else  
    1 + 1

De eerste expressie (2 + 2) wordt geselecteerd als de logische expressie (2 > 1) waar is en de tweede expressie (1 + 1) is geselecteerd als deze onwaar is. De geselecteerde expressie (in dit geval 2 + 2) wordt geëvalueerd en wordt het resultaat van de if expressie (4).

Fouten

Een fout is een indicatie dat het proces voor het evalueren van een expressie geen waarde kan produceren.

Fouten worden gegenereerd door operators en functies die foutvoorwaarden tegenkomen of door de foutexpressie te gebruiken. Fouten worden verwerkt met behulp van de try expressie. Wanneer er een fout optreedt, wordt een waarde opgegeven die kan worden gebruikt om aan te geven waarom de fout is opgetreden.

let Sales = 
    [ 
        Revenue = 2000, 
        Units = 1000, 
        UnitPrice = if Units = 0 then error "No Units"
                    else Revenue / Units 
    ], 
    UnitPrice = try Number.ToText(Sales[UnitPrice])
in "Unit Price: " & 
    (if UnitPrice[HasError] then UnitPrice[Error][Message]
    else UnitPrice[Value])

In het bovenstaande voorbeeld wordt het Sales[UnitPrice] veld geopend en wordt de waarde opgemaakt die het resultaat produceert:

"Unit Price: 2"

Als het Units veld nul was, zou het UnitPrice veld een fout hebben gegenereerd, die zou zijn verwerkt door de try. De resulterende waarde zou dan zijn:

"No Units"

Een try expressie converteert de juiste waarden en fouten naar een recordwaarde die aangeeft of de try expressie een fout heeft verwerkt, of niet, en de juiste waarde of de foutrecord die is geëxtraheerd bij het verwerken van de fout. Denk bijvoorbeeld aan de volgende expressie die een fout genereert en deze vervolgens meteen afhandelt:

try error "negative unit count"

Deze expressie evalueert naar de volgende geneste recordwaarde, waarin de opzoekacties [Error]voor [Message] velden [HasError]in het vorige voorbeeld van de eenheidsprijs worden uitgelegd.

[ 
    HasError = true, 
    Error = 
        [ 
            Reason = "Expression.Error", 
            Message = "negative unit count", 
            Detail = null 
        ] 
]

Een veelvoorkomend geval is het vervangen van fouten door standaardwaarden. De try expressie kan worden gebruikt met een optionele otherwise component om alleen dat in een compacte vorm te bereiken:

try error "negative unit count" otherwise 42 
// 42