class references : https://github.com/juanandasatria/ZCL_UPLOAD_EXCEL.git
In a standard way, we can create a network and activity using code CJ20N under project and WBS. But now we have a request to create a program to mass-create the network activity using BAPI.
BAPI on PS has unique behavior to make it work properly. They must run with this sequence:
- BAPI_PS_INITIALIZATION
- BAPI_BUS**** (this is the main BAPI that does the Create/Change on your program)
- BAPI_PS_PRECOMMIT
- BAPI_TRANSACTION_COMMIT
Based on the sequence, we can use the BAPI just for testing purposes. We have to know that one of the functions of BAPI_PS_PRECOMMIT is to generate the document number, while BAPI_BUS**** is doing all the checks and preparing the document. And finally, BAPI_TRANSACTION_COMMIT will publish the document.
If we want to run in test mode without generating the document number then it should be run the BAPI_PS_INITIALIZATION then BAPI_BUS**** only.
BAPI that we can use:
- Create Network : BAPI_BUS2002_CREATE
- Create Activity : BAPI_BUS2002_ACT_CREATE_MULTI
Here is the example of the code that running BAPI create Network:
* ==================================================================== *
* Description..: Upload Network Activity *
* ==================================================================== *
REPORT z_upl_network_activity.
* -------------------------------------------------------------------- *
* G L O B A L V A R I A B L E
* -------------------------------------------------------------------- *
DEFINE _set_text.
TRY.
lo_col = lo_cols->get_column( &1 ).
lo_col->set_short_text( CONV scrtext_s( &2 ) ).
lo_col->set_medium_text( CONV scrtext_m( &2 ) ).
lo_col->set_long_text( CONV scrtext_l( &2 ) ).
CATCH cx_salv_not_found.
ENDTRY.
END-OF-DEFINITION.
TABLES: sscrfields.
CLASS: lcl_main DEFINITION DEFERRED.
TYPES: BEGIN OF ty_xlsx_raw,
" NETWORK
project_definition TYPE char100,
wbs_element TYPE char100,
network TYPE char100,
network_type TYPE char100,
short_text TYPE char100,
plant TYPE char10,
profit_ctr TYPE char100,
mrp_controller TYPE char100,
profile TYPE char100,
bus_area TYPE char100,
" ACTIVITY
control_key TYPE char100,
activity TYPE char100,
description TYPE char100,
duration_normal TYPE dummy,
duration_normal_unit TYPE char100,
work TYPE dummy,
work_unit TYPE dummy,
work_center TYPE dummy,
matl_group TYPE char100,
purch_org TYPE char100,
pur_group TYPE char100,
requisitioner TYPE char100,
recipient TYPE char100,
tracking_number TYPE dummy,
currency TYPE char100,
operation_qty TYPE char100,
operation_measure_unit TYPE char100,
price TYPE char100,
price_unit TYPE char100,
cost_elem TYPE char100,
start_date TYPE char10,
finish_date TYPE char10,
END OF ty_xlsx_raw,
tt_xlsx_raw TYPE TABLE OF ty_xlsx_raw.
" must have same fieldname with ty_xlsx_raw
" fields sort order is not necessary
TYPES: BEGIN OF ty_xlsx,
" NETWORK
project_definition TYPE bapi_bus2002_new-project_definition,
wbs_element TYPE bapi_bus2002_new-wbs_element,
network TYPE bapi_bus2002_new-network,
network_type TYPE bapi_bus2002_new-network_type,
short_text TYPE bapi_bus2002_new-short_text,
plant TYPE bapi_bus2002_new-plant,
profit_ctr TYPE bapi_bus2002_new-profit_ctr,
mrp_controller TYPE bapi_bus2002_new-mrp_controller,
profile TYPE bapi_bus2002_new-profile,
bus_area TYPE bapi_bus2002_new-bus_area,
" ACTIVITY
control_key TYPE bapi_bus2002_act_new-control_key,
activity TYPE bapi_bus2002_act_new-activity,
description TYPE bapi_bus2002_act_new-description,
duration_normal TYPE bapi_bus2002_act_new-duration_normal, " dummy
duration_normal_unit TYPE bapi_bus2002_act_new-duration_normal_unit,
work TYPE bapi_bus2002_act_new-work_activity, " dummy,
work_unit TYPE bapi_bus2002_act_new-un_work, " dummy,
work_center TYPE bapi_bus2002_act_new-work_cntr, " dummy,
matl_group TYPE bapi_bus2002_act_new-matl_group,
purch_org TYPE bapi_bus2002_act_new-purch_org,
pur_group TYPE bapi_bus2002_act_new-pur_group,
requisitioner TYPE bapi_bus2002_act_new-preq_name,
recipient TYPE bapi_bus2002_act_new-gr_rcpt,
tracking_number TYPE bapi_bus2002_act_new-trackingno, "dummy,
currency TYPE bapi_bus2002_act_new-currency,
operation_qty TYPE bapi_bus2002_act_new-operation_qty,
operation_measure_unit TYPE bapi_bus2002_act_new-operation_measure_unit,
price TYPE bapi_bus2002_act_new-price,
price_unit TYPE bapi_bus2002_act_new-price_unit,
cost_elem TYPE bapi_bus2002_act_new-cost_elem,
start_date TYPE bapi_bus2002_act_new-early_start_date,
finish_date TYPE bapi_bus2002_act_new-early_finish_date,
END OF ty_xlsx,
tt_xlsx TYPE TABLE OF ty_xlsx.
TYPES: BEGIN OF ty_data,
icon TYPE icon_d.
INCLUDE TYPE ty_xlsx.
TYPES: aufnr TYPE afko-aufnr,
message TYPE char255,
END OF ty_data,
tt_data TYPE TABLE OF ty_data.
DATA: t_xlsx_raw TYPE tt_xlsx_raw,
t_data TYPE tt_data,
gv_error TYPE boolean.
DATA: o_main TYPE REF TO lcl_main.
CONSTANTS:
c_start_time TYPE syst-uzeit VALUE '000000',
c_finish_time TYPE syst-uzeit VALUE '000000',
c_icon_error TYPE icon_d VALUE icon_led_red,
c_icon_success TYPE icon_d VALUE icon_led_green.
* -------------------------------------------------------------------- *
* S E L E C T I O N S C R E E N
* -------------------------------------------------------------------- *
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS: p_file TYPE file_table-filename LOWER CASE.
PARAMETERS: p_test AS CHECKBOX USER-COMMAND test.
SELECTION-SCREEN END OF BLOCK b1.
SELECTION-SCREEN FUNCTION KEY 1.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
p_file = zclzca_upload_excel=>f4_filename( ).
AT SELECTION-SCREEN.
IF sscrfields-ucomm = 'FC01'.
PERFORM f_download.
ENDIF .
* -------------------------------------------------------------------- *
* C L A S S
* -------------------------------------------------------------------- *
CLASS lcl_main DEFINITION INHERITING FROM zclzca_upload_excel.
PUBLIC SECTION.
METHODS:
get_data,
show_data,
create_ps
IMPORTING
i_test TYPE boolean,
convert_data.
PRIVATE SECTION.
DATA: mv_is_external TYPE nriv-externind,
mo_alv TYPE REF TO cl_salv_table.
METHODS:
alv_set_columns,
get_interval_external,
create_network
IMPORTING
i_test TYPE boolean
is_data TYPE ty_data
EXPORTING
e_aufnr TYPE aufnr
e_msg TYPE string
e_error TYPE boolean,
create_activities
IMPORTING
i_aufnr TYPE aufnr
i_test TYPE boolean
it_data TYPE tt_data
EXPORTING
e_msg TYPE string
e_error TYPE boolean.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD get_data.
convert_xlsx_to_itab( EXPORTING i_file = p_file i_initial_row = 2 CHANGING ct_data = t_xlsx_raw ).
convert_data( ).
ENDMETHOD. " get_data
METHOD convert_data.
DATA: ls_xlsx TYPE ty_xlsx_raw.
DATA(lo_struct) = CAST cl_abap_structdescr( cl_abap_tabledescr=>describe_by_data( ls_xlsx ) ).
DATA(lt_comps) = lo_struct->components.
LOOP AT t_xlsx_raw INTO ls_xlsx.
APPEND INITIAL LINE TO t_data ASSIGNING FIELD-SYMBOL(<lfs_data>).
DO.
DATA(lv_index) = sy-index.
ASSIGN COMPONENT lv_index OF STRUCTURE ls_xlsx TO FIELD-SYMBOL(<lfs_source>).
IF sy-subrc NE 0.
EXIT.
ELSE.
READ TABLE lt_comps INTO DATA(ls_comp) INDEX lv_index.
IF sy-subrc EQ 0.
ASSIGN COMPONENT ls_comp-name OF STRUCTURE <lfs_data> TO FIELD-SYMBOL(<lfs_target>).
IF sy-subrc EQ 0.
CASE ls_comp-name.
WHEN 'WORK_UNIT' OR 'DURATION_NORMAL_UNIT'.
<lfs_target> = convert_in_unit( <lfs_source> ).
WHEN 'NETWORK'.
<lfs_target> = |{ <lfs_source> ALPHA = IN }|.
WHEN 'PRICE'.
ASSIGN COMPONENT 'CURRENCY' OF STRUCTURE ls_xlsx TO FIELD-SYMBOL(<lfs_cuky>).
IF <lfs_cuky> EQ 'IDR'.
<lfs_target> = <lfs_source> / 100.
ELSE.
<lfs_target> = <lfs_source>.
ENDIF.
WHEN 'START_DATE' OR 'FINISH_DATE'.
<lfs_target> = convert_in_date( <lfs_source> ).
WHEN OTHERS.
<lfs_target> = <lfs_source>.
ENDCASE.
ENDIF.
ENDIF.
ENDIF.
ENDDO.
ENDLOOP.
ENDMETHOD. " convert_data
METHOD create_network.
DATA: lt_bapiret2 TYPE TABLE OF bapiret2,
ls_network TYPE bapi_bus2002_new,
lv_msg TYPE string,
lv_dummy TYPE char100.
IF is_data-network IS NOT INITIAL.
SELECT SINGLE aufnr
FROM afko
INTO @DATA(lv_aufnr)
WHERE aufnr = @is_data-network.
IF sy-subrc EQ 0.
CONCATENATE 'Order' lv_aufnr 'is already been created' INTO lv_msg SEPARATED BY space.
WRITE:/ lv_msg.
MESSAGE s003(zca) DISPLAY LIKE 'E' WITH lv_aufnr. " Order & is already been created
EXIT.
ENDIF.
ENDIF.
CALL FUNCTION 'BAPI_PS_INITIALIZATION'.
IF mv_is_external EQ 'X'.
ls_network-network = is_data-network.
ELSE.
ls_network-network = ''.
ENDIF.
ls_network-network_type = is_data-network_type.
ls_network-profile = is_data-profile.
ls_network-plant = is_data-plant.
ls_network-mrp_controller = is_data-mrp_controller.
ls_network-short_text = is_data-short_text.
ls_network-start_date = is_data-start_date.
ls_network-finish_date = is_data-finish_date.
ls_network-sched_type = '1'.
ls_network-not_auto_schedule = 'X'.
ls_network-not_mrp_applicable = 'X'.
ls_network-project_definition = is_data-project_definition.
ls_network-wbs_element = is_data-wbs_element.
ls_network-bus_area = is_data-bus_area.
ls_network-objectclass = 'IV'.
ls_network-currency = is_data-currency.
CALL FUNCTION 'BAPI_BUS2002_CREATE'
EXPORTING
i_network = ls_network
TABLES
et_return = lt_bapiret2.
LOOP AT lt_bapiret2 INTO DATA(ls_bapiret2).
lv_msg = build_message_bapiret2( ls_bapiret2 ).
WRITE:/ ls_bapiret2-type, lv_msg.
IF ls_bapiret2-type EQ 'E'.
IF e_msg IS NOT INITIAL.
CONCATENATE e_msg lv_msg INTO e_msg SEPARATED BY ';'.
ELSE.
e_msg = lv_msg.
ENDIF.
ENDIF.
ENDLOOP.
IF line_exists( lt_bapiret2[ type = 'E' ] ).
e_error = 'X'.
EXIT.
ENDIF.
IF i_test NE 'X'.
CALL FUNCTION 'BAPI_PS_PRECOMMIT' TABLES et_return = lt_bapiret2.
READ TABLE lt_bapiret2 INTO ls_bapiret2 WITH KEY type = 'S' id = 'CNIF_PI' number = '052'.
IF sy-subrc EQ 0.
SPLIT ls_bapiret2-message_v2 AT space INTO e_aufnr lv_dummy.
e_aufnr = |{ e_aufnr ALPHA = IN }|.
ENDIF.
LOOP AT lt_bapiret2 INTO ls_bapiret2.
lv_msg = build_message_bapiret2( ls_bapiret2 ).
WRITE:/ ls_bapiret2-type, lv_msg.
IF ls_bapiret2-type EQ 'E'.
IF e_msg IS NOT INITIAL.
CONCATENATE e_msg lv_msg INTO e_msg SEPARATED BY ';'.
ELSE.
e_msg = lv_msg.
ENDIF.
ENDIF.
ENDLOOP.
IF line_exists( lt_bapiret2[ type = 'E' ] ).
e_error = 'X'.
EXIT.
ENDIF.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
ENDMETHOD. " create_network
METHOD create_activities.
DATA: lt_bapiret2 TYPE TABLE OF bapiret2,
lt_activity TYPE TABLE OF bapi_bus2002_act_new,
lv_msg TYPE string,
lv_aufnr TYPE aufnr,
lv_vornr TYPE afvc-vornr.
IF i_test EQ 'X'.
lv_vornr = '8000'.
ELSE.
SELECT SINGLE MAX( vornr )
FROM afvc AS a
INNER JOIN afko AS b ON b~aufpl = a~aufpl
INTO lv_vornr
WHERE b~aufnr = i_aufnr.
ENDIF.
CALL FUNCTION 'BAPI_PS_INITIALIZATION'.
LOOP AT it_data INTO DATA(ls_data).
APPEND INITIAL LINE TO lt_activity ASSIGNING FIELD-SYMBOL(<lfs_act>).
" if there is already activity created inside the network, then continue numbering (+10)
" if not then start with 10
lv_vornr = lv_vornr + 10.
<lfs_act>-activity = |{ lv_vornr ALPHA = IN }|.
<lfs_act>-control_key = ls_data-control_key.
<lfs_act>-plant = ls_data-plant.
<lfs_act>-description = ls_data-description.
<lfs_act>-wbs_element = ls_data-wbs_element. " converted value
<lfs_act>-purch_org = ls_data-purch_org.
<lfs_act>-pur_group = ls_data-pur_group.
<lfs_act>-matl_group = ls_data-matl_group.
<lfs_act>-price = ls_data-price.
<lfs_act>-price_unit = ls_data-price_unit.
<lfs_act>-currency = ls_data-currency.
<lfs_act>-cost_elem = ls_data-cost_elem.
<lfs_act>-operation_qty = ls_data-operation_qty.
<lfs_act>-operation_measure_unit = ls_data-operation_measure_unit.
<lfs_act>-constraint_start_date = ls_data-start_date.
<lfs_act>-constraint_finish_date = ls_data-finish_date.
<lfs_act>-bus_area = ls_data-bus_area.
<lfs_act>-preq_name = ls_data-requisitioner.
<lfs_act>-gr_rcpt = ls_data-recipient.
ENDLOOP.
IF i_test EQ 'X'.
DATA(lv_pronr) = convert_in_project( ls_data-project_definition ).
DATA(lv_pspel) = convert_in_wbs( ls_data-wbs_element ).
SELECT SINGLE a~aufnr
FROM aufk AS a
INNER JOIN afko AS b ON a~aufnr = b~aufnr
INTO lv_aufnr
WHERE a~auart = ls_data-network_type
AND a~pspel = lv_pspel
AND b~pronr = lv_pronr.
ELSE.
lv_aufnr = i_aufnr.
ENDIF.
CALL FUNCTION 'BAPI_BUS2002_ACT_CREATE_MULTI'
EXPORTING
i_number = lv_aufnr
TABLES
it_activity = lt_activity
et_return = lt_bapiret2.
LOOP AT lt_bapiret2 INTO DATA(ls_bapiret2).
lv_msg = build_message_bapiret2( ls_bapiret2 ).
WRITE:/ ls_bapiret2-type, lv_msg.
IF ls_bapiret2-type EQ 'E'.
IF e_msg IS NOT INITIAL.
CONCATENATE e_msg lv_msg INTO e_msg SEPARATED BY ';'.
ELSE.
e_msg = lv_msg.
ENDIF.
ENDIF.
ENDLOOP.
IF line_exists( lt_bapiret2[ type = 'E' ] ).
e_error = 'X'.
EXIT.
ENDIF.
IF i_test NE 'X'.
CALL FUNCTION 'BAPI_PS_PRECOMMIT' TABLES et_return = lt_bapiret2.
LOOP AT lt_bapiret2 INTO ls_bapiret2.
lv_msg = build_message_bapiret2( ls_bapiret2 ).
WRITE:/ ls_bapiret2-type, lv_msg.
IF ls_bapiret2-type EQ 'E'.
IF e_msg IS NOT INITIAL.
CONCATENATE e_msg lv_msg INTO e_msg SEPARATED BY ';'.
ELSE.
e_msg = lv_msg.
ENDIF.
ENDIF.
ENDLOOP.
IF line_exists( lt_bapiret2[ type = 'E' ] ).
e_error = 'X'.
EXIT.
ENDIF.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
ENDMETHOD. " create_activities
METHOD get_interval_external.
SELECT SINGLE externind
FROM nriv
INTO mv_is_external
WHERE object = 'AUFTRAG'
AND nrrangenr = '15'.
ENDMETHOD. " get_interval_external
METHOD create_ps.
DATA: lt_data_act TYPE tt_data,
lv_aufnr TYPE aufnr,
lv_msg TYPE string,
lv_error TYPE boolean.
SORT t_data BY network.
get_interval_external( ).
LOOP AT t_data ASSIGNING FIELD-SYMBOL(<lfs_data_net>) GROUP BY <lfs_data_net>-network.
CLEAR: lv_error.
lv_msg = `Processing : ` && <lfs_data_net>-network.
WRITE: / lv_msg.
" Create Network
CLEAR: lv_aufnr, lv_msg.
create_network( EXPORTING i_test = i_test is_data = <lfs_data_net> IMPORTING e_aufnr = lv_aufnr e_msg = lv_msg e_error = lv_error ).
LOOP AT GROUP <lfs_data_net> ASSIGNING FIELD-SYMBOL(<lfs_data_act>).
IF lv_error EQ 'X'.
<lfs_data_act>-icon = c_icon_error.
<lfs_data_act>-message = lv_msg.
ELSE.
<lfs_data_act>-aufnr = lv_aufnr.
ENDIF.
ENDLOOP.
CHECK lv_error EQ ''.
" Create Activities
CLEAR: lt_data_act, lv_msg.
LOOP AT GROUP <lfs_data_net> ASSIGNING <lfs_data_act>.
APPEND <lfs_data_act> TO lt_data_act.
ENDLOOP.
create_activities( EXPORTING i_aufnr = lv_aufnr i_test = i_test it_data = lt_data_act IMPORTING e_msg = lv_msg e_error = lv_error ).
LOOP AT GROUP <lfs_data_net> ASSIGNING <lfs_data_act>.
IF lv_error EQ 'X'.
<lfs_data_act>-icon = c_icon_error.
<lfs_data_act>-message = lv_msg.
ELSE.
<lfs_data_act>-aufnr = lv_aufnr.
<lfs_data_act>-icon = c_icon_success.
ENDIF.
ENDLOOP.
WRITE:/ sy-uline.
ENDLOOP.
WRITE:/ sy-uline.
IF line_exists( t_data[ icon = c_icon_error ] ).
gv_error = 'X'.
ENDIF.
IF gv_error NE 'X'.
IF p_test EQ 'X'.
WRITE:/ 'File is ready to run'.
MESSAGE s004(zca). " File is ready to run
ELSE.
WRITE:/ 'Process has been completed'.
MESSAGE s002(zca). " Process has been completed
ENDIF.
ELSE.
WRITE:/ 'Error occurred'.
MESSAGE s005(zca) DISPLAY LIKE 'E'. " Error occurred
ENDIF.
ENDMETHOD. " create_ps
METHOD alv_set_columns.
DATA: lo_col TYPE REF TO cl_salv_column.
DATA(lo_cols) = mo_alv->get_columns( ).
lo_cols->set_optimize( ).
_set_text 'ICON' 'Icon'.
_set_text 'MESSAGE' 'Message'.
ENDMETHOD. " alv_set_columns
METHOD show_data.
TRY.
CALL METHOD cl_salv_table=>factory
IMPORTING
r_salv_table = mo_alv
CHANGING
t_table = t_data.
CATCH cx_salv_msg.
ENDTRY.
DATA(lo_functions) = mo_alv->get_functions( ).
lo_functions->set_all( abap_true ).
alv_set_columns( ).
mo_alv->display( ).
ENDMETHOD. " show_data
ENDCLASS.
* -------------------------------------------------------------------- *
* I N I T I A L I Z A T I O N
* -------------------------------------------------------------------- *
INITIALIZATION.
CREATE OBJECT o_main.
sscrfields-functxt_01 = 'Download Template'.
* -------------------------------------------------------------------- *
* S T A R T O F S E L E C T I O N
* -------------------------------------------------------------------- *
START-OF-SELECTION.
PERFORM f_main.
* -------------------------------------------------------------------- *
* E N D O F S E L E C T I O N
* -------------------------------------------------------------------- *
END-OF-SELECTION.
PERFORM f_end.
* -------------------------------------------------------------------- *
* S U B R O U T I N E S
* -------------------------------------------------------------------- *
*&---------------------------------------------------------------------*
*& Form f_MAIN
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM f_main .
o_main->get_data( ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form f_download
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM f_download .
" File should saved in tcode : OAOR
o_main->download_template( i_description = 'UPLOAD_NETWORK_ACTIVITY' ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form f_end
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM f_end .
o_main->create_ps( i_test = p_test ).
o_main->show_data( ).
MESSAGE s002(zca). " Process has been completed
ENDFORM.