Good source to start is here.
Hot to get BDC commands?
If you are new here, definitely take a look at transaction SHDB (Batch Input Transaction Recorder). It can save you lot of pains when you would be searching for proper BDC commands. Sometime even dynamically generated screens have one dynpro number in foreground and different one in background call. It means, without tool as SHDB, you are absolutely lost.In my case, I imitated manual usage of transaction LX47. The result of such a SHDB recording can looks like this.
Ok, we have a list of commands needed for background call. Now we can setup our tool set. There is some abstract base class suitable to be an ancestor of some real controller class.
The class definition
*----------------------------------------------------------------------*
* CLASS lcl_ctrl_bapi DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_ctrl_base DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
bdc_call_transaction
IMPORTING iv_transaction TYPE bdc_prog
iv_mode TYPE c1
iv_dynrbegin TYPE bdc_start
RAISING lcx_msg_exception,
bdc_add_dynpro
IMPORTING iv_program TYPE bdc_prog
iv_dynpro TYPE bdc_dynr
iv_dynrbegin TYPE bdc_start,
bdc_add_param
IMPORTING iv_name TYPE fnam_____4
iv_value TYPE bdc_fval,
bdc_init,
bdc_send_enter,
bdc_send_execute,
bdc_send_end,
bdc_send_update,
bdc_send_select_all.
PRIVATE SECTION.
DATA: t_bdcdata TYPE STANDARD TABLE OF bdcdata,
s_bdcdata LIKE LINE OF t_bdcdata. " Structure type of bdcdata
ENDCLASS. "lcl_ctrl_base DEFINITION
The class implementation
*----------------------------------------------------------------------*
* CLASS lcl_ctrl_bapi IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_ctrl_base IMPLEMENTATION.
METHOD bdc_call_transaction.
DATA: lt_msg TYPE TABLE OF bdcmsgcoll. " Collecting Error messages
FIELD-SYMBOLS: <fs_msg> TYPE bdcmsgcoll.
CALL TRANSACTION
iv_transaction
USING t_bdcdata
MODE iv_mode
UPDATE 'S' " Synchronous/Asynchronous/Local update task
MESSAGES INTO lt_msg.
IF sy-subrc NE 0.
* Error Found - fire the first one...
LOOP AT lt_msg INTO <fs_msg> WHERE msgtyp EQ 'E'.
RAISE EXCEPTION TYPE lcx_msg_exception
EXPORTING
is_msg_bdcmsgoll = <fs_msg>.
ENDLOOP.
ENDIF.
ENDMETHOD. "bdc_call_transaction
METHOD bdc_add_dynpro.
CLEAR s_bdcdata.
s_bdcdata-program = iv_program.
s_bdcdata-dynpro = iv_dynpro.
s_bdcdata-dynbegin = iv_dynrbegin.
APPEND s_bdcdata TO t_bdcdata.
ENDMETHOD. "bdc_add_dynpro
METHOD bdc_add_param.
CLEAR s_bdcdata.
s_bdcdata-fnam = iv_name.
s_bdcdata-fval = iv_value.
CONDENSE s_bdcdata-fval.
APPEND s_bdcdata TO t_bdcdata.
ENDMETHOD. "bdc_add_field
METHOD bdc_init.
CLEAR s_bdcdata.
REFRESH t_bdcdata.
ENDMETHOD. "bdc_init
METHOD bdc_send_enter.
me->bdc_add_param(
EXPORTING
iv_name = 'BDC_OKCODE'
iv_value = '/00').
ENDMETHOD. "bdc_enter
METHOD bdc_send_execute.
me->bdc_add_param(
EXPORTING
iv_name = 'BDC_OKCODE'
iv_value = '=ONLI').
ENDMETHOD. "bdc_send_execute
METHOD bdc_send_end.
me->bdc_add_param(
EXPORTING
iv_name = 'BDC_OKCODE'
iv_value = '/EECAN'). "iv_value = '/EENDE').
ENDMETHOD. "bdc_send_end
METHOD bdc_send_update.
me->bdc_add_param(
EXPORTING
iv_name = 'BDC_OKCODE'
iv_value = '=COMMIT').
ENDMETHOD. "bdc_send_update
METHOD bdc_send_select_all.
me->bdc_add_param(
EXPORTING
iv_name = 'BDC_OKCODE'
"iv_value = '/EENDE').
iv_value = '=&ALL').
ENDMETHOD. "bdc_send_select_all
ENDCLASS. "lcl_ctrl_base IMPLEMENTATION
And now, how to use it?
Imagine, you have some your own controller class inheriting from abstract base class above. So its method can looks as follows.
METHOD bdc_call_lx47.
" Input check
IF ( iv_lgnum IS INITIAL ) OR ( iv_tanum IS INITIAL ).
RETURN.
ENDIF.
DATA lv_value TYPE bdc_fval.
me->bdc_init( ).
me->bdc_add_dynpro(
EXPORTING
iv_program = 'RLLX4700'
iv_dynpro = '1000'
iv_dynrbegin = 'X'
).
MOVE iv_lgnum TO lv_value.
me->bdc_add_param(
EXPORTING
iv_name = 'PV_LGNUM' " warehouse num.
iv_value = lv_value
).
CLEAR lv_value.
MOVE iv_tanum TO lv_value.
me->bdc_add_param(
EXPORTING
iv_name = 'PR_TANUM-LOW' " transfer order num.
iv_value = lv_value
).
me->bdc_add_param(
EXPORTING
iv_name = 'PV_MARK' " set active, the checkbox
iv_value = 'X'
).
me->bdc_send_execute( ). " emulate click on first screen
" Select all
me->bdc_add_dynpro(
EXPORTING
iv_program = 'SAPMSSY0'
iv_dynpro = '0120'
iv_dynrbegin = 'X'
).
me->bdc_send_select_all( ).
" Update
me->bdc_add_dynpro(
EXPORTING
iv_program = 'SAPMSSY0'
iv_dynpro = '0120'
iv_dynrbegin = 'X'
).
me->bdc_send_update( ).
me->bdc_call_transaction(
EXPORTING
iv_transaction = 'LX47'
iv_mode = 'N' " A - foreground / E - errors only / N - no display
iv_dynrbegin = abap_true
).
ENDMETHOD. "bdc_call_lx47
To be exact in case of LX47 I had to check if any data exists before calling of second screen number 120, that why I used below check before actual BDC call. So this part is just for those who are interested in full LX47 call :)
METHOD bdc_check_call_lx47.
" Input check
IF ( iv_lgnum IS INITIAL ) OR ( iv_tanum IS INITIAL ).
RETURN.
ENDIF.
" LX47 data check
" Read data from the transfer order header table
DATA: lv_mark TYPE lvs_selkz,
lv_item TYPE lvs_selkz,
lt_ltodn TYPE STANDARD TABLE OF ltodn,
lt_tanum TYPE STANDARD TABLE OF range_n10,
ls_tanum LIKE LINE OF lt_tanum.
lv_mark = abap_true.
ls_tanum-sign = 'I'.
ls_tanum-option = 'EQ'.
ls_tanum-low = iv_tanum.
APPEND ls_tanum TO lt_tanum.
CALL FUNCTION 'L_TO_DN_READ'
EXPORTING
iv_lgnum = iv_lgnum
iv_mark = lv_mark
iv_item = lv_item
TABLES
et_ltodn = lt_ltodn
ir_tanum = lt_tanum
"ir_vbeln = pr_vbeln
EXCEPTIONS
not_found = 1
not_found_to_dn = 2
not_found_dn = 3.
IF sy-subrc NE 0.
RETURN. " no data for BDC LX47 call
ENDIF.
me->bdc_call_lx47(
EXPORTING
iv_lgnum = iv_lgnum
iv_tanum = iv_tanum
).
ENDMETHOD. "bdc_check_call_lx47
No comments:
Post a Comment