Commit pending finance and Power BI work
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
let
|
||||
// ===== REXX #757 LADEN =====
|
||||
Src757 = Excel.Workbook(File.Contents("C:\temp\Saldiperstichdatum.xlsx"), null, true),
|
||||
Data757 = Src757{0}[Data],
|
||||
Head757 = Table.PromoteHeaders(Data757, [PromoteAllScalars = true]),
|
||||
|
||||
Ren757 = Table.RenameColumns(Head757, {
|
||||
{"Personalnummer", "Personalnummer"},
|
||||
{"Kürzel", "Kuerzel"},
|
||||
{"Nachname, Vorname (Link Personal)", "Name_Rexx"},
|
||||
{"Stelle", "Stelle_Rexx"},
|
||||
{"Organisation", "Organisation_Text"},
|
||||
{"Kostenstelle", "Kostenstelle_Rexx"},
|
||||
{"Leitung j/n", "Leitung"},
|
||||
{"Eintrittsdatum", "Eintrittsdatum_Raw"},
|
||||
{"Personal Status", "Personal_Status"},
|
||||
{"Anstellungsverhältnis", "Anstellungsverhaeltnis"},
|
||||
{"Stunden Saldo", "Stunden_Saldo_Raw"},
|
||||
{"Urlaubsanspruch", "Urlaubsanspruch_Raw"},
|
||||
{"Urlaub Rest", "Urlaub_Rest_Raw"},
|
||||
{"Ferien ausstehend (Tage)", "Ferien_Ausstehend_Raw"},
|
||||
{"Lohnart", "Lohnart"},
|
||||
{"Lohn", "Lohn_Raw"},
|
||||
{"Lohn Währung", "Lohn_Waehrung"}
|
||||
}),
|
||||
|
||||
TypePernr = Table.TransformColumnTypes(Ren757, {{"Personalnummer", Int64.Type}}),
|
||||
|
||||
AddKey = Table.AddColumn(TypePernr, "PERNR_Key", each Text.From([Personalnummer]), type text),
|
||||
|
||||
// Name_Voll früh erzeugen für Name-Join mit #732
|
||||
AddNameVollEarly = Table.AddColumn(AddKey, "Name_Voll", each
|
||||
Text.From(if [Name_Rexx] = null then "" else [Name_Rexx]), type text),
|
||||
|
||||
// ===== REXX #732 LADEN (Geburtsdatum + AZ-Modell) =====
|
||||
// Hat keine Personalnummer → Join über Name
|
||||
Tbl732 = try
|
||||
let
|
||||
S = Excel.Workbook(File.Contents("C:\temp\Exportkommengehen.xlsx"), null, true),
|
||||
D = S{0}[Data],
|
||||
H = Table.PromoteHeaders(D, [PromoteAllScalars = true]),
|
||||
Sel = Table.SelectColumns(H, {
|
||||
"Nachname, Vorname (Link Personal)",
|
||||
"Geburtsdatum",
|
||||
"Arbeitszeitmodell",
|
||||
"Ø tägliche Sollarbeitszeit (Woche)"
|
||||
}, MissingField.UseNull),
|
||||
Ren = Table.RenameColumns(Sel, {
|
||||
{"Nachname, Vorname (Link Personal)", "Name_732"},
|
||||
{"Geburtsdatum", "Geburtsdatum_Raw"},
|
||||
{"Arbeitszeitmodell", "Arbeitszeitmodell"},
|
||||
{"Ø tägliche Sollarbeitszeit (Woche)", "Avg_Sollzeit_Tag_Raw"}
|
||||
})
|
||||
in Ren
|
||||
otherwise null,
|
||||
|
||||
// Merge #757 + #732 ueber Name
|
||||
Merged732 = if Tbl732 <> null then
|
||||
let
|
||||
M = Table.NestedJoin(AddNameVollEarly, {"Name_Voll"}, Tbl732, {"Name_732"}, "R732", JoinKind.LeftOuter),
|
||||
E = Table.ExpandTableColumn(M, "R732", {"Geburtsdatum_Raw", "Arbeitszeitmodell", "Avg_Sollzeit_Tag_Raw"})
|
||||
in E
|
||||
else
|
||||
let
|
||||
A1 = Table.AddColumn(AddNameVollEarly, "Geburtsdatum_Raw", each null),
|
||||
A2 = Table.AddColumn(A1, "Arbeitszeitmodell", each null, type text),
|
||||
A3 = Table.AddColumn(A2, "Avg_Sollzeit_Tag_Raw", each null)
|
||||
in A3,
|
||||
|
||||
// ===== SAP LADEN (HR_KPI_Export.xlsx) =====
|
||||
TblSAP = try
|
||||
let
|
||||
S = Excel.Workbook(File.Contents("C:\temp\HR_KPI_Export.xlsx"), null, true),
|
||||
D = S{0}[Data],
|
||||
H = Table.PromoteHeaders(D, [PromoteAllScalars = true]),
|
||||
Sel = Table.SelectColumns(H, {
|
||||
"Personalnummer", "Buchungskreis", "Personalbereich", "Personalteilbereich",
|
||||
"Mitarbeitergruppe", "Mitarbeiterkreis", "Teilzeitkraft",
|
||||
"Beschäftigungsgrad %", "Geschlecht", "Planstelle", "Stellenschlüssel",
|
||||
"Nichtberufsunfall Tage", "Berufsunfall Tage",
|
||||
"Abrechnungskreis"
|
||||
}, MissingField.UseNull),
|
||||
Ren = Table.RenameColumns(Sel, {
|
||||
{"Personalnummer", "PERNR_SAP"},
|
||||
{"Teilzeitkraft", "Teilzeitkennzeichen"},
|
||||
{"Beschäftigungsgrad %", "Beschaeftigungsgrad_Prozent"},
|
||||
{"Stellenschlüssel", "Soll_Stelle"},
|
||||
{"Nichtberufsunfall Tage", "NBU_Tage"},
|
||||
{"Berufsunfall Tage", "BU_Tage"}
|
||||
}, MissingField.Ignore),
|
||||
// PERNR-Key normalisiert (entfernt fuehrende Nullen)
|
||||
AddK = Table.AddColumn(Ren, "PERNR_SAP_Key", each
|
||||
try Text.From(Number.FromText(Text.Trim(Text.From([PERNR_SAP])))) otherwise null,
|
||||
type text)
|
||||
in AddK
|
||||
otherwise null,
|
||||
|
||||
// Merge + SAP
|
||||
MergedSAP = if TblSAP <> null then
|
||||
let
|
||||
M = Table.NestedJoin(Merged732, {"PERNR_Key"}, TblSAP, {"PERNR_SAP_Key"}, "SAP", JoinKind.LeftOuter),
|
||||
E = Table.ExpandTableColumn(M, "SAP", {
|
||||
"Buchungskreis", "Personalbereich", "Personalteilbereich",
|
||||
"Mitarbeitergruppe", "Mitarbeiterkreis", "Teilzeitkennzeichen",
|
||||
"Beschaeftigungsgrad_Prozent", "Geschlecht", "Planstelle", "Soll_Stelle",
|
||||
"NBU_Tage", "BU_Tage",
|
||||
"Abrechnungskreis"
|
||||
})
|
||||
in E
|
||||
else
|
||||
let
|
||||
A1 = Table.AddColumn(Merged732, "Buchungskreis", each null),
|
||||
A2 = Table.AddColumn(A1, "Personalbereich", each null),
|
||||
A3 = Table.AddColumn(A2, "Personalteilbereich", each null),
|
||||
A4 = Table.AddColumn(A3, "Mitarbeitergruppe", each null),
|
||||
A5 = Table.AddColumn(A4, "Mitarbeiterkreis", each null),
|
||||
A6 = Table.AddColumn(A5, "Teilzeitkennzeichen", each null, type text),
|
||||
A7 = Table.AddColumn(A6, "Beschaeftigungsgrad_Prozent", each null),
|
||||
A8 = Table.AddColumn(A7, "Geschlecht", each null),
|
||||
A9 = Table.AddColumn(A8, "Planstelle", each null),
|
||||
A10 = Table.AddColumn(A9, "Soll_Stelle", each null, type text),
|
||||
A11 = Table.AddColumn(A10, "NBU_Tage", each null),
|
||||
A12 = Table.AddColumn(A11, "BU_Tage", each null),
|
||||
A13 = Table.AddColumn(A12, "Abrechnungskreis", each null, type text)
|
||||
in A13,
|
||||
|
||||
// ===== BERECHNETE SPALTEN =====
|
||||
|
||||
// Eintrittsdatum
|
||||
AddEintritt = Table.AddColumn(MergedSAP, "Eintrittsdatum", each
|
||||
let raw = [Eintrittsdatum_Raw] in
|
||||
if raw = null then null
|
||||
else if raw is date then raw
|
||||
else if raw is datetime then Date.From(raw)
|
||||
else try Date.FromText(Text.From(raw), [Format = "dd.MM.yyyy"]) otherwise null,
|
||||
type date),
|
||||
|
||||
// Geburtsdatum
|
||||
AddGebdat = Table.AddColumn(AddEintritt, "Geburtsdatum", each
|
||||
let raw = [Geburtsdatum_Raw] in
|
||||
if raw = null then null
|
||||
else if raw is date then raw
|
||||
else if raw is datetime then Date.From(raw)
|
||||
else try Date.FromText(Text.From(raw), [Format = "dd.MM.yyyy"]) otherwise null,
|
||||
type date),
|
||||
|
||||
// Numerische Konvertierungen
|
||||
AddNum = Table.TransformColumnTypes(AddGebdat, {
|
||||
{"Urlaubsanspruch_Raw", type number},
|
||||
{"Urlaub_Rest_Raw", type number},
|
||||
{"Ferien_Ausstehend_Raw", type number},
|
||||
{"Lohn_Raw", type number},
|
||||
{"Avg_Sollzeit_Tag_Raw", type number},
|
||||
{"Beschaeftigungsgrad_Prozent", type number},
|
||||
{"Geschlecht", Int64.Type},
|
||||
{"NBU_Tage", type number},
|
||||
{"BU_Tage", type number}
|
||||
}),
|
||||
|
||||
RenNum = Table.RenameColumns(AddNum, {
|
||||
{"Urlaubsanspruch_Raw", "Urlaubsanspruch"},
|
||||
{"Urlaub_Rest_Raw", "Urlaub_Rest"},
|
||||
{"Ferien_Ausstehend_Raw", "Ferien_Ausstehend"},
|
||||
{"Lohn_Raw", "Bruttolohn"},
|
||||
{"Avg_Sollzeit_Tag_Raw", "Avg_Sollzeit_Tag"}
|
||||
}),
|
||||
|
||||
// Abrechnungskreis als Text sicherstellen (fuehrende Null bleibt erhalten)
|
||||
TypAbkrs = Table.TransformColumnTypes(RenNum, {{"Abrechnungskreis", type text}}),
|
||||
|
||||
// Name splitten
|
||||
AddNachname = Table.AddColumn(TypAbkrs, "Nachname", each
|
||||
let n = Text.From(if [Name_Rexx] = null then "" else [Name_Rexx]) in
|
||||
Text.Trim(Text.Split(n, ","){0}), type text),
|
||||
AddVorname = Table.AddColumn(AddNachname, "Vorname", each
|
||||
let n = Text.From(if [Name_Rexx] = null then "" else [Name_Rexx]),
|
||||
p = Text.Split(n, ",") in
|
||||
if List.Count(p) > 1 then Text.Trim(p{1}) else "", type text),
|
||||
|
||||
// Stunden_Saldo parsen: "58:10" → 58.17, "-6:12" → -6.20
|
||||
AddSaldo = Table.AddColumn(AddVorname, "Stunden_Saldo", each
|
||||
let
|
||||
raw = Text.Trim(Text.From(if [Stunden_Saldo_Raw] = null then "0:00" else [Stunden_Saldo_Raw])),
|
||||
isNeg = Text.StartsWith(raw, "-"),
|
||||
cleaned = Text.Replace(raw, "-", ""),
|
||||
parts = Text.Split(cleaned, ":"),
|
||||
h = try Number.FromText(parts{0}) otherwise 0,
|
||||
m = if List.Count(parts) > 1 then (try Number.FromText(parts{1}) otherwise 0) else 0,
|
||||
dec = h + m / 60
|
||||
in if isNeg then -dec else dec,
|
||||
type number),
|
||||
|
||||
// FTE
|
||||
AddFTE = Table.AddColumn(AddSaldo, "FTE", each
|
||||
if [Beschaeftigungsgrad_Prozent] <> null and [Beschaeftigungsgrad_Prozent] > 0
|
||||
then [Beschaeftigungsgrad_Prozent] / 100
|
||||
else if [Arbeitszeitmodell] = "Vollzeit" then 1 else 0.5,
|
||||
type number),
|
||||
|
||||
// Alter
|
||||
AddAlter = Table.AddColumn(AddFTE, "Alter_Jahre", each
|
||||
if [Geburtsdatum] = null then null
|
||||
else Number.RoundDown(Duration.TotalDays(Date.From(DateTime.LocalNow()) - [Geburtsdatum]) / 365.25),
|
||||
Int64.Type),
|
||||
|
||||
// Altersgruppe
|
||||
AddAG = Table.AddColumn(AddAlter, "Altersgruppe", each
|
||||
if [Alter_Jahre] = null then "Unbekannt"
|
||||
else if [Alter_Jahre] < 30 then "< 30"
|
||||
else if [Alter_Jahre] < 40 then "30-39"
|
||||
else if [Alter_Jahre] < 50 then "40-49"
|
||||
else if [Alter_Jahre] < 60 then "50-59"
|
||||
else "60+", type text),
|
||||
|
||||
// Geschlecht Text
|
||||
AddGT = Table.AddColumn(AddAG, "Geschlecht_Text", each
|
||||
if [Geschlecht] = 1 then "Maennlich"
|
||||
else if [Geschlecht] = 2 then "Weiblich"
|
||||
else "Unbekannt", type text),
|
||||
|
||||
// Ist Teilzeit
|
||||
AddTZ = Table.AddColumn(AddGT, "Ist_Teilzeit", each
|
||||
if [Beschaeftigungsgrad_Prozent] <> null and [Beschaeftigungsgrad_Prozent] > 0
|
||||
then [Beschaeftigungsgrad_Prozent] < 100
|
||||
else if [Arbeitszeitmodell] <> null then [Arbeitszeitmodell] = "Teilzeit"
|
||||
else false, type logical),
|
||||
|
||||
// Dienstjahre
|
||||
AddDJ = Table.AddColumn(AddTZ, "Dienstjahre", each
|
||||
if [Eintrittsdatum] = null then null
|
||||
else Number.RoundDown(Duration.TotalDays(Date.From(DateTime.LocalNow()) - [Eintrittsdatum]) / 365.25),
|
||||
Int64.Type),
|
||||
|
||||
// Ist Aktiv
|
||||
AddAktiv = Table.AddColumn(AddDJ, "Ist_Aktiv", each [Personal_Status] = "Aktiv", type logical),
|
||||
|
||||
// Periode
|
||||
AddPeriode = Table.AddColumn(AddAktiv, "Periode", each Date.StartOfMonth(Date.From(DateTime.LocalNow())), type date),
|
||||
AddJahr = Table.AddColumn(AddPeriode, "Jahr", each Date.Year([Periode]), Int64.Type),
|
||||
AddMonat = Table.AddColumn(AddJahr, "Monat", each Date.Month([Periode]), Int64.Type),
|
||||
AddPT = Table.AddColumn(AddMonat, "Periode_Text", each
|
||||
Text.From([Jahr]) & "-" & Text.PadStart(Text.From([Monat]), 2, "0"), type text),
|
||||
|
||||
// Sollarbeitstage
|
||||
AddSAT = Table.AddColumn(AddPT, "Sollarbeitstage", each 21, Int64.Type),
|
||||
|
||||
// Ferien bezogen
|
||||
AddFB = Table.AddColumn(AddSAT, "Ferien_Bezogen", each
|
||||
let a = if [Urlaubsanspruch] = null then 0 else [Urlaubsanspruch],
|
||||
r = if [Urlaub_Rest] = null then 0 else [Urlaub_Rest],
|
||||
au = if [Ferien_Ausstehend] = null then 0 else [Ferien_Ausstehend]
|
||||
in a - r - au, type number),
|
||||
AddFT = Table.AddColumn(AddFB, "Ferientage", each
|
||||
let fb = [Ferien_Bezogen] in if fb = null or fb < 0 then 0 else fb, type number),
|
||||
|
||||
// GLZ Ampel
|
||||
AddGLZ = Table.AddColumn(AddFT, "GLZ_Ampel", each
|
||||
let abs = Number.Abs([Stunden_Saldo]) in
|
||||
if abs <= 50 then "Gruen" else if abs <= 100 then "Gelb" else "Rot", type text),
|
||||
AddGLZS = Table.AddColumn(AddGLZ, "GLZ_Ampel_Sort", each
|
||||
if [GLZ_Ampel] = "Gruen" then 1 else if [GLZ_Ampel] = "Gelb" then 2 else 3, Int64.Type),
|
||||
|
||||
// Restferien Ampel
|
||||
AddRA = Table.AddColumn(AddGLZS, "Restferien_Ampel", each
|
||||
if [Urlaub_Rest] = null or [Urlaub_Rest] <= 5 then "Gruen" else "Rot", type text),
|
||||
|
||||
// Mitarbeitertyp
|
||||
AddMT = Table.AddColumn(AddRA, "Mitarbeitertyp", each
|
||||
let s = Text.Lower(Text.From(if [Stelle_Rexx] = null then "" else [Stelle_Rexx])) in
|
||||
if Text.Contains(s, "praktik") then "Praktikant"
|
||||
else if Text.Contains(s, "werkstudent") then "Werkstudent"
|
||||
else if Text.Contains(s, "aushilfe") then "Aushilfe"
|
||||
else if Text.Contains(s, "lehrling") then "Lehrling"
|
||||
else "Festangestellt", type text),
|
||||
|
||||
// Kostenstelle
|
||||
AddKNr = Table.AddColumn(AddMT, "Kostenstelle", each
|
||||
let raw = Text.From(if [Kostenstelle_Rexx] = null then "" else [Kostenstelle_Rexx]),
|
||||
parts = Text.Split(raw, "/"),
|
||||
num = Text.Trim(parts{0})
|
||||
in try Number.FromText(num) otherwise null, Int64.Type),
|
||||
AddKTxt = Table.AddColumn(AddKNr, "Kostenstelle_Text", each
|
||||
if [Kostenstelle_Rexx] = null then "" else Text.From([Kostenstelle_Rexx]), type text),
|
||||
|
||||
// Organisation + Stelle Klartext
|
||||
AddOrg = Table.AddColumn(AddKTxt, "Organisationseinheit", each
|
||||
if [Organisation_Text] = null then "" else Text.From([Organisation_Text]), type text),
|
||||
AddSt = Table.AddColumn(AddOrg, "Stelle", each
|
||||
if [Stelle_Rexx] = null then "" else Text.From([Stelle_Rexx]), type text),
|
||||
|
||||
// Nur aktive MA
|
||||
FilterAktiv = Table.SelectRows(AddSt, each [Personal_Status] = "Aktiv"),
|
||||
|
||||
// Hilfsspalten entfernen
|
||||
Clean = Table.RemoveColumns(FilterAktiv, {
|
||||
"Name_Rexx", "Stelle_Rexx", "Organisation_Text",
|
||||
"Kostenstelle_Rexx", "Eintrittsdatum_Raw", "Geburtsdatum_Raw",
|
||||
"Stunden_Saldo_Raw", "Personal_Status", "PERNR_Key"
|
||||
}),
|
||||
|
||||
// Sortieren
|
||||
Sorted = Table.Sort(Clean, {{"Personalnummer", Order.Ascending}})
|
||||
in
|
||||
Sorted
|
||||
Reference in New Issue
Block a user