diklabu-Webuntis.psm1
<# .Synopsis Anmelden an Webuntis .DESCRIPTION Anmelden an Webuntis .EXAMPLE login-Untis -url https://borys.webuntis.com/WebUntis/jsonrpc.do?school=MMBbS%20Hannover -credential (Get-Credential Tuttas) #> function Login-Untis { [CmdletBinding()] Param ( # URL des Webuntis Systems [Parameter(Position=0)] [String]$url, # Credentials f. das Moodle Systems [Parameter(Position=1)] [PSCredential]$credential ) Begin { if (-not $url -or -not $credential) { if ($global:logins.webuntis) { $url=$Global:logins.webuntis.location; $password = $Global:logins.webuntis.password | ConvertTo-SecureString -Key $global:keys $credential = New-Object System.Management.Automation.PsCredential($Global:logins.webuntis.user,$password) } else { Write-Error "Bitte url und credentials angeben!" return; } } $base=$url $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=Get-Random $data.method="authenticate" $data.jsonrpc="2.0" $params = "" | Select-Object -Property "user","password","client" $params.client="ps" $params.user=$credential.UserName; $params.password=$credential.GetNetworkCredential().Password $data.params=$params $headers=@{} $headers["content-Type"]="application/json" #$data | ConvertTo-Json $r=Invoke-RestMethod -Method POST -Uri $url -Body (ConvertTo-Json $data) -Headers $headers -SessionVariable session $global:session = $session if ($r.error) { Write-Verbose "Login fehlgeschlagen" Write-Error $r.error.message; } else { Write-Verbose "Login erfolgreich" $global:webuntis=$base $global:untistoken=$r.result.sessionId $r } Set-Keystore -key "webuntis" -server $base -credential $credential } } <# .Synopsis Abfrage der Räume .DESCRIPTION Abfrage der Räume .EXAMPLE Get-UntisRooms Abfrage der Räume #> function Get-UntisRooms { [CmdletBinding()] Param ( ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=$Global:untistoken $data.method="getRooms" $params = @{} $data.params=$params $data.jsonrpc="2.0" #ConvertTo-Json $data $headers=@{} $headers["content-Type"]="application/json" $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session #$r if ($r.error) { Write-Error $r.error.message } else { $r.result } } } <# .Synopsis Abfrage der Klassen .DESCRIPTION Abfrage der Klassen .EXAMPLE Get-UntisCoures Abfrage der Klassen #> function Get-UntisCourses { [CmdletBinding()] Param ( ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=$Global:untistoken $data.method="getKlassen" $params = @{} $data.params=$params $data.jsonrpc="2.0" #ConvertTo-Json $data $headers=@{} $headers["content-Type"]="application/json" $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session #$r if ($r.error) { Write-Error $r.error.message } else { $r.result } } } <# .Synopsis Abfrage der Lehrer .DESCRIPTION Abfrage der Lehrer .EXAMPLE Get-UntisTeachers Abfrage der Lehrer #> function Get-UntisTeachers { [CmdletBinding()] Param ( ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } $headers=@{} $headers["content-Type"]="application/json" $url=$Global:logins.webuntis.location.Substring(0,$Global:logins.webuntis.location.LastIndexOf("/")) $url=$url+"/api/public/timetable/weekly/pageconfig?type=2"; #Write-Host $url $r=Invoke-RestMethod -Method GET -Uri $url -Headers $headers -websession $global:session #$r if ($r.error) { Write-Error $r.error.message } else { $r.data.elements } } } <# .Synopsis Abfrage der Schüler .DESCRIPTION Abfrage der Schüler .EXAMPLE Get-UntisStudents Abfrage der Schüler #> function Get-UntisStudents { [CmdletBinding()] Param ( ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=$Global:untistoken $data.method="getStudents" $params = @{} $data.params=$params $data.jsonrpc="2.0" #ConvertTo-Json $data $headers=@{} $headers["content-Type"]="application/json" $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session #$r if ($r.error) { Write-Error $r.error.message } else { $r.result } } } <# .Synopsis Abfrage der Fächer .DESCRIPTION Abfrage der Fächer .EXAMPLE Get-UntisSubjects Abfrage der Fächer #> function Get-UntisSubjects { [CmdletBinding()] Param ( ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=$Global:untistoken $data.method="getSubjects" $params = @{} $data.params=$params $data.jsonrpc="2.0" #ConvertTo-Json $data $headers=@{} $headers["content-Type"]="application/json" $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session #$r if ($r.error) { Write-Error $r.error.message } else { $r.result } } } <# .Synopsis Abfrage der Abteilungen .DESCRIPTION Abfrage der Abteilungen .EXAMPLE Get-UntisDepartments Abfrage der Abteilungen #> function Get-UntisDepartments { [CmdletBinding()] Param ( ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=$Global:untistoken $data.method="getDepartments" $params = @{} $data.params=$params $data.jsonrpc="2.0" #ConvertTo-Json $data $headers=@{} $headers["content-Type"]="application/json" $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data) -Headers $headers -websession $global:session #$r if ($r.error) { Write-Error $r.error.message } else { $r.result } } } <# .Synopsis Abfrage der Belegung einzelnet Elemente .DESCRIPTION Abfrage der Belegung einzelnet Elemente (1 = class, 2 = teacher, 3 = subject, 4 = room, 5 = student) .EXAMPLE Get-UntisTimetable -elementType room -id 424 Abfrage der Belegung des Raumes mit der ID 424 für den heutigen Tag .EXAMPLE Get-UntisTimetable -elementtype student -id 151 -startDate 20171101 -endDate 20171201 Abfrage des Stundenplans des Schülers mit der id 151 für den gewählten Zeitbereich .EXAMPLE 151,152 | Get-UntisTimetable -elementtype student -startDate 20171101 -endDate 20171201 Abfrage des Stundenplans der Schülers mit den id's 151 und 152 für den gewählten Zeitbereich #> function Get-UntisTimetable { [CmdletBinding()] Param ( # Elementtype [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateSet('class','teacher','subject','room','student')] [String]$elementtype, # ID [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, Position=1)] [int]$id , # Start Datum YYYYMMDD (wenn nicht gesetzt, dann wird das aktuelle Datum genommen) [String]$startDate, # Ende Datum YYYYMMDD (wenn nicht gesetzt, dann wird das aktuelle Datum genommen) [String]$endDate ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } } Process { $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=$Global:untistoken $data.method="getTimetable" $params = "" | Select-Object -Property "options" $options = "" | Select-Object -Property "element","showBooking","showInfo","showSubsText","showLsText","showLsNumber","showStudentgroup","klasseFields","roomFields","subjectFields","teacherFields" #$options = "" | Select-Object -Property "element","showBooking","showInfo","showSubsText","showLsText","showLsNumber","showStudentgroup" $element = "" | Select-Object -Property "id","type" if ($startDate) { $options | Add-Member -MemberType NoteProperty -Name "startDate" -Value $startDate $options | Add-Member -MemberType NoteProperty -Name "endDate" -Value $startDate } if ($endDate) { $options | Add-Member -MemberType NoteProperty -Name "endDate" -Value $endDate -force } $element.id=$id if ($elementtype -eq "class") { $element.type="1" } if ($elementtype -eq "teacher") { $element.type="2" } if ($elementtype -eq "subject") { $element.type="3" } if ($elementtype -eq "room") { $element.type="4" } if ($elementtype -eq "student") { $element.type="5" } $options.element=$element; $options.showBooking=$true $options.showInfo=$true $options.showSubsText=$true $options.showLsText=$true $options.showLsNumber=$true $options.showStudentgroup=$true $itemArray = @("id", "name", "longname", "externalkey") #$itemArray $options.klasseFields=$itemArray $options.roomFields=$itemArray $options.subjectFields=$itemArray $options.teacherFields=$itemArray $params.options=$options $data.params=$params $data.jsonrpc="2.0" #ConvertTo-Json $data -Depth 3 $headers=@{} $headers["content-Type"]="application/json" $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body (ConvertTo-Json $data -Depth 3) -Headers $headers -websession $global:session #$r if ($r.error) { Write-Error $r.error.message } else { $r.result } } } <# .Synopsis Suchen eines Schülers oder Lehrers .DESCRIPTION Suchen eines Schülers oder Lehrers .EXAMPLE tisPerson -elementType stunden -sn Tuttas -fn Jörg Sucht die ID des Schülers Jörg Tuttas #> function Find-UntisPerson { [CmdletBinding()] Param ( # Elementtype [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateSet('teacher','student')] [String]$elementtype, # Surname [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=1)] [String]$sn , # Forename [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=2)] [String]$fn, # Geburtstag [Parameter(ValueFromPipelineByPropertyName=$true, Position=3)] [int]$dob=0 ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } } Process { $data=echo "" | Select-Object -Property "id","method","jsonrpc","params" $data.id=$Global:untistoken $data.method="getPersonId" $params = "" | Select-Object -Property "type","sn","fn","dob" if ($elementtype -eq "teacher") { $params.type="2" } if ($elementtype -eq "student") { $params.type="5" } $params.sn= $sn $params.fn= $fn $params.dob=$dob $data.params=$params $data.jsonrpc="2.0" #ConvertTo-Json $data -Depth 3 $headers=@{} $headers["content-Type"]="application/json;charset=UTF-8" $body = ConvertTo-Json $data -Depth 3 $r=Invoke-RestMethod -Method POST -Uri $($Global:logins.webuntis.location) -Body $body -Headers $headers -websession $global:session -ContentType "application/json;charset=UTF-8" #$r if ($r.error) { Write-Error $r.error.message } else { $r.result } } } <# .Synopsis Mitglieder einer Klasse anzeigen .DESCRIPTION Mitglieder einer Klasse anzeigen .EXAMPLE Get-UntisCoursemember -id 171 -startDate "2018-10-22" -type class Sucht Schüler der Klasse mit der ID 171 am 22.10.2018 .EXAMPLE Get-UntisCoursemember -id 125 -startDate "2018-10-25" -type subject Sucht Schüler des Kurses mit der ID 171 am 25.10.2018 .EXAMPLE Get-UntisCoursemember -id 125 -startDate "2018-10-25","2018-10-18","2018-11-08" -type subject Sucht Schüler des Kurses mit der ID 171 am 25.10.2018 (Do. block rot), 18.10.2018 (Do. block gelb) und 8.11.2018 (Do. block blau) .EXAMPLE Get-UntisCourses | Where-Object {$_ -match "FIAE18"} | Get-UntisCoursemember -startDate "2018-10-22","2018-10-15","2018-11-05" -type class Listet alle Schüler des Jahrgangs FIAE18 auf .EXAMPLE Get-UntisSubjects | Where-Object {$_.name -match "-TU"} | Get-UntisCoursemember -startDate "2018-10-25","2018-10-18","2018-11-08" -type subject Listet alle Schüler aus dem WPK-TU auf #> function Get-UntisCoursemember { [CmdletBinding()] Param ( # ID [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [int]$id, # Date [Parameter(Mandatory=$true, Position=1)] [String[]]$startDate, # Type [Parameter(Mandatory=$true, Position=2)] [ValidateSet('class','subject')] [String]$type ) Begin { if (-not $global:untistoken) { Write-Error "Sie sind nicht an WebUntis angemeldet, veruchen Sie es mit Login-Untis" return } } Process { #ConvertTo-Json $data -Depth 3 Write-Verbose "---- Process ID($id) type($type) ----" $startDate | ForEach-Object { $dateNumber=[int]$_.replace("-","") Write-Verbose "Date = $_" $headers=@{} $headers["content-Type"]="application/json" $url=$Global:logins.webuntis.location.Substring(0,$Global:logins.webuntis.location.LastIndexOf("/")) if ($type -eq "class") { $reg1=$url+"/api/public/timetable/weekly/data?elementType=1&elementId=$id&date=$_&formatId=3" } if ($type -eq "subject") { $reg1=$url+"/api/public/timetable/weekly/data?elementType=3&elementId=$id&date=$_&formatId=3" } #$reg1 try { $r=Invoke-WebRequest -Uri $reg1 -websession $global:session } catch { Login-Untis $r=Invoke-WebRequest -Uri $reg1 -websession $global:session } Write-Verbose "Status Code is $($r.StatusCode)" $obj=ConvertFrom-Json $r.content if ($obj.isSessionTimeout -eq $true) { Write-Error "Session timed out, please login again" break; } $array = $obj.data.result.data.elementPeriods."$id" $matchingLessons=@{} foreach ($entry in $array) { Write-Verbose "Date is $($entry.date) Studen-Group $($entry.studenGroup)" if ($entry.date -eq $dateNumber -and $entry.studentGroup) { if ($type -eq "subject") { $matchingLessons[$($entry.studentGroup)]=$entry } if ($type -eq "class") { if (-not $entry.studentGroup -and -not $entry.hasPeriodText) { $matchingLessons["$id"]=$entry break; } else { if ($entry.hasPeriodText) { Write-Warning "Klasse mit ID $id am $_ mit Kommentar $($entry.periodText)" } Write-Verbose "Found Stundent Group $($entry.studentGroup) -> skipped!"; } } } } if ($matchingLessons.Count -eq 0) { Write-Warning "No matching lesson found!" } else { foreach ($lesson in $matchingLessons.GetEnumerator()) { $lessonID=$lesson.Value.lessonId; $periodID=$lesson.Value.id Write-Verbose "Found LessonID $lessonID and PeriodID $periodID" $url=$Global:logins.webuntis.location.Substring(0,$Global:logins.webuntis.location.LastIndexOf("/")) $url=$url+"/lessonstudentlist.do?lsid="+$lessonID+"&periodId="+$periodID; #$url $r=Invoke-WebRequest $url -websession $global:session if ($r.error) { Write-Error $r.error.message } else { ## Extract the tables out of the web request $tables = @($r.ParsedHtml.getElementById("lessonStudentListForm.assignedStudents")) if ($tables) { $table = $tables[0] $titles = @() $rows = @($table.Rows) $titles += "studentGroup" ## Go through all of the rows in the table foreach($row in $rows) { $cells = @($row.Cells) ## If we've found a table header, remember its titles if($cells[0].tagName -eq "TH") { $titles = @($cells | % { ("" + $_.InnerText).Trim() }) continue } ## If we haven't found any table headers, make up names "P1", "P2", etc. if(-not $titles) { $titles = @(1..($cells.Count + 2) | % { "P$_" }) } ## Now go through the cells in the the row. For each, try to find the ## title that represents that column and create a hashtable mapping those ## titles to content $resultObject = [Ordered] @{} for($counter = 0; $counter -lt $cells.Count; $counter++) { $title = $titles[$counter] if(-not $title) { continue } $resultObject[$title] = ("" + $cells[$counter].InnerText).Trim() $resultObject["stundentGroup"]=$lesson.Name } ## And finally cast that hashtable to a PSCustomObject [PSCustomObject] $resultObject } } } } } } } } ### get-sjNds ### ##### JoKe 2025-01-11 ################################################### <# .Synopsis Gibt Anfangsdatum und Endedatum des im Parameter übergebenen Schuljahres im Format "yyyyMMdd" zurück .DESCRIPTION Gibt Anfangsdatum und Endedatum des im Parameter übergebenen Schuljahres im Format "yyyyMMdd" zurück Parameter ist irgendein Datum innerhalb des gesuchten Schuljahres, Parameter hat ebenfalls das Format "yyyyMMdd" Falls kein Parameter angegeben wurde, wird das aktuelle Tagesdatum benutzt Basisdaten stammen vom 21.8.2023 von https://www.schulferien.org/deutschland/ferien/niedersachsen/ .EXAMPLE get-sjNds .EXAMPLE get-sjNds "20250407" #> function get-sjNds { Param( [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] [String]$sj = (get-date -Format "yyyyMMdd") # Format "yyyyMMdd" ) Begin{ # start and end school day of the term $sjs = @{ SJ2324 = @{ startdate="20230817" enddate="20240621" } SJ2425 = @{ startdate="20240805" enddate="20250702" } SJ2526 = @{ startdate="20250814" enddate="20260701" } SJ2627 = @{ startdate="20260813" enddate="20270707" } SJ2728 = @{ startdate="20270819" enddate="20280719" } } # end of schoolterm list } Process{ $start ="00000000" $end = "00000000" foreach ($entry in $sjs.GetEnumerator()){ if ($sj -in $entry.value['startdate']..$entry.value['enddate']){ $start = $entry.value['startdate'] $end = $entry.value['enddate'] } } $dates=@{} $dates.startdate=$start $dates.enddate=$end return $dates } } ### add-untisDay ### ##### JoKe 2025-01-11 ###################################################### <# .Synopsis Addiert einen Tag zum Datum im Übergabeformat yyyyMMdd .DESCRIPTION Addiert einen Tag zum Datum im Übergabeformat yyyyMMdd Beispielsweise wird aus "20233112" --> "20240101" .EXAMPLE add-untisDay "20233112" #> function add-untisDay { Param ( [Parameter(Mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$true)] [String]$datestring # Date in diklabu datestring format yyyyMMdd ) $d=[DateTime]::ParseExact($datestring,"yyyyMMdd",$Null) $d=$d.AddDays(1) return $d.tostring("yyyyMMdd") } # end function add-untisDay ####################################### ende add-untisDay ############################################## ##### get-untisClassTeacherTeams ##### ##### JoKe 2025-01-11 ################################################################################## <# .Synopsis Baut eine Hashliste mit der Zuordnung Klasse zu Lehrkräfteteam .DESCRIPTION Baut eine Hashliste mit der Zuordnung Klasse zu Lehrkräfteteam mit Daten aus dem aktuellen Webuntis Key: Klassenname, Value: Komma separierte Liste mit Lehrkräftekürzeln, z.B. FISI24D: "KE,LE,WE" Wenn $checkHashlistClassesTeachers $true gesetzt wird (default ist $false), wird nach einer vorher abgespeicherten Version der Hashliste geschaut und, falls diese vorhanden UND TAGESAKTUELL ist, diese verwendet anstelle der Webuntisdaten. Dieses Verfahren bietet Geschwindigkeitsvorteile gegenüber der Abfrage in Webuntis, nutzt aber evtl. nicht die aktuellen Daten .EXAMPLE get-untisClassTeacherTeams .EXAMPLE get-untisClassTeacherTeams $true #> function get-untisClassTeacherTeams{ Param( [Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)] [Boolean]$checkHashlistClassesTeachers = $false, # $true: use stored CSV-file if available and from today [Parameter(Mandatory=$true)] [string]$WUlocationClassTeachers, [Parameter(Mandatory=$true)] [string]$WUclassesTeachersDelimiter, [Parameter(Mandatory=$true)] [System.Management.Automation.PSCredential]$WUcreds ) Begin{ $funcName = $MyInvocation.InvocationName # wer bin ich? } Process { if ($checkHashlistClassesTeachers -and (Test-Path ($WUlocationClassTeachers)) -and ((Get-Item ($WUlocationClassTeachers)).LastWriteTime.Date -eq (Get-Date).Date)) { # Hashlist classes-teachers must be used and they are already created and from today $hashClassesTeachers = @{} $f=Import-Csv $WUlocationClassTeachers foreach ($row in $f){$hashClassesTeachers[$row.name]=$row.value} } else{ # No check if lists are stored or CSV-file not found --> Login Untis $feedbacklogin=login-untis -url https://borys.webuntis.com/WebUntis/jsonrpc.do?school=MMBbS%20Hannover -credential $WUcreds write-verbose $feedbacklogin.toString() # damit keine Logininformationen im Klartext in der Konsole erscheinen # Alle Lehrkräfte aus dem aktuellen Stundenplan ermitteln $alleLuL = Get-UntisTeachers # Speicher für Timetable schulweit und über ein Jahr $classesTeachersRaw=@() foreach ($LoL in $alleLuL){ # Ask Untis to start today $year = (get-date).year $monthString = ((get-date).Month).tostring() if ([int]$monthString -lt 8) {$year-=1} # second half of the school term $dateString = $year.toString() + "1231" # we need a valid date within the school term $startEndTerm=get-sjNds -sj $dateString write-host "$funcName : --$($LoL.name)-- hole Stundenplaneinträge von Webuntis ..." $classesTeacherRaw=(Get-UntisTimetable -elementtype teacher -id $LoL.id -startDate $startEndTerm.startDate -endDate $startEndTerm.enddate) $classesTeachersRaw+=$classesTeacherRaw Start-Sleep -Milliseconds 100 } # Ende foreach ($LoL in $alleLuL) # sort and bind teachers to classes Write-Host "$funcName : Sortiere und lösche Duplikate in Hashtabelle Klassen/ Lehrkräfte..." $classesTeachers =@{} foreach ($entry in $classesTeachersRaw){ foreach ($class in $entry.kl){ # Klasse schon eingetragen? if ($classesTeachers.($class.name) -ne $null){ # class already exists foreach ($teacher in $entry.te){ # multiple teachers possible (teamteaching) # Lehrkräfte in Array speichern, weil in einer Liste mit Trennzeichen sich # Suchprobleme ergeben (NO ist in KNO enthalten z.B.) $listContainsTeacher = $false $arrayClassTeachers = @() $arrayClassTeachers = ($classesTeachers.($class.name)).split(",") foreach ($elementOfClassTeachers in $arrayClassTeachers){ if ($elementOfClassTeachers -eq $teacher.name){ $listContainsTeacher = $true } } if (!$listContainsTeacher){ # teacher not yet associated $classesTeachers.($class.name) += $teacher.name } } } else { # class not in list right now --> create and fill in 1st teacher $classesTeachers.($class.name)=[Array]$entry.te.name } } } Write-Host "$funcName : Alles sortiert und Duplikate entfernt!" Write-Host "$funcName : Baue die Hashtabelle mit Klassen (keys) und Komma separierte Liste mit Lehrkräftekürzeln ..." # das oben für die Suche nach bereits eingetragenen Lehrkräften angelegte Array für die Lehrkraftkürzel # (Grund z.B.: NO ist Element von KNO und wird dann nicht gefunden) wieder auflösen und als Liste mit # Trennzeichen erstellen $hashClassesTeachers= @{} foreach ($key in $classesTeachers.Keys){ $hashClassesTeachers[$key] = @($classesTeachers[$key] | where-object {$_ -like '*'}) -join $WUclassesTeachersDelimiter } $hashClassesTeachers.GetEnumerator()| export-csv -noTypeInformation -path $WUlocationClassTeachers -encoding UTF8 } # end else write-host "$funcName : Hashtabelle mit Klassen und Lehrkräften fertig erstellt!" return $hashClassesTeachers } # end Process } # end function get-untisClassTeacherTeams |