Glasauswahl

In diesem Tutorial will ich dir zeigen, wie du über die UI Masken Gläser auswählen kannst, die eingestellten Gläser abfragen kannst und diese dann auch noch einstellen kannst.

ACHTUNG! Dieses Tutorial funktioniert nicht zwangsläufig für jedes System. Einige der dafür notwendigen Funktionen sind nicht in allen Systemen verfügbar. Sollte dieses Tutorial bei dir also nicht klappen, dann melde dich bei uns und wir prüfen, ob wir eventuell fehlende Funktionen nachreichen können.

Zuerst wollen wir uns unsere Maske aufbauen. Ich starte mit einer komplett leeren Maske und setze dort lediglich eine Combo-Box ein. Du kannst aber natürlich auch die Combo-Box in eine bestehende Maske einbauen.

Mehr müssen wir vorerst in der Maske nicht erledigen. Wir können also zum IN-Skript springen. Dieser Bereich wird wieder etwas umfangreicher. Ich zeige dir 2 Wege. Die Gläser, die zur Auswahl stehen sollen, müssen ja nur irgendwie in die Maske kommen. Das kann man einfach erledigen. Man kann aber auch die Gläser aus der Datenbank auslesen. Dann sind die immer mit den Daten synchron. Aber das ist wieder mehr Arbeit, beim Einrichten verhindert aber, dass wir permanent die Listen pflegen müssen.

Fangen wir also mit unserer einfachen „leeren“ Vorlage an. Ihr dürft gerne alles in eine bereits bestehende Maske einbauen.

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)

Eine Combobox braucht im einfachsten Fall nur eine Liste mit Werten. Jeder Wert besteht aus einem Anzeigewert und einem Datenwert. Wie diese Werte aussehen, bleibt uns vollkommen frei überlassen.

[

(„Meine Anzeige 1“ , „Einstellung 1“) ,

(„Meine Anzeige 2“ , „Einstellung 2“)

]

Was wir im Hinterkopf behalten sollten ist folgendes: Der erste Teil „Meine Anzeige X“ ist das, was der Benutzer in der UI Maske sieht. Der zweite Teil „Einstellung X“ ist der Wert, den wir im Out-Skript bekommen werden. Und je nachdem, was da im Out-Skript als Wert ankommt, müssen wir dann entsprechend handeln.

Schauen wir uns das doch einmal an.

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def dachGlasEintragen(sc):
    listeGpf = [
        („Meine Anzeige 1“ , „Einstellung 1“),
        („Meine Anzeige 2“ , „Einstellung 2“),
        („Meine Anzeige 3“ , „Einstellung 3“),
        („Meine Anzeige 4“ , „Einstellung 4“)
    ]
    vorausgewaehlt = „Einstellung 2“
    sc.initComboBox(„cmbGpfDachglas“ , vorausgewaehlt , listeGpf)
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    dachGlasEintragen(sc)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)

Ziemlich einfach, oder? Schauen wir uns mal das Out-Skript an. Ich nehme wieder ein leeres Skript und baue einfach nur eine Funktion ein, die den eingestellten ausliest.

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
def stelleDachglasEin(sc):
    cmbBox = sc.findByName(„cmbGpfDachglas“)
    if cmbBox is None: return #Falls die Combobox nicht in der UI sein sollte, dann abbrechen
    sWert = cmbBox.m_sValue
    kkp.MsgBox(sWert , 0)
if __name__ == ‚__main__‘:
    sc = SC.SegmentConfig()
    sc.fromfile(kkp.Get_Projektdir() + „\\segmentConfig_ui.xml“)
    stelleDachglasEin(sc)

Okay, wir sehen also, wir bekommen nicht den Anzeigetext sondern den „versteckten“ Wert.

Und nun könnten wir natürlich in dem Out-Skript sagen, wenn „Einstellung 1“ dann, stelle Glas XY ein und Wenn „Einstellung 2“ dann stelle Glas XYZ ein.

Und genau das werden wir jetzt erst einmal auch machen.

Dafür müssen wir zuerst natürlich unser Dach mit etwas Dachglas ausstatten.

Und dann müssen wir 3 tun.

  1. Wir müssen je nach Einstellung eine Artikelnummer für das Glas verwenden
  2. Wir müssen den Typ der Verglasung in den Glasscheiben einstellen (in diesem Fall auf den Typ Dachglas)
  3. Wir müssen die Artikelnummer der Verglasung in die Glasscheiben eintragen.

