Introduktion

Oversigt

Microsoft Power Query giver en effektiv "hent data"-oplevelse, der omfatter mange funktioner. En kernefunktion i Power Query er at filtrere og kombinere, dvs. at "mikse" data fra en eller flere af en omfattende samling af understøttede datakilder. Sådanne data miks udtrykkes ved hjælp af Formelsproget i Power Query (uformelt kaldet "M"). Power Query integrerer M-dokumenter i en lang række Microsoft-produkter, herunder Excel, Power BI, Analysis Services og Dataverse, for at aktivere gentagelig miks af data.

Dette dokument indeholder specifikationen for M. Efter en kort introduktion, der har til formål at opbygge nogle første intuition og kendskab til sproget, dokumentet dækker sproget præcist i flere progressive trin:

  1. Den leksikalske struktur definerer det sæt tekster, der er leksikalt gyldige.

  2. Værdier, udtryk, miljøer og variabler, identifikatorer og evalueringsmodellen udgør sprogets grundlæggende begreber.

  3. Den detaljerede specifikation af værdier, både primitive og strukturerede, definerer sprogets destinationsdomæne.

  4. Værdier har typer, der i sig selv er en særlig type værdi, som både karakteriserer de grundlæggende typer værdier og indeholder yderligere metadata, der er specifikke for figurerne af strukturerede værdier.

  5. Sættet af operatorer i M definerer, hvilke typer udtryk der kan dannes.

  6. Funktioner, en anden form for særlige værdier, giver grundlaget for et rigt standardbibliotek til M og giver mulighed for tilføjelse af nye abstraktioner.

  7. Der kan opstå fejl , når operatorer eller funktioner anvendes under evaluering af udtryk. Selvom fejl ikke er værdier, er der måder at håndtere fejl på, der knytter fejl tilbage til værdier.

  8. Let-udtryk gør det muligt at introducere hjælpedefinitioner, der bruges til at opbygge komplekse udtryk i mindre trin.

  9. If-udtryk understøtter betinget evaluering.

  10. Afsnit indeholder en enkel modularitetsmekanisme. (Sektioner udnyttes endnu ikke af Power Query).

  11. Endelig indsamler en konsolideret grammatik grammatikfragmenterne fra alle andre afsnit i dette dokument i en enkelt komplet definition.

For computersprogteoretikere: Det formelsprog, der er angivet i dette dokument, er hovedsageligt et rent, højere ordenssprog, dynamisk skrevet, delvist dovent funktionelt sprog.

Udtryk og værdier

Den centrale konstruktion i M er udtrykket. Et udtryk kan evalueres (beregnes) og give en enkelt værdi.

Selvom mange værdier kan skrives bogstaveligt som et udtryk, er en værdi ikke et udtryk. Udtrykket 1 evalueres f.eks. til værdien 1. Udtrykkene 1+1 evalueres til værdien 2. Denne skelnen er diskret, men vigtig. Udtryk er opskrifter til evaluering. værdier er resultaterne af evalueringen.

Følgende eksempler illustrerer de forskellige typer værdier, der er tilgængelige i M. Som konvention skrives en værdi ved hjælp af den konstantformular, hvor de vises i et udtryk, der evalueres til netop denne værdi. Bemærk, at // angiver starten af en kommentar, som fortsætter til slutningen af linjen.

  • En primitiv værdi er en enkeltdelt værdi, f.eks. et tal, en logisk værdi, en tekst eller en null-værdi. En null-værdi kan bruges til at angive fraværet af data.

    123                  // A number
    true                 // A logical
    "abc"                // A text
    null                 // null value
    
  • En listeværdi er en sorteret sekvens af værdier. M understøtter uendelige lister, men hvis de skrives som konstanter, har listerne en fast længde. Krøllede klammeparenteser { og } angiver starten og slutningen af en liste.

    {123, true, "A"}     // list containing a number, a logical, and 
                          //     a text 
    {1, 2, 3}            // list of three numbers 
    
  • En post er et sæt felter. Et felt er et navne-/værdipar, hvor navnet er en tekstværdi, der er entydig i feltets post. Konstantsyntaksen for postværdier gør det muligt at skrive navnene uden anførselstegn, en formular, der også kaldes identifikatorer. I det følgende vises en post, der indeholder tre felter med navnet "A", "B" og "C", som har værdier 1, 2og 3.

    [ 
          A = 1,  
          B = 2,  
          C = 3 
    ]
    
  • En tabel er et sæt værdier, der er organiseret i kolonner (som identificeres ved navn) og rækker. Der er ingen konstantsyntaks til oprettelse af en tabel, men der er flere standardfunktioner, der kan bruges til at oprette tabeller ud fra lister eller poster.

    Eksempler:

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

    Dette opretter en tabel med følgende figur:

    Image of an example table in the M formula language.

  • En funktion er en værdi, der, når den kaldes med argumenter, opretter en ny værdi. En funktion skrives ved at angive funktionens parametre i parentes efterfulgt af symbolet =>for at gå til efterfulgt af det udtryk, der definerer funktionen. Dette udtryk henviser typisk til parametrene (efter navn).

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

