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,

  1. Das Objekt zu sperren
  2. Die Kundenadresse neu zu lesen

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.