Das Skript sieht dann so aus:

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import ole
def stelleDachglasEin(sc):
    cmbBox = sc.findByName(„cmbGpfDachglas“)
    if cmbBox is None: return #Falls die Combobox nicht in der UI sein sollte, dann abbrechen
    sWert = cmbBox.m_sValue
    sArtikelnrGlas = „“
    if sWert == „Einstellung 1“: sArtikelnrGlas = „VGR-004“
    if sWert == „Einstellung 2“: sArtikelnrGlas = „VGR-006“
    if sWert == „Einstellung 3“: sArtikelnrGlas = „VGR-012“
    if sWert == „Einstellung 4“: sArtikelnrGlas = „VGR-024“
    GPF_TYP_DACHGLAS = 0x1
    PY_SONSTIGES_Zweifachglas_SetTyp = 7011
    kkp.py32ci.callback(PY_SONSTIGES_Zweifachglas_SetTyp , [sc.objnr() , GPF_TYP_DACHGLAS])
    PY_SONSTIGES_Zweifachglas_SetArtikelnr = 7012
    kkp.py32ci.callback(PY_SONSTIGES_Zweifachglas_SetArtikelnr , [sc.objnr() , GPF_TYP_DACHGLAS , sArtikelnrGlas])
if __name__ == ‚__main__‘:
    sc = SC.SegmentConfig()
    sc.fromfile(kkp.Get_Projektdir() + „\\segmentConfig_ui.xml“)
    stelleDachglasEin(sc)

Nun können wir die Zuweisung der Artikelnummer für das Glas etwas vereinfachen. Zum Beispiel könnten wir ja den Wert nicht „Einstellung X“ nennen sondern eben direkt die Artikelnummer der Glasscheibe verwenden. Das sieht dann im In-Skript so aus:

def dachGlasEintragen(sc):
    listeGpf = [
        („Meine Anzeige 1“ , „VGR-004“),
        („Meine Anzeige 2“ , „VGR-006“),
        („Meine Anzeige 3“ , „VGR-012“),
        („Meine Anzeige 4“ , „VGR-024“)
    ]
    vorausgewaehlt = „Einstellung 2“
    sc.initComboBox(„cmbGpfDachglas“ , vorausgewaehlt , listeGpf)

Wenn wird das jetzt im Out-Skript anschauen, dann bekommen wir als sWert ja immer direkt die Artikelnummer. Also können wir die auch verwenden.

def stelleDachglasEin(sc):
    cmbBox = sc.findByName(„cmbGpfDachglas“)
    if cmbBox is None: return #Falls die Combobox nicht in der UI sein sollte, dann abbrechen
    sWert = cmbBox.m_sValue
    sArtikelnrGlas = sWert
    GPF_TYP_DACHGLAS = 0x1
    PY_SONSTIGES_Zweifachglas_SetTyp = 7011
    kkp.py32ci.callback(PY_SONSTIGES_Zweifachglas_SetTyp , [sc.objnr() , GPF_TYP_DACHGLAS])
    PY_SONSTIGES_Zweifachglas_SetArtikelnr = 7012
    kkp.py32ci.callback(PY_SONSTIGES_Zweifachglas_SetArtikelnr , [sc.objnr() , GPF_TYP_DACHGLAS , sArtikelnrGlas])

Und mehr brauchen wir im Out-Skript auch nicht machen. Und auch das In-Skript können wir auf diese Weise verwenden.


Alles, was jetzt kommt, ist also eine „Automatisierung“ zum Befüllen der Combo-Box im In-Skript. Das soll einfach nur verhindern, dass wir diese Einträge („Einstellung 1“, „VGR-004“) … von Hand in das Skript schreiben müssen.

Dafür brauchen wir zuerst einmal eine Funktion mit der wir alle Gläser abfragen können. Dafür müssen wir aber auch noch 2 Module importieren und wir können unsere Funktion zum Befüllen der Combobox so nicht verwenden, müssen dort also erst einiges deaktivieren, bis wir das später wieder aktiv schalten können.

Hier das Skript im Ganzen, mit den importierten Modulen, der Funktion zum Abfragen aller möglichen Ggf (Glas – Paneele – Füllung).

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import ole
import xml.etree.ElementTree as ET
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def getAlleGlaeser():
    gpfListe = []
    glasliste = kkp.OLE_CMD(ole.OLE_XML_GET_Liste_mit_Glas_Paneele_Fuellungen , ())
    if len(glasliste) < 2: return None
    glasliste = glasliste[1]
    if glasliste is None or len(glasliste) == 0: return None
    xmlRoot = None
    try: xmlRoot = ET.fromstring(glasliste)
    except: return None
    for xmlGpf in xmlRoot.findall(„CDaten“):
            gpfListe.append(xmlGpf)
    return gpfListe
