This blog post is a little call to the community to share code snippets of "copy programs" for BAPI business objects. I explain the concept, how to create such a program, and propose one example.
It may be a little bit difficult to develop a program from scratch for creating a Business Object (*) by calling a create BAPI function module:
That would be much easier if there was a copy program provided to create a business object via BAPI from an existing business object:
Again, the goal of the custom program is not to copy a template business object in the production system, but to create a business object from scratch according to some client requirements; the goal of the copy program is to help developing this custom program.
The easiest way to create a copy program is to call the read BAPI to get all the business object details and pass them to the create BAPI, because the parameters are usually very similar. When they differ, usually only a small conversion logic is needed.
Here's one example of what could be such a copy program, applied to the business object BUS2172 (projects in the SAP Portfolio and Project Management module - PPM). The BAPI used by this copy program are BAPI_BUS2172_GET_DETAIL and BAPI_BUS2172_CREATE. For information, this business object is mainly stored in the table DPR_PROJECT; it can be created and maintained via the Web Dynpro application INM_WORKCENTER_APP (with the URL query ?iv_appl_type=DPO&iv_context=WS&iv_obj_type_r=DPO&iv_portal_role=DPR_PROJECT&sap-client=...)
To fill the parameters of the create BAPI, the easiest way is to call the "read" BAPI (BAPI_BUS2172_GET_DETAIL) because the parameters are usually very similar.
The read and create BAPI parameters may differ, so the parameters must be converted. For BUS2172, they differ on these points:
BAPI_BUS2172_CREATE has several specificities (which are documented in the function module documentation):
This copy program should work in all projects. Don't add anything custom when you share it.
Now we can run this copy program.
After making sure the copy program has created the business object, the parameters passed to BAPI_BUS2172_CREATE can be carefully analyzed by debug:
Now, the custom program may be created (manually) with the required logic to reproduce the same parameter values (at least for the first test run).
That would be great if people can share such copy programs because they are easy to create, they are useful and they don't contain any confidential information.
Thanks a lot for reading me!
Sandra
Here's the code of the copy program for BUS2172 (note that it's currently limited because it doesn't copy the project elements like the phases, tasks, checklist headers and items, which correspond respectively to the business object types BUS2173, BUS2175, BUS2176 and BUS2174). It works in an ABAP 7.40 system:
REPORT z_bus2172_copy_program.
PARAMETERS projguid TYPE bapi_ts_guid-project_definition_guid.
PARAMETERS projnum TYPE dpr_project-project_id.
CLASS lcl_app DEFINITION DEFERRED.
DATA go_app TYPE REF TO lcl_app.
LOAD-OF-PROGRAM.
CALL METHOD lcl_app=>('CREATE')
RECEIVING
result = go_app.
START-OF-SELECTION.
CALL METHOD go_app->('START_OF_SELECTION').
CLASS lcl_app DEFINITION FINAL
CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS class_constructor.
CLASS-METHODS create
RETURNING VALUE(result) TYPE REF TO lcl_app.
METHODS start_of_selection.
PRIVATE SECTION.
CLASS-DATA initial_external_date TYPE bapi_date.
CLASS-METHODS conv_date_ext_to_int
IMPORTING iv_date_format_externe_courant TYPE csequence
RETURNING VALUE(result) TYPE d.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD class_constructor.
DATA(d) = VALUE d( ).
WRITE d TO initial_external_date.
ENDMETHOD.
METHOD conv_date_ext_to_int.
IF iv_date_format_externe_courant = initial_external_date.
result = VALUE #( ).
ELSE.
cl_abap_datfm=>conv_date_ext_to_int( EXPORTING im_datext = iv_date_format_externe_courant
IMPORTING ex_datint = result ).
ENDIF.
ENDMETHOD.
METHOD create.
result = NEW lcl_app( ).
ENDMETHOD.
METHOD start_of_selection.
TYPES tt_description_lines TYPE STANDARD TABLE OF dpr_tv_bapi_description WITH EMPTY KEY.
DATA project_definition_guid TYPE bapi_ts_guid-project_definition_guid.
DATA es_project_definition_detail TYPE bapi_ts_project_def_detail.
DATA es_extension_out TYPE bapiparex.
DATA et_name TYPE STANDARD TABLE OF bapi_ts_name.
DATA et_description TYPE STANDARD TABLE OF bapi_ts_description.
DATA et_status TYPE STANDARD TABLE OF bapi_ts_status.
DATA et_authorization TYPE STANDARD TABLE OF bapi_ts_authorization_out.
DATA return_tab TYPE STANDARD TABLE OF bapiret2.
DATA is_extension_in TYPE bapiparex.
DATA is_project_definition TYPE bapi_ts_project_def.
DATA is_project_definition_upd TYPE bapi_ts_project_def_upd.
IF projguid IS NOT INITIAL.
project_definition_guid = projguid.
ELSE.
SELECT SINGLE guid FROM dpr_project WHERE project_id = @projnum INTO @DATA(dpr_project_guid).
IF sy-subrc <> 0.
MESSAGE |Project "{ projnum }" not found in table DPR_PROJECT| TYPE 'I' DISPLAY LIKE 'E'.
RETURN.
ENDIF.
project_definition_guid = dpr_project_guid.
ENDIF.
CALL FUNCTION 'BAPI_BUS2172_GET_DETAIL'
EXPORTING
project_definition_guid = project_definition_guid
IMPORTING
es_project_definition_detail = es_project_definition_detail
es_extension_out = es_extension_out
TABLES
et_name = et_name
et_description = et_description
et_status = et_status
et_authorization = et_authorization
return = return_tab.
LOOP AT return_tab REFERENCE INTO DATA(return_line)
WHERE type CA 'AEX'.
WRITE / return_line->message.
ENDLOOP.
IF sy-subrc = 0.
MESSAGE 'Error(s) during GET_DETAIL c.f. messages in the list/spool' TYPE 'I' DISPLAY LIKE 'E'.
RETURN.
ENDIF.
is_extension_in = es_extension_out.
es_extension_out = VALUE #( ).
DATA(description_lines) = VALUE tt_description_lines( FOR <description_line> IN et_description
WHERE ( language = es_project_definition_detail-master_language )
( <description_line>-description_line ) ).
CONCATENATE LINES OF description_lines INTO DATA(project_description) RESPECTING BLANKS.
cl_dpr_bapi_services=>convert_string_to_rawparts( EXPORTING iv_desc_string = project_description
IMPORTING ev_desc_part1 = DATA(desc_part1)
ev_desc_part2 = DATA(desc_part2)
ev_desc_part3 = DATA(desc_part3)
ev_desc_part4 = DATA(desc_part4) ).
" The error "Enter an object number" (DPR_CGPL_MESSAGES003) happens if IS_PROJECT_DEFINITION-PROJECT_ID
" is filled, but no error if it's empty!? --> let's keep it empty then...
is_project_definition = VALUE bapi_ts_project_def(
project_number = ''
project_name_language = es_project_definition_detail-master_language " es_project_definition_detail-project_name_language
project_name = VALUE #( et_name[ language = es_project_definition_detail-master_language ]-name OPTIONAL ) " es_project_definition_detail-project_name
project_type = es_project_definition_detail-project_type
project_cause = es_project_definition_detail-project_cause
responsible_role_guid = es_project_definition_detail-responsible_role_guid
priority = es_project_definition_detail-priority
fixed_start_constraint_type = es_project_definition_detail-fixed_start_constraint_type
fixed_start_date = conv_date_ext_to_int( es_project_definition_detail-fixed_start_date )
fixed_finish_constraint_type = es_project_definition_detail-fixed_finish_constraint_type
fixed_finish_date = conv_date_ext_to_int( es_project_definition_detail-fixed_finish_date )
calendar = es_project_definition_detail-calendar
sold_to_party_number = es_project_definition_detail-sold_to_party_number
customer_number = es_project_definition_detail-customer_number
grouping = es_project_definition_detail-grouping
search_field = es_project_definition_detail-search_field
actual_work = es_project_definition_detail-actual_work
actual_work_unit = es_project_definition_detail-actual_work_unit
responsible_orga_unit = es_project_definition_detail-responsible_orga_unit
project_description_language = es_project_definition_detail-master_language " es_project_definition_detail-project_description_language
project_description_part1 = desc_part1 " es_project_definition_detail-project_description_part1
project_description_part2 = desc_part2 " es_project_definition_detail-project_description_part2
project_description_part3 = desc_part3 " es_project_definition_detail-project_description_part3
project_description_part4 = desc_part4 " es_project_definition_detail-project_description_part4
location = es_project_definition_detail-location
allocation_unit = es_project_definition_detail-allocation_unit
period_type = es_project_definition_detail-period_type
forecasted_start = conv_date_ext_to_int( es_project_definition_detail-forecasted_start )
forecasted_finish = conv_date_ext_to_int( es_project_definition_detail-forecasted_finish )
master_language = es_project_definition_detail-master_language ).
is_project_definition_upd = VALUE bapi_ts_project_def_upd(
project_number = xsdbool( is_project_definition-project_number IS NOT INITIAL )
project_name_language = xsdbool( is_project_definition-project_name_language IS NOT INITIAL )
project_name = xsdbool( is_project_definition-project_name IS NOT INITIAL )
project_type = xsdbool( is_project_definition-project_type IS NOT INITIAL )
project_cause = xsdbool( is_project_definition-project_cause IS NOT INITIAL )
responsible_role_guid = xsdbool( is_project_definition-responsible_role_guid IS NOT INITIAL )
priority = xsdbool( is_project_definition-priority IS NOT INITIAL )
fixed_start_constraint_type = xsdbool( is_project_definition-fixed_start_constraint_type IS NOT INITIAL )
fixed_start_date = xsdbool( is_project_definition-fixed_start_date IS NOT INITIAL )
fixed_finish_constraint_type = xsdbool( is_project_definition-fixed_finish_constraint_type IS NOT INITIAL )
fixed_finish_date = xsdbool( is_project_definition-fixed_finish_date IS NOT INITIAL )
calendar = xsdbool( is_project_definition-calendar IS NOT INITIAL )
sold_to_party_number = xsdbool( is_project_definition-sold_to_party_number IS NOT INITIAL )
customer_number = xsdbool( is_project_definition-customer_number IS NOT INITIAL )
grouping = xsdbool( is_project_definition-grouping IS NOT INITIAL )
search_field = xsdbool( is_project_definition-search_field IS NOT INITIAL )
actual_work = xsdbool( is_project_definition-actual_work IS NOT INITIAL )
actual_work_unit = xsdbool( is_project_definition-actual_work_unit IS NOT INITIAL )
responsible_orga_unit = xsdbool( is_project_definition-responsible_orga_unit IS NOT INITIAL )
project_description_language = xsdbool( is_project_definition-project_description_language IS NOT INITIAL )
project_description = xsdbool( is_project_definition-project_description_part1 IS NOT INITIAL
OR is_project_definition-project_description_part2 IS NOT INITIAL
OR is_project_definition-project_description_part3 IS NOT INITIAL
OR is_project_definition-project_description_part4 IS NOT INITIAL )
location = xsdbool( is_project_definition-location IS NOT INITIAL )
allocation_unit = xsdbool( is_project_definition-allocation_unit IS NOT INITIAL )
period_type = xsdbool( is_project_definition-period_type IS NOT INITIAL )
forecasted_start = xsdbool( is_project_definition-forecasted_start IS NOT INITIAL )
forecasted_finish = xsdbool( is_project_definition-forecasted_finish IS NOT INITIAL )
extensions = xsdbool( is_extension_in IS NOT INITIAL ) ).
CALL FUNCTION 'BAPI_BUS2172_CREATE'
EXPORTING
is_project_definition = is_project_definition
is_project_definition_upd = is_project_definition_upd
is_extension_in = is_extension_in
IMPORTING
es_extension_out = es_extension_out
TABLES
return = return_tab.
LOOP AT return_tab REFERENCE INTO return_line
WHERE type CA 'AEX'.
WRITE : / return_line->type, return_line->number, return_line->id, return_line->message.
ENDLOOP.
IF sy-subrc = 0.
CALL FUNCTION 'BAPI_CPROJECTS_ROLLBACK_WORK'
TABLES
return = return_tab.
MESSAGE 'Error(s) during CREATE c.f. messages in the list/spool' TYPE 'I' DISPLAY LIKE 'E'.
RETURN.
ENDIF.
LOOP AT return_tab REFERENCE INTO return_line.
WRITE : / return_line->type, return_line->number, return_line->id, return_line->message.
ENDLOOP.
IF 0 = 1.
MESSAGE s114(dpr_bapi) ##MG_MISSING.
ENDIF.
DATA(success_message) = VALUE #( return_tab[ id = 'DPR_BAPI'
number = '114' ] OPTIONAL ).
CALL FUNCTION 'BAPI_CPROJECTS_COMMIT_WORK'
TABLES
return = return_tab.
LOOP AT return_tab REFERENCE INTO return_line.
WRITE : / return_line->type, return_line->number, return_line->id, return_line->message.
ENDLOOP.
IF success_message IS NOT INITIAL.
DATA(project_guid) = CONV dpr_project-guid( success_message-message_v1 ).
SELECT SINGLE project_id FROM dpr_project WHERE guid = @project_guid INTO @DATA(project_id).
IF sy-subrc = 0.
WRITE / |GUID { project_guid } = Project { project_id } |.
ENDIF.
ENDIF.
ENDMETHOD.
ENDCLASS.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 13 | |
| 7 | |
| 6 | |
| 4 | |
| 4 | |
| 3 | |
| 2 | |
| 2 | |
| 2 | |
| 2 |