Język Power Fx i logika

Jak tworzyć czytelne formuły i niezawodną logikę w Power Apps? Poznaj składnię Power Fx, zmienne, kolekcje i instrukcje warunkowe. Sprawdź, jak pracować z dużymi zbiorami danych, walidować formularze i skutecznie obsługiwać błędy.
15 listopada 2026
blog

Wprowadzenie do Power Fx w Power Apps: składnia, typy danych i kontekst działania formuł

W Power Apps formuła może decydować o tym, co widzi użytkownik, jakie dane pojawiają się na ekranie i jak aplikacja reaguje na jego działania. Językiem służącym do opisywania tej logiki jest Power Fx. Jego składnia nawiązuje do formuł Excela, ale zamiast odwołań do komórek wykorzystuje między innymi właściwości kontrolek, rekordy i źródła danych. W aplikacjach kanwowych zrozumienie tych odwołań jest podstawą świadomego projektowania zachowania interfejsu.

Formuła jako opis właściwości lub reakcja na zdarzenie

Power Fx ma charakter przede wszystkim deklaratywny: opisujesz oczekiwany wynik, a środowisko oblicza go na podstawie zależności. Jeśli tekst etykiety zależy od wartości wpisanej w polu, zmiana tej wartości może automatycznie zaktualizować etykietę. Nie trzeba osobno programować każdego odświeżenia interfejsu. Nie oznacza to jednak, że każda formuła automatycznie pobiera aktualne dane z zewnętrznego systemu.

Znaczenie formuły zależy od właściwości, do której ją przypiszesz. Właściwość Text etykiety oczekuje tekstu, Visible określa widoczność kontrolki, a Items galerii wskazuje tabelę rekordów do wyświetlenia. Każda z tych właściwości pełni inną funkcję i wymaga wyniku odpowiedniego typu.

Inaczej działają formuły behawioralne, umieszczane na przykład we właściwości OnSelect przycisku. Uruchamiają się w odpowiedzi na zdarzenie i mogą wykonywać działania, takie jak przejście na inny ekran lub zapis danych. Warto od początku rozróżniać obliczanie wartości od wykonywania operacji: to dwa odmienne sposoby wykorzystania języka.

Podstawy składni: funkcje, operatory i odwołania

Formuły powstają z nazw funkcji, argumentów, operatorów oraz odwołań do elementów aplikacji. Funkcje wykonują określone obliczenia lub przekształcenia, a operatory pozwalają między innymi porównywać wartości, prowadzić obliczenia arytmetyczne i łączyć tekst. Nawiasy wyznaczają argumenty funkcji oraz pomagają jednoznacznie określić kolejność działań.

Kropka służy do odwoływania się do właściwości kontrolki lub pola rekordu. Tekst wpisywany bezpośrednio w formule ujmuje się w podwójny cudzysłów. Pojedynczy cudzysłów ma inne zastosowanie: pozwala zapisywać identyfikatory zawierające na przykład spacje. Nazwa kolumny i tekst o identycznym brzmieniu nie są więc dla języka tym samym.

Istotne są również ustawienia regionalne. W środowisku używającym przecinka dziesiętnego, typowo przy polskich ustawieniach, argumenty funkcji rozdziela się średnikami. W przykładach przygotowanych dla ustawień angielskich często zobaczysz w tym miejscu przecinki. Różnica separatorów nie oznacza innej logiki, ale wymaga uwagi podczas przenoszenia formuł między środowiskami.

Typy danych: co właściwie zwraca formuła?

Power Fx rozpoznaje typy wartości i sprawdza, czy pasują one do wykonywanych operacji. Na początku najważniejsze jest rozróżnienie kilku podstawowych kategorii:

  • Tekst — opisy, nazwy i identyfikatory, na których nie wykonuje się obliczeń. Ciąg cyfr może być tekstem, na przykład gdy oznacza kod pocztowy.
  • Liczby — wartości używane w obliczeniach, takie jak ilość, cena czy wynik pomiaru.
  • Wartości logiczne — prawda lub fałsz, wykorzystywane między innymi do określania widoczności elementów.
  • Daty, godziny oraz wartości daty i czasu — dane opisujące termin lub moment zdarzenia. Ich format wyświetlania nie jest tym samym co ich wartość.
  • Rekordy i tabele — rekord skupia nazwane pola pojedynczego obiektu, natomiast tabela zawiera rekordy.

Wartość pusta, określana jako Blank, oznacza brak wartości lub wartość nieznaną. Nie należy automatycznie utożsamiać jej z zerem, fałszem ani tabelą bez rekordów. Podobnie tekst wyglądający jak liczba nie zawsze może być traktowany jak liczba bez konwersji. Świadomość tych różnic ułatwia poprawne łączenie danych z kontrolkami.

Kontekst działania: skąd formuła bierze dane?

Formułę trzeba zawsze czytać razem z miejscem jej użycia. Etykieta znajdująca się wewnątrz szablonu galerii może odwoływać się do aktualnie wyświetlanego rekordu przez ThisItem. Ta sama formuła przeniesiona poza galerię może stracić właściwy kontekst. Z kolei funkcje przetwarzające tabele mogą tworzyć własny zakres rekordu, dostępny przez ThisRecord lub nadany alias.

Kontekst rekordu nie jest tym samym co zakres dostępności nazw w aplikacji. Pierwszy wskazuje, który rekord jest właśnie przetwarzany; drugi określa, do jakich elementów i wartości można się odwołać w danym miejscu. Przy zagnieżdżonych zakresach szczególnie ważne staje się jednoznaczne wskazanie, z którego rekordu pochodzi pole.

Przed napisaniem formuły warto więc ustalić trzy rzeczy: jaka właściwość będzie z niej korzystać, jakiego typu wyniku oczekuje i w jakim kontekście formuła zostanie obliczona. To pozwala odróżnić problem ze składnią od sytuacji, w której poprawne wyrażenie odwołuje się do niewłaściwych danych.

Zmienne w praktyce: globalne (Set) vs kontekstowe (UpdateContext) – scenariusze i przykłady