def dachGlasEintragen(sc):
    gpfListe = getAlleGlaeser()
    kkp.MsgBox(str(gpfListe) , 0)
    return
    vorausgewaehlt = „Einstellung 2“
    sc.initComboBox(„cmbGpfDachglas“ , vorausgewaehlt , listeGpf)
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    dachGlasEintragen(sc)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)

die Funktion getAlleGlaeser() liefert uns eine Liste zurück mit XML Daten, In jedem Feld der Liste befindet sich ein XML Eintrag vom Typ CDaten. Dieser Typ ist je nach Inhalt anders aufgebaut, bei GPF verfügt er über folgende Informationen.

[

<CDaten m_bFarbeSystemvorgabeVerwenden=“1″ m_bMaterialstaerkeFiltern=“1″ m_bVorgerichtet=“0″ m_dGlasgewicht=“2.5″ m_dMaterialstaerke=“8″  m_iTyp=“40″ m_iVerwendetAls=“0″ m_rgbAussen=“0;0;0;0″ m_rgbInnen=“0;0;0;0″ m_strArtikelnr=“VGR-008″ m_strArtikelnummerZugeordnetePaneele=““ m_strAussenTexturDateiname=““ m_strInnenTexturDateiname=““ m_strAussenfarbe=““ m_strInnenfarbe=““ m_strBezeichnung=“Glas VSG vorgerichtet für 8mm“ m_strFarbkalkulationsdaten=““/>

<CDaten …/>

]

Okay, das sind nun sehr viele Informationen. Wir brauchen davon aber nur ein paar. Zum einen brauchen wir die Bezeichnung für die Anzeige in der ComboBox und zum anderen die Artikel als versteckte Daten. Da wird ja eine Liste von Daten haben, müssen wir diese auch mit einer Schleife durchlaufen.

Übrigens: wenn du mal wissen möchtest, wie man ein XML Objekt in Python in einen String verwandelt, den man dann per print Befehl ausgeben kann:

def dachGlasEintragen(sc):
    gpfListe = getAlleGlaeser()
    xmlstr = ET.tostring(gpfListe[0], encoding=’utf8′)
    kkp.MsgBox(str(xmlstr) , 0)

Hier die Funktion mit der wir die Artikelnummer und Bezeichnung auslesen können. Die so entstehende Liste können wir übrigens auch wieder in der ComboBox anzeigen.

def dachGlasEintragen(sc):
    gpfListe = getAlleGlaeser()
    listeGpf = []
    for cDaten in gpfListe:
         sArtikelnr = cDaten.get(‚m_strArtikelnr‘)
         sBezeichnung = cDaten.get(„m_strBezeichnung“)
         eintrag = [sBezeichnung , sArtikelnr]
         listeGpf.append(eintrag)
    vorausgewaehlt = „Einstellung 2“
    sc.initComboBox(„cmbGpfDachglas“ , vorausgewaehlt , listeGpf)

Wenn man nun aber genau hinschaut, kann man erkennen, dass in der Liste einfach alle GPF drin sind. Wir wollen in dieser Combo-Box aber nur Gläser haben, und auch nur solche, die für den Dachbereich zugelassen sind. Also müssen wir die Liste nach dem verwendeten Typ filtern.

Der Typ für Dachglas ist 0x1. Bei den Typen gilt, dass dieser Fläg für mehrere Einträge gelten kann. Beispiel: Ein Glas darf Dachbereich eingesetzt werden und auch im Vertikalbereich.

Dachglas = 1 = 0x1, Vertikalglas = 32 = 0x20 => GpfTyp = 1+32 = 33 bzw. 0x1 | 0x20 = 0x21

def filterByTyp(gpfListe , t):
    liste = []
    for gpf in gpfListe:
          typ = gpf.get(‚m_iTyp‘)
          try: iTyp = int(typ)
          except: iTyp = 0
          if iTyp & t == t:
               liste.append(gpf)
    return liste
def dachGlasEintragen(sc):
    gpfListe = getAlleGlaeser()
    gpfListe = filterByTyp(gpfListe , 0x01)

