Skąd biorą się problemy z separatorami dziesiętnymi w Power Query
Różne standardy zapisu liczb a import do Power Query
Polski użytkownik jest przyzwyczajony, że separator dziesiętny to przecinek, a kropka służy co najwyżej jako separator tysięcy. W systemach anglojęzycznych jest odwrotnie: kropka to separator dziesiętny, przecinek – tysięcy. Gdy te dwa światy spotykają się w jednym modelu danych, Power Query musi podjąć decyzję, jak zinterpretować zapis 1.234. Czy chodzi o tysiąc dwieście trzydzieści cztery, czy o jedną i 234 tysięczne?
Jeżeli format w pliku źródłowym nie jest zgodny z ustawieniami regionalnymi Power Query, dane liczbowe mogą zostać zaimportowane jako tekst lub z błędną wartością. Ten sam ciąg znaków w zależności od „kultury” (culture) systemu może oznaczać inną liczbę albo w ogóle zostać uznany za niepoprawny.
W praktyce prowadzi to do sytuacji, w której raport wygląda poprawnie wizualnie (wszystko przypomina liczby), ale obliczenia są błędne lub nie działają wcale. Trzeba więc zadać pytanie kontrolne: co wiemy o źródle danych i jego formacie, a czego wciąż nie wiemy o tym, jak Power Query je odczytuje.
Rola ustawień regionalnych systemu i aplikacji
Power Query funkcjonuje w konkretnym kontekście regionalnym. Na ten kontekst wpływają:
- ustawienia regionu systemu Windows (np. Polska, Niemcy, Stany Zjednoczone),
- ustawienia języka i regionu w Excelu lub Power BI Desktop,
- format regionalny zaszyty w samej logice zapytania M (culture),
- ewentualne informacje o kulturze w źródle, np. w niektórych bazach danych.
Gdy użytkownik importuje plik CSV z systemu amerykańskiego na komputerze z ustawieniami polskimi, dane liczbowe z kropką jako separatorem dziesiętnym mogą zostać potraktowane jako tekst. Z kolei te same dane wczytywane na komputerze z kulturą en-US mogą być od razu poprawnie rozpoznane jako liczby. To rodzi problem spójności: dwa raporty korzystające z tego samego pliku mogą zachowywać się inaczej w zależności od maszyny.
Bez świadomego sterowania kulturą w Power Query trudno utrzymać przewidywalne zachowanie, szczególnie w zespołach wielojęzycznych lub przy współdzieleniu raportów między krajami.
Co widać w interfejsie, a czego nie widać
Użytkownik widzi w Power Query kolumnę z wartościami typu „1.23” albo „1,23” i zadaje sobie pytanie: czy to liczba, czy tekst? Ikona typu danych przy nagłówku kolumny już daje jakąś odpowiedź, ale nie wyjaśnia, jak Power Query zrozumiał konkretny separator. Gdy zmieni się typ na liczbowy, część wartości może zmienić się na null lub błąd, a część zostać przekonwertowana niezgodnie z oczekiwaniami.
Rzeczywisty problem kryje się w tym, w jakiej kulturze Power Query analizuje tekst i przekształca go na liczbę. Kultura decyduje o tym, co jest separatorem dziesiętnym, co separatorem tysięcy, jak traktowany jest znak minus, jak wygląda zapis wartości ujemnych i wiele innych detali. Bez jawnego ustawienia tej kultury Power Query często opiera się na domyślnych ustawieniach systemu lub aplikacji, które mogą nie być zgodne z formatem danych źródłowych.
Typowe objawy błędnego zrozumienia separatora dziesiętnego
Najczęściej spotykane symptomy problemu z separatorem dziesiętnym po imporcie do Power Query to:
- kolumna z liczbami ma typ Tekst – mimo że wartości wyglądają jak klasyczne liczby, np. 12.50 albo 12,50,
- nie działa sortowanie numeryczne – sort rosnący układa wartości jak tekst (1, 10, 100, 2…),
- agregacje zwracają 0 lub są niedostępne – brak możliwości wybrania sumy, średniej w widoku danych w Power BI,
- po zmianie typu część wartości staje się null – np. 1.23 zamienia się na null w polskim środowisku, gdy przecinek jest wymaganym separatorem dziesiętnym,
- po zmianie typu pojawiają się błędy – komunikaty o nieudanej konwersji tekstu na liczbę,
- część wartości zostaje błędnie zinterpretowana – np. 1.234 zostaje odczytane jako 1234 zamiast 1,234 lub odwrotnie.
Jeżeli którykolwiek z tych objawów się pojawia, trzeba ustalić, czy problem leży w samych danych, czy w sposobie, w jaki Power Query je czyta. To kluczowe rozróżnienie, zanim do gry wejdą kolejne transformacje.
Jak Power Query rozumie liczby – podstawy (typy, kultura, format)
Typy danych liczbowych w Power Query
Power Query rozróżnia kilka typów liczbowych, które mają znaczenie przy obsłudze separatorów dziesiętnych:
- Whole Number – liczba całkowita (bez części ułamkowej),
- Decimal Number – liczba zmiennoprzecinkowa podwójnej precyzji (typ number w M),
- Fixed Decimal Number – liczba dziesiętna o stałej precyzji (skala 4 miejsca po przecinku),
- Currency – liczba o precyzji walutowej (dokładność do czterech miejsc po przecinku, zakres ograniczony).
W kontekście separatorów dziesiętnych najczęściej problem dotyczy przejścia z typu Tekst na Decimal Number lub Fixed Decimal Number. W tym momencie kultura odgrywa zasadniczą rolę: ten sam ciąg znaków może być poprawny w jednej kulturze, a błędny w innej.
Zdarza się też, że Power Query automatycznie definiuje typ całkowity (Whole Number) mimo, że w danych występują wartości z częścią dziesiętną. Jeśli w pierwszych wierszach nie widać przecinków lub kropek, mechanizm rozpoznawania typu zakłada liczbę całkowitą. Gdy w dalszej części pliku pojawi się separator dziesiętny, wartości mogą zostać zaokrąglone lub utracone.
Kultura (culture) w języku M
W języku M istnieje pojęcie culture, które definiuje lokalne zasady zapisu liczby. Kultura jest przekazywana do wielu funkcji konwertujących tekst na liczby lub daty. Przykładowe symbole kultur to:
"pl-PL"– język polski, Polska (separator dziesiętny: przecinek, tysięcy: spacja lub kropka w zależności od ustawień),"en-US"– język angielski, Stany Zjednoczone (separator dziesiętny: kropka, tysięcy: przecinek),"de-DE"– język niemiecki, Niemcy (separator dziesiętny: przecinek, tysięcy: kropka).
Wiele funkcji M ma wersję przyjmującą kulturę jako dodatkowy argument, np. Number.FromText, Date.FromText, Time.FromText. Dzięki temu można wymusić interpretację tekstu w innej kulturze niż domyślna. Jest to kluczowy mechanizm naprawiania liczb z importu, zwłaszcza przy pracy z plikami z zagranicznych systemów.
Jeśli kultura nie zostanie podana explicite, funkcja użyje domyślnych ustawień regionalnych środowiska. To właśnie prowadzi do rozbieżności między zachowaniem na różnych komputerach i w różnych instalacjach.
Automatyczna detekcja typu danych przy imporcie
Power Query podczas wczytywania danych uruchamia mechanizm automatycznego rozpoznawania typów danych. Na podstawie kilku pierwszych wierszy tabeli system próbuje określić, które kolumny są liczbami, które datami, a które tekstem. Efektem tego mechanizmu jest automatycznie dodawany krok Changed Type (Zmiana typu).
Automatyczna detekcja ma jednak wyraźne ograniczenia:
- analizuje ograniczoną liczbę pierwszych wierszy – jeżeli pierwszych kilkanaście rekordów nie zawiera separatora dziesiętnego, kolumna może zostać uznana za całkowitą,
- opiera się na domyślnej kulturze środowiska – jeśli plik jest w formacie en-US, a środowisko w kulturze pl-PL, funkcja rozpoznawania może oznaczyć kolumnę jako tekst,
- nie radzi sobie z mieszanymi formatami w jednej kolumnie – np. części wierszy z przecinkiem, części z kropką.
W efekcie krok Changed Type często trzeba świadomie usunąć lub nadpisać własną transformacją z użyciem „Użyj ustawień regionalnych” albo funkcji M z parametrem kultura. W przeciwnym razie błędne założenia z początku zapytania będą propagować się przez kolejne kroki.
Znaczenie pierwszych kilku wierszy danych
Mechanizm auto-detekcji typów w Power Query szczególnie polega na pierwszych wierszach danych. Jeśli na samym początku pliku znajdują się wartości typu „1000” bez części dziesiętnej, a dopiero dalej „1000,50”, Power Query może oznaczyć całą kolumnę jako Whole Number. Wtedy wszystkie części dziesiętne zostaną utracone już w momencie zmiany typu.
Analogiczny problem występuje przy mieszanych separatorach. Jeżeli w pierwszych wierszach użyto formatu zgodnego z kulturą systemu, a później wystąpią inne zapisy (np. z kropką jako separatorem dziesiętnym w środowisku polskim), część wierszy pozostanie tekstem lub zostanie przekonwertowana na null.
W praktyce jedną z pierwszych decyzji jest często wyłączenie automatycznej zmiany typów i ręczne zdefiniowanie typów po upewnieniu się, jaki format występuje w danych. To daje większą kontrolę i eliminuje zależność od zmiennej zawartości pierwszych wierszy.
Ustawienia regionalne Excela, Power BI i plików źródłowych – kto tu rządzi?
System Windows vs aplikacja: dwa poziomy ustawień
W środowisku Windows co najmniej dwa poziomy ustawień wpływają na interpretację liczb:
- ustawienia regionu systemu (Panel sterowania → Region),
- ustawienia języka i regionu w aplikacji (Excel, Power BI Desktop).
System operacyjny definiuje podstawowe konwencje, w tym separator dziesiętny i separator listy. Aplikacje, takie jak Excel, mogą korzystać z ustawień systemu lub posiadać własne ustawienia formatowania. Dodatkowo Power BI Desktop ma konfigurację regionalną wpływającą na interpretację danych w modelu i podczas odświeżania.
Kiedy Power Query pracuje w ramach Excela, część decyzji podejmowana jest na podstawie regionalnych ustawień Excela i systemu. W Power BI Desktop większą rolę odgrywa konfiguracja samej aplikacji i ewentualnie ustawienia serwera (np. w Power BI Service). To prowadzi do pytania: które ustawienie jest nadrzędne dla konkretnego zapytania?
Format pliku źródłowego: CSV, TXT, Excel i ich ograniczenia
Pliki tekstowe, takie jak CSV lub TXT, w większości przypadków nie przechowują informacji o kulturze. Zawierają jedynie znaki, a interpretacja tych znaków zależy od klienta wczytującego. Plik CSV może więc mieć:
- przecinek jako separator kolumn i kropkę jako separator dziesiętny,
- średnik jako separator kolumn i przecinek jako separator dziesiętny,
- tabulator jako separator kolumn i dowolny znak jako separator dziesiętny.
Power Query podczas importu plików tekstowych wymaga wskazania separatora kolumn (np. przecinek, średnik, tabulator), ale separator dziesiętny jest już wnioskowany na podstawie kultury. To oznacza, że dwa różne środowiska mogą inaczej zinterpretować ten sam plik CSV.
Pliki Excela przechowują dane z informacją o typie komórki, więc sytuacja jest nieco lepsza. Liczba zapisana jako wartość numeryczna w Excelu będzie odczytana jako liczba w Power Query niezależnie od lokalnego formatu wyświetlania w skoroszycie (choć przy eksporcie do CSV lub udostępnianiu między różnymi regionami problem może powrócić).
Przykład: niemiecki CSV na polskim Excelu
Dla zobrazowania konfliktu kultur warto przeanalizować prosty scenariusz. Raport finansowy z systemu niemieckiego został wyeksportowany do pliku CSV. W pliku liczby zapisano z:
- przecinkiem jako separatorem dziesiętnym – np.
1234,56, - kropką jako separatorem tysięcy – np.
1.234,56, - średnikiem jako separatorem kolumn – standard w wielu niemieckich konfiguracjach.
Plik trafia do użytkownika w Polsce, który ma system Windows ustawiony na polski format liczbowy, a Excel również działa w kulturze polskiej. Przy imporcie do Power Query użytkownik wybiera separator kolumn: średnik. Dane wczytują się poprawnie do kolumn, ale wartości liczbowe typu 1.234,56 mogą zostać potraktowane różnie:
- jako tekst – jeśli mechanizm detekcji uzna zapis za niejednoznaczny,
- jako liczba 1.234 z przecinkiem jako separatorem tysięcy zignorowanym,
- jako błąd – jeśli Power Query “nie ufa” takiemu formatowi przy danej kulturze.
W takiej sytuacji konieczne jest wymuszenie właściwej kultury (np. "de-DE") na etapie konwersji tekstu na liczby. Dopiero wtedy zapis 1.234,56 zostanie poprawnie zinterpretowany jako tysiąc dwieście trzydzieści cztery i 56/100.
Brak informacji o kulturze w formatach tekstowych
Konsekwencje braku kultury w CSV dla Power Query
Brak zakodowanej kultury w formatach tekstowych powoduje, że Power Query musi zgadywać. To nie jest jedynie problem „estetyczny”, ale techniczny – wpływa na wyniki obliczeń, a więc na raporty, decyzje, a czasem na zgodność z księgami.
Co wiemy? Ten sam plik CSV:
- na komputerze z kulturą
pl-PLmoże dać liczby odczytane jako tekst, - na komputerze z kulturą
en-USmoże zostać zinterpretowany częściowo poprawnie, a częściowo jako null, - w Power BI Service (gdzie kultura serwera bywa inna niż desktopu) może zachowywać się inaczej niż w Power BI Desktop.
Czego nie wiemy na pierwszy rzut oka? Tego, czy liczby zostały przekonwertowane spójnie. W jednym zapytaniu można mieć mieszankę: część wierszy jako liczby, część jako tekst, część jako błędy. Przy dużych zbiorach danych te rozbieżności giną w tłumie i ujawniają się dopiero przy audycie lub odchyleniach w raportach.
Dlatego przy imporcie „obcych” CSV pierwszym krokiem diagnostycznym powinno być szybkie przefiltrowanie kolumn liczbowych i sprawdzenie:
- czy występują błędy,
- czy widać naprzemiennie wartości numeryczne i tekstowe,
- czy liczby z separatorem tysięcy zostały potraktowane inaczej niż te bez niego.
Dopiero po takim przeglądzie można świadomie zdecydować, czy wystarczy zmiana kultury, czy konieczne będą dodatkowe korekty tekstu (np. usunięcie separatora tysięcy przed konwersją).
„Użyj ustawień regionalnych” – ręczne sterowanie kulturą
Ręczna zmiana typu kolumny z określeniem kultury
Jednym z najpraktyczniejszych narzędzi kontroli separatorów dziesiętnych jest opcja „Użyj ustawień regionalnych” podczas zmiany typu kolumny. Z technicznego punktu widzenia Power Query generuje wówczas funkcję typu Value.ReplaceType lub bezpośrednie wywołanie Table.TransformColumnTypes z parametrem “pl-PL”, “de-DE” itd.
Procedura w interfejsie jest prosta, ale często pomijana:
- Zaznaczenie kolumny zawierającej liczby w formie tekstu.
- Prawy przycisk myszy → Zmień typ → Użyj ustawień regionalnych.
- Wybór docelowego typu (np. Fixed decimal number lub Decimal number).
- Wybór kultury pasującej do formatu w pliku, a nie do własnego systemu (np.
de-DEdla niemieckiego CSV).
Power Query zapisze wtedy krok w postaci zbliżonej do:
Table.TransformColumnTypes(
Źródło,
{{ "Kwota", type number }},
"de-DE"
)
Kluczowe jest ostatnie „"de-DE"” – to ono mówi, jak interpretować przecinki, kropki i spacje w tekście przed konwersją na typ liczbowy.
Porównanie z domyślną zmianą typu
Dla kontrastu, domyślny krok Changed Type wygenerowany automatycznie zazwyczaj wygląda tak:
Table.TransformColumnTypes(
Źródło,
{{"Kwota", type number}}
)
Brak trzeciego argumentu oznacza użycie kultury środowiska. Jeśli zapytanie zostanie otwarte na innym komputerze lub w usłudze w chmurze, efekt może być inny niż na maszynie autora.
Praca z jawnie podaną kulturą ma dwie przewagi:
- zapewnia powtarzalność niezależnie od miejsca uruchomienia zapytania,
- czytelnie dokumentuje założenie: „ta kolumna jest w formacie de-DE”, „ta w en-US”.
Strategia: jedna kolumna – jedna kultura
Power Query nie rozwiązuje dobrze sytuacji, w której w tej samej kolumnie znajdują się liczby zapisane w różnych kulturach (np. część z kropką, część z przecinkiem jako separatorem dziesiętnym). Typowa sytuacja: część danych pochodzi z eksportu polskiego systemu, reszta została dopisana ręcznie przez kogoś z angielskimi ustawieniami.
Technicznie mamy wtedy trzy wyjścia:
- ujednolicić format już w pliku źródłowym (rekomendacja w sytuacjach, gdy ma się wpływ na proces eksportu),
- podzielić kolumnę na dwie – na podstawie wzorca (np. „zawiera kropkę i przecinek” vs „zawiera tylko kropkę”) – każdą przetworzyć inną kulturą, a następnie scalić z powrotem,
- przekształcić zapis ręcznie, zastępując odpowiednie znaki, zanim jakakolwiek funkcja M zamieni tekst na liczbę.
Ostatnie rozwiązanie bywa konieczne np. w raportach, gdzie w jednym polu mogą pojawiać się zapisy „1234.56”, „1234,56” i „1 234,56”. Wtedy nawet kultura nie wystarczy – trzeba wprost usunąć spacje jako separator tysięcy i świadomie wybrać, czy kropka ma być kropką dziesiętną, czy tylko elementem grupowania cyfr.
Funkcje M do naprawy separatorów dziesiętnych
Number.FromText z kulturą
W wielu przypadkach zamiast polegać na ogólnym Changed Type, praktyczniejsze jest użycie funkcji Number.FromText w niestandardowej kolumnie. Pozwala ona precyzyjnie określić, jak zinterpretować tekst w danej kolumnie.
Przykładowa transformacja kolumny "KwotaTekst" do liczby z użyciem kultury niemieckiej:
= Table.AddColumn(
#"Poprzedni krok",
"Kwota",
each Number.FromText([KwotaTekst], "de-DE"),
type number
)
Taki zapis jest bardziej jednoznaczny niż anonimowy krok zmiany typu i można go łatwiej modyfikować – np. dodać obsługę błędów:
= Table.AddColumn(
#"Poprzedni krok",
"Kwota",
each try Number.FromText([KwotaTekst], "de-DE") otherwise null,
type nullable number
)
To szczególnie użyteczne przy „brudnych” danych, gdzie sporadycznie pojawiają się znaki spoza zakresu liczby (np. „ok.”, „szac.”, „<0”).
Text.Replace i Text.Select jako filtr wstępny
Nie zawsze da się polegać wyłącznie na kulturze. Czasem trzeba najpierw „posprzątać” tekst, a dopiero potem zamieniać go na liczbę. Klasyczne narzędzie: Text.Replace i Text.Select.
Scenariusz: w kolumnie z liczbami z niemieckiego systemu pojawiają się spacje jako separator tysięcy („1 234,56”) oraz kropki („1.234,56”). Chcemy je wszystkie sprowadzić do formatu poprawnego w kulturze de-DE, czyli przecinek jako separator dziesiętny i brak separatora tysięcy.
Przykładowy krok:
= Table.AddColumn(
#"Poprzedni krok",
"KwotaOczyszczona",
each let
t1 = Text.Replace([KwotaTekst], " ", ""),
t2 = Text.Replace(t1, ".", "")
in
Number.FromText(t2, "de-DE"),
type number
)
Tutaj najpierw usuwane są spacje i kropki (interpretowane jako separator tysięcy), a dopiero później funkcja Number.FromText korzysta z kultury do rozpoznania przecinka dziesiętnego.
W innych przypadkach sprawdza się Text.Select, które filtruje tylko cyfry oraz wybrane znaki:
= Text.Select([KwotaTekst], {"0".."9", ",", "."})
Takie „odsianie” znaków bywa przydatne przy kolumnach, gdzie wartości są opatrzone adnotacjami („123,45 EUR”, „~67.89”).
Obsługa formatów procentowych
Jednym z mniej oczywistych obszarów są procenty zapisane w różnych kulturach, np. „12,5%” vs „12.5 %”. Power Query może odczytywać je jako tekst, a użytkownik oczekuje wartości numerycznej 0,125.
Bezpośrednia zmiana typu często kończy się błędami lub interpretacją jako 12,5 zamiast 0,125. Bezpieczniejszy wariant to rozbicie operacji na dwa etapy:
- Usunięcie znaku „%” i ewentualnych spacji,
- Konwersja
Number.FromTextz odpowiednią kulturą i podział przez 100.
= Table.AddColumn(
#"Poprzedni krok",
"Procent",
each let
t1 = Text.Replace([ProcentTekst], "%", ""),
t2 = Text.Trim(t1),
n = Number.FromText(t2, "pl-PL")
in
n / 100,
type number
)
Taki zapis jest jawny: widać, że autor zakłada procenty z przecinkiem dziesiętnym w kulturze polskiej i dzieli przez 100, aby trafić do typowego formatu używanego w modelach danych.

Typy liczbowe w Power Query a separatory
Różnica między „Decimal number”, „Fixed decimal number” i „Whole number”
Warstwa kultury to jedno, ale efekt końcowy zależy również od docelowego typu liczbowego nadanego kolumnie. Power Query (i model danych w Power BI) rozróżnia m.in.:
- Whole Number – liczby całkowite,
- Decimal Number – liczby zmiennoprzecinkowe (podwójna precyzja, binarna reprezentacja),
- Fixed Decimal Number – liczby dziesiętne o stałej precyzji (4 miejsca po przecinku, wewnętrznie przechowywane jako liczby całkowite /10000).
Przy konwersji tekstu z separatorem dziesiętnym do Decimal Number mogą pojawić się minimalne różnice reprezentacji binarnej, typowe dla liczb zmiennoprzecinkowych. W raportach finansowych częściej stosuje się Fixed Decimal Number, aby uniknąć efektów zaokrągleń przy sumowaniu dużej liczby pozycji.
Przykład: kolumna „Kwota” z niemieckiego CSV przechodzi ścieżkę:
- Tekst „1.234,56” jest oczyszczany z kropki tysiąca i konwertowany z kulturą
de-DEna typ liczbowy, - docelowy typ ustawiony jest na Fixed Decimal Number, aby zachować dwie cyfry po przecinku bez zaskakujących odchyleń.
Ostatni krok można wymusić zarówno z interfejsu (zmiana typu), jak i w kodzie:
Table.TransformColumnTypes(
#"Poprzedni krok",
{{"Kwota", type number}} // lub: type fixed
)
W kontekście separatorów dziesiętnych wybór między tymi typami decyduje więc nie tylko o formacie, ale też o bezpieczeństwie arytmetyki w dalszych etapach analizy.
Pułapka automatycznego zaokrąglania przy zmianie typu
Gdy Power Query uzna kolumnę za Whole Number, kolejne próby wymuszenia innego typu mogą skutkować nieodwracalną utratą części dziesiętnej. Dzieje się tak, gdy krok Changed Type wykonał się już na etapie, gdy przecinki i kropki nie były jeszcze poprawnie rozpoznane.
Typowa sekwencja błędów wygląda tak:
- Import CSV → Power Query analizuje pierwsze wiersze i uznaje kolumnę za całkowitą.
- W dalszych wierszach pojawiają się wartości typu „100,50”, ale z powodu kultury są odczytywane jako 10050 lub generują błędy.
- Użytkownik później próbuje ręcznie zmienić typ na Decimal Number, lecz część informacji jest już utracona.
Rozwiązaniem jest cofnięcie się w edytorze kroków do momentu przed automatyczną zmianą typu, usunięcie kroku Changed Type i ponowne zdefiniowanie typów z użyciem kultury. W przeciwnym razie pracujemy na danych, które już zostały błędnie zinterpretowane.
Praktyczne schematy naprawy liczb z importu
Scenariusz 1: Plik CSV z kropką dziesiętną w środowisku pl-PL
Załóżmy plik CSV z systemu amerykańskiego: liczby zapisane jako „1234.56”, separator kolumn to przecinek. Użytkownik pracuje na polskim Windows, Excel i Power BI domyślnie oczekują przecinka dziesiętnego.
Sprawdzony schemat działania:
- Import pliku z poprawnym wskazaniem separatora kolumn (przecinek).
- Usunięcie automatycznego kroku Changed Type.
- Ręczne zdefiniowanie typu kolumny liczbowej przez „Użyj ustawień regionalnych” z kulturą
en-US.
Power Query wygeneruje krok w rodzaju:
Table.TransformColumnTypes(
#"Poprzedni krok",
{{"Kwota", type number}},
"en-US"
)
Dzięki temu kropka zostanie odczytana jako separator dziesiętny, mimo że kultura systemu jest polska. Dalsze operacje (sumy, średnie) będą wykonywane już na poprawnych liczbach.
Scenariusz 2: Plik CSV z przecinkiem dziesiętnym i kropką tysiąca
Drugi często spotykany wariant: „1.234,56” w kolumnie „KwotaBrutto”. Środowisko pracy – polski Windows, ale plik pochodzi z niemieckiego ERP.
Scenariusz 3: Wielojęzyczne raporty – mieszanka kropek, przecinków i spacji
W raportach łączących dane z kilku krajów w jednej tabeli często spotykają się równolegle formaty „1234.56”, „1 234,56” oraz „1.234,56”. Jedna kolumna, trzy style zapisu. Interfejs Power Query widzi to jako tekst i nie jest w stanie samodzielnie dobrać jednej kultury.
Co wiemy? Wszystkie ciągi mają część całkowitą i potencjalnie część dziesiętną, ale separatory pełnią różne role. Czego nie wiemy? Który znak w danym wierszu jest separatorem dziesiętnym, a który tylko grupuje tysiące.
Typowy kompromis to wstępne „znormalizowanie” tekstu do jednego standardu, np. wariantu technicznego z kropką dziesiętną i bez separatora tysięcy, a dopiero potem konwersja do liczby:
= Table.AddColumn(
#"Poprzedni krok",
"KwotaUnified",
each let
src = [KwotaTekst],
hasComma = Text.Contains(src, ","),
hasDot = Text.Contains(src, "."),
hasSpace = Text.Contains(src, " "),
// 1. usunięcie spacji tysiąca
noSpace = Text.Replace(src, " ", ""),
// 2. rozstrzygnięcie, co jest separatorem dziesiętnym
normalized =
if hasComma and hasDot then
// traktuj kropki jako tysiące, przecinek jako dziesiętny
Text.Replace(noSpace, ".", "")
else if hasComma and not hasDot then
// przecinek jako dziesiętny → zamieniamy na kropkę
Text.Replace(noSpace, ",", ".")
else
// tylko kropka lub tylko cyfry
noSpace
in
Number.FromText(normalized, "en-US"),
type number
)
Ten schemat zakłada prostą logikę: jeśli w jednej wartości występuje i kropka, i przecinek, to kropka pełni rolę tysiąca. W realnych projektach bywa konieczne dodanie dodatkowych warunków (np. długość części po separatorze, minimalna liczba cyfr przed separatorem), ale baza pozostaje podobna – standaryzacja tekstu przed przekazaniem go do Number.FromText.
Scenariusz 4: Eksport z Excela zapisany „nie tą kulturą”
Gdy użytkownik otwiera w Excelu plik CSV z innego regionu i zapisuje go ponownie, bywa, że dane tekstowe zostają „przefiltrowane” przez kulturę Excela. W efekcie w pliku pojawiają się wartości typu „1234,56” w kolumnie, która w systemie źródłowym miała kropkę dziesiętną, a separator kolumn pozostaje niezmieniony.
W Power Query taki plik często wygląda jak klasyczny przypadek lokalny, ale jeden szczegół zdradza problem: liczby, które pierwotnie miały więcej miejsc po przecinku, bywają zaokrąglone już na etapie Excela. Power Query nie ma jak tego przywrócić, może jedynie poprawnie zinterpretować to, co zostało.
Najbezpieczniejsza procedura przy takich plikach:
- Jeżeli to możliwe – w pierwszej kolejności dotrzeć do oryginalnego eksportu (np. surowy CSV z systemu źródłowego) i pracować na nim bez pośredniego zapisu w Excelu.
- Jeżeli nie – potraktować dane jak lokalne, ale zachować ostrożność przy porównywaniu z systemem źródłowym (różnice na czwartej–piątej cyfrze po przecinku mogą pochodzić z wcześniejszego zaokrąglenia).
- Przy imporcie do Power Query usunąć automatyczny Changed Type i jawnie użyć kultury zgodnej z aktualnym zapisem (zwykle
pl-PLlubde-DE).
Tutaj Power Query nie naprawi zniekształceń wprowadzonych przez inne narzędzie. Może jedynie utrzymać spójność separatorów i typów liczbowych w dalszym procesie.
Scenariusz 5: Dane z formularzy i ankiet online
W ankietach wprowadzanych ręcznie przez użytkowników systemu globalnego pojawia się pełen przekrój formatów: „10.5”, „10,5”, „10,50”, „10.500” (jako dziesięć tysięcy pięćset) oraz „10 500”. Trudno narzucić jedną kulturę w momencie wprowadzania danych, dlatego ciężar normalizacji ląduje w Power Query.
Jednym ze sposobów jest wprowadzenie prostego „detektora” formatu na poziomie wiersza oraz próby konwersji według kilku strategii:
= Table.AddColumn(
#"Poprzedni krok",
"Wartosc",
each let
txt = Text.Trim([OdpowiedzTekst]),
// 1. próba interpretacji jak pl-PL
vPL = try Number.FromText(txt, "pl-PL"),
// 2. próba interpretacji jak en-US
vUS = try Number.FromText(txt, "en-US")
in
if vPL[HasError] and vUS[HasError] then
null
else if not vPL[HasError] and vUS[HasError] then
vPL[Value]
else if vPL[HasError] and not vUS[HasError] then
vUS[Value]
else
// obie interpretacje możliwe – wybór według dodatkowej logiki
vPL[Value],
type nullable number
)
To rozwiązanie nie jest idealne – przy wartościach całkowitych bez separatorów obie kultury zwrócą poprawną liczbę i trudno jednoznacznie rozstrzygnąć, która jest „prawdziwa”. Dla wielu formularzy i pytań (np. oceny w skali 1–10) to jednak akceptowalne – głównym celem jest przejście z mieszanego tekstu do spójnej liczby.
Zaawansowane techniki kontroli separatorów
Własna funkcja M do standaryzacji liczb
Przy powtarzalnych schematach importu często przydaje się własna funkcja, którą można stosować w wielu zapytaniach. Zamiast kopiować blok let ... in w kolejnych krokach, lepiej zdefiniować jedną, dobrze przetestowaną funkcję „fxNormalizeNumber”.
let
fxNormalizeNumber = (txt as nullable text) as nullable number =>
let
src = if txt = null then null else Text.Trim(txt),
res =
if src = null or src = "" then
null
else
let
hasComma = Text.Contains(src, ","),
hasDot = Text.Contains(src, "."),
hasSpace = Text.Contains(src, " "),
noSpace = Text.Replace(src, " ", ""),
// przykład: logika podobna jak w scenariuszu mieszanym
normalized =
if hasComma and hasDot then
Text.Replace(noSpace, ".", "")
else if hasComma and not hasDot then
Text.Replace(noSpace, ",", ".")
else
noSpace,
n = try Number.FromText(normalized, "en-US")
in
if n[HasError] then null else n[Value]
in
res
in
fxNormalizeNumber
Po zapisaniu funkcji w jednym zapytaniu można używać jej w innych tabelach:
= Table.AddColumn(
#"Poprzedni krok",
"Kwota",
each fxNormalizeNumber([KwotaTekst]),
type nullable number
)
Największa zaleta takiego podejścia to jedno miejsce, w którym aktualizuje się logikę. Gdy pojawi się nowy wariant zapisu liczb (np. „1’234,56” z apostrofem jako separatorem tysiąca), wystarczy dopisać go do funkcji.
Diagnostyka błędów i kolumny pomocnicze
Przy skomplikowanych zestawach danych praktyczne jest rozdzielenie etapu „czyszczenia” i „konwersji”. Zamiast od razu konwertować tekst na liczbę, można najpierw dodać kolumnę z oczyszczonym tekstem i dopiero później rzutować ją na typ liczbowy. Ułatwia to diagnozowanie, których wartości nie da się przekształcić.
Jedna z prostszych metod:
- Kolumna „SurowyTekst” – oryginalne dane z importu.
- Kolumna „TekstOczyszczony” – np.
Text.Selectlub własna logika normalizacji separatorów. - Kolumna „Liczba” –
Number.FromTextz kulturą lub bez.
W dalszym kroku można dodać kolumnę logiczną z informacją, czy konwersja się powiodła:
= Table.AddColumn(
#"Poprzedni krok",
"KonwersjaOK",
each try Number.FromText([TekstOczyszczony], "pl-PL") is number,
type logical
)
Takie oznaczenie ułatwia filtrowanie przypadków spornych i ich ręczną analizę – szczególnie gdy dane pochodzą z wielu źródeł i trudno przewidzieć wszystkie kombinacje separatorów.
Monitorowanie kultury na poziomie całego zapytania
Power Query pozwala nadawać kulturę nie tylko w pojedynczych funkcjach, ale też w niektórych operacjach tabelowych. Przy większych modelach przydaje się spójność: ta sama kultura tekstu-liczby, co w kroku importu i w kroku końcowym przed załadowaniem do modelu.
W praktyce warto unikać mieszania konstrukcji:
Number.FromText([Kolumna])bez kultury,Table.TransformColumnTypes(..., "pl-PL")z kulturą,- oraz ręcznych kroków z
Text.Replacepod założenia innej kultury.
Jeżeli kultura jest jawnie wskazana w Table.TransformColumnTypes, dobrze trzymać się jej we wszystkich konwersjach w tym zapytaniu. W przeciwnym razie ryzyko rozbieżności rośnie niezauważalnie – część kolumn będzie powstawać na bazie ustawień systemowych, część według odrębnych parametrów.
Synchronizacja separatorów między Power Query, modelem i raportem
Różne etapy, różne „kultury wyświetlania”
Power Query odpowiada za interpretację tekstu jako liczby. Sposób wyświetlania (kropka/przecinek, format walutowy, liczba miejsc po przecinku) zależy później od modelu danych i ustawień raportu w Power BI lub Excela. To dwa osobne tematy, które łatwo ze sobą pomylić.
Typowy przypadek nieporozumienia:
- w Power Query kolumna jest poprawnie liczbowa (sprawdzona funkcją
Value.Islub podglądem błędów), - w raporcie liczby wyświetlają się z „innym” separatorem niż oczekiwano (np. kropka zamiast przecinka),
- wina przypisywana jest krokom w Power Query, choć problem dotyczy już warstwy formatowania.
W takiej sytuacji pierwszym krokiem jest weryfikacja, czy Power Query rzeczywiście dostarcza liczby, a nie tekst. Dopiero potem sens mają zmiany w ustawieniach regionalnych raportu lub formatach pól miar i kolumn.
Kiedy lepiej zostawić tekst i nie konwertować na liczbę
Zdarzają się przypadki, w których liczba wyglądająca na zwykłą wartość finansową nie powinna być konwertowana na typ liczbowy. Przykłady z praktyki:
- kody identyfikacyjne zawierające wiodące zera, zapisane jako „001,234” w jednym systemie i „001.234” w innym,
- specjalne formaty ratingów, w których przecinek oznacza kategorię, a nie część dziesiętną.
Jeżeli kolumna ma pełnić wyłącznie funkcję identyfikatora lub etykiety, wymuszanie na niej typu liczbowego i zabawa separatorami może prowadzić do utraty istotnej części informacji (np. długości kodu, postaci oryginalnej). W takich sytuacjach bardziej uzasadnione jest pozostawienie typu tekstowego i ewentualne przygotowanie osobnej kolumny liczbowej do obliczeń.
Kontrola jakości: porównanie sum z systemem źródłowym
Najprostszą metodą weryfikacji, czy separatory dziesiętne zostały poprawnie zinterpretowane, jest porównanie zagregowanych wartości z systemem źródłowym. Zamiast sprawdzać każdy wiersz, można porównać sumę całej kolumny lub sumy po wybranych kluczach (np. po kliencie, dziale).
Minimalny pakiet kontroli wygląda tak:
- W Power Query lub w raporcie obliczyć sumę kluczowej kolumny (np. przychodów) po pełnym procesie oczyszczania separatorów.
- W systemie źródłowym (ERP, system fakturowy) wygenerować analogiczny raport, najlepiej w tym samym zakresie dat i filtrach.
- Porównać wynik z dokładnością do najmniejszej jednostki (np. grosza, centa). Różnice równe wielokrotności 10, 100, 1000 często wskazują na błąd interpretacji separatorów (np. „100,50” jako „10050”).
Takie porównanie ma charakter czysto kontrolny, ale w praktyce szybko ujawnia, gdzie proces czyszczenia separatorów wymaga korekty lub dodatkowego scenariusza.
Najważniejsze wnioski
- Problemy z separatorami dziesiętnymi wynikają z konfliktu standardów zapisu liczb (pl vs en-US): ten sam zapis, np. „1.234”, może oznaczać zupełnie inną wartość w zależności od kultury.
- Bez zgodności między formatem pliku źródłowego a ustawieniami regionalnymi Power Query liczby są często wczytywane jako tekst lub z błędną wartością, przez co raport „wygląda dobrze”, ale liczy źle.
- Na interpretację liczb wpływa kilka nakładających się warstw regionu: Windows, Excel/Power BI, ustawiona w M kultura (culture) oraz ewentualne ustawienia źródła danych – co prowadzi do różnych wyników na różnych komputerach.
- Typowe objawy błędnej interpretacji separatora to: kolumny liczbowe jako Tekst, sortowanie alfabetyczne zamiast numerycznego, brak agregacji, pojawiające się null/błędy po zmianie typu oraz mylne odczytanie wartości (np. 1.234 → 1234).
- Kluczowe pytanie kontrolne brzmi: czy problem leży w danych źródłowych, czy w sposobie, w jaki Power Query je czyta w danej kulturze; dopiero po odpowiedzi można bezpiecznie stosować kolejne transformacje.
- Automatyczne rozpoznawanie typów danych w Power Query bywa mylące: gdy w pierwszych wierszach nie ma separatora dziesiętnego, system ustawia Whole Number, a późniejsze wartości z przecinkiem/kropką mogą zostać obcięte lub zniekształcone.
- Świadome sterowanie kulturą (culture) w funkcjach M przy konwersji tekst → liczba jest konieczne, aby te same dane zachowywały się identycznie w różnych środowiskach i zespołach międzynarodowych.