W aplikacji kanwowej Power Apps zmienna pozwala zapamiętać stan, który ma przetrwać pojedynczą interakcję użytkownika: wybór rekordu, otwarcie panelu czy przełączenie widoku w tryb edycji. Wybór między Set a UpdateContext zależy przede wszystkim od tego, gdzie ta informacja będzie potrzebna. Zmienna globalna jest dostępna w całej aplikacji, a kontekstowa — na konkretnym ekranie. W Cognity często słyszymy pytania, jak w praktyce dobrać zasięg zmiennej — odpowiadamy na nie także na blogu.

Set: wspólny stan dla wielu ekranów

Funkcja Set tworzy lub aktualizuje zmienną globalną. To właściwe rozwiązanie, gdy kilka ekranów ma korzystać z tej samej zapamiętanej wartości, na przykład wybranego projektu, bieżącego okresu rozliczeniowego albo identyfikatora rekordu obsługiwanego w wieloetapowym procesie.

Przykładowo użytkownik wybiera projekt na ekranie startowym, następnie przegląda jego zadania i przechodzi do raportu. Jeżeli wszystkie te widoki mają odnosić się do tego samego wyboru, zmienna globalna pozwala udostępnić go w całej aplikacji. Nie trzeba przekazywać tej informacji osobno przy każdym przejściu między ekranami.

Szeroki zasięg oznacza jednak większą odpowiedzialność za aktualizację wartości. Zmianę zmiennej globalnej może wywołać działanie na różnych ekranach. Warto więc ustalić, kiedy wybór zostaje ustawiony, kiedy można go zmienić i w jakich okolicznościach należy go wyczyścić. Bez takich zasad użytkownik może rozpocząć nową operację ze stanem pozostałym po poprzedniej.

UpdateContext: stan potrzebny na jednym ekranie

Funkcja UpdateContext tworzy lub aktualizuje zmienne kontekstowe bieżącego ekranu. Najlepiej sprawdzają się one w obsłudze lokalnego interfejsu: widoczności okna potwierdzenia, rozwinięcia panelu filtrów, wybranej zakładki czy lokalnego trybu podglądu i edycji.

Załóżmy, że na ekranie szczegółów przycisk otwiera panel z dodatkowymi informacjami. Stan otwarcia panelu nie jest potrzebny w pozostałych widokach, dlatego zmienna kontekstowa będzie czytelniejszym wyborem niż globalna. Cała logika tego elementu pozostaje związana z ekranem, na którym jest używany.

Ważne rozróżnienie: lokalny zasięg nie oznacza automatycznego resetowania po opuszczeniu ekranu. Zmienna kontekstowa zachowuje wartość przy przechodzeniu między ekranami w tej samej sesji aplikacji. Jeśli panel ma być zamknięty przy każdym wejściu, trzeba jawnie ustawić odpowiedni stan, na przykład w zdarzeniu OnVisible. Takie ustawienie powinno być celowe — bezwarunkowy reset może również usunąć wybór, który użytkownik chciał zachować.

Przekazanie wartości na ekran nie zawsze wymaga zmiennej globalnej

Sam fakt, że informacja pochodzi z innego ekranu, nie przesądza o użyciu Set. Funkcja Navigate pozwala podczas nawigacji przekazać wartości do zmiennych kontekstowych ekranu docelowego. To przydatny wzorzec, gdy użytkownik wybiera rekord na liście, a następnie otwiera jego szczegóły. Jeżeli wybrany rekord jest potrzebny tylko w widoku szczegółowym, nie ma konieczności udostępniania go globalnie.

Co warto ustalić przed dodaniem zmiennej?

Najpierw sprawdź, czy wartość rzeczywiście trzeba zapamiętać. Jeśli można ją bezpośrednio wyliczyć z właściwości kontrolek lub aktualnych danych, dodatkowa zmienna często tylko komplikuje utrzymanie aplikacji. Wartość przypisana przez Set lub UpdateContext nie przelicza się automatycznie po zmianie danych użytych przy przypisaniu. Zapamiętany wynik wymaga ponownej aktualizacji.

Oba rodzaje zmiennych przechowują stan w pamięci aplikacji, a nie zapewniają trwałego zapisu. Po zamknięciu aplikacji ich wartości są tracone. Czytelne nazwy, jednoznaczne miejsca ustawiania i świadomie dobrany zasięg pomagają uniknąć sytuacji, w której interfejs pokazuje nieaktualny stan. Praktyczna zasada jest prosta: UpdateContext dla stanu jednego ekranu, Set dla informacji rzeczywiście współdzielonych między ekranami.

Kolekcje jako warstwa robocza: Collect, ClearCollect, Patch – typowe wzorce i zastosowania

Koszyk pozycji, lista wybranych rekordów czy dane przygotowywane do zatwierdzenia nie zawsze powinny od razu trafiać do źródła danych. W aplikacjach kanwowych Power Apps rolę takiego bufora może pełnić kolekcja: tabela przechowywana w pamięci aplikacji, dostępna na różnych ekranach. Pozwala zebrać dane, wyświetlić je w galerii i modyfikować bez zapisywania każdej zmiany w Dataverse, SharePoint lub innym systemie.

Kolekcja jest jednak osobnym zbiorem, a nie aktywnym połączeniem z rekordami źródłowymi. Zmiana lokalnej kopii nie aktualizuje źródła danych, a zmiana w źródle nie odświeża automatycznie kolekcji. Jej zawartość nie jest też domyślnie zachowywana po zamknięciu aplikacji.

Collect, ClearCollect i Patch – trzy różne zadania

FunkcjaDziałanieTypowe zastosowanie
CollectDodaje rekord lub zestaw rekordów do kolekcji. Jeśli kolekcja nie istnieje, tworzy ją.Dokładanie pozycji do koszyka, gromadzenie wyborów użytkownika.
ClearCollectUsuwa dotychczasowe rekordy kolekcji, a następnie wypełnia ją przekazanymi danymi.Inicjalizacja bufora, ponowne zbudowanie listy roboczej.
PatchModyfikuje wskazany rekord; może również tworzyć rekordy przy odpowiednim użyciu. Działa na kolekcjach i obsługiwanych źródłach danych.Zmiana ilości, ceny lub innego pola bez zastępowania całej tabeli.

Te funkcje zmieniają stan danych, dlatego umieszcza się je w formułach zachowania, na przykład we właściwości OnSelect przycisku. Galeria może następnie wyświetlać wynik, mając nazwę kolekcji ustawioną we właściwości Items.

Dodawanie pozycji a budowanie kolekcji od nowa