so könnten wir nun auch eine andere Liste aufbauen, indem wir einfach nach dem Typ 1024 = Hohlkammerplatten im Dachbereich suchen.  Ziemlich praktisch, oder?

Übrigens mit einer ganz ähnlichen Funktion könnten wir auch nach der Verglasungsstärke filtern. Wenn wir nicht m_iTyp sondern m_dMaterialstaerke abfragen, bekommen wir den Wert wie dick das Glas ist und können dann sagen, wenn es zwischen x und y liegt, ist es zulässig, sonst nicht.

Jetzt sollten wir uns aber noch darum kümmern, welches Glas überhaupt eingetragen ist, damit wir dem Benutzer eine Vorstellung geben können. Leider bietet uns das KKP dafür keine Funktion an. Wir müssen uns also mit einen Trick also Notlösung behelfen. Und hier hilft uns wieder der Warenkorb, den wir im anderen Tutorial bereits kennengelernt haben. Der Warenkorb kann nicht nur Artikel verwalten, sondern auch Optionen. Wir bekommen also nicht direkt den Inhalt was in der Konstruktion eingestellt wurde. Wenn also ein Anwender von Hand die Einstellungen der Gläser ändert, bekommen wir beim Laden falsche Werte, aber immerhin haben wir so überhaupt eine Chance das eingestellte GPF anzuzeigen.

Hier ist das Out-Skript mit dem wir die eingestellte GPF als Option in den Warenkorb eintragen können.

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import ole
import Warenkorb as WK
def stelleDachglasEin(sc , wk):
    cmbBox = sc.findByName(„cmbGpfDachglas“)
    if cmbBox is None: return #Falls die Combobox nicht in der UI sein sollte, dann abbrechen
    sWert = cmbBox.m_sValue
    sArtikelnrGlas = sWert
    GPF_TYP_DACHGLAS = 0x1
    PY_SONSTIGES_Zweifachglas_SetTyp = 7011
    kkp.py32ci.callback(PY_SONSTIGES_Zweifachglas_SetTyp , [sc.objnr() , GPF_TYP_DACHGLAS])
    PY_SONSTIGES_Zweifachglas_SetArtikelnr = 7012
    kkp.py32ci.callback(PY_SONSTIGES_Zweifachglas_SetArtikelnr , [sc.objnr() , GPF_TYP_DACHGLAS , sArtikelnrGlas])
    wk.addOption(„gpf_partno“ , sArtikelnrGlas)
if __name__ == ‚__main__‘:
    sc = SC.SegmentConfig()
    sc.fromfile(kkp.Get_Projektdir() + „\\segmentConfig_ui.xml“)
    wk = WK.Warenkorb(sc.objnr())
    wk.load()
    stelleDachglasEin(sc , wk)
    wk.save()

Und das ist das komplette In-Skript:

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import ole
import xml.etree.ElementTree as ET
import Warenkorb as WK
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def getAlleGlaeser():
    gpfListe = []
    glasliste = kkp.OLE_CMD(ole.OLE_XML_GET_Liste_mit_Glas_Paneele_Fuellungen , ())
    if len(glasliste) < 2: return None
    glasliste = glasliste[1]
    if glasliste is None or len(glasliste) == 0: return None
    xmlRoot = None
    try: xmlRoot = ET.fromstring(glasliste)
    except: return None
    for xmlGpf in xmlRoot.findall(„CDaten“):
            gpfListe.append(xmlGpf)
    return gpfListe
def filterByTyp(gpfListe , t):
    liste = []
    for gpf in gpfListe:
          typ = gpf.get(‚m_iTyp‘)
          try: iTyp = int(typ)
          except: iTyp = 0
          if iTyp & t == t:
               liste.append(gpf)
    return liste
def dachGlasEintragen(sc , wk):
    gpfListe = getAlleGlaeser()
    gpfListe = filterByTyp(gpfListe , 0x01)
    listeGpf = []
    for cDaten in gpfListe:
         sArtikelnr = cDaten.get(‚m_strArtikelnr‘)
         sBezeichnung = cDaten.get(„m_strBezeichnung“)
         eintrag = [sBezeichnung , sArtikelnr]
         listeGpf.append(eintrag)
    vorausgewaehlt = wk.option(„gpf_partno“)
    sc.initComboBox(„cmbGpfDachglas“ , vorausgewaehlt , listeGpf)
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    wk = WK.Warenkorb(sc.objnr())
    wk.load()
    dachGlasEintragen(sc , wk)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)