Daten mit Umlauten in Power Query wie in Excel sortieren
#1
Hallo zusammen,

das Bundesinnenministerium gibt eine PDF heraus, gibt es hier oder im Anhang.
Pauschbeträge für Verpflegungsmehraufwendungen  und  Übernachtungskosten im Ausland

Diese Daten importiere ich mit Power Query und transformiere die Länderbezeichnungen etwas um, die Bezeichnung "Im Übrigen" ist recht dämlich. 

Wenn man mit einer Formel die Sätze für ein Land abfragt, dann müsste es der Logik zufolge für jedes Land ein "Im Übrigen" geben, das gibt es aber nicht. Und wenn man das nach Land/Region sortiert, dann landet "Im Übrigen" bei manchen irgendwo dazwischen.

Also habe ich "Im Übrigen"entfernt und der Standardsatz für ein Land sollte immer an erster Stelle stehen. Und an der Stelle kommt das Problem.

Ich kann wunderbar in Power Query nach Land und Region sortieren und bekomme die Reihenfolge die ich brauche... bis auf Ägypten, Äquatorialguinea, Äthiopien, Österreich, die landen am Ende der Liste. 

.xlsx   2025-12-05-steuerliche-behandlung-reisekosten-2026.xlsx (Größe: 37,63 KB / Downloads: 6)

Wenn ich nun in Excel die Spalte Land AZ sortiere, dann werden diese Länder zwischen die anderen einsortiert... 

DIN 5007, Teil 1 (Standard: Umlaute wie Grundvokale) 
  • Ä, Ö, Ü werden wie A, O, U behandelt.
  • Beispiel: Müller, Müllerin, Müllerisch, Münster.
  • Sind Wörter bis auf den Umlaut identisch, steht der Grundvokal vor dem Umlaut.
    • Beispiel: Gabler vor Gäbler. 

Hat jemand eine function für Power Query um diese Sortierung schnell und einfach direkt zu bekommen?

Andreas.


Angehängte Dateien
.pdf   2025-12-05-steuerliche-behandlung-reisekosten-2026.pdf (Größe: 681,16 KB / Downloads: 11)
Antworten Top
#2
Excel sortiert wohl nach kulturellen Gewichtungen. PQ nicht.


Angehängte Dateien
.xlsx   Sort_PQ.xlsx (Größe: 38,45 KB / Downloads: 5)
Antworten Top
#3
Hallo Andreas,