Evaluering

Evalueringsmodellen for M-sproget modelleres efter den evalueringsmodel, der ofte findes i regneark, hvor beregningsrækkefølgen kan bestemmes på baggrund af afhængigheder mellem formlerne i cellerne.

Hvis du har skrevet formler i et regneark, f.eks Excel, kan du måske genkende formlerne til venstre resultere i værdierne til højre, når de beregnes:

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

I M kan dele af et udtryk referere til andre dele af udtrykket efter navn, og evalueringsprocessen bestemmer automatisk den rækkefølge, som refererede udtryk beregnes i.

Du kan bruge en post til at oprette et udtryk, der svarer til det forrige regnearkseksempel. Når du initialiserer værdien af et felt, kan du referere til andre felter i posten ved hjælp af navnet på feltet på følgende måde:

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

Ovenstående udtryk svarer til følgende (ved at begge evalueres til lig med værdier):

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

Poster kan være indeholdt i eller indlejret i andre poster. Du kan bruge opslagsoperatoren ([]) til at få adgang til felterne i en post efter navn. Følgende post har f.eks. et felt med navnet Sales , der indeholder en post, og et felt med navnet Total , der har FirstHalf adgang til felterne og SecondHalf i posten Sales :

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

Ovenstående udtryk svarer til følgende, når det evalueres:

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

Poster kan også være indeholdt på lister. Du kan bruge positionsindeksoperatoren ({}) til at få adgang til et element på en liste ved hjælp af det numeriske indeks. Der refereres til værdierne på en liste ved hjælp af et nulbaseret indeks fra starten af listen. Indekserne 0 og 1 bruges f.eks. til at referere til det første og det andet element på listen nedenfor:

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

Udtryk for liste- og postmedlem (samt let-udtryk) evalueres ved hjælp af doven evaluering, hvilket betyder, at de kun evalueres efter behov. Alle andre udtryk evalueres ved hjælp af en ivrig evaluering, hvilket betyder, at de evalueres med det samme, når de registreres under evalueringsprocessen. En god måde at tænke på dette på er at huske, at evalueringen af et liste- eller postudtryk returnerer en liste- eller postværdi, der selv husker, hvordan listeelementerne eller postfelterne skal beregnes, når der anmodes om det (af opslags- eller indeksoperatorer).

Funktioner

I M er en funktion en tilknytning fra et sæt inputværdier til en enkelt outputværdi. En funktion skrives ved først at navngive det påkrævede sæt inputværdier (parametrene til funktionen) og derefter angive et udtryk, der beregner resultatet af funktionen ved hjælp af disse inputværdier (funktionens brødtekst) efter symbolet for at gå til (=>). Eksempler:

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

En funktion er en værdi på samme måde som et tal eller en tekstværdi. I følgende eksempel vises en funktion, der er værdien af et tilføj-felt, som derefter aktiveres eller udføres fra flere andre felter. Når en funktion aktiveres, angives der et værdisæt, der logisk erstattes af det påkrævede sæt inputværdier i funktionsbrødtekstudtrykket.

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

Bibliotek

M indeholder et fælles sæt definitioner, der kan bruges fra et udtryk, der kaldes standardbiblioteket, eller blot et bibliotek . Disse definitioner består af et sæt navngivne værdier. Navnene på værdier, der leveres af et bibliotek, er tilgængelige til brug i et udtryk uden at være defineret eksplicit af udtrykket. Eksempler:

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

Operatorer

M indeholder et sæt operatorer, der kan bruges i udtryk. Operatorer anvendes på operander for at danne symbolske udtryk. I udtrykket 1 + 2 er tallene 1 og 2 f.eks. operander, og operatoren er additionsoperatoren (+).

