====== 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