Collect sprawdza się wtedy, gdy kolejne działania użytkownika mają rozszerzać listę. Poniższy przykład dodaje rekord do kolekcji roboczej. Przykłady używają separatorów właściwych dla polskich ustawień regionalnych: średników między argumentami i polami rekordu.

Collect(
    colPozycje;
    { ID: 101; Nazwa: "Monitor"; Ilosc: 1 }
)

Ponowne wykonanie tej formuły doda kolejny rekord — również z takim samym polem ID. Kolekcja nie wymusza unikatowości identyfikatorów. Jeżeli dodanie istniejącego produktu ma zwiększać jego ilość, aplikacja musi rozróżniać dodanie nowej pozycji od aktualizacji już obecnej.

ClearCollect służy natomiast do zastąpienia zawartości, a nie do jej uzupełniania. Jest przydatne przy rozpoczęciu nowej operacji lub świadomym ponownym załadowaniu danych do bufora:

ClearCollect(
    colPozycje;
    { ID: 101; Nazwa: "Monitor"; Ilosc: 1 };
    { ID: 102; Nazwa: "Klawiatura"; Ilosc: 2 }
)

Takiego resetowania nie warto bezrefleksyjnie przypisywać do każdego wejścia na ekran. Jeśli użytkownik wróci do edycji, ponowne wykonanie ClearCollect może usunąć jego niezapisane zmiany. Moment inicjalizacji powinien wynikać z przebiegu pracy, a nie wyłącznie z nawigacji.

Patch: aktualizacja konkretnego rekordu

Gdy zmienia się tylko jedno pole, nie trzeba odbudowywać kolekcji. Patch pozwala wskazać rekord i przekazać wyłącznie zmieniane wartości:

Patch(
    colPozycje;
    LookUp(colPozycje; ID = 101);
    { Ilosc: 3 }
)

Przykład zakłada, że rekord istnieje, a jego identyfikator jest unikatowy w kolekcji. Funkcja LookUp wybiera go z tabeli, natomiast Patch zmienia pole Ilosc, pozostawiając pozostałe pola bez zmian. Stabilny identyfikator jest tu ważniejszy niż nazwa wyświetlana użytkownikowi, która może się powtarzać lub zostać zmieniona.

Bufor edycji i granica zapisu

Praktyczny wzorzec polega na pobraniu potrzebnych danych do kolekcji, udostępnieniu ich do edycji i zapisaniu dopiero po zatwierdzeniu. Użytkownik może wtedy przygotować kilka zmian, zanim zostaną utrwalone. Rezygnacja oznacza odrzucenie lokalnych modyfikacji, bez konieczności cofania zmian w źródle.

O miejscu zapisu decyduje pierwszy argument funkcji Patch. Jeśli jest nim kolekcja, zmiana pozostaje lokalna. Zapis do źródła wymaga osobnej operacji skierowanej do tego źródła oraz prawidłowego powiązania z jego rekordem. W buforze warto więc zachować identyfikatory źródłowe i przechowywać tylko dane potrzebne do danej operacji. Kolekcja ma upraszczać pracę użytkownika, nie zastępować trwałego magazynu danych.

Logika warunkowa i sterowanie przepływem: If, Switch oraz imitowanie pętli z ForAll

W Power Fx warunek może wyznaczać tekst etykiety, kolor kontrolki, dostępność przycisku albo akcję wykonywaną po kliknięciu. Nie zawsze oznacza więc sterowanie kolejnymi krokami programu — często po prostu oblicza wartość właściwości. If wybiera wynik na podstawie warunków logicznych, Switch dopasowuje jedną wartość do zdefiniowanych przypadków, a ForAll stosuje formułę do rekordów tabeli. Wybór właściwej funkcji ułatwia zarówno zapis reguł, jak i późniejsze utrzymanie aplikacji. W Cognity omawiamy dobór tych funkcji zarówno od strony technicznej, jak i praktycznej — odnosząc go do reguł biznesowych, z którymi uczestnicy pracują na co dzień.

If — różne warunki i znaczenie ich kolejności

Funkcja If sprawdza warunek i zwraca wynik przypisany do spełnionego warunku. Sprawdza się przy porównaniach liczbowych, zakresach dat oraz regułach łączących kilka kryteriów. W jednym wywołaniu można podać wiele par warunek–wynik, bez budowania kolejnych zagnieżdżeń.

Przykładowo właściwość Color etykiety w galerii zadań może wyróżniać zadania o wysokim priorytecie, a następnie te po terminie:

If(
    ThisItem.Priorytet = "Wysoki"; Color.Red;
    ThisItem.Termin < Today(); Color.Orange;
    Color.Gray
)

Wygrywa pierwszy spełniony warunek. Zadanie o wysokim priorytecie będzie czerwone również wtedy, gdy jego termin już minął. Kolejność warunków powinna zatem odzwierciedlać hierarchię reguł biznesowych. Po znalezieniu spełnionego warunku funkcja nie sprawdza następnych; oblicza przypisany do niego wynik.

Ostatni argument w przykładzie jest wynikiem domyślnym. Jeśli zostanie pominięty, a żaden warunek nie będzie spełniony, funkcja zwróci Blank(). Warto świadomie ustalać wartość domyślną, zamiast pozostawiać zachowanie kontrolki przypadkowi.

Switch — kilka wariantów jednej wartości

Switch jest czytelniejszy od rozbudowanego If, gdy wszystkie decyzje zależą od tego samego wyrażenia, na przykład tekstowego statusu rekordu. Funkcja oblicza to wyrażenie raz, porównuje wynik z kolejnymi przypadkami i wybiera pierwszy pasujący.

Dla tekstowej kolumny Status formuła we właściwości Text etykiety może wyglądać następująco:

Switch(
    ThisItem.Status;
    "Nowe"; "Oczekuje na rozpoczęcie";
    "W toku"; "Praca trwa";
    "Zamknięte"; "Zakończono";
    "Status nierozpoznany"
)

Ostatni argument obsługuje wartość, której nie uwzględniono w przypadkach. Bez niego brak dopasowania oznacza wynik Blank(). Switch wybieraj do dopasowania konkretnych wartości, a If — do niezależnych kryteriów i przedziałów, takich jak kwota przekraczająca próg czy termin wcześniejszy od dzisiejszej daty.

