Udostępnij za pośrednictwem


Wprowadzenie

Przegląd

Dodatek Microsoft Power Query zapewnia zaawansowane środowisko "pobierania danych", które obejmuje wiele funkcji. Podstawową funkcją dodatku Power Query jest filtrowanie i łączenie danych, czyli przetwarzanie danych z jednego lub kilku spośród licznych obsługiwanych źródeł danych. Takie mashupy danych są wyrażane przy użyciu języka formuł Power Query (nieformalnie nazywanego "M"). Dodatek Power Query osadza dokumenty języka M w wielu produktach firmy Microsoft, w tym w programie Excel, usłudze Power BI, usługach Analysis Services i usłudze Dataverse, aby umożliwić powtarzalne łączenie danych.

Ten dokument zawiera specyfikację języka M. Po krótkim wprowadzeniu, które ma na celu zbudowanie pierwszej intuicji i znajomości języka, dokument obejmuje język dokładnie w kilku krokach postępowych:

  1. Struktura leksy kalna definiuje zestaw tekstów, które są prawidłowe leksykalnie.

  2. Wartości, wyrażenia, środowiska i zmienne, identyfikatory i model oceny tworzą podstawowe pojęcia języka .

  3. Szczegółowa specyfikacja wartości , zarówno pierwotnych, jak i strukturalnych, definiuje domenę docelową języka.

  4. Wartości mają typy , które same w sobie są szczególnym rodzajem wartości, charakteryzującym podstawowe rodzaje wartości i zawierającym dodatkowe metadane specyficzne dla kształtów wartości strukturalnych.

  5. Zestaw operatorów w języku M określa, jakie rodzaje wyrażeń można utworzyć.

  6. Functions, inny rodzaj specjalnych wartości, stanowią podstawę bogatej standardowej biblioteki języka M i umożliwiają dodanie nowych abstrakcji.

  7. błędy mogą wystąpić podczas stosowania operatorów lub funkcji podczas obliczania wyrażenia. Chociaż błędy nie są wartościami, istnieją sposoby obsługi błędów, które przywracają błędy do wartości.

  8. Wyrażenia Let umożliwiają wprowadzenie definicji pomocniczych używanych do tworzenia złożonych wyrażeń w mniejszych krokach.

  9. Jeśli wyrażenia obsługują ocenę warunkową.

  10. Sekcje zapewniają prosty mechanizm modułowości. (Sekcje nie są jeszcze wykorzystywane przez Power Query.)

  11. Ostateczna skonsolidowana gramatyka zbiera fragmenty gramatyki ze wszystkich pozostałych sekcji tego dokumentu w jedną kompletną definicję.

Dla teoretyków języka komputerowego: język formuł określony w tym dokumencie jest w większości czystym, wyższego rzędu, dynamicznie typowanym, częściowo leniwym językiem funkcyjnym.

Wyrażenia i wartości

Centralna konstrukcja w języku M to wyrażenie . Wyrażenie można obliczyć, dając pojedynczą wartość .

Chociaż wiele wartości można zapisywać dosłownie jako wyrażenie, wartość nie jest wyrażeniem. Na przykład wyrażenie 1 oblicza wartość 1; wyrażenia 1+1 oblicza wartość 2. To rozróżnienie jest subtelne, ale ważne. Wyrażenia to przepisy na ocenę; wartości to wyniki oceny.

