*&---------------------------------------------------------------------* *& Report Name : /EUTIN/HCM_PROVIDE *& Title : ABAP-Demo: HCM - PROVIDE *& Developer : EUTINM - 20260108 *& Development Class : /EUTIN/TOOLS *& Description : *& short demo of PROVIDE statement in context with HCM *& *& expected output (combined periods containing identical data) *& requested period: from 01.01.1900 to 31.12.9999 *& PERNR: 00001001 Michael Eutin / Period: 01.01.1980 - 30.03.2025 / Action: / / BUKRS: WERKS: PERSG: PERSK: *& PERNR: 00001001 Michael Eutin / Period: 01.04.2025 - 31.12.2026 / Action: 0001 / 0001 / BUKRS: 0100 WERKS: 9100 PERSG: 1 PERSK: 06 *& PERNR: 00001001 Michael Eutin / Period: 01.01.2027 - 31.12.2028 / Action: 0012 / 0100 / BUKRS: 0100 WERKS: 9201 PERSG: 1 PERSK: 06 *& PERNR: 00001001 Michael Eutin / Period: 01.01.2029 - 31.12.9999 / Action: 0012 / 0100 / BUKRS: 0100 WERKS: 9201 PERSG: 1 PERSK: 07 *&---------------------------------------------------------------------* *& CHANGE HISTORY *&---------------------------------------------------------------------* *& Date Description *&---------------------------------------------------------------------* *& *& *& *& *&---------------------------------------------------------------------* REPORT /eutin/hcm_provide NO STANDARD PAGE HEADING. TYPES: BEGIN OF ts_p0000, pernr TYPE n LENGTH 8, "Personnel Number (PERNR_D) endda TYPE datum, "End Date (ENDDA) begda TYPE datum, "Start Date (BEGDA) massn TYPE c LENGTH 4, "Action Type (MASSN), check table T529A massg TYPE c LENGTH 4, "Reason for Action (MASSG), check table T530 END OF ts_p0000, BEGIN OF ts_p0001, pernr TYPE n LENGTH 8, "Personnel Number (PERNR_D) endda TYPE datum, "End Date (ENDDA) begda TYPE datum, "Start Date (BEGDA) bukrs TYPE c LENGTH 4, "Company Code (BUKRS), check table T001 werks TYPE c LENGTH 4, "Personnel Area (PERSA), check table T500P persg TYPE c LENGTH 1, "Employee Group (PERSG), check table T501 persk TYPE c LENGTH 2, "Employee Subgroup (PERSK), check table T503K END OF ts_p0001, BEGIN OF ts_p0002, pernr TYPE n LENGTH 8, "Personnel Number (PERNR_D) endda TYPE datum, "End Date (ENDDA) begda TYPE datum, "Start Date (BEGDA) cname TYPE c LENGTH 160, "Complete Name (PAD_CNAME) END OF ts_p0002, BEGIN OF ts_key, pernr TYPE n LENGTH 8, "Personnel Number (PERNR_D) endda TYPE datum, "End Date (ENDDA) begda TYPE datum, "Start Date (BEGDA) END OF ts_key, BEGIN OF ts_data, cname TYPE c LENGTH 160, "Complete Name (PAD_CNAME) massn TYPE c LENGTH 4, "Action Type (MASSN), T529A massg TYPE c LENGTH 4, "Reason for Action (MASSG), T530 bukrs TYPE c LENGTH 4, "Company Code (BUKRS), T001 werks TYPE c LENGTH 4, "Personnel Area (PERSA), T500P persg TYPE c LENGTH 1, "Employee Group (PERSG), T501 persk TYPE c LENGTH 2, "Employee Subgroup (PERSK), T503K END OF ts_data, BEGIN OF ts_output, key TYPE ts_key, data TYPE ts_data, END OF ts_output, tt_p0000 TYPE STANDARD TABLE OF ts_p0000 WITH EMPTY KEY, tt_p0001 TYPE STANDARD TABLE OF ts_p0001 WITH EMPTY KEY, tt_p0002 TYPE STANDARD TABLE OF ts_p0002 WITH EMPTY KEY. PARAMETERS: begda TYPE datum OBLIGATORY DEFAULT '19990101', endda TYPE datum OBLIGATORY DEFAULT '99991231', combine AS CHECKBOX DEFAULT 'X', with_gap AS CHECKBOX DEFAULT ' '. START-OF-SELECTION. PERFORM main. *&---------------------------------------------------------------------* *& Form main *&---------------------------------------------------------------------* *& text *&---------------------------------------------------------------------* FORM main. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DATA: ls_p0000 TYPE ts_p0000, ls_p0001 TYPE ts_p0001, ls_p0002 TYPE ts_p0002, ls_key TYPE ts_key, ls_data TYPE ts_data, ls_output TYPE ts_output, lv_p0000 TYPE abap_bool, lv_p0001 TYPE abap_bool, lv_p0002 TYPE abap_bool, lv_begda TYPE c LENGTH 10, lv_endda TYPE c LENGTH 10. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *--- check input IF begda IS INITIAL OR begda GT endda. MESSAGE 'Start date (field BEGDA) must be less or equal end date (field ENDDA)!' TYPE 'S' DISPLAY LIKE 'E'. RETURN. ENDIF. *--- populate demo entries DATA(lt_p0000) = VALUE tt_p0000( ( pernr = '00001001' endda = '20261231' begda = '20250401' massn = '0001' massg = '0001' ) ( pernr = '00001001' endda = '20270131' begda = '20270101' massn = '0012' massg = '0100' ) ( pernr = '00001001' endda = '20270331' begda = '20270201' massn = '0012' massg = '0100' ) ( pernr = '00001001' endda = '20281231' begda = '20270401' massn = '0012' massg = '0100' ) ( pernr = '00001001' endda = '99991231' begda = '20290101' massn = '0012' massg = '0100' ) ). DATA(lt_p0001) = VALUE tt_p0001( ( pernr = '00001001' endda = '20261231' begda = '20260201' bukrs = '0100' werks = '9100' persg = '1' persk = '06' ) ( pernr = '00001001' endda = '20281231' begda = '20270101' bukrs = '0100' werks = '9201' persg = '1' persk = '06' ) ( pernr = '00001001' endda = '99991231' begda = '20290101' bukrs = '0100' werks = '9201' persg = '1' persk = '07' ) ). DATA(lt_p0002) = VALUE tt_p0002( ( pernr = '00001001' endda = '99991231' begda = '19800101' cname = 'Michael Eutin' ) ). *--- collect data incl. gaps (no entries in requested period) WRITE begda TO lv_begda. WRITE endda TO lv_endda. WRITE: / |requested period: from { lv_begda } to { lv_endda }|. SKIP 1. CLEAR: ls_key, ls_data, ls_output. *--- ensure data sources are sorted on bounded fields! SORT lt_p0000 ASCENDING BY pernr begda endda. SORT lt_p0001 ASCENDING BY pernr begda endda. SORT lt_p0002 ASCENDING BY pernr begda endda. IF with_gap IS NOT INITIAL. DELETE lt_p0000 WHERE begda EQ '20270201'. ENDIF. TRY. *--- process requested period incl. gaps where no records exist PROVIDE FIELDS * FROM lt_p0000 INTO ls_p0000 VALID lv_p0000 BOUNDS begda AND endda FIELDS * FROM lt_p0001 INTO ls_p0001 VALID lv_p0001 BOUNDS begda AND endda FIELDS * FROM lt_p0002 INTO ls_p0002 VALID lv_p0002 BOUNDS begda AND endda WHERE pernr EQ '00001001' BETWEEN begda AND endda INCLUDING GAPS. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *--- Note: *--- To automatically combine all splits holding identical data in bounded fields, just specify all required fields using PROVIDE FIELDS! *--- In this case, you do not have to merge periods containing identical data (no selection parameter COMBINE required). * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * PROVIDE FIELDS pernr massn massg FROM lt_p0000 INTO ls_p0000 VALID lv_p0000 BOUNDS begda AND endda * FIELDS pernr bukrs werks persg persk FROM lt_p0001 INTO ls_p0001 VALID lv_p0001 BOUNDS begda AND endda * FIELDS pernr cname FROM lt_p0002 INTO ls_p0002 VALID lv_p0002 BOUNDS begda AND endda * WHERE pernr EQ '00001001' * BETWEEN begda AND endda INCLUDING GAPS. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CLEAR: ls_key, ls_data. IF lv_p0000 IS NOT INITIAL. MOVE-CORRESPONDING ls_p0000 TO ls_key. MOVE-CORRESPONDING ls_p0000 TO ls_data. ENDIF. IF lv_p0001 IS NOT INITIAL. MOVE-CORRESPONDING ls_p0001 TO ls_key. MOVE-CORRESPONDING ls_p0001 TO ls_data. ENDIF. IF lv_p0002 IS NOT INITIAL. MOVE-CORRESPONDING ls_p0002 TO ls_key. MOVE-CORRESPONDING ls_p0002 TO ls_data. ENDIF. CASE combine. WHEN abap_true. IF ls_key-begda EQ begda. "first period found ls_output-key = ls_key. ls_output-data = ls_data. ENDIF. IF ls_data EQ ls_output-data. "change start date and end date of the period using identical data ls_output-key-endda = ls_key-endda. ls_key-begda = ls_output-key-begda. ELSE. "output collected data of previous period before processing current period IF ls_output-key-begda GE begda. WRITE ls_output-key-begda TO lv_begda. WRITE ls_output-key-endda TO lv_endda. WRITE: / |PERNR: { ls_output-key-pernr } { ls_output-data-cname }|. WRITE: | / Period: { lv_begda } - { lv_endda }|. WRITE: | / Action: { ls_output-data-massn } / { ls_output-data-massg } |. WRITE: | / BUKRS: { ls_output-data-bukrs } WERKS: { ls_output-data-werks } PERSG: { ls_output-data-persg } PERSK: { ls_output-data-persk }|. ENDIF. ls_output-key = ls_key. ls_output-data = ls_data. ENDIF. IF ls_output-key-endda EQ endda. "output collected data of final entry WRITE ls_output-key-begda TO lv_begda. WRITE ls_output-key-endda TO lv_endda. WRITE: / |PERNR: { ls_output-key-pernr } { ls_output-data-cname }|. WRITE: | / Period: { lv_begda } - { lv_endda }|. WRITE: | / Action: { ls_output-data-massn } / { ls_output-data-massg } |. WRITE: | / BUKRS: { ls_output-data-bukrs } WERKS: { ls_output-data-werks } PERSG: { ls_output-data-persg } PERSK: { ls_output-data-persk }|. ENDIF. ls_output-key = ls_key. ls_output-data = ls_data. WHEN OTHERS. IF ls_key IS NOT INITIAL. ls_output-key = ls_key. ls_output-data = ls_data. WRITE ls_output-key-begda TO lv_begda. WRITE ls_output-key-endda TO lv_endda. WRITE: / |PERNR: { ls_output-key-pernr } { ls_output-data-cname }|. WRITE: | / Period: { lv_begda } - { lv_endda }|. WRITE: | / Action: { ls_output-data-massn } / { ls_output-data-massg } |. WRITE: | / BUKRS: { ls_output-data-bukrs } WERKS: { ls_output-data-werks } PERSG: { ls_output-data-persg } PERSK: { ls_output-data-persk }|. ENDIF. ENDCASE. ENDPROVIDE. CATCH cx_sy_provide_interval_overlap INTO DATA(lx_sy_provide_interval_overlap). MESSAGE lx_sy_provide_interval_overlap->get_text( ) TYPE 'I' DISPLAY LIKE 'E'. RETURN. CATCH cx_sy_provide_table_not_sorted INTO DATA(lx_sy_provide_table_not_sorted). MESSAGE lx_sy_provide_table_not_sorted->get_text( ) TYPE 'I' DISPLAY LIKE 'E'. RETURN. CATCH cx_root INTO DATA(lx_root). MESSAGE lx_root->get_text( ) TYPE 'I' DISPLAY LIKE 'E'. RETURN. ENDTRY. ENDFORM.