Obie funkcje mogą również wybierać akcje w formule zachowania, na przykład we właściwości OnSelect. Istotny jest kontekst: formuła koloru zwraca kolor, natomiast formuła przycisku może uruchomić nawigację. Sama funkcja warunkowa nie zmienia właściwości obliczeniowej w miejsce wykonywania dowolnych działań.

ForAll — przetwarzanie rekordów, nie klasyczna pętla

ForAll oblicza wskazaną formułę dla każdego rekordu tabeli. Może służyć do przygotowania tabeli wynikowej albo wykonania niezależnych operacji na rekordach. Przykład przekształca tabelę PozycjeKoszyka, zawierającą kolumny Nazwa, Cena i Ilosc, w zestawienie wartości pozycji:

ForAll(
    PozycjeKoszyka As pozycja;
    {
        Produkt: pozycja.Nazwa;
        Wartosc: pozycja.Cena * pozycja.Ilosc
    }
)

Alias wprowadzony przez As jednoznacznie wskazuje bieżący rekord. Wynikiem jest nowa tabela — źródłowe rekordy nie zostają przez tę formułę zmienione.

Najważniejsze ograniczenie dotyczy kolejności: rekordy mogą być przetwarzane w dowolnym porządku, a tam, gdzie to możliwe, równolegle. Nie należy więc traktować ForAll jak pętli, w której następny krok korzysta z efektu poprzedniego. Kolejność wyników w zwracanej tabeli odpowiada kolejności danych wejściowych, ale nie gwarantuje kolejności wykonywania działań.

ForAll nie udostępnia też instrukcji break. Warunek If wewnątrz jego formuły może decydować, co zrobić z danym rekordem, lecz nie przerywa przetwarzania pozostałych. Jeśli celem jest jedynie wybranie rekordów albo zsumowanie wartości, zwykle czytelniejsze będą funkcje przeznaczone do tych zadań, takie jak Filter lub Sum.

Przykłady używają separatorów polskich ustawień regionalnych: średnik oddziela argumenty funkcji. W środowisku z innymi ustawieniami separatorem może być przecinek.

Delegation w dużych zbiorach danych: co jest delegowalne, jak wykrywać ostrzeżenia i jak projektować pod delegowanie

Galeria nie pokazuje szukanego rekordu, choć ten istnieje w źródle danych? Przyczyną może być brak delegowania. W Power Apps poprawna składniowo formuła nie zawsze przeszukuje cały zbiór. Jeśli aplikacja musi wykonać operację lokalnie, może otrzymać jedynie początkowy fragment danych — i na jego podstawie wyświetlić pozornie poprawny, lecz niepełny wynik.

Co oznacza delegowanie w Power Apps?

Delegowanie polega na przekazaniu obsługiwanych operacji do źródła danych, na przykład Dataverse, SQL Server lub SharePoint. Zamiast pobierać wszystkie rekordy do aplikacji, Power Apps zleca źródłu filtrowanie lub sortowanie, a następnie pobiera potrzebne wyniki. Dzięki temu aplikacja może pracować na zbiorach znacznie większych niż lokalny limit przetwarzania.

Dla zapytań niedelegowalnych domyślny limit wynosi 500 rekordów; w ustawieniach aplikacji można zwiększyć go maksymalnie do 2000. Nie jest to jednak limit wielkości źródła ani łącznej liczby rekordów, które delegowalna galeria może pobierać stronicami. Ograniczenie dotyczy danych pobieranych do lokalnej oceny niedelegowalnego zapytania.

Podniesienie limitu nie naprawia problemu. Jeśli lista zawiera 50 000 pozycji, lokalne przeszukanie pierwszych 2000 nadal może pominąć właściwy rekord. To przede wszystkim ryzyko niekompletności wyników, a nie tylko kwestia wydajności.

Co można delegować — i od czego to zależy?

Nie istnieje jedna lista funkcji delegowalnych we wszystkich sytuacjach. Znaczenie mają jednocześnie konektor, użyta funkcja lub operator, typ kolumny oraz konstrukcja całego wyrażenia. Samo zastosowanie funkcji Filter nie gwarantuje więc, że filtr zostanie wykonany po stronie źródła.

OperacjaPraktyczna zasada
Filtrowanie przez Filter i wyszukiwanie przez LookUpMogą być delegowane, jeśli konektor obsługuje wszystkie elementy warunku. Proste porównanie kolumny z wartością jest zwykle dobrym punktem wyjścia.
Wyszukiwanie początku tekstu przez StartsWithJest obsługiwane dla odpowiednich kolumn tekstowych w popularnych konektorach, m.in. SharePoint, Dataverse i SQL Server. Trzeba sprawdzić ograniczenia danego typu kolumny.
Wyszukiwanie fragmentu przez Search lub inObsługa różni się między konektorami. Wzorca działającego delegowalnie w Dataverse nie należy automatycznie przenosić do SharePoint.
Sortowanie przez Sort i SortByColumnsNajbezpieczniejszym wzorcem jest sortowanie po obsługiwanej kolumnie źródłowej. Wyrażenia przekształcające jej wartości mogą uniemożliwić delegowanie.
Agregacje, np. Sum lub CountRowsWymagają osobnej weryfikacji. Dostępność delegowania, limity i warunki zależą od źródła oraz ustawień.

Przy projektowaniu zapytania sprawdzaj dokumentację delegowania konkretnego konektora, zwłaszcza dla kolumn typu Choice, Lookup i Person. Nie należy traktować ich jak zwykłego tekstu.

Przykład: wyszukiwanie na liście SharePoint

Dla listy Zgloszenia i jej standardowej kolumny tekstowej Title właściwość Items galerii może korzystać z następującego wzorca:

Filter(
    Zgloszenia;
    StartsWith(Title; txtSzukaj.Text)
)

Przykład zakłada klasyczną kontrolkę tekstową txtSzukaj i polskie ustawienia regionalne, w których argumenty oddziela się średnikami. Filtrowanie po początku wartości w Title może zostać przekazane do SharePoint, zamiast ograniczać wyszukiwanie do lokalnie pobranej części listy.

Warto jednak pamiętać o intencji użytkownika: StartsWith wyszukuje początek tekstu, a nie dowolny fragment. Nie jest zatem równoważnym zamiennikiem wyszukiwania pełnotekstowego. Jeśli aplikacja wymaga szukania słów w dowolnym miejscu opisu, trzeba dobrać obsługiwany mechanizm wyszukiwania lub inne źródło danych.

