Die Änderung von Daten des SAP-System ist komplexer als das Lesen. Folgendes ist zu beachten:
Als Beispiel nehmen wir die Änderung einiger Felder der Kundenadresse in unsere Anwendung auf. Dazu definieren wir als erstes einen Button innerhalb der Anzeige der Adresse, mit dem der Benutzer in den Änderungsmodus umschalten kann:
In der HTML-Datei ist der Button wie folgt definiert:
<!-- Adresse ändern --> <img src="../../../icons/edit.png" style="width:32px; margin:8px; float:right" onclick="S10Apply('to_change');"/>
Das heisst, wir zeigen ein passendes png-Bild an, schieben es mit "float:right" auf die rechte Seite und führen bei einem Klick darauf die ABAP Methode "to_change" aus.
Falls die Anwendung auch als Desktop-Anwendung gedacht ist, spendieren wir dem Button einen Tooltip mit der Option title=, also zum Beispiel <img ... title="Adresse ändern" />:
In der ABAP-Methode "to_change" navigieren wir zu einem neuen Screen "change". Davor ist es nötig,
denn es kann sein, dass ein anderer Benutzer die Adresse geändert hat, während wir eine Weile auf dem Anzeigebild waren. Im Änderungsmodus müssen wir immer die aktuellen Daten anzeigen, sonst überschreiben wir bei "Sichern" eine zwischenzeitliche Änderung eines anderen Benutzers. Also bei Übergang in den Änderungsmodus immer erst sperren, dann nochmal lesen:
* to address change method to_change. * enqueue KNA1 enqueue( ). * read data again s10databaseread( ). * to adress change s10nextscreen( 'change'). endmethod.
Das SAP-System enthält generierte Funktionsbausteine zum Sperren von Objekten; ihr Name beginnt mit "enqueue_". Welchen Enqueue-Baustein Sie aufrufen müssen, bekommen Sie am einfachsten dadurch heraus, dass Sie die jeweiligen SAP-Änderungstransaktion aufrufen und dann mit SM12 nachschauen, welche Sperre mit Ihrem Benutzernamen angelegt wurde. Ein Doppelklick auf den Sperreintrag zeigt die technischen Eigenschaften und dort den "Enqueue-Objekt-Namen":
In diesem Fall sehen wir, dass der Funktionsbaustein "ENQUEUE_EXKNA1" zum Sperren aufgerufen werden muss. In unserer ABAP-Methode "enqueue" geben wir eine passende Fehlermeldung aus, wenn das Objekt zur Zeit gesperrt ist. Der Benutzer, der zur Zeit das Objekt gesperrt hat, findet sich nach Aufruf des Enqueue-Bausteins im Systemfeld "sy-msgv1".
* enqueue KNA1 method enqueue. call function 'ENQUEUE_EXKNA1' exporting kunnr = kunnr exceptions others = 1. if sy-subrc ne 0. s10errormessage( exporting text = |Kunde wird zur Zeit durch Benutzer | && sy-msgv1 && | bearbeitet| ). endif. endmethod.
Wenn der Kunde nicht gesperrt ist, wird durch s10nextscreen( "change" ) der Änderungsscreen "change" aufgerufen:
Die Adressfelder sind nun eingabereit und als obligatorische Eingabe gekennzeichnet. Das Land ist über ein dropdown-Feld selektierbar, und es stehen die Funktionen "Prüfen", "Sichern" und "Zurück" zur Verfügung. DIe HTML-Datei dazu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=400"> <link rel='stylesheet' type='text/css' href='../../../style/s10.style.css'> <link rel='stylesheet' type='text/css' href='../../../style/custom.style.css'> <script src='../../synactiveS10/synactiveS10.java.js'></script> <title>Kundendaten)</title> </head> <body style="width: 100%; margin: 0px; padding: 0px;" onload='init();' class="colorscheme9"> <div class="headerarea" style="width: 100%; padding: 10px;"> <b>Adressänderung Kunde <span class='output' type="text" name='kunnr'></span> </b> <br /> <br /> <button type="button" class="toolbarbutton" onclick="S10Apply('check');"> Prüfen </button> <button type="button" class="toolbarbutton" onclick="S10Apply('save');"> Sichern </button> <button type="button" class="toolbarbutton" onclick="S10Apply('change_to_display');"> Zurück </button> </div> <div style="max-width: 800px"> <!-- Name 1 --> <div class="infoblock2" style="height: 50px"> <label class='label output' name="name1" for='name1'></label> <br /> <input type="text" class="input" required name="name1" id="name1" style="width: 300px;"> </div> <br /> <!-- Strasse --> <div class="infoblock2" style="height: 50px"> <label class='label output' name="stras" for='stras'></label> <br /> <input type="text" class="input" required name="stras" id="stras" style="width: 300px;"> </div> <br /> <!-- Postleitzahl --> <div class="infoblock" style="width: 100px; height: 50px;"> <label class='label output' name="pstlz" for='pstlz'></label> <br /> <input type="text" class="input" required name="pstlz" id="pstlz" style="width: 80px;"> </div> <!-- Ort --> <div class="infoblock2" style="height: 50px"> <label class='label output' name="ort01" for='ort01'></label> <br /> <input type="text" class="input" required name="ort01" id="ort01" style="width: 300px;"> </div> <!-- Land --> <div class="infoblock2" style="height: 50px;"> <label class='label output' name='land1' for='land1'></label> <br /> <select size="1" name='land1' data-s10dropdownlist='land1@dropdownlist' id='land1' class='inputselect' required style='width: 240px;'> </select> </div> </div> </body> </html> |
Einige Anmerkungen:
"Prüfen" und "Sichern" implementieren wir über die ABAP-Technik "Call transaction using...", mit der wir die SAP-Transaktion im Hintergrund durchführen, welche dann auch alle SAP-Prüfungen durchführt.
Für den Benutzer sieht es zum Beispiel wie folgt aus:
Bei "Prüfen" führen wir am Ende nur "Enter" statt "Sichern" aus; dadurch erhalten wir die Original-SAP-Fehlermeldungen. Zum Aufbau der Batch Input Mappe für XD02 können wir den "Recording Modus" in Transaktion SHDB nutzen:
Die Aufzeichnung setzen wir dann in ABAP Coding um, in dem wir aus den aktuellen Eingabedaten eine Batch-Input-Mappe aufbauen:
method save. check_or_save( save = 'X' ). endmethod. method check. check_or_save( save = 'N' ). s10infomessage( 'Eingabedaten geprüft' ). endmethod. method check_or_save. * bdc data data: bdcdatawa type bdcdata, bdcdata type table of bdcdata. * message table for call transaction data: messtabwa type bdcmsgcoll, messtab type table of bdcmsgcoll. * create bdc data * screen 101 clear bdcdatawa. bdcdatawa-program = 'SAPMF02D'. bdcdatawa-dynpro = '0101'. bdcdatawa-dynbegin = 'X'. append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'RF02D-KUNNR'. bdcdatawa-fval = s10getuservalue( 'KUNNR' ). append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'RF02D-D0110'. bdcdatawa-fval = 'X'. append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'BDC_OKCODE'. bdcdatawa-fval = '/0'. append bdcdatawa to bdcdata. * screen 110 clear bdcdatawa. bdcdatawa-program = 'SAPMF02D'. bdcdatawa-dynpro = '0110'. bdcdatawa-dynbegin = 'X'. append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'KNA1-NAME1'. bdcdatawa-fval = s10getuservalue( 'NAME1' ). append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'KNA1-ORT01'. bdcdatawa-fval = s10getuservalue( 'ORT01' ). append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'KNA1-STRAS'. bdcdatawa-fval = s10getuservalue( 'STRAS' ). append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'KNA1-PSTLZ'. bdcdatawa-fval = s10getuservalue( 'PSTLZ' ). append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'KNA1-LAND1'. bdcdatawa-fval = s10getuservalue( 'LAND1' ). append bdcdatawa to bdcdata. clear bdcdatawa. bdcdatawa-fnam = 'BDC_OKCODE'. if save = 'X'. bdcdatawa-fval = '=UPDA'. else. bdcdatawa-fval = '/0'. endif. append bdcdatawa to bdcdata. * dequeue, otherwise account is locked dequeue( ). call transaction 'XD02' with authority-check using bdcdata mode 'N' update 'S' messages into messtab. * enqueue again enqueue( ). data: messagetext type string. loop at messtab into messtabwa. * get message text message id messtabwa-msgid type messtabwa-msgtyp number messtabwa-msgnr with messtabwa-msgv1 messtabwa-msgv2 messtabwa-msgv3 messtabwa-msgv4 into messagetext. case messtabwa-msgtyp. when 'E' or 'A'. * set focus for known input fields case messtabwa-fldname. when 'KNA1-LAND1'. s10setfocus( 'LAND1' ). when 'KNA1-PSTLZ'. s10setfocus( 'PSTLZ' ). endcase. s10errormessage( messagetext ). when others. * final message after "save" if save = 'X'. s10infomessage( messagetext ). endif. endcase. endloop. endmethod.
Bitte dabei beachten:
Die Implementierung der Funktion "Zurück aus dem Änderungsmodus" ist im Prinzip simpel, wir entsperren das Objekt und setzen den Folgescreen "display". Lesen Sie an dieser Stelle aber auf alle Fälle die Daten neu ein, damit bei fehlerhaften Eingaben und dann "Zurück" alle Felder auf dem aktuell gespeicherten Stand sind.
method change_to_display. * dequeue KNA1 dequeue( ). * read data again s10databaseread( ). * next screen: display s10nextscreen( 'display'). endmethod.