Changing SAP data is more complex than reading it. The following should be noted:
As an example, we include the change of some fields of the customer address in our application. For this we first define a button within the display of the address, with which the user can switch to the change mode:
In the HTML file the button is defined as follows:
<!-- Change address --> <img src="../../../icons/edit.png" style="width:32px; margin:8px; float:right" onclick="S10Apply('to_change');"/>
That is, we display a suitable png image, move it to the right side with "float:right" and execute the ABAP method "to_change" when clicking on it.
If the application is also intended to be a desktop application, we give the button a tooltip with the option title=, for example <img ... title="Change address" />:
In the ABAP method "to_change" we navigate to a new screen "change". Before that it is necessary
since it may be that another user has changed the address while we were on the display screen for a while. In change mode we must always display the actual data, otherwise when we "Save" we overwrite an intermediate change made by another user. So when transitioning to change mode, always lock first, then read again:
* to address change method to_change. * enqueue KNA1 enqueue( ). * read data again s10databaseread( ). * to adress change s10nextscreen( 'change'). endmethod.
The SAP system contains generated function modules for locking objects; their names begin with "enqueue_". The easiest way to find out which enqueue module you need to call is to call the relevant SAP change transaction and then use SM12 to see which lock was created with your user name. A double click on the lock entry shows the technical properties and there the "Lock Object name":
In this case we see that the function module "ENQUEUE_EXKNA1" must be called to lock. In our ABAP method "enqueue" we issue a suitable error message if the object is currently locked. The user who has currently locked the object can be found in the system field "sy-msgv1" after calling the enqueue module.
* enqueue KNA1 method enqueue. call function 'ENQUEUE_EXKNA1' exporting kunnr = kunnr exceptions others = 1. if sy-subrc ne 0. s10errormessage( exporting text = |Customer is currently being processed by user | && sy-msgv1 ). endif. endmethod.
If the customer is not locked, s10nextscreen( "change" ) will call the change screen "change":
The address fields are now ready for input and marked as mandatory. The country is selectable via a dropdown field and the functions "Check", "Save" and "Back" are available. The HTML file for this:
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>Customer information</title> </head> <body style="width: 100%; margin: 0px; padding: 0px;" onload='init();' class="colorscheme9"> <div class="headerarea" style="width: 100%; padding: 10px;"> <b>Address change customer <span class='output' type="text" name='kunnr'></span> </b> <br /> <br /> <button type="button" class="toolbarbutton" onclick="S10Apply('check');"> Check </button> <button type="button" class="toolbarbutton" onclick="S10Apply('save');"> Save </button> <button type="button" class="toolbarbutton" onclick="S10Apply('change_to_display');"> Back </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 /> <!-- Street --> <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 /> <!-- Postal code --> <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> <!-- City --> <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> <!-- Country --> <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> |
Some notes:
We implement "Check" and "Save" via the ABAP technique "Call transaction using...", which we use to execute the SAP transaction in the background, which then also performs all SAP checks.
For the user it then looks like this, for example::
For "Check", we just execute "Enter" instead of "Save" at the end; this way we get the original SAP error messages. To build the batch input session for XD02 we can use the "Recording Mode" in transaction SHDB:
We then convert the recording into ABAP coding by building a batch input session from the current input data:
method save. check_or_save( save = 'X' ). endmethod. method check. check_or_save( save = 'N' ). s10infomessage( 'Input data checked' ). 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.
Please note:
The implementation of the function "Back from change mode" is simple in principle: we unlock the object and set the next screen "display". At this point, however, be sure to re-read the data so that in the event of incorrect entries and then "Back", all fields are at the currently saved status.
method change_to_display. * dequeue KNA1 dequeue( ). * read data again s10databaseread( ). * next screen: display s10nextscreen( 'display'). endmethod.