Jak rozpoznawać i sprawdzać problemy?

Power Apps Studio sygnalizuje potencjalny problem m.in. niebieskim podkreśleniem fragmentu formuły oraz ostrzeżeniem delegowania. Otwórz komunikat i ustal, który element powoduje ograniczenie: funkcja, operator, konwersja typu czy odwołanie do kolumny. Nie wystarczy sprawdzić wyłącznie zewnętrznej funkcji zapytania.

Przydatnym testem jest tymczasowe ustawienie limitu wierszy dla zapytań niedelegowalnych na 1. Lokalna ocena zapytania staje się wtedy łatwiejsza do zauważenia. Testuj również wyszukiwanie znanych rekordów spoza początkowego fragmentu zbioru. Sam brak ostrzeżeń ani poprawny wynik na małej próbce nie stanowią dowodu, że rozwiązanie będzie kompletne na danych produkcyjnych.

Jak projektować aplikację pod delegowanie?

  • Filtruj bezpośrednio w źródle. Nie pobieraj dużej tabeli do kolekcji tylko po to, by następnie ją przeszukiwać. Lokalne filtrowanie kolekcji nie odzyska rekordów pominiętych podczas pobierania.
  • Upraszczaj warunki dotyczące kolumn. Konwersje i przekształcenia wartości każdego rekordu mogą blokować delegowanie. Jeśli to możliwe, przygotuj odpowiedni typ danych lub pole do wyszukiwania już w źródle.
  • Weryfikuj całą formułę po każdej zmianie. Dodanie jednego niedelegowalnego warunku może zmienić sposób wykonania zapytania, które wcześniej działało poprawnie.
  • Uwzględniaj wydajność źródła. Indeksy, widoki i właściwy model danych mogą usprawnić obsługiwane zapytania. Indeks nie sprawi jednak, że niedelegowalna formuła stanie się delegowalna.

Kryterium odbioru takiego rozwiązania powinno być konkretne: aplikacja odnajduje właściwe rekordy w całym docelowym zbiorze, a nie tylko działa szybko na danych testowych.

💡 Pro tip: Dodaj do testów regresyjnych wyszukiwanie znanego rekordu spoza pierwszych 2000 pozycji i uruchamiaj je z limitem wierszy dla zapytań niedelegowalnych ustawionym na 1. Powtarzaj test po każdej zmianie filtrowania lub sortowania — nawet drobne przekształcenie kolumny może sprawić, że zapytanie przestanie być delegowalne.

Zaawansowana walidacja formularzy: walidacja pól i wielopolowa, komunikaty dla użytkownika, UX walidacji

Formularz powinien nie tylko blokować niepoprawny zapis, ale także jasno wskazywać, co wymaga poprawy i jak to zrobić. W Power Apps warto rozdzielić trzy warstwy: wymagania wynikające ze źródła danych, reguły biznesowe zapisane w Power Fx oraz sposób prezentowania błędów. Dzięki temu poprawność danych nie zależy wyłącznie od wyglądu kontrolek, a użytkownik nie musi zgadywać, dlaczego nie może wysłać formularza.

Walidacja pojedynczych pól: wymagane wartości, format i zakres

W formularzu edycji podstawą są właściwości kart danych, przede wszystkim Required, Valid i Error. Właściwość Valid formularza agreguje poprawność jego kart. To dobry punkt wyjścia, ale nie pełna walidacja biznesowa: formularz może spełniać wymagania źródła danych, a jednocześnie zawierać nieakceptowalną kombinację wartości.

Dodatkowe reguły powinny odpowiadać znaczeniu pola. Dla wymaganego tekstu sprawdzaj nie tylko pustą wartość, lecz także wpis składający się z samych spacji. Dla adresu e-mail kontroluj format, a dla liczby — dopuszczalny zakres. Poprawny format adresu nie oznacza, że skrzynka istnieje; to osobny rodzaj weryfikacji.

Przykładowa reguła poprawności wymaganego adresu e-mail w klasycznej kontrolce tekstowej wygląda następująco. Przykłady korzystają z polskich separatorów Power Fx: średników między argumentami oraz podwójnego średnika między kolejnymi akcjami.

!IsBlank(Trim(txtEmail.Text)) &&
IsMatch(Trim(txtEmail.Text); Match.Email)

Dla pola opcjonalnego reguła powinna natomiast dopuszczać brak wartości i sprawdzać format dopiero po jej wpisaniu. Warto również ustalić sposób normalizacji danych: jeśli walidujesz tekst po usunięciu zbędnych spacji, zapisuj wartość przygotowaną według tej samej zasady, na przykład przez właściwość Update karty.

Walidacja wielopolowa: poprawne pola nie zawsze tworzą poprawny rekord

Reguły wielopolowe sprawdzają zależności, których nie da się ocenić na podstawie jednej kontrolki. Typowe przykłady to data końcowa nie wcześniejsza niż początkowa, obowiązkowe uzasadnienie po wybraniu określonej opcji albo suma pozycji mieszcząca się w zadanym limicie. Każde pole może być poprawne osobno, choć cały zestaw narusza zasady procesu.

Najpierw sprawdzaj kompletność danych, potem ich wzajemną zgodność. Komunikat „Data końcowa nie może być wcześniejsza niż początkowa” powinien pojawić się dopiero wtedy, gdy obie daty są podane. Przy braku jednej z nich właściwa informacja to prośba o jej uzupełnienie.

Poniższy przykład właściwości OnSelect przycisku zapisu zakłada obowiązkowy e-mail i obie daty. Łączy walidację formularza z dodatkowymi warunkami biznesowymi:

Set(varProbaZapisu; true);;
With(
    {
        emailPoprawny: !IsBlank(Trim(txtEmail.Text)) &&
            IsMatch(Trim(txtEmail.Text); Match.Email);
        datyPoprawne: !IsBlank(dpOd.SelectedDate) &&
            !IsBlank(dpDo.SelectedDate) &&
            dpDo.SelectedDate >= dpOd.SelectedDate
    };
    If(
        frmWniosek.Valid && emailPoprawny && datyPoprawne;
        SubmitForm(frmWniosek)
    )
)

