In zahlreichen SAP Transaktionen wird ein "table control" verwendet, um Daten in tabellarischer Form anzuzeigen oder eingeben zu lassen. Mit dem InputAssistant können Sie eigene Spalten in einem "table control" hinzufügen, und zwar sowohl zur Anzeige von Informationen als auch zur Dateneingabe. Die in den eigenen Spalten eingegebenen Werte können in einem InputScript verarbeitet werden. |
Die Anzeige von Daten in eigenen Tabellenspalten ist nicht allzu schwierig, während die Dateneingabe mehr Aufwand erfordert. Wir beschäftigen uns im ersten Teil des Tutorials mit der Anzeige, im zweiten mit der Dateneingabe. Unsere Beispielanwendung zur Anzeige ist folgende: In Transaktion VA01 (Auftragserfassung) wollen wir eine neue Drucktaste "Anzeigen Daten vorhergehende Bestellung" anbieten, über die der Benutzer drei neue Spalten einblenden kann. In den neuen Spalten werden pro Material der neu erfassten Bestellung einige Daten der vorhergehenden Bestellung des jeweiligen Materials durch den gleichen Kunden angezeigt: jeweils bestellte Menge, Datum und Auftragsnummer. Wir rufen dazu pro Bestellposition ein BAPI auf und füllen unsere Spalten mit den zurückgelieferten Werten. Die nachfolgenden Bilder zu diesem Beispiel wurden in einem SAP ERP 2004 IDES System unter Verwendung von SAP GUI 7.1 erstellt. Sie können die Scripte aber ohne Änderung auch in diversen anderen SAP Releaseständen verwenden, zum Beispiel in einem 4.6C System mit SAP GUI 6.20 oder 6.40.
Zur Implementierung gehen wir am besten in zwei Schritten vor. Als erstes realisieren wir die Anzeige der zusätzlichen Spalten über eine Drucktaste: // GuiXT Script SAPMV45A.D4001.TXT // nur für Transaktion VA01, Reiter Verkauf if Q[Transaction=VA01] and Q[Page=Verkauf] // Drucktaste am Ende der Tabelle anzeigen, rechts neben dem Button "Liefergruppenkorrelation APO" (nur als Ikone angezeigt) // hierbei keine feste Position verwenden, da die Tabelle je nach Window-Grösse unterschiedlich viele Zeilen hat if not V[VA_show_cols] Pushbutton P[Liefergruppenkorr.]+(0,15) "@3S@Anzeigen Daten vorhergehende Bestellung" process="VA_show_cols.txt" else Pushbutton P[Liefergruppenkorr.]+(0,15) "@3T@Schliessen Daten vorhergehende Bestellung" process="VA_hide_cols.txt" // drei neue Spalten hinzufügen Column "V.Menge" size=10 name="VA_pq" position=4 -readOnly -alignRight Column "V.Datum" size=10 name="VA_pd" position=5 -readOnly -alignRight Column "V.A.-Nr." size=10 name="VA_po" position=6 -readOnly -alignRight endif
Die beiden InputScripte sind sehr einfach; sie setzen nur die Variable zur Anzeige der Spalten: //
InputScript VA_show_cols.txt //
InputScript VA_hide_cols.txt
Man kann die Spalten auch mit einer geeigneten Ikone hervorheben, zum Beispiel so:
Hierzu verwenden wir (wie generell bei Textelementen möglich) die Notation "@xx@text..." wobei xx die SAP Ikonen-Id ist.
// Hinzufügen dreier neuer Spalten mit Ikonen Nun fehlen uns nur noch die Daten in den neuen Spalten. Jeder Zelle in den neuen Spalten ist eine Variable zugeordnet, deren Name sich aus dem durch "name=" angegebenen Namen, einem Punkt sowie der Zeilennummer ergibt. Beispiel: Zeile1:
V[VA_pq.1] V[VA_pd.1]
V[VA_po.1] Dabei bezieht sich der Zeilenindex auf die gesamte Tabelle, nicht nur auf den gerade angezeigten Bereich. Falls der Benutzer zum Beispiel in der Tabelle auf Zeile 4 vorwärtsgeblättert hat, sind nur die oben blau dargestellten Zeilen sichtbar, und die Variablennamen im angezeigten Bereich beginnen mit Zeile 4. Zum Füllen der Spaltenvariablen sind zwei verschiedene Vorgehensweisen möglich. Entweder füllt man die Variablen für sämtliche Zeilen, auch für die gerade nicht sichtbaren, zu Beginn der Transaktion. Man muss dann beim Blättern durch die Tabelle nichts mehr tun. Das funktioniert allerdings nur, wenn sich der Inhalt der Tabelle in der Transaktion nicht ändern kann. In unserem Fall (VA01) brauchen wir ein anderes Verfahren, da die Materialnummer jederzeit überschrieben werden kann, und auch Zeilen gelöscht oder eingefügt werden können. In solchen Fällen ist es am besten, nur den jeweils sichtbaren Bereich der Tabelle (also den oben blau dargestellten) bei der Anzeige zu füllen. Hierzu benötigen wir eine Schleife über den sichtbaren Bereich der Tabelle: // Alle sichtbaren Tabellenzeilen
verarbeiten Set V[k] &V[fvr] // absolute Zeilennummer in der gesamten Tabelle (also k=4 im Beispiel oben) label prev_order_beg // Zeile gefüllt?Set V[Pos] "&cell[Alle Positionen,Pos,&V[i]]" if not V[Pos] goto prev_order_end endif // Die angezeigte Zeile i verarbeiten. Die absolute Zeilennummer ist k ... Set V[colvar.&V[k]] "...neuer Wert..." // nächste Zeile Set V[k] &V[k] + 1 goto prev_order_beg label prev_order_end Innerhalb dieses Rahmens müssen wir jetzt noch die eigentlichen Daten lesen. Hierzu rufen wir pro Zeile die Funktion "BAPI_SALESORDER_GETLIST" auf. Die Eingabeparameter für das BAPI sind die Kundennummer, die Materialnummer und der Vertriebsbereich. Das BAPI liefert eine Tabelle mit den vorhergehenden Bestellungen dieses Materials zurück, absteigend sortiert nach Datum. Aus der ersten Tabellenzeile können wir daher die gewünschten Daten entnehmen. Das ganze Script sieht damit wie folgt aus: // GuiXT Script SAPMV45A.D4001.TXT // nur für Transaktion VA01, Reiter Verkauf if Q[Transaction=VA01] and Q[Page=Verkauf] //
Drucktaste am Ende der Tabelle anzeigen, rechts neben dem Button "Liefergruppenkorrelation
APO" (nur als Ikone angezeigt)
// drei neue Spalten hinzufügen GetTableAttribute T[Alle Positionen] firstVisibleRow="fvr" Set V[i] 1 Set V[k] &V[fvr] // Alte Werte löschen Set V[VA_pq.*] "" Set V[VA_pd.*] "" Set V[VA_po.*] "" Set V[customer] "&F[Auftraggeber]" Set V[customer] 10000000000 + &V[customer] Set V[customer] &V[customer](2-11) label prev_order_beg // Zeile gefüllt? Set V[Pos] "&cell[Alle Positionen,Pos,&V[i]]" if not V[Pos] goto prev_order_end endif Set V[matnr] "&cell[Alle Positionen,Material,&V[i]]" if not V[matnr] goto prev_order_end endif // über SAP BAPI vorhergehende Bestellungen lesen Call "BAPI_SALESORDER_GETLIST" in.CUSTOMER_NUMBER="&V[customer]" in.Verkauf_ORGANIZATION="&F[Vertr.bereich]" in.MATERIAL="&V[matnr]" table.SALES_ORDERS="so"
// die erste
Zeile enthält die jüngste Bestellung
// gewünschte Felder in unsere Spaltenvariablen übertragen
//
"Menge": Das BAPI liefert sie in "dezimal gepacktem" Format mit 3
Nachkommastellen
// "Auftragsnummer": mit führenden Nullen geliefert, die wir über eine Rechenoperation entfernen Set V[ordno] "&V[sowa](BAPIORDERS-SD_DOC)" Set V[ordno] &V[ordno] + 0 Set V[VA_po.&V[k]] "&V[ordno]" endif Set V[i] &V[i] + 1 Set V[k] &V[k] + 1 goto prev_order_beg label prev_order_end endif // V[VA_show_cols] endif // VA01 + page=Verkauf
Unser zweites Beispiel behandelt die Dateneingabe in zusätzlichen Tabellenspalten. In Transaktion ME51N (Bestellanforderung anlegen) wollen wir das Feld "Einkaufsorganisation" als neue Tabellenspalte anbieten. Im Standard ist die Eingabe der Einkaufsorganisation im Detailbild der Bestellposition auf dem Reiter "Bezugsquelle" möglich, erfordert also jeweils die Auswahl der Position und in der Detailansicht eventuell den Klick auf den richtigen Reiter. Bemerkung: In neuen SAP Systemen kann der Benutzer über die Drucktaste "Pers. Einstellungen" entweder ein "grid control" oder ein "table control" auswählen. Nur im "table control" ist die hier vorgestellte Technik anwendbar. In dem GuiXT Script fragen wir daher als erstes ab, ob überhaupt eine Tabelle angezeigt wird.
Mit der neu eingefügten Spalte "EOrg" wird die Eingabe der Einkaufsorganisation unmittelbar in der Tabelle ermöglicht:
Transaktion ME51N besitzt einige Besonderheiten, verglichen mit anderen SAP Transaktionen:
Eine weitere Schwierigkeit, die auch in zahlreichen anderen Transaktionen auftritt, besteht darin, dass der Benutzer auch nach F3, F12 oder F15 (Zurück, Abbrechen, Beenden) noch in einem Popup-Bild "Sichern" kann. Auch in diesem Fall soll unser InputScript ablaufen, das die Werte aus der Spalte "EOrg" in das Eingabefeld im Detailbild der jeweiligen Position einträgt. Beginnen wir mit dem GuiXT Script: if Q[Transaction=ME51N] // nur falls Tabelle sichtbar ist (könnte durch Benutzer ausgeblendet sein, oder "grid control" aktiviert)if T[Table] // Tabelle noch leer? Dann alle Variablen zurücksetzen GetTableAttribute T[Table] firstVisibleRow=fvr if V[fvr=1] Set V[material] "&cell[Table,Material,1]" if not V[material] Set V[ME51N_*] "" endif endif // Zusatzspalte mit Bezug auf Positionsnummer Column "EOrg" position=8 size=4 name="ME51N_EKORG" keyColumn="Banf-position" techName="MEREQ3322-EKORG" //
Merken Zusatzspalte aktiv
// Zusatzspalte
aktiv? sonst Script beenden if F[EinkOrganisation] del F[EinkOrganisation] endif // bei Sichern eigenes InputScript aufrufen on "/11" process="ME51N_D_save.txt" // bei Prüfen ebenfalls on "/39" process="ME51N_D_save.txt" using MODE = "C" // falls der
Benutzer die Transaktion verlässt, das Popup abfangen endif Einige Erläuterungen zu dem Script:
Das "ME51N_D_leave.txt" Script wartet in dem Popup auf eine Benutzereingabe, um bei Anwahl von "Sichern" das eigene InputScript zu starten: // InputScript "ME51N_D_leave.txt"
// popup "Soll der erfasste Beleg vorher gesichert werden?" Wir starten bei "Ja" im Popup ebenfalls das Sichern-Script und setzen den Parameter POPUP = "X". Das Sichern-Script bricht dann zunächst das Popup ab und läuft anschliessend so ab wie bei "Sichern" im Hauptbild. Im "Sichern"-Script wird geprüft, ob die Positionstabelle und das Detailbild geöffnet sind. Das Detailbild wird am Ende wieder geschlossen, falls es durch das InputScript geöffnet wurde, damit der Benutzer bei der "Prüfen" Funktion in der vollen Tabellenanzeige bleiben kann. // InputScript "ME51N_D_save.txt" Parameter POPUP "N" // "X falls von Popup gestartet Parameter MODE "S" // S= Sichern C = Prüfen // Den automatischen Neuaufruf der Transaktion bei Fehlern abschalten,
sonst würden die eingegebenen Daten verloren gehen // Merken ob das InputScript das Detailbild selbst öffnen musste Set V[ME51N_detail] "" // Vom Popup gestartet? Enter "=CANC" // Popup abbrechen und erst sichern else Enter endif // Während der Verarbeitung des InputScript soll ein entsprechender Titel sichtbar sein if U[Mode=S] Set V[ME51N_Title] "Sichern der Bestellanforderung... Bitte warten" else Set V[ME51N_Title] "Prüfen der Bestellanforderung... Bitte warten" endif Screen saplmegui.0014Title "&V[ME51N_Title]" // Positionstabelle aufgeklappt? if T[Table] goto Pos_table_open endif // Positionstabelle aufklappen Enter "=MEV4001BUTTON" Screen saplmegui.0014Title "&V[ME51N_Title]"
label
Pos_table_open
Screen label position_details_open GetTableAttribute T[Table] firstVisibleRow=FVisZeile
if
V[FVisZeile=1] Enter "/scrollToLine=1" table="T[Table]" label new_screen Screen saplmegui.0014Title "&V[ME51N_Title]" label scroll_beg_done GetTableAttribute T[Table] firstVisibleRow=FVisZeile lastVisibleRow=LVisZeile lastRow=LastRow Set V[relRow] 1 label new_Zeile // Ende der Tabelle? if V[absRow>&V[LastRow]] goto end_of_table endif // keine weiteren Zeilen mehr in der Anzeige? if V[absRow>&V[LVisZeile]] Enter "/scrollToLine=&V[absRow]" table="T[Table]" goto new_screen endif Set V[Pos] "&cell[Table,Requisn. Pos,&V[relRow]]" if not V[Pos] goto end_of_table endif Set V[ME51N_EKORG] "&V[ME51N_EKORG.&V[Pos]]" Set V[ME51N_EKORG_previous] "&V[ME51N_EKORG.&V[Pos]_previous]" // keine neue Eingabe in der EOrg-Spalte?? if V[ME51N_EKORG=&V[ME51N_EKORG_previous]] Set V[absRow] &V[absRow] + 1 Set V[relRow] &V[relRow] + 1 goto new_Zeile endif // Eingabe sichern für spätere Vergleiche Set V[ME51N_EKORG.&V[Pos]_previous] "&V[ME51N_EKORG]" // Cursor in die Zeile setzen und Details anzeigen SetCursor cell[Table,Requisn. Pos,&V[relRow]] Enter "/2" Screen SAPLMEGUI.0014Title "&V[ME51N_Title]" if F[EinkOrganisation] goto screen_EKORG endif // Auf Reiter "Bezugsquelle" wechseln Enter "=TABREQDT7" Screen SAPLMEGUI.0014Title "&V[ME51N_Title]" label screen_EKORG Set F[EinkOrganisation] "&V[ME51N_EKORG]" Set V[absRow] &V[absRow] + 1 Set V[relRow] &V[relRow] + 1 goto new_Zeile label end_of_table // Detailbild im InputScript aufgeklappt? if not V[ME51N_detail=X] goto screen_collapse_done endif // Detailbild zuklappen Enter "=MEV4002BUTTON" Screen SAPLMEGUI.0014Title "&V[ME51N_Title]" label screen_collapse_done // Sichern oder Prüfen? if U[MODE=S] Enter "/11" else Enter "/39" endif // Aus Popup gestartet? sonst sind wir jetzt fertig if not U[POPUP=X] Leave endif
// Transaktion
verlassen Enter "/3" // Falls Popup
nochmal erscheint: nicht Sichern, ist ja schon durchgeführt Noch einige Erläuterungen zu "Goto" und "Label" in einem InputScript: Bei der Verwendung von "goto" und "label" muss man beachten, ob das "label" vor oder nach einer "Screen"-Anweisung gesetzt wird. Bei den folgenden beiden Varianten ist (1) richtig, (2) dagegen falsch: (1) Screen
saplmegui.0014 Screen saplmegui.0014label item_table_open (2) Screen
saplmegui.0014
label
item_table_open In der zweiten Variante (label vor Screen) wird kein "Enter" durchlaufen für die erste "Screen" Anweisung. Das InputScript zeigt dann den Screen einfach an und wartet auf eine Benutzereingabe, statt automatisch weiterzulaufen. Ein anderer möglicher Fehler wäre, die Screen Anweisung in if..endif einzuschliessen: Screen
saplmegui.0014
// Positionstabelle aufklappen
Screen
saplmegui.0014
Nach diesen negativen Beispielen noch eine korrekte Alternative: Wir verwenden "goto", um jeweils zu der gleichen Screen Anweisung zurückzuspringen, nachdem wir über einen Funktionscode die Tabelle oder die Detailsicht aufgeklappt haben: ... Screen saplmegui.0014Title "&V[ME51N_Title]" // Positionstabelle aufgeklappt? if not T[Table] // Postionstabelle aufklappen Enter "=MEV4001BUTTON" goto main_screen endif // Positionsdetails
aufgeklappt? if V[FVisRow=1] goto scroll_beg_done endif // auf erste Zeile positionieren Enter "/scrollToLine=1" table="T[Table]" label new_screen Screen saplmegui.0014Title "&V[ME51N_Title]" label scroll_beg_done ... Hier ist es wichtig, das Label "main_screen" vor die Screen Anweisung zu setzen. Falls es hinter der Screen-Anweisung steht, fährt GuiXT nach dem Enter mit der Verarbeitung fort und durchläuft ein weiteres Enter. Mehr als ein Enter pro Screen macht aber keinen Sinn; es führt zu einer GuiXT-Fehlermeldung und das erste Enter wird verschluckt. Generell gilt daher die Regel, pro Screen höchstens einmal ein Enter abzusetzen, und in der Regel auch genau einmal. Nur in den folgenden beiden Fällen macht eine Screen-Anweisung ohne Enter Sinn: Entweder wenn man in einem Popup-Screen auf die Eingabe des Benutzers warten will und dann im InputScript weitermacht, wie wir es in "ME51N_D_leave.txt" benutzt haben. Oder (ein sehr spezieller Fall), wenn man über "ApplyGUIScript" ein VBScript-Programm aufruft, das seinerseits eine "Enter"-Aktion enthält, also z.B. einen Pushbutton drückt. |