Datenaustausch Magellan-Untis

Grober Ablauf:

  1. Magellan-Backup erstellen
  2. Untis-Backup erstellen
  3. Magellan: Schüler exportieren
  4. mit Python Export in Untis-Import umwandeln
  5. doppelte UntisID-Schüler eindeutig machen und neue IDs in doppelteSchueler-Kopie speichern
  6. Untis: Schülerdaten importieren
  7. Untis: Schülerfachdaten exportieren
  8. im Python-Code die Daten für das aktuelle Halbjahr anpassen
  9. mit Python Export in Magellan-Import umwandeln
  10. Magellan: mit leerer Fachtafel alle Schülerfachdaten löschen
  11. Magellan-Administrator: Schülerfachdaten importieren
  12. Magellan: mit Sammellöschungen überflüssige Fächer entfernen
  13. 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.

  1. Magellan → Extras → Export → Units… → SDTF-Datei → M2U-01-MagellanSchuelerExport.txt auswählen und überschreiben → Übernehme Schüler aller Klassen → Alle Schüler → Starten
  2. M2U-02-MagellanSchuelerExport2UntisSchuelerImport.py starten
  3. 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.

  1. Untis → Datei → Import/Export → Deutschland → Schuldatentransferformat → Exportieren → Durchsuchen (richtigen Pfad überprüfen!!!) → U2M-04-UntisSchuelerfachdatenExport.txt auswählen und überschreiben
  2. Im folgenden Programm stehen Anfangs- und Enddatum des aktuellen Schulhalbjahrs fest drin. Die müssen angepasst werden.
  3. 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?
  4. einmalig: Magellan → Verzeichnisse → Fachtafeln → neue Fachtafel 'leer' erstellen - ohne Fächer
  5. Magellan → Schüler → Zeugnis → Fächer → leere Fachtafel zuweisen → alle Schüler markieren → 'leer' zuweisen
  6. 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
  7. 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?
  8. 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 -> claudius<at>euteneuers<punkt>de
##
##  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 -> claudius<at>euteneuers<punkt>de
##
##  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
Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
Falls nicht anders bezeichnet, ist der Inhalt dieses Wikis unter der folgenden Lizenz veröffentlicht: CC Attribution-Noncommercial-Share Alike 4.0 International