Flaga próby zapisu służy tutaj do sterowania widocznością komunikatów. Samo wyświetlenie etykiety błędu nie zmienia właściwości Valid formularza. Własne warunki trzeba więc uwzględnić w ścieżce zapisu, a nie tylko w warstwie wizualnej. Jeżeli aplikacja udostępnia kilka sposobów zatwierdzania danych, każdy powinien respektować te same reguły.

Komunikaty: konkretna przyczyna i wskazówka poprawy

Komunikat umieszczaj przy polu, którego dotyczy. Przy zależności między datami naturalnym miejscem jest pole daty końcowej; przy limicie sumy — obszar podsumowania pozycji. Ogólne powiadomienie może zwrócić uwagę na problem, ale nie powinno zastępować informacji lokalnej.

  • Brak wartości: „Podaj adres e-mail”.
  • Niewłaściwy format: „Wpisz adres w formacie nazwa@domena.pl”.
  • Niespójność pól: „Data końcowa musi przypadać w dniu rozpoczęcia lub później”.
  • Wymaganie warunkowe: „Dodaj uzasadnienie dla wybranej opcji”.

Pokazuj jeden najważniejszy problem na pole. Pusta kontrolka nie powinna jednocześnie zgłaszać braku wartości i błędnego formatu. Reguła sterująca komunikatem musi być zgodna z regułą blokującą zapis — inaczej formularz może wyglądać na poprawny, choć nie da się go wysłać.

UX walidacji: właściwy moment i dostępna informacja

Nie oznaczaj wszystkich pustych pól jako błędnych od razu po otwarciu nowego formularza. Wymagania warto pokazać wcześniej, natomiast błędy ujawniać po interakcji z polem lub po pierwszej próbie zapisu. Po wykryciu problemu informacja powinna aktualizować się wraz z poprawianiem danych, z uwzględnieniem sposobu aktualizacji wartości przez daną kontrolkę.

Nie polegaj wyłącznie na czerwonym obramowaniu. Dodaj czytelny tekst, zadbaj o kontrast i etykiety dostępności. W długim formularzu przydatne jest krótkie zestawienie problemów oraz skierowanie użytkownika do odpowiedniego miejsca. Nieaktywny przycisk „Zapisz” bez wyjaśnienia zwykle utrudnia zadanie; aktywny przycisk, który ujawnia błędy bez wysyłania niepoprawnych danych, daje wyraźniejszą informację zwrotną.

Przy rozpoczęciu nowego wpisu lub przejściu do innego rekordu wyczyść stan prezentacji błędów. Zachowuj natomiast dane podczas poprawiania formularza. Walidacja po stronie aplikacji ułatwia pracę, ale krytyczne ograniczenia muszą obowiązywać również w źródle danych lub warstwie serwerowej — szczególnie gdy rekordy mogą być modyfikowane poza tą aplikacją.

💡 Pro tip: Dla każdej reguły biznesowej przygotuj trzy przypadki testowe: brak wartości, wartość graniczną i naruszenie warunku, a następnie sprawdź zarówno komunikat, jak i możliwość zapisu. To pozwala wychwycić sytuacje, w których formularz pokazuje błąd, ale nadal zapisuje dane, albo blokuje zapis bez wyjaśnienia.

Obsługa błędów i odporność aplikacji: IfError, informacje o błędzie i centralny handler

Zapis do źródła danych może się nie udać mimo poprawnie wypełnionego formularza. Przyczyną bywa utrata połączenia, brak uprawnień, konflikt zmian lub chwilowa niedostępność usługi. Odporna aplikacja rozpoznaje takie sytuacje, nie wyświetla przedwcześnie potwierdzenia sukcesu i pozwala użytkownikowi zachować wykonaną pracę. W Power Apps warto rozdzielić dwa zadania: obsługę przewidywalnych błędów przy konkretnej operacji oraz centralne raportowanie problemów, które nie zostały obsłużone lokalnie.

IfError — reakcja w miejscu wystąpienia problemu

IfError pozwala wykryć błąd podczas obliczania wyrażenia i uruchomić zdefiniowaną reakcję. Przy zapisie danych może to być wyświetlenie komunikatu, przywrócenie możliwości edycji lub pozostawienie użytkownika na bieżącym ekranie. Przy pobieraniu informacji pomocniczych dopuszczalne bywa zastosowanie wartości zastępczej, o ile nie prowadzi to do błędnej interpretacji danych.

Najważniejsze jest uzależnienie dalszych działań od rzeczywistego wyniku operacji. Samo umieszczenie zapisu i przejścia na kolejny ekran w jednej sekwencji nie gwarantuje, że nawigacja zostanie zatrzymana po błędzie. Potwierdzenie sukcesu, wyczyszczenie formularza i zamknięcie widoku powinny następować wyłącznie wtedy, gdy zapis się powiedzie. Obsługa błędu nie powinna też zwracać przypadkowej wartości zastępczej — jej typ musi być zgodny z wymaganiami wyrażenia, w którym zastosowano IfError.

Co oznacza „Err” w kontekście Power Fx?

W Power Fx nie ma standardowej funkcji obsługi błędów o nazwie Err. Taka nazwa może występować w konkretnej aplikacji jako własny identyfikator, ale nie należy traktować jej jako wbudowanego mechanizmu języka. Podczas obsługi błędów w IfError dostępne są przede wszystkim FirstError, czyli rekord pierwszego błędu, oraz AllErrors, czyli tabela błędów dostępnych w danym kontekście obsługi.

Informacje takie jak Kind i Message pomagają rozpoznać kategorię problemu oraz odczytać jego opis. Zależnie od miejsca wystąpienia błędu dostępne mogą być także dane o jego źródle lub szczegóły odpowiedzi sieciowej. Osobnym narzędziem jest funkcja Errors, służąca do odczytywania informacji o błędach operacji na źródle danych. Nie należy jej mylić z funkcją Error, która pozwala utworzyć lub ponownie zgłosić błąd.

Centralny handler z wykorzystaniem App.OnError

Właściwość App.OnError jest miejscem do obsługi błędów, które nie zostały przechwycone wcześniej. Może pełnić rolę centralnego handlera: ujednolicać ogólne komunikaty i przekazywać informacje diagnostyczne do przyjętego mechanizmu monitorowania. Nie zastępuje jednak lokalnej obsługi operacji. App.OnError nie cofa wykonanych działań ani nie zmienia błędnego wyniku na poprawny.

Praktyczny podział odpowiedzialności jest prosty: lokalna obsługa wie, jak pomóc użytkownikowi przy konkretnym zadaniu, a centralna zapewnia widoczność nieprzewidzianych problemów. Błąd przechwycony przez IfError nie trafi automatycznie do App.OnError. Jeżeli wymaga rejestracji, trzeba uwzględnić ją w lokalnej ścieżce obsługi albo świadomie przekazać błąd dalej. Warto przy tym zapobiegać podwójnym powiadomieniom o tym samym zdarzeniu.

Przykłady zachowania odpornej aplikacji

  • Nieudany zapis: aplikacja zachowuje wpisane dane, nie resetuje formularza i informuje, że nie udało się potwierdzić zapisu. Użytkownik otrzymuje możliwość dalszego działania zamiast utraty pracy.
  • Brak uprawnień: komunikat wskazuje ograniczenie dostępu. Wielokrotne ponawianie tej samej operacji nie jest proponowane jako rozwiązanie problemu.
  • Niedostępność danych pomocniczych: aplikacja może ograniczyć wybraną funkcję i wyjaśnić przyczynę. Nie powinna przedstawiać nieudanego odczytu jako poprawnie pobranej, pustej listy.
  • Przekroczenie czasu oczekiwania: aplikacja uwzględnia możliwość, że serwer wykonał zapis, lecz odpowiedź nie dotarła. Przed ponowieniem warto sprawdzić stan danych, aby uniknąć utworzenia duplikatu.

Komunikat dla użytkownika a diagnostyka

Użytkownik potrzebuje informacji, co się stało, czy jego dane są bezpieczne i jaki krok może wykonać. Surowy komunikat konektora zazwyczaj nie spełnia tego zadania. Szczegóły techniczne należy kierować do diagnostyki, ograniczając zapisywanie danych osobowych i poufnych. Funkcja Trace może wspierać analizę zdarzeń w narzędziu Monitor, ale trwałe przechowywanie logów wymaga odpowiednio zaprojektowanego rozwiązania.

Obsługę błędów warto sprawdzać celowo: przy utracie połączenia, odmowie dostępu i niedostępności usługi. O jej skuteczności świadczy nie sam komunikat, lecz to, czy aplikacja pozostaje w spójnym stanie, zachowuje pracę użytkownika i nie wykonuje kolejnych działań na podstawie niepotwierdzonego sukcesu.

💡 Pro tip: Przy użyciu SubmitForm umieszczaj potwierdzenie sukcesu, reset formularza i nawigację w Form.OnSuccess, a reakcję na nieudany zapis w Form.OnFailure. Nie dopisuj tych działań bezpośrednio po SubmitForm w OnSelect — samo wywołanie zapisu nie oznacza jeszcze jego powodzenia.

Dobre praktyki i najczęstsze błędy początkujących w Power Fx i Power Apps

Aplikacja może działać poprawnie podczas prezentacji, a mimo to sprawiać trudności przy pierwszej zmianie wymagań. W Power Apps jakość rozwiązania zależy nie tylko od poprawności formuł, lecz także od organizacji logiki, czytelności nazw i sposobu testowania. Dobra formuła powinna być zrozumiała również dla osoby, która nie uczestniczyła w jej tworzeniu.

Nazywaj elementy tak, aby ujawniały swoje przeznaczenie

Domyślne nazwy kontrolek szybko przestają wystarczać. Gdy na ekranie znajduje się kilkanaście pól i przycisków, trudno rozpoznać, do czego odnosi się formuła korzystająca z kolejnego numerowanego elementu. Stosuj konsekwentny schemat nazewnictwa, który wskazuje rolę kontrolki i jej znaczenie biznesowe. Ważniejsza od wyboru konkretnej konwencji jest jej spójność w całej aplikacji.

Podobnie traktuj nazwy ekranów, komponentów i przechowywanych wartości. Unikaj skrótów zrozumiałych wyłącznie dla autora. Komentarze wykorzystuj przede wszystkim do wyjaśniania powodu zastosowania reguły, na przykład wyjątku wynikającego z procesu biznesowego, zamiast opisywać oczywiste działanie funkcji.

Nie powielaj logiki i nie przechowuj zbędnego stanu

Kopiowanie tej samej reguły do wielu kontrolek przyspiesza pierwszy etap pracy, ale utrudnia utrzymanie aplikacji. Zmiana wymaga wtedy odnalezienia wszystkich kopii, a pominięcie jednej prowadzi do niespójnego działania. Powtarzalne elementy interfejsu warto wydzielać do komponentów, natomiast wspólne obliczenia — definiować w jednym miejscu, na przykład jako formuły nazwane, jeśli odpowiada to ich przeznaczeniu.

Częstym błędem jest również zapisywanie wartości, którą można bezpośrednio wyliczyć z aktualnych danych. Każda dodatkowa kopia oznacza konieczność pilnowania jej aktualności. Przechowuj stan wtedy, gdy reprezentuje rzeczywistą decyzję użytkownika lub etap procesu, a nie tylko dlatego, że rozbicie obliczenia na kolejne przypisania wydaje się prostsze. W Cognity łączymy teorię z praktyką — dlatego zasady organizacji logiki aplikacji rozwijamy także w formie ćwiczeń na szkoleniach.

Oddzielaj wygodę interfejsu od bezpieczeństwa danych

Ukrycie przycisku albo zablokowanie pola może ułatwiać obsługę aplikacji, ale nie zastępuje uprawnień w źródle danych. Użytkownik powinien mieć dostęp tylko do tych informacji i operacji, które są mu potrzebne, niezależnie od tego, co pokazuje ekran. Ograniczenia dostępu projektuj w mechanizmach bezpieczeństwa źródła danych, a widoczność kontrolek traktuj jako uzupełnienie doświadczenia użytkownika.

Nie umieszczaj haseł, kluczy API ani innych sekretów w formułach czy ukrytych kontrolkach. Korzystaj z odpowiednio skonfigurowanych połączeń i mechanizmów uwierzytelniania. To, że element nie jest widoczny podczas zwykłej obsługi aplikacji, nie czyni go bezpiecznym miejscem przechowywania poufnych informacji.

Testuj scenariusze pracy, nie tylko pojedyncze kliknięcia

Test wykonany na własnym koncie i jednym rekordzie potwierdza jedynie bardzo wąski przypadek. Sprawdzaj także powrót na wcześniej otwarty ekran, ponowne wykonanie tej samej operacji, wolniejsze połączenie oraz działanie na koncie z ograniczonymi uprawnieniami. Jeśli aplikacja ma być używana na telefonie, oceń ją na rzeczywistym urządzeniu, a nie wyłącznie w podglądzie edytora.

Uwzględnij obsługę klawiaturą, czytelne etykiety i komunikaty, których znaczenie nie zależy wyłącznie od koloru. Problemy z wydajnością diagnozuj przy użyciu narzędzi takich jak Monitor: szukaj powtarzających się żądań i operacji uruchamianych niepotrzebnie. Optymalizowanie formuł na podstawie pomiarów jest skuteczniejsze niż przypadkowe skracanie ich zapisu.

Zmiany wprowadzaj małymi krokami i po każdej istotnej modyfikacji sprawdzaj najważniejsze ścieżki użytkownika. Przed publikacją korzystaj z narzędzia App checker, pamiętając, że wykrycie problemów technicznych nie zastępuje weryfikacji reguł biznesowych. Czytelna, przewidywalna aplikacja jest cenniejsza niż rozwiązanie oparte na efektownych, lecz trudnych do utrzymania formułach.

Najczęściej zadawane pytania i odpowiedzi odnośnie Język Power Fx i logika

Kiedy używać Set, a kiedy UpdateContext w Power Apps?

Set służy do przechowywania stanu współdzielonego między ekranami, a UpdateContext — stanu konkretnego ekranu. Zmienna globalna sprawdzi się przy wyborze projektu używanego w kilku widokach. Zmienna kontekstowa wystarczy do sterowania lokalnym panelem lub zakładką. Jeśli wartość jest potrzebna tylko na ekranie docelowym, można przekazać ją przez Navigate. Opuszczenie ekranu nie resetuje automatycznie zmiennej kontekstowej.

Czym różnią się Collect, ClearCollect i Patch w Power Fx?

Collect dodaje rekordy, ClearCollect zastępuje zawartość kolekcji, a Patch pozwala zmodyfikować wskazany rekord. Wybór funkcji powinien odpowiadać temu, co użytkownik robi z danymi:

  • Collect — dokłada kolejną pozycję do listy roboczej.
  • ClearCollect — buduje bufor od nowa.
  • Patch — aktualizuje wybrane pola bez odbudowy całej tabeli.

Patch skierowany do kolekcji nie zapisuje zmian w źródle danych. Zapis wymaga osobnej operacji skierowanej do tego źródła.

Kiedy wybrać If, a kiedy Switch w Power Fx?

If sprawdza warunki logiczne, natomiast Switch dopasowuje jedną wartość do określonych przypadków. Dobór funkcji wynika z rodzaju reguły:

  • If sprawdza się przy progach kwotowych, zakresach dat i niezależnych kryteriach.
  • Switch porządkuje warianty zależne od jednego statusu lub wyboru.

W obu funkcjach znaczenie ma kolejność: wybierany jest pierwszy spełniony warunek lub pasujący przypadek. Jawny wynik domyślny pozwala uniknąć niezamierzonego Blank().

Czy ForAll w Power Fx działa jak zwykła pętla?

ForAll przetwarza rekordy tabeli, ale nie gwarantuje kolejności wykonywania działań. Operacje mogą przebiegać w dowolnym porządku, a tam, gdzie to możliwe, równolegle. Nie należy więc uzależniać obsługi kolejnego rekordu od efektu poprzedniego. ForAll nie udostępnia również instrukcji break. Do samego wybierania rekordów lub sumowania wartości zwykle czytelniejsze będą odpowiednio Filter i Sum.

Dlaczego galeria Power Apps nie pokazuje wszystkich pasujących rekordów?

Przyczyną niepełnych wyników może być niedelegowalna formuła, która przeszukuje tylko początkowy fragment źródła danych. Domyślny limit takiego przetwarzania wynosi 500 rekordów i można go zwiększyć do 2000, ale nie rozwiązuje to problemu większych zbiorów. Sprawdź ostrzeżenia w Power Apps Studio oraz obsługę całego warunku przez konektor. Testuj wyszukiwanie znanego rekordu spoza początkowej części danych.

Dlaczego formularz Power Apps ma Valid ustawione na true mimo błędu biznesowego?

Właściwość Valid formularza agreguje poprawność kart danych, ale nie uwzględnia automatycznie każdej własnej reguły biznesowej. Wyświetlenie etykiety z błędem nie zmienia tej właściwości. Warunki takie jak zgodność dat czy obowiązkowe uzasadnienie trzeba uwzględnić również przed uruchomieniem zapisu. Każda dostępna ścieżka zatwierdzania powinna sprawdzać te same reguły, a komunikaty wskazywać użytkownikowi konkretny sposób poprawy danych.

Jak obsłużyć nieudany zapis w Power Apps, żeby użytkownik nie stracił danych?

Po nieudanym zapisie zachowaj dane użytkownika i nie uruchamiaj resetowania formularza ani nawigacji przewidzianej po sukcesie. Przy SubmitForm umieść działania potwierdzające zapis w OnSuccess formularza, a reakcję na błąd w OnFailure. Przy operacjach obsługiwanych przez IfError uzależnij dalsze działania od wyniku zapisu. Komunikat powinien jasno wyjaśniać problem i wskazywać możliwy następny krok.

Czy App.OnError zastępuje obsługę błędów przez IfError?

App.OnError nie zastępuje IfError: służy do centralnej obsługi błędów, których nie przechwycono wcześniej. IfError pozwala zareagować przy konkretnej operacji, natomiast App.OnError może ujednolicać ogólne komunikaty i wspierać diagnostykę. Błąd obsłużony lokalnie nie trafia tam automatycznie. Jeśli wymaga rejestracji, trzeba zaplanować ją w lokalnej obsłudze albo świadomie przekazać błąd dalej, unikając podwójnych powiadomień.

icon

Formularz kontaktowyContact form

Imię *Name
NazwiskoSurname
Adres e-mail *E-mail address
Telefon *Phone number
UwagiComments