Betydningen af en operator kan variere, afhængigt af hvilken type værdier operanderne er. Plusoperatoren kan f.eks. bruges sammen med andre typer værdier ud over tal:

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

Et andet eksempel på en operator med operand-afhængig betydning er kombinationsoperatoren (&):

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

Bemærk, at nogle operatorer ikke understøtter alle kombinationer af værdier. Eksempler:

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

Udtryk, der, når de evalueres, støder på udefinerede operatorbetingelser, evalueres til fejl.

Metadata

Metadata er oplysninger om en værdi, der er knyttet til en værdi. Metadata repræsenteres som en postværdi, der kaldes en metadatapost. Felterne i en metadatapost kan bruges til at gemme metadataene for en værdi.

Hver værdi har en metadatapost. Hvis værdien af metadataposten ikke er angivet, er metadataposten tom (indeholder ingen felter).

Metadataposter gør det muligt at knytte yderligere oplysninger til en hvilken som helst værdi på en diskret måde. Tilknytning af en metadatapost med en værdi ændrer ikke værdien eller dens funktionsmåde.

En metadatapostværdi y er knyttet til en eksisterende værdi x ved hjælp af syntaksen x meta y. Følgende kode knytter f.eks. en metadatapost til Rating og Tags -felter med tekstværdien "Mozart":

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

For værdier, der allerede indeholder en metadatapost, der ikke er tom, er resultatet af at anvende meta, at du beregner postfletningen af den eksisterende og den nye metadatapost. Følgende to udtryk svarer f.eks. til hinanden og til det forrige udtryk:

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

Du kan få adgang til en metadatapost for en given værdi ved hjælp af funktionen Value.Metadata . I følgende eksempel får udtrykket i feltet ComposerRating adgang til metadataposten for værdien i feltet Composer og får Rating derefter adgang til feltet for metadataposten.

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

Let-udtryk

Mange af de eksempler, der er vist indtil videre, har inkluderet alle konstantværdierne for udtrykket i resultatet af udtrykket. Udtrykket let gør det muligt at beregne et værdisæt, tildele navne og derefter bruge det i et efterfølgende udtryk, der følger efter in. I eksemplet med salgsdata kan du f.eks. gøre følgende:

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

Resultatet af ovenstående udtryk er en talværdi (4600), der beregnes ud fra de værdier, der er bundet til navnene Sales2007 og Sales2008.

If-udtryk

Udtrykket if vælger mellem to udtryk baseret på en logisk betingelse. Eksempler:

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

Det første udtryk (2 + 2) vælges, hvis det logiske udtryk (2 > 1) er sandt, og det andet udtryk (1 + 1) vælges, hvis det er falsk. Det valgte udtryk (i dette tilfælde 2 + 2) evalueres og bliver resultatet af if udtrykket (4).

Fejl

En fejl er en indikation af, at processen til evaluering af et udtryk ikke kunne oprette en værdi.

Fejl udløses af operatorer og funktioner, der støder på fejltilstande eller ved hjælp af fejludtrykket. Fejl håndteres ved hjælp af udtrykket try . Når der udløses en fejl, angives der en værdi, der kan bruges til at angive, hvorfor fejlen opstod.

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

Ovenstående eksempel får adgang til feltet Sales[UnitPrice] og formaterer den værdi, der giver resultatet:

"Unit Price: 2"

Hvis feltet Units havde været nul, UnitPrice ville feltet have udløst en fejl, som ville være blevet håndteret af try. Den resulterende værdi ville derefter have været:

"No Units"

Et try udtryk konverterer korrekte værdier og fejl til en postværdi, der angiver, om try udtrykket håndterede en fejl eller ej, og enten den korrekte værdi eller den fejlpost, det udtrækkede under håndteringen af fejlen. Overvej f.eks. følgende udtryk, der udløser en fejl og derefter håndterer det med det samme:

try error "negative unit count"

Dette udtryk evalueres til følgende indlejrede postværdi, der forklarer opslagene [HasError]i feltet , [Error]og [Message] i det forrige eksempel på enhedspris.

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

Det er almindeligt at erstatte fejl med standardværdier. Udtrykket try kan bruges sammen med en valgfri otherwise delsætning for at opnå netop dette i en kompakt form:

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