====== Datenaustausch Magellan-Untis ====== Grober Ablauf: - Magellan-Backup erstellen - Untis-Backup erstellen - Magellan: Schüler exportieren - mit Python Export in Untis-Import umwandeln - doppelte UntisID-Schüler eindeutig machen und neue IDs in doppelteSchueler-Kopie speichern - Untis: Schülerdaten importieren - Untis: Schülerfachdaten exportieren - im Python-Code die Daten für das aktuelle Halbjahr anpassen - mit Python Export in Magellan-Import umwandeln - Magellan: mit leerer Fachtafel alle Schülerfachdaten löschen - Magellan-Administrator: Schülerfachdaten importieren - Magellan: mit Sammellöschungen überflüssige Fächer entfernen - Magellan: Positionen der Fächer für Zeugnisdruck mit den Fachtafeln hinzufügen ===== Magellan2Untis ===== Insbesondere für Noteneingabe und Stundenplan ist es notwendig, dass etliche Daten zwischen Schulverwaltungsprogramm (zur Zeit Magellan 6) und Stundenplanprogramm (zur Zeit Untis 2017) synchronisiert werden. Da das, jedenfalls hat es sich mir nicht anders erschlossen, weder in der einen noch in der anderen Richtung funktioniert, habe ich selbst Konvertierungsprogramme geschrieben. Hier findet sich der Teil, der Daten von Magellan nach Untis portiert. - **Magellan** -> Extras -> Export -> Units... -> SDTF-Datei -> M2U-01-MagellanSchuelerExport.txt auswählen und überschreiben -> Übernehme Schüler aller Klassen -> Alle Schüler -> Starten - **M2U-02-MagellanSchuelerExport2UntisSchuelerImport.py** starten - **Untis** -> Datei -> Import/Export -> Import TXT Datei -> Studenten -> Semikolon, nicht UTF-8 -> M2U-03-UntisSchuelerImport.txt Es ist nirgends festgelegt, dass Leistungskurse mit Groß- und Grundkurse mit Kleinbuchstaben benannt werden müssen. Daher exportiert Magellan alles in Großbuchstaben und schreibt dabei, ob es sich um einen Leistungs- oder Grundkurs handelt. Untis wiederum ist es völlig wurscht, was Leistungs- und was Grundkurse sind. Sie dauern halt unterschiedlich lang, alles andere ist für den Stundenplan irrelevant. Daher kann Untis nicht wissen, was es beim Import eines Leistungskurses anders machen soll, als bei einem Grundkurs. Daher ist ein Programm von Nöten, dass aus dem Export von Magellan eine spezielle DIF-Datei für Untis bastelt, mit deren Untis die Daten so importieren kann, wie gewünscht. Problematisch dabei ist, dass man in Untis ungern die ID aus Magellan als Kürzel für den Schüler hätte. Also benötigt man eine eineindeutige Definition für ein Schülerkürzel. Ich nutze folgende Festlegung: 3 Buchstaben des Nachnamen 5 Buchstaben des Vornamen 2 letzte Ziffern des Geburtsjahrgangs ... da fehlt noch was, da es noch nicht eindeutig ist. ==== Was mache ich, wenn nach dem Aufruf von M2U-02-MagellanSchuelerExport2UntisSchuelerImport.py die Datei doppelteSchueler.txt nicht leer ist? ==== Dann muss man sich UntisIDs ausdenken, die eindeutig sind. Ich hätte von vornherein die MagellanID als UntisID nutzen können, aber die ist wenig alltagstauglich. Ich bin mehr dafür, bei der Portierung der Daten gerade die wenigen Schüler, auf die das zutrifft, per Hand anzupassen. Beispiel: Bei mir ist EutClaud71 doppelt. "EutClaud71";"Euteneuer";;;;;"M";"Claudius";;"12";"1";;"19711014";"claudiusateuteneuerspunktde"; "EutClaud71";"Euteneuer";;;;;"W";"Claudia";;"12";"1";;"19711014";"claudiaateuteneuerspunktde"; Zufällig ausgewählt erhält der erste EutClaud71 nun EuetClaud71 (oder EutClaud71a, oder...) als UntisID. Das sollte man sich aufschreiben. Z.B. in die ''M2U-04-doppelteSchueler - Kopie.txt'', damit man später nachlesen kann und bei der nächsten Portierung den Schüler nicht doppelt erstellt. ===== Untis2Magellan ===== Insbesondere für Noteneingabe und Stundenplan ist es notwendig, dass etliche Daten zwischen Schulverwaltungsprogramm (zur Zeit Magellan 6) und Stundenplanprogramm (zur Zeit Untis 2017) synchronisiert werden. Da das, jedenfalls hat es sich mir nicht anders erschlossen, weder in der einen noch in der anderen Richtung funktioniert, habe ich selbst Konvertierungsprogramme geschrieben. Als Fehler habe ich zum Beispiel erhalten, dass der Unterschied zwischen Leisuntgs- und Grundkurs nicht vermittelt wird. Könnte daran liegen, dass wir die Unterschied mit Hilfe von Groß- und Kleinschreibung festlegen. Aber das sollte möglich sein. Hier findet sich der Teil, der Daten von Untis nach Magellan portiert. - **Untis** -> Datei -> Import/Export -> Deutschland -> **Schuldatentransferformat -> Exportieren** -> Durchsuchen (richtigen Pfad überprüfen!!!) -> U2M-04-UntisSchuelerfachdatenExport.txt auswählen und überschreiben - Im folgenden Programm stehen Anfangs- und Enddatum des aktuellen Schulhalbjahrs fest drin. Die müssen angepasst werden. - **U2M-05-SDTF2Schuelerfachdaten.py** starten (übersetzt soeben erstellte Datei **U2M-06-MagellanSchuelerfachdatenImport.csv**) * Schüler ohne Geburtsdatum? (Nach ".." suchen) *AG Namen im Stundenplan länger als 10 Zeichen? - einmalig: Magellan -> Verzeichnisse -> Fachtafeln -> neue Fachtafel 'leer' erstellen - ohne Fächer - **Magellan** -> Schüler -> Zeugnis -> Fächer -> **leere Fachtafel zuweisen** -> alle Schüler markieren -> 'leer' zuweisen - **Magellan-Administrator** -> Datenimporte -> Magellan-Importformat -> weiter -> **importiere aus Datei -> U2M-06-MagellanSchuelerfachdatenImport.csv** auswählen -> 4. Schüler-Fachdaten (Zeitraumbezogen) -> Mandant wählen -> Fertigstellen -> Fehlermeldungen nach Excel exportieren - **Magellan** * Sammellöschungen: Magellan -> Schüler -> einen auswählen -> Zeugnis -> Fächer -> Sammellöschung * alle mit et ODER rk: ER löschen * alle mit et ODER ev: KR löschen * alle mit ev ODER rk: ET löschen * alle männlichen: SPM löschen * alle weiblichen: SPJ löschen * alle nicht russisch (R, R1, RA): R löschen * Französisch? * Latein? - **Magellan**: Positionen der Fächer für den Zeugnisdruck mit Hilfe der Fachtafeln zuweisen. Zur Zeit muss man den 4. Haken anklicken, damit nicht die Fächer, sondern nur die Positionen angepasst werden. ===== Sourcecodes ===== ==== M2U-02-MagellanSchuelerExport2UntisSchuelerImport.py ==== ## ## Autor: Claudius Euteneuer ## Version: 2017-01-12 ## Copyrights: alle bei mir ## Bedienung: umständlich - mann muss wissen, was das Programm braucht ## Anleitung: mehr als dürftig ## Fragen: immer gerne an mich -> claudiuseuteneuersde ## ## Voraussetzung: ## ## ## ## Ziel: Eine Datei namens 01-MagellanSchuelerExport.txt wird genutzt, ## um eine Datei 03-UntisSchuelerImport.txt zu erstellen, mit deren ## Hilfe man in Untis alle Schüler einlesen kann. ## ## Anleitung: ## ## # Konstanten (erst einmal...) iDateiname = "M2U-01-MagellanSchuelerExport.txt" oDateiname = "M2U-03-UntisSchuelerImport.txt" dsDateiname = "M2U-04-doppelteSchueler.txt" zeitraumVon = "01.08.2016" zeitraumBis = "31.01.2017" halbjahr = "1" # globale Variablen schueler = {""} ## HAUPTPROGRAMM # Eingabedatei auf einmal einlesen alleZeilen = open(iDateiname).readlines() # Ausgabedateien öffnen fOutput = open(oDateiname,"w") fDoppelteSchueler = open(dsDateiname,"w") # Schüler einlesen und die Zeilen bestimmen ausgabe = [] schuelerfachwahlen = [] i = -1 for zeile in alleZeilen: # Anführungszeichen entfernen zeile=zeile.replace('"','') elemente=zeile.split(';') if (elemente[0]=="P1"): i+=1 magellanID = elemente[1] klasse = elemente[2] nachname = elemente[3] vorname = elemente[4] geschlechtNr = elemente[5] if (geschlechtNr=="1"): geschlechtText = "M" geschlechtNr="2" else: geschlechtText = "W" geschlechtNr="1" #geburtsdatum = elemente[6][-2:]+"."+elemente[6][4:6]+"."+elemente[6][:4] geburtsdatum = elemente[6] untisID = nachname[:3]+vorname[:5]+geburtsdatum[2:4] # +"-"+magellanID email = elemente[7] ausgabe.append('"'+untisID+'";"'+nachname+'";;;;;"'+geschlechtText+'";"'+vorname+'";;"'+klasse+'";"'+geschlechtNr+'";;"'+geburtsdatum+'";"'+email+'";') if (untisID in schueler): fDoppelteSchueler.write (untisID+"\n") else: schueler.add(untisID) # Ausgabe for n in ausgabe: fOutput.write (n+"\n") # Ausgabedatei schließen fOutput.close() fDoppelteSchueler.close() ==== U2M-06-SDTF2Schuelerfachdaten.py ==== ## ## Autor: Claudius Euteneuer ## Version: 2016-12-30 ## Copyrights: alles bei mir ## Bedienung: umständlich - mann muss wissen, was das Programm braucht ## Anleitung: mehr als dürftig ## Fragen: immer gerne an mich -> claudiuseuteneuersde ## ## Voraussetzung: die, die stüber in ## ftp://ftp.stueber.de/pub/doc/de/schulverwaltung/dokumentation/Magellan6Import.pdf ## selbst definiert. Man beachte die Reihenfolge der Importdateien. ## ## ## ## Ziel: Eine Datei namens U2M-04-UntisSchuelerfachdatenExport.txt wird ## genutzt, um eine Datei U2M-06-MagellanSchuelerfachdatenImport.csv zu ## erstellen, mit deren Hilfe der Magellan-Administrator alle ## Schülerfachdaten einlesen kann. ## ## neues feature: ## Eine Textdatei 07-U2M-MagellanSchuelerfachwahlenUebersicht.csv mit ## alle Schülerfachwahlen ## ## Anleitung: ## - Untis -> Datei -> Import/Export -> Deutschland -> Schuldatentransferformat -> Schuldatentransferformat.txt ## ## ## ## ## ## # Konstanten (erst einmal...) iDateiname = "U2M-05-UntisSchuelerfachdatenExport.txt" oDateiname = "U2M-07-MagellanSchuelerfachdatenImport.csv" sfwDateiname = "U2M-08-MagellanSchuelerfachwahlenUebersicht.csv" zeitraumVon = "01.08.2016" zeitraumBis = "31.01.2017" halbjahr = "1" # globale Variablen klassenunterricht = {} unterricht = {} # fügt einer Zeichenkette mit Sonderzeichen vorne und hinten Anführungszeichen hinzu def st (zeichenkette): zeichenkette=zeichenkette.replace('"','') sonderzeichen = False for z in zeichenkette: if ('ABCDEFGHIJKLMNOPQRSTUVWXYZ"'.find(z.upper())==-1): sonderzeichen = True if (sonderzeichen): return '"'+zeichenkette+'"' else: return zeichenkette # extrahiert die Klassenstufe aus einem Klassenkürzel def klassenstufe (name): if (name[1].isdigit()): z = name[0:2] else: z = name[0] return (int(z)) ## HAUPTPROGRAMM # Eingabedatei auf einmal einlesen alleZeilen = open(iDateiname).readlines() # Ausgabedateien öffnen fSchuelerFachdaten = open(oDateiname,"w") fSchuelerFachwahlen = open (sfwDateiname,"w") # Spalten für Magellan festlegen fSchuelerFachdaten.write("KlasseKuerzel;SchuelerNachname;SchuelerVorname;SchuelerGeburtsdatum;ZeitraumVon;ZeitraumBis;Halbjahr;FachKuerzel;Unterrichtsart;Kursnr;LehrerKuerzel;\n") # die Daten herausholen for zeile in alleZeilen: elemente=zeile.split(';') # Klassen einlesen if (elemente[0]=="K1"): klassenunterricht[elemente[2]] = {} # gekoppelte Unterrichte einlesen # in elemente[2] steht, wieviele Klassen gekoppelt sind # klassenunterricht wird im Abschitt "Unterrichte einlesen" gefüllt if (elemente[0]=="U6"): for n in range(1,int(elemente[2])): klasse = elemente[3+n] unterrichtsnr = elemente[1] # ist ein String! fach_nr_art = unterricht[unterrichtsnr][1] lehrer = unterricht[unterrichtsnr][2] klassenunterricht[klasse][fach_nr_art] = lehrer # Unterrichte einlesen if (elemente[0]=="U1"): # Unterricht in einer Klasse? (sonst ist es kein Unterricht) if (elemente[2]!=""): klasse = elemente[2] fach="" for z in elemente[6]: if (not z.isdigit()): fach+=z if (klassenstufe(klasse)>=11): # MSS if (elemente[6][-1:].isdigit()): nr = elemente[6][-1:] else: nr = "1" # LK? (sonst GK) if (elemente[6].upper()==elemente[6]): art = "LK" else: art = "GK" else: # SekI art = "" nr = "" fach=fach.upper() lehrer = elemente[3] klassenunterricht[klasse][fach+nr+art] = lehrer unterricht.update({elemente[1]:[klasse,fach+nr+art,lehrer]}) # Schüler einlesen und die Zeilen bestimmen ausgabe = [] schuelerfachwahlen = [] i = -1 for zeile in alleZeilen: elemente=zeile.split(';') if (elemente[0]=="P1"): i+=1 klasse = elemente[2] nachname = elemente[3] vorname = elemente[4] geburtsdatum = elemente[6][-2:]+"."+elemente[6][4:6]+"."+elemente[6][:4] if (klassenstufe(klasse)>=11): # MSS # in elemente[19] steht, wie viele Fächer der Schüler belegt hat schuelerfachwahlen.append(klasse+";"+nachname+";"+vorname+";"+geburtsdatum) for n in range(20, 19+int(elemente[19])*11, 11): fach = elemente[n] nr = elemente[n+1] if (elemente[n].upper()==elemente[n]): art = "LK" else: art = "GK" fach = fach.upper() lehrer = klassenunterricht[klasse][fach+nr+art] ausgabe.append(klasse+";"+st(nachname)+";"+st(vorname)+";"+geburtsdatum+";"+zeitraumVon+";"+zeitraumBis+";"+halbjahr+";"+fach+";"+art+";"+nr+";"+lehrer+";") schuelerfachwahlen[len(schuelerfachwahlen)-1]+=";"+fach+nr+"_"+art i+=1 else: # SekI nr="" art="" for fach in klassenunterricht[klasse]: lehrer = klassenunterricht[klasse][fach] ausgabe.append(klasse+";"+st(nachname)+";"+st(vorname)+";"+geburtsdatum+";"+zeitraumVon+";"+zeitraumBis+";"+halbjahr+";"+fach+";"+art+";"+nr+";"+lehrer+";") # Ausgabe: schueler_fachdaten.import.csv for n in ausgabe: fSchuelerFachdaten.write (n+"\n") # Ausgabe: schuelerfachwahlen for n in schuelerfachwahlen: fSchuelerFachwahlen.write (n+"\n") #Ausgabedateien schließen fSchuelerFachdaten.close() fSchuelerFachwahlen.close() ===== Definition Schülerfachtenimport ===== entnommen aus Stübers Doku SchuelerIDExtern;SchuelerVorname;SchuelerNachname;SchuelerGeburtsdatum;KlasseIDExtern;KlasseKuerzel;ZeitraumVon;ZeitraumBis;Halbjahr;FachIDExtern;FachKuerzel;Fachstatus;Unterrichtsart;Schwerpunkt;Niveau;Kursnr;Beurteilung;Endnote1;Endnote2;Notenart;Faktor;Merkmal;LehrerIDExtern;LehrerKuerzel SchuelerIDExtern; IP nicht verwenden SchuelerVorname; AVP 30 SchuelerNachname; AVP 30 SchuelerGeburtsdatum; DVP 10 TT.MM.JJJJ KlasseIDExtern; IVP nicht verwenden KlasseKuerzel; AVP 10 Verweis auf "Klassen" (Kuerzel) ZeitraumVon; DP 10 TT.MM.JJJJ ZeitraumBis; DP 10 TT.MM.JJJJ Halbjahr; SP 1 oder 2 FachIDExtern; nicht verwenden FachKuerzel; AVP 10 Verweis auf "Faecher" (Kuerzel) Fachstatus; AV 10 Verweis auf "Faechstati" (Kuerzel) Unterrichtsart; AV 10 Verweis auf das Schlüsselverzeichnis "Unterrichtsarten" (Kuerzel) Schwerpunkt; AV 10 Verweis auf das Schlüsselverzeichnis "Fachschwerpunkte" (Kuerzel) Niveau; AV 10 Verweis auf das Schlüsselverzeichnis "FachNiveaus" (Kuerzel) Kursnr; S Beurteilung; M 255 Endnote1; N Endnote2; N Notenart; A 1 Mögliche Werte: N=Notenwert, P=Punktwert, F=Füllwert - Voraussetzung für Noten Faktor; S Merkmal; A 8 LehrerIDExtern; IV nicht verwenden LehrerKuerzel AV 10 Verweis auf "Lehrer" (Kuerzel) A Textfeld mit maximaler Länge D Datum I 32-Bit Integer L Logisches Feld (J/N) M Memofeld mit variabler Länge N Kommazahl S 16-Bit Integer P Pflichtfeld V Verweis