das kann man via Hilfsspalte machen. 
Code:
let
    Quelle = Pdf.Tables(
        File.Contents("C:\...\2025-12-05-steuerliche-behandlung-reisekosten-2026.pdf"),
        [Implementation="1.3"]
    ),
    TabellenZeilen = Table.SelectRows(Quelle, each [Kind] = "Table"),
    TabellenListe = List.Transform(
        TabellenZeilen[Data],
        each Table.PromoteHeaders(_, [PromoteAllScalars=true])
    ),
    Vereinigt = Table.Combine(TabellenListe),
    Gefiltert = Table.SelectRows(Vereinigt, each Record.FieldCount(_) > 0),
    Umbenannt = Table.TransformColumnNames(Gefiltert, each Text.Trim(_)),
    #"Zusammengeführte Spalten" =
        Table.CombineColumns(
            Umbenannt,
            {"Column1", "Column2"},
            Combiner.CombineTextByDelimiter("", QuoteStyle.None),
            "Zusammengeführt"
        ),
    #"GefiltertOhneLand" =
        Table.SelectRows(
            #"Zusammengeführte Spalten",
            each not Text.Contains([Zusammengeführt], "Land")
        ),
    #"Gefilterte Zeilen" =
        Table.SelectRows(
            #"GefiltertOhneLand",
            each not Text.Contains([#"Pauschbeträge für#(lf)Verpflegungsmehr-aufwendungen"], "€")
        ),

    // Hilfsspalte für DIN 5007 (Wörterbuchsortierung)
    DIN5007 =
        Table.AddColumn(
            #"Gefilterte Zeilen",
            "SortKey",
            each Text.Replace(
                    Text.Replace(
                        Text.Replace([Zusammengeführt], "Ä", "A{"),
                    "Ö", "O{"),
                "Ü", "U{"
            ),
            type text
        ),

    // Sortieren nach DIN 5007 über SortKey
    Sortiert =
        Table.Sort(
            DIN5007,
            {{"SortKey", Order.Ascending}}
        ),
    Ergebnis = Table.RemoveColumns(Sortiert, {"SortKey"})
in
    Ergebnis

Gruß Uwe
Antworten Top
#4
Moin Andreas,

...und die Region "im Übrigen" durch nichts, null oder ein "z" (bzw. ein "A" oder "Allgemein", denn es soll ja an 1. Stelle stehen) zu ersetzen wäre keine Option? Dann kannst Du auch ggf. die letzten 3 Schritte der Abfrage weglassen, denn die Quelle ist ja bereits entsprechend sortiert.
Der sicherste Ansatz für einen Irrtum ist der Glaube, alles im Griff zu haben.
Nur, weil ich den Recorder bedienen kann, macht mich das noch lange nicht zum Musiker.

Ciao, Ralf

Antworten Top
#5
(06.02.2026, 12:01)Ralf A schrieb: weshalb willst Du denn sortieren? Die Quelle ist doch bereits nach Ländern und Regionen sortiert. Wenn Du die letzten 3 Schritte der Abfrage weglässt, hast Du doch das gewünschte Ergebnis. Oder hab ich hier was übersehen?

Ja, das Problem ist das "Im Übrigen" weg soll und dann muss diese Zeile nach oben (1te Zeile in diesem Land).

Nun ja, im übrigen habe ich mich wohl didaktisch falsch ausgedrückt, Entschuldigung dafür an alle. Ich suche nicht (nur) eine Sonderlösung für diesen einen speziellen Fall, es sollte auch schon das nächste Mal und am besten allgemein für alle Arten von Daten funktionieren.

Das einfache Ersetzen von Ä,Ö,Ü zu A,O,U ist da leider viel zu einfach, und auch für diesen Sonderfall falsch.

Quelle:
https://de.wikipedia.org/wiki/Alphabetische_Sortierung

[Schnipp]
Das deutsche Alphabet ergänzt das moderne lateinische Alphabet um die Umlaute Ä, Ö und Ü sowie den Buchstaben ß. Diese zusätzlichen Buchstaben können auf vier Arten einsortiert werden:
  1. Ignorieren der Umlautpunkte. Müll wird wie Mull sortiert.
  2. Auflösung des Umlauts. Müll wird wie Muell vor Muffe einsortiert.
  3. Gleichordnung von Grundbuchstaben, Doppelbuchstaben und Umlaut, wenn Doppelbuchstabe wie Umlaut gesprochen wird. Müll wird wie Muell oder Mull sortiert. Duell dagegen zwischen Duden und Dugast.
  4. Separierung als selbstständiger Buchstabe.
    1. Einordnung hinter dem Grundbuchstaben. Müll steht zwischen Muzin und Münze. Später folgt Myalgie.
    2. Einordnung am Ende des Alphabets. Müll steht hinter Mythos.
Für alle sonstigen (fremdsprachigen) diakritischen Zeichen gilt im deutschsprachigen Raum, dass sie einheitlich weggelassen werden; so auch alle Akzente, Tilde, Makron: é und e, ç und c, ñ und n, č und c, ō und o sind gleich.
[Schnapp]

Das Mega-Problem wird deutlich im letzten Satz, es gibt wirklich viele diakritische Zeichen. Und es gibt auch Länder die diese Zeichen haben:
Côte d’Ivoire
São Tomé – Príncipe

Nach vielen Stunden der Suche und Unterhaltung mit ChatGPT bin ich letztendlich fündig geworden:
https://www.dingbatdata.com/2018/06/07/m...comparers/

Da hat sich "Camwallace" wirklich Gedanken gemacht und es funktioniert ganz hervorragend.

Ich sortiere ganz normal wie üblich
= Table.Sort(#"Replaced LF",{{"Land", Order.Ascending}, {"Region", Order.Ascending}})
und dann wandel ich den Code einfach ab und rufe seine function auf
= TableComparerSort(#"Replaced LF",{{"Land", Order.Ascending, Comparer.FromCulture("de-DE", false)}, {"Region", Order.Ascending}})

Das war's. Da muss man schon sagen: Hut ab, perfekte Lösung, oder?

Andreas.
Antworten Top
#6
Hallo Andreas,

ich bin jetzt nicht so der PQ-Fachmann, aber wenn ich das in der Doku richtig interpretiere, sollte jede Sort-Methode einen Parameter "comparisonCriteria" akzeptieren. Dieser Parameter akzeptiert auch eine Funktion, z.B. "Comparer.FromCulture("de-DE")", womit Umlaute eigentlich korrekt einsortiert werden sollten.

Code:
// Sortieren einer Liste mit deutscher Kultur
List.Sort({"ä", "a", "b"}, Comparer.FromCulture("de-DE"))

Das Beispiel sollte auch für Table.Sort gelten. Vielleicht kannst du das ja mal eruieren?

Gruß Knobbi38

PS:
hier ein paar weitere Beispiele:
https://blog.crossjoin.co.uk/2017/01/22/...-argument/
Antworten Top
#7
...wow... wusste bisher nicht einmal, dass es möglich ist, syllabisch zu sortieren...  16
Komplexeres Thema als gedacht...

@Knobbi38,

Listensortierung bringt hier nicht viel. Ein Liste kann zwar durchaus auch eine Liste von Tabellen sein, aber in diesem Fall soll ja nur eine (oder auch 2) Spalte(n) einer Tabelle sortiert werden. Dann hab ich die zwar sortiert, sie stehen dann aber nicht mehr in Bezug zu den anderen Spalten. Deshalb muss die gesamte Tabelle entsprechend der Spaltensortierung auf die Sortierung reagieren.

Den von Dir angesprochenen Comparer bietet Table.Sort leider nicht an.
Der sicherste Ansatz für einen Irrtum ist der Glaube, alles im Griff zu haben.
Nur, weil ich den Recorder bedienen kann, macht mich das noch lange nicht zum Musiker.

Ciao, Ralf

Antworten Top
#8
hier entnommen: https://learn.microsoft.com/en-us/powerq...table-sort

Dort wird auch erwähnt, dass man eine Tabelle nach einer Spalte sortieren könnte:
Zitat:Sorts the table using the list of one or more column names and optional comparisonCriteria
in the form { { col1, comparisonCriteria }, {col2} }.

Wenn man der Doku glauben darf, ich habe es allerdings noch nie verwendet.

vielleich so:
Code:
Table.Sort(Source, {{"Column1", (x, y) => Comparer.FromCulture("de-DE")(x, y)}})

Knobbi38
Antworten Top
#9
ah, also ganz anders als wie ursprünglich beschrieben.

Gruß Uwe
Antworten Top
#10
Mit der Referenz ding... hat mir Copilot folgenden Code erstellt, der auch das gewünschte Ergebnis bringt.

Code:
let
    Pfad             = fnParameter("Parameter","Pfad"),
    Datei            = fnParameter("Parameter","Datei"),
    Source           = Pdf.Tables(File.Contents(Pfad&Datei)),
    Filter_Tables    = Table.SelectRows(Source, each ([Kind] = "Table")),
    Keep_Data        = Table.SelectColumns(Filter_Tables,{"Data"}),
    Expand_Data      = Table.ExpandTableColumn(Keep_Data, "Data", {"Column1", "Column2", "Column3", "Column4", "Column5"},
                                                                  {"Column1", "Column2", "Column3", "Column4", "Column5"}),
    #"Filter_Col1/2" = Table.SelectRows(Expand_Data, each ([Column1] <> null) or ([Column2] <> null)),
    Filter_LandHdr   = Table.SelectRows(#"Filter_Col1/2", each ([Column2] <> "Land")),
    Col_Land         = Table.AddColumn(Filter_LandHdr, "Land", each if [Column1] = "–" then null else if [Column1] = null then [Column2] else [Column1]),
    Col_Region       = Table.AddColumn(Col_Land, "Region", each if [Land]=null and [Column2] <> "im Übrigen" then [Column2] else null),
    FillDown_Land    = Table.FillDown(Col_Region,{"Land"}),
    Rename_Cols      = Table.RenameColumns(FillDown_Land,{{"Column3", "24h"}, {"Column4", "8h"}, {"Column5", "Übernachtungskosten"}}),
    KeepNeeded_Cols  = Table.SelectColumns(Rename_Cols,{"Land", "Region", "24h", "8h", "Übernachtungskosten"}),
    Filter_valid     = Table.SelectRows(KeepNeeded_Cols, each ([Übernachtungskosten] <> "")),
    #"Replaced LF"   = Table.ReplaceValue(Filter_valid,"#(lf)"," ",Replacer.ReplaceText,{"Land", "Region"}),
    //                 Index für stabile Sortierung
    MitIndex         = Table.AddIndexColumn(#"Replaced LF", "Index", 0, 1),
    //                 Sortierung mit Comparer.FromCulture – ACHTUNG: 2. Argument ist eine FUNKTION, keine Liste
    Sorted           = Table.Sort(MitIndex, (x as record, y as record) as number =>
                       let
                        // 1. Vergleich nach Land
                        c1 = Comparer.FromCulture("de-DE", true)(x[Land], y[Land]),

                        // 2. Wenn Land gleich, dann Region sortieren
                        c2 =
                         if c1 <> 0 then
                            c1
                         else
                            // Leere Region zuerst
                            if x[Region] = "" and y[Region] <> "" then -1
                            else if x[Region] <> "" and y[Region] = "" then 1
                            else Comparer.FromCulture("de-DE", true)(x[Region], y[Region])
                       in
                         c2
                        ),
    //                 Index wieder entfernen
    Ergebnis         = Table.RemoveColumns(Sorted, {"Index"})
in
    Ergebnis
Antworten Top


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 2 Gast/Gäste