W poniższych przykładach przedstawiono różne rodzaje wartości dostępnych w języku M. Zgodnie z konwencją wartość jest zapisywana przy użyciu formularza literału, w którym będą one wyświetlane w wyrażeniu, które daje w wyniku tylko ową wartość. (Należy pamiętać, że // wskazuje początek komentarza, który jest kontynuowany na końcu wiersza).

  • Wartość prymitywna jest wartością jednoczęściową, taką jak liczba, logiczna, tekst lub null. Wartość null może służyć do wskazywania braku jakichkolwiek danych.

    123                  // A number
    true                 // A logical
    "abc"                // A text
    null                 // null value
    
  • Wartość na liście jest uporządkowaną sekwencją wartości. M obsługuje listy nieskończone, ale jeśli są zapisane jako literały, listy mają stałą długość. Znaki nawiasu klamrowego { i } oznaczają początek i koniec listy.

    {123, true, "A"}     // list containing a number, a logical, and 
                          //     a text 
    {1, 2, 3}            // list of three numbers 
    
  • Rekord to zestaw pól . Pole jest parą nazwa/wartość, w której nazwa jest wartością tekstową unikatową w rekordzie pola. Składnia literału dla wartości rekordów umożliwia zapisywanie nazw bez cudzysłowów, formularz nazywany również identyfikatorami . Poniżej przedstawiono rekord zawierający trzy pola o nazwie "A", "B" i "C", które mają wartości 1, 2i 3.

    [ 
          A = 1,  
          B = 2,  
          C = 3 
    ]
    
  • Tabela to zestaw wartości zorganizowanych w kolumny (które są identyfikowane według nazwy) i wierszy. Nie ma dosłownej składni do tworzenia tabeli, ale istnieje kilka standardowych funkcji, których można użyć do tworzenia tabel na podstawie list lub rekordów.

    Na przykład:

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

    Spowoduje to utworzenie tabeli o następującym kształcie:

    Obraz przykładowej tabeli w języku formuł M.

  • Funkcja jest wartością, która po wywołaniu z argumentami generuje nową wartość. Funkcja jest zapisywana przez wymienienie parametrów funkcji w nawiasach, po czym następuje symbol strzałki =>, a następnie wyrażenie definiujące funkcję. To wyrażenie zwykle odnosi się do parametrów (według nazwy).

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

Ocena

Model oceny języka M jest modelowany po modelu oceny często spotykanym w arkuszach kalkulacyjnych, gdzie kolejność obliczeń można określić na podstawie zależności między formułami w komórkach.

Jeśli napisałeś formuły w arkuszu kalkulacyjnym, takim jak Excel, możesz rozpoznać, że formuły po lewej stronie w rezultacie dają wartości po prawej stronie po obliczeniu.

Obraz formuł po prawej stronie, które prowadzą do wartości po lewej stronie.

W języku M części wyrażenia mogą odwoływać się do innych części wyrażenia według nazwy, a proces oceny automatycznie określa kolejność, w której są obliczane przywoływane wyrażenia.

Możesz użyć rekordu, aby utworzyć wyrażenie, które jest równoważne poprzedniemu przykładowi arkusza kalkulacyjnego. Podczas inicjowania wartości pola można odwoływać się do innych pól w rekordzie przy użyciu nazwy pola w następujący sposób:

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

Powyższe wyrażenie jest równoważne z następującymi wartościami (w tym oba wyrażenia są obliczane na równe wartości):

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

Rekordy mogą być zawarte wlub zagnieżdżone w innych rekordach. Aby uzyskać dostęp do pól rekordu według nazwy, możesz użyć operatora wyszukiwania ([]). Na przykład następujący rekord ma pole o nazwie Sales zawierające rekord oraz pole o nazwie Total, które uzyskuje dostęp do pól FirstHalf i SecondHalf rekordu Sales:

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

Powyższe wyrażenie jest równoważne następującemu, gdy zostanie obliczone:

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

Rekordy mogą się również zawierać w listach. Aby uzyskać dostęp do elementu na liście według indeksu liczbowego, można użyć operatora indeksu pozycyjnego ({}). Wartości na liście są określane przy użyciu indeksu opartego na zerach od początku listy. Na przykład indeksy 0 i 1 są używane do odwołowania się do pierwszych i drugich elementów na poniższej liście:

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

Wyrażenia składowe listy i rekordów (a także wyrażenia let) są ewaluowane przy użyciu leniwej ewaluacji, co oznacza, że są ewaluowane tylko zgodnie z potrzebami. Wszystkie inne wyrażenia są oceniane przy użyciu metody bezwzględnej oceny, co oznacza, że są one oceniane natychmiast po napotkania podczas procesu oceny. Dobrym sposobem myślenia o tym jest pamiętanie, że ocena wyrażenia listy lub rekordu zwraca wartość listy lub rekordu, która sama pamięta, jak należy obliczyć jego elementy listy lub pola rekordu, gdy jest to wymagane (według operatorów odnośnika lub indeksu).

Funkcje

W języku M funkcja jest mapowaniem z zestawu wartości wejściowych na pojedynczą wartość wyjściową. Funkcja jest zapisywana przez najpierw nazewnictwo wymaganego zestawu wartości wejściowych (parametrów funkcji), a następnie podanie wyrażenia, które oblicza wynik funkcji przy użyciu tych wartości wejściowych (treść funkcji) po symbolu goes-to (=>). Na przykład:

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

Funkcja jest wartością podobną do liczby lub wartości tekstowej. W poniższym przykładzie pokazano funkcję, która jest wartością pola Dodaj, które jest następnie wywoływanelub wykonywane, z kilku innych pól. Po wywołaniu funkcji określony jest zestaw wartości, które są logicznie zastępowane wymaganym zestawem wartości wejściowych w wyrażeniu treści funkcji.

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

Biblioteka

Język M zawiera wspólny zestaw definicji dostępnych do użycia z wyrażenia o nazwie biblioteki standardowejlub po prostu biblioteki. Te definicje składają się z zestawu nazwanych wartości. Nazwy wartości udostępnianych przez bibliotekę są dostępne do użycia w wyrażeniu bez jawnego zdefiniowania przez wyrażenie. Na przykład:

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

Operatorów

Język M zawiera zestaw operatorów, których można używać w wyrażeniach. operatory są stosowane do operandów do tworzenia wyrażeń symbolicznych. Na przykład w wyrażeniu 1 + 2 liczby 1 i 2 są operandami, a operator jest operatorem dodawania (+).

Znaczenie operatora może się różnić w zależności od rodzaju wartości, jakie są jego operandy. Na przykład operator plus może być używany z innymi rodzajami wartości oprócz liczb:

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

Innym przykładem operatora z argumentem zależnym od operandu jest operator kombinacji (&):

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

Należy pamiętać, że niektóre operatory nie obsługują wszystkich kombinacji wartości. Na przykład:

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

Wyrażenia, które podczas wykonywania napotykają na niezdefiniowane warunki operatorów, skutkują błędami .

Metadane

Metadata to informacje o wartości skojarzonej z wartością. Metadane są reprezentowane jako wartość rekordu, nazywana rekordem metadanych . Pola rekordu metadanych mogą służyć do przechowywania metadanych dla wartości.

Każda wartość ma rekord metadanych. Jeśli wartość rekordu metadanych nie została określona, rekord metadanych jest pusty (nie zawiera pól).

Rekordy metadanych umożliwiają kojarzenie dodatkowych informacji z dowolną wartością w sposób dyskretny. Skojarzenie rekordu metadanych z wartością nie powoduje zmiany wartości ani jej zachowania.

Wartość rekordu metadanych y jest skojarzona z istniejącą wartością x przy użyciu składni x meta y. Na przykład poniższy kod kojarzy rekord metadanych z polami Rating i Tags z wartością tekstową "Mozart":

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

W przypadku wartości, które mają już niepusty rekord metadanych, wynikiem zastosowania meta jest obliczanie scalania rekordów istniejącego i nowego rekordu metadanych. Na przykład następujące dwa wyrażenia są równoważne sobie i poprzedniemu wyrażeniu:

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

Dostęp do rekordu metadanych dla danej wartości można uzyskać przy użyciu funkcji Value.Metadata. W poniższym przykładzie wyrażenie w polu ComposerRating uzyskuje dostęp do rekordu metadanych wartości w polu Composer, a następnie uzyskuje dostęp do pola Rating rekordu metadanych.

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

Wyrażenie "Let"

Wiele z przedstawionych do tej pory przykładów zawiera wszystkie wartości stałe wyrażenia w wyniku wyrażenia. Wyrażenie let umożliwia obliczenie zestawu wartości, przypisanie im nazw, a następnie użycie w kolejnym wyrażeniu, które następuje po in. Na przykład w naszym przykładzie danych sprzedaży można wykonać następujące czynności:

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

Wynikiem powyższego wyrażenia jest wartość liczbowa (4600), która jest obliczana z wartości powiązanych z nazwami Sales2007 i Sales2008.

Wyrażenie If

Wyrażenie if wybiera między dwoma wyrażeniami na podstawie warunku logicznego. Na przykład:

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

Pierwsze wyrażenie (2 + 2) jest zaznaczone, jeśli wyrażenie logiczne (2 > 1) ma wartość true, a drugie wyrażenie (1 + 1) jest zaznaczone, jeśli jest to fałsz. Wybrane wyrażenie (w tym przypadku 2 + 2) jest oceniane i staje się wynikiem wyrażenia if (4).

Błędy

Błąd oznacza, że proces obliczania wyrażenia nie może wygenerować wartości.

Błędy są zgłaszane przez operatory i funkcje napotykające warunki błędu lub przez użycie wyrażenia błędu. Błędy są obsługiwane przy użyciu wyrażenia try. Po wystąpieniu błędu zostanie określona wartość, która może służyć do wskazania przyczyny wystąpienia błędu.

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

Powyższy przykład uzyskuje dostęp do pola Sales[UnitPrice] i formatuje wartość generującą wynik:

"Unit Price: 2"

Gdyby pole Units było zerowe, to pole UnitPrice spowodowałoby wystąpienie błędu, który zostałby obsłużony przez try. Wynikowa wartość byłaby wtedy:

"No Units"

Wyrażenie try konwertuje odpowiednie wartości i błędy na wartość rekordu, która wskazuje, czy wyrażenie try obsłużyło błąd, czy nie, oraz odpowiednią wartość lub rekord błędu wyodrębniony podczas obsługi błędu. Rozważmy na przykład następujące wyrażenie, które zgłasza błąd, a następnie obsługuje je od razu:

try error "negative unit count"

To wyrażenie przekształca się w następującą wartość zagnieżdżonego rekordu, wyjaśniając wyszukiwania pól [HasError], [Error]i [Message] w poprzednim przykładzie ceny jednostkowej.

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

Typowym przypadkiem jest zastąpienie błędów wartościami domyślnymi. Wyrażenie try może być używane z opcjonalną klauzulą otherwise, aby osiągnąć tylko to w formie kompaktowej:

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