ZHR_AUSW05 – Auswertung von Zeitarten

Hier ein Bsp. für die Auswertung von Zeitarten ,hier die Anzahl der Mehrstunden (Hier Zeitart 9320)

Per Ampelsystem wird auf Handlungsbedarf hingewiesen.

Personen ohne Zeitart 9320 haben keine Mehrstunden (Fehler).

Personen mit Zeitart 9320 unter einem Schwellwert sind unkritisch (Grün).

Personen mit Zeitart 9320 über einen Schwellwert sind kritisch (Rot).

REPORT zhr_ausw05.
*
* Programm zur Ausgabe von Stunden (Mehrstunden)
* Fehler, wenn keine Daten vorhanden sind.
* Saldotabelle fehlerhaft.
* HST20190904 Version 003
*   Sortierung eingebaut
*   Aggregation der Stunden einegebaut
* HST20190903 Version 002
*   Anzahl eingebaut dezimal, Anzahl eingebaut hh:mm
* HST20190902 Version 001
*   Erstversion
CONSTANTS p_debug VALUE 1. "0 Kein Debug 1 Debug
CONSTANTS p_begin(2) TYPE c VALUE '16'. "Periodenbeginn
TABLES: pa0001, pa0007, pa2001, pa2002.

TYPE-POOLS: icon.


TYPES: BEGIN OF ty_alv,
         ampel(4)  TYPE c,
         pernr     TYPE persno,
         nachn     TYPE pad_nachn,
         vorna     TYPE pad_vorna,
         begda     TYPE begda,
         endda     TYPE endda,
         anzhl     TYPE p DECIMALS 2,
         anzhlc(8) TYPE c,
         anzhlp    TYPE p DECIMALS 2, "Anzahl Periodenanfang
         "         anzhlpc(8) TYPE c,
         anzhld    TYPE p DECIMALS 2, "Differenz Anzahl
         "         anzhldc(8) TYPE c,
*         anzhl    TYPE ptm_quonum,   "Abtragungskontingent
*         desta    TYPE ptm_dedstart, "Abtragungsbeginn
*         deend    TYPE ptm_dedend,   "Abtragungsende
*         urlgep   TYPE p DECIMALS 1, "Geplanter Urlaub
*         urlugep  TYPE p DECIMALS 1, "Ungeplanter offener Urlaub
*         urloffen TYPE p DECIMALS 1, "Ungeplanter und geplanter Urlaub, nicht genossen
         persk     TYPE persk,
         persg     TYPE persg, "Mitarbeitergruppe
         abkrs     TYPE abkrs, "Abrechnungskreis
         btrtl     TYPE btrtl, "Teilbereich
         teilk     TYPE teilk, "Teilzeit

*         ausw(6)   TYPE c,
*         "datvo type
*         kunnr     TYPE bsad-kunnr,
*         name1     TYPE kna1-name1,
*         belnr     TYPE bsad-belnr,
*         gjahr     TYPE bsad-gjahr,
*         shkzg     TYPE bsad-shkzg,
*         dmbtr     TYPE bsad-dmbtr,
*         sknto     TYPE bsad-sknto,
*         blart     TYPE bsad-blart,
*         budat     TYPE bsad-budat,
*         bldat     TYPE bsad-bldat,
*         "faedt     TYPE bsad-faedt,
*         augdt     TYPE bsad-augdt,
*         zfbdt     TYPE bsad-zfbdt,
*         zbd1t     TYPE bsad-zbd1t,
*         zbd2t     TYPE bsad-zbd2t,
*         zbd1p     TYPE bsad-zbd1p,
*         zbd2p     TYPE bsad-zbd2p,
*         faed1     TYPE bsad-zfbdt, "FälligSkonto
*         faed2     TYPE bsad-zfbdt, "FälligNetto
*         meng1     TYPE bsad-zbd1t,
*         meng2     TYPE bsad-zbd1t,
*         bewer     TYPE mseg-menge, "Bewertung
         ausw(11)  TYPE c,     "Filterauswahl
         bemer(50) TYPE c,
       END OF ty_alv.
DATA: gt_alv_pers TYPE STANDARD TABLE OF ty_alv,
      gt_alv      TYPE STANDARD TABLE OF ty_alv,
      gs_alv      TYPE ty_alv.




SELECTION-SCREEN BEGIN OF BLOCK all WITH FRAME.
SELECTION-SCREEN BEGIN OF BLOCK per WITH FRAME TITLE text-001.
SELECT-OPTIONS: so_pernr FOR pa0001-pernr MATCHCODE OBJECT prem. " DEFAULT '1998'.
SELECT-OPTIONS: so_persk FOR pa0001-persk."Mitarbeiterkreis AE Arbeiter AH Angestellte
SELECT-OPTIONS: so_persg FOR pa0001-persg."Mitarbeitergruppe Aktiv etc.
SELECT-OPTIONS: so_abkrs FOR pa0001-abkrs."Abrechnungskreis A1, A2
SELECT-OPTIONS: so_zterf FOR pa0007-zterf NO-DISPLAY."Zeiterfasssungskennzeichen 1 aktiv

PARAMETERS:
  p_zterf TYPE xfeld AS CHECKBOX DEFAULT ''.
SELECTION-SCREEN SKIP.

"Werden weiter unten ausgeblendet
PARAMETERS :
  p_arb  RADIOBUTTON GROUP g1,
  p_ang  RADIOBUTTON GROUP g1,
  p_alle RADIOBUTTON GROUP g1 DEFAULT 'X'.


"parameters: p_orgeh type orgeh.
SELECTION-SCREEN END OF BLOCK per.
SELECTION-SCREEN BEGIN OF BLOCK dat WITH FRAME TITLE text-002.
SELECT-OPTIONS: so_datum FOR sy-datum OBLIGATORY NO-EXTENSION.
"Ohne Verwendung ????
SELECTION-SCREEN SKIP.
PARAMETERS:
  p_anz TYPE p DECIMALS 1 DEFAULT 5.
"PARAMETERS :
"  p_ugep  RADIOBUTTON GROUP g3 DEFAULT 'X',
"  p_offen RADIOBUTTON GROUP g3.
PARAMETERS: p_factid TYPE wfcid DEFAULT 'AT' NO-DISPLAY.
SELECTION-SCREEN END OF BLOCK dat.


SELECTION-SCREEN BEGIN OF BLOCK sort WITH FRAME TITLE text-004.
PARAMETERS:
  p_sortn RADIOBUTTON GROUP g2 DEFAULT 'X', "Nachname sortiert
  p_sortp RADIOBUTTON GROUP g2.             "Personalnummer sortiert
SELECTION-SCREEN SKIP.
PARAMETERS:
  p_visibl TYPE xfeld AS CHECKBOX DEFAULT abap_false. "0007 Felder sichtbar

SELECTION-SCREEN END OF BLOCK sort.


SELECTION-SCREEN BEGIN OF BLOCK outp WITH FRAME TITLE text-005.
PARAMETERS:
  p_out0 RADIOBUTTON GROUP g4 , "DEFAULT 'X', "Dialog Output
  p_out1 RADIOBUTTON GROUP g4 DEFAULT 'X'.             "ALV Output
SELECTION-SCREEN SKIP.
PARAMETERS:
  p_outp TYPE xfeld AS CHECKBOX DEFAULT abap_false. "Perioden Anzahl Anfang und Differenz
SELECTION-SCREEN END OF BLOCK outp.


SELECTION-SCREEN END OF BLOCK all.

DATA lt_pa0007 TYPE TABLE OF pa0007."AZP Aktiv
DATA lt_pa0000 TYPE TABLE OF pa0000."Maßnahmen (Aktiv)
DATA lt_pa0002 TYPE TABLE OF pa0002."Namen- und Adressdaten
DATA lt_pa0001 TYPE TABLE OF pa0001."Orgzugehörigkeit
DATA lt_pa2001 TYPE TABLE OF pa2001."Abwesenheiten
DATA lt_pa2002 TYPE TABLE OF pa2002."Anwesenheiten

DATA lt_pa2006 TYPE TABLE OF pa2006."Urlaubskontingente
DATA ls_pa2006 TYPE pa2006."Urlaubskontingente


TYPES: BEGIN OF ty_pers,
         pernr TYPE persno,
         begda TYPE begda,
         endda TYPE endda,
       END OF ty_pers.

DATA ls_pa TYPE ty_pers.
DATA lt_pa TYPE TABLE OF ty_pers.


CLASS cl_event_handler DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS on_before_salv_function         " BEFORE_SALV_FUNCTION
      FOR EVENT if_salv_events_functions~before_salv_function
                  OF cl_salv_events_table
      IMPORTING e_salv_function.

    CLASS-METHODS on_after_salv_function          " AFTER_SALV_FUNCTION
      FOR EVENT if_salv_events_functions~before_salv_function
                  OF cl_salv_events_table
      IMPORTING e_salv_function.

    CLASS-METHODS on_added_function               " ADDED_FUNCTION
      FOR EVENT if_salv_events_functions~added_function
                  OF cl_salv_events_table
      IMPORTING e_salv_function.

    CLASS-METHODS on_top_of_page                  " TOP_OF_PAGE
      FOR EVENT if_salv_events_list~top_of_page
                  OF cl_salv_events_table
      IMPORTING r_top_of_page
                  page
                  table_index.

    CLASS-METHODS on_end_of_page                  " END_OF_PAGE
      FOR EVENT if_salv_events_list~end_of_page
                  OF cl_salv_events_table
      IMPORTING r_end_of_page
                  page.

    CLASS-METHODS on_double_click                 " DOUBLE_CLICK
      FOR EVENT if_salv_events_actions_table~double_click
                  OF cl_salv_events_table
      IMPORTING row
                  column.

    CLASS-METHODS on_link_click                   " LINK_CLICK
      FOR EVENT if_salv_events_actions_table~link_click
                  OF cl_salv_events_table
      IMPORTING row
                  column.
ENDCLASS.                    "cl_event_handler DEFINITION

*----------------------------------------------------------------------*
*       CLASS cl_event_handler IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS cl_event_handler IMPLEMENTATION.

  METHOD on_before_salv_function.
    "BREAK-POINT.
  ENDMETHOD.                    "on_before_salv_function

  METHOD on_after_salv_function.
    "BREAK-POINT.
  ENDMETHOD.                    "on_after_salv_function

  METHOD on_added_function.
    "BREAK-POINT.
  ENDMETHOD.                    "on_added_function

  METHOD on_top_of_page.
    "BREAK-POINT.
  ENDMETHOD.                    "on_top_of_page

  METHOD on_end_of_page.
    "BREAK-POINT.
  ENDMETHOD.                    "on_end_of_page

  METHOD on_double_click.
    "PERFORM display_mm03 TABLES gt_alv USING row column.
  ENDMETHOD.                    "on_double_click

  METHOD on_link_click.
    PERFORM display TABLES gt_alv USING row column.
  ENDMETHOD.                    "on_link_click
ENDCLASS.                    "cl_event_handler IMPLEMENTATION




INITIALIZATION.
*
*  MOVE '20181201' TO so_datum-low.
*
*  DATA: lv_date TYPE endda.
*  lv_date = so_datum-low + 31.
*  CONCATENATE lv_date(6) '01' INTO so_datum-high.
*  so_datum-high = so_datum-high - 1.
*  lv_date = so_datum-low - 20.
*  CONCATENATE lv_date(6)  '16' INTO so_datum-low.

  IF p_debug EQ 1.
    CLEAR so_pernr.
    so_pernr-sign = 'I'.
    so_pernr-option = 'BT'.
    so_pernr-low = '3100'.
    so_pernr-high = '3200'.
    APPEND so_pernr.

    MOVE '20180101' TO so_datum-low.
    MOVE '20181231' TO so_datum-high.
    APPEND so_datum.
  ELSE.
    so_datum-sign = 'I'.
    so_datum-option = 'BT'.

    IF sy-datum+6(2) GT '16'.
      so_datum-low = sy-datum - 29.
      so_datum-high = sy-datum.
      "if sy-datum(6) gt '16'.
    ELSE.
      so_datum-low = sy-datum - 58.
      so_datum-high = sy-datum - 29.
    ENDIF.
    CONCATENATE so_datum-low(6) '16' INTO so_datum-low.
    CONCATENATE so_datum-high(6) '15' INTO so_datum-high.
    APPEND so_datum.


  ENDIF.







AT SELECTION-SCREEN OUTPUT.

  "Parameter ausblenden
  LOOP AT SCREEN.
    IF screen-name = 'P_ALLE' OR screen-name = 'P_ARB' OR screen-name = 'P_ANG'.
      screen-input = 0.
      screen-invisible = abap_true.
      screen-active = 0.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.

START-OF-SELECTION.

  PERFORM initial.
  PERFORM collect_pers.
  PERFORM collect_data.
  PERFORM sort_data.
  PERFORM show_data.

  EXIT.


FORM initial.

  CLEAR gt_alv_pers.

  "Zeiterfassungscheckbox in Select Option umsetzen
  IF p_zterf EQ 'X'.
    so_zterf-sign = 'I'.
    so_zterf-option = 'EQ'.
    so_zterf-low = '1'.
    APPEND so_zterf.
  ELSE.
    CLEAR so_zterf.
  ENDIF.

  "Parameter Arbeiter oder Angestellte umsetzen
  "Derzeit nicht in Verwendung
  IF p_arb EQ abap_true.
    so_persk-sign = 'I'.
    so_persk-option = 'EQ'.
    so_persk-low = 'AE'.
    APPEND so_persk.
  ENDIF.
  IF p_ang EQ abap_true.
    so_persk-sign = 'I'.
    so_persk-option = 'EQ'.
    so_persk-low = 'AH'.
    APPEND so_persk.
  ENDIF.

ENDFORM.
FORM collect_pers.
  "Selektion der MA über PA0007
  "Begin muss im Selektionszeitraum liegen
  "oder
  "Ende muss im Selektionszeitraum liegen
  "oder
  "Selektionszeitraum muss nach Begin und vor Endedatum liegen.
  SELECT pernr FROM pa0007 AS a "Sollarbeitszeit
  INTO CORRESPONDING FIELDS OF TABLE lt_pa "0007
  WHERE a~pernr IN so_pernr
  "AND a~begda LT sy-datum
  "AND a~endda GT sy-datum
  AND a~zterf IN so_zterf "Zeiterfassung aktiv, wenn ausgewählt
  AND
  (
  a~begda IN so_datum
  OR
  a~endda IN so_datum
  OR
  (
  a~begda LT so_datum-low
  AND
  a~endda GT so_datum-high
  )
  )
  GROUP BY pernr
  .


  IF sy-subrc IS INITIAL.
    "if lt_pa0007[] is not initial.  ist besser.
    "lt_pa0007 darf nicht leer sein, sonst werden alle Sätze genommen.
    "Auswahl der Maßnahmen 3 Beschäftigt im besagtem Zeitraum
    SELECT * FROM pa0000 AS a INTO TABLE lt_pa0000
    FOR ALL ENTRIES IN lt_pa
    WHERE pernr = lt_pa-pernr
    AND stat2 = '3' "Beschäftigung ist aktiv
    AND
    (
    a~begda IN so_datum
    OR
    a~endda IN so_datum
    OR
    (
    a~begda LT so_datum-low
    AND
    a~endda GT so_datum-high
    )
    ).
    "Selektion für alle MA
    "Selektion für noch aktive MA
    "AND begda LT so_datum-high"LE so_datum-low
    "AND endda GE so_datum-high.

    "Auswahl der Org. Zugehörigkeit im besagtem Zeitraum
    SELECT * FROM pa0001 AS b INTO TABLE lt_pa0001
    FOR ALL ENTRIES IN lt_pa "Darf ja nicht leer sein.
    WHERE pernr = lt_pa-pernr
    AND b~persk IN so_persk "Personenkreis Angestelle und Arbeiter
    AND b~persg IN so_persg
    AND b~abkrs IN so_abkrs
    AND b~begda LT so_datum-high"LE so_datum-low
    AND b~endda GE so_datum-high.
    "Auswahl der Namens- und Adressdaten im besagtem Zeitraum
    SELECT * FROM pa0002 INTO TABLE lt_pa0002
    FOR ALL ENTRIES IN lt_pa
    WHERE pernr = lt_pa-pernr
    AND begda LT so_datum-high"LE so_datum-low
    AND endda GE so_datum-high.
    "Auswahl der Sollarbeitszeit
    SELECT * FROM pa0007 INTO TABLE lt_pa0007
    FOR ALL ENTRIES IN lt_pa
    WHERE pernr = lt_pa-pernr
    AND zterf IN so_zterf
    AND begda LT so_datum-high"LE so_datum-low
    AND endda GE so_datum-high.
  ELSE.
    EXIT.
  ENDIF.

  "Durchgehen aller MA
  "Ergänzung um Maßnahme
  "Ergänzung um Adresse
  "Ergänzung um Personalkreis
  "Ergänzung um Sollarbeitszeit
  "Tabelle gt_alv_pers wird mit einem Satz pro MA gefüllt

  DATA: lv_ok0, lv_ok1, lv_ok2, lv_ok7 TYPE c.


  LOOP AT lt_pa
  ASSIGNING FIELD-SYMBOL(<pa>).
    CLEAR gs_alv.
    CLEAR lv_ok0.
    CLEAR lv_ok1.
    CLEAR lv_ok2.
    CLEAR lv_ok7.
    gs_alv-pernr = <pa>-pernr.
    LOOP AT lt_pa0000 ASSIGNING FIELD-SYMBOL(<pa0000>) WHERE pernr = <pa>-pernr.
      gs_alv-begda = <pa0000>-begda. "Maßnahme Beginn Datum
      gs_alv-endda = <pa0000>-endda. "
      <pa>-begda = <pa>-begda.
      <pa>-endda = <pa>-endda.
      lv_ok0 = 'X'.
    ENDLOOP.
    "Ergänzen der Adress- und Namensinformation
    LOOP AT lt_pa0002 ASSIGNING FIELD-SYMBOL(<pa0002>) WHERE pernr = <pa>-pernr.
      gs_alv-nachn = <pa0002>-nachn.
      gs_alv-vorna = <pa0002>-vorna.
      lv_ok2 = 'X'.
    ENDLOOP.
    "Ergänzen der Daten um Personalkreiszugehörigkeit Angestellte und Arbeiter.
    LOOP AT lt_pa0001 ASSIGNING FIELD-SYMBOL(<pa0001>) WHERE pernr = <pa>-pernr.
      gs_alv-persk = <pa0001>-persk.
      gs_alv-persg = <pa0001>-persg.
      gs_alv-abkrs = <pa0001>-abkrs.
      gs_alv-btrtl = <pa0001>-btrtl.
      lv_ok1 = 'X'.
    ENDLOOP.
    "Sollarbeitszeit
    LOOP AT lt_pa0007 ASSIGNING FIELD-SYMBOL(<pa0007>) WHERE pernr = <pa>-pernr.
      gs_alv-pernr = <pa>-pernr."Satz ist immer vorhanden
      gs_alv-teilk = <pa0007>-teilk.
      lv_ok7 = 'X'.
    ENDLOOP.
    IF lv_ok0 = 'X' AND lv_ok1 = 'X' AND lv_ok2 = 'X' AND lv_ok7 = 'X'.
      APPEND gs_alv TO gt_alv_pers.
    ENDIF.

    "cl_demo_output=>display( <ls_alv>-pernr ).
  ENDLOOP.
ENDFORM.
FORM collect_data.




  FIELD-SYMBOLS: <ls_alv> TYPE ty_alv.

*  DATA: BEGIN OF b2_key.               "key für perg-zugriff
*          INCLUDE STRUCTURE pc2b0.
*  DATA: END OF b2_key.
  DATA b2_key             LIKE pc2b0.
  DATA gt_zes             LIKE pc2b6 OCCURS 0 WITH HEADER LINE.
  DATA gt_saldo           LIKE pc2b5 OCCURS 0 WITH HEADER LINE.

  DATA lv_datum TYPE sy-datum.  "Hilfsdatum für Monat = Periode August = 9.
  DATA lv_period TYPE sy-datum. "Periodenanfang
  DATA lv_days TYPE p.

  "Periode ermitteln: 16.8. bis 15.9 ist Periode 9
  "In Hilfsdatum lv_datum steht nachher der 16-te des Monats (wenn Tag kleiner als 16)
  "oder Folgemonats (wenn Tag größer gleich 16)
  "Der Monat des Hilfsdatums lv_datum ist die Periode.
  IF so_datum-high+6(2) GE p_begin. "Konstante 16. Hier das Datum um einen Monat erhöhen.
    "16.12.2018 ist Periode 01/2019
    "15.12.2018 ist Periode 12/2018
    lv_datum = so_datum-high(6) && p_begin.
    CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
      EXPORTING
        "date      = <ls_alv>-begda
        date      = lv_datum
        days      = 0
        months    = 1
        signum    = '+'
        years     = 0
      IMPORTING
        calc_date = lv_datum.
  ELSE.
    lv_datum = so_datum-high(6) && p_begin.
  ENDIF.

  "Anzahl der Tage ermitteln für ZES Tabelle
  CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
    EXPORTING
      "date      = <ls_alv>-begda
      date      = lv_datum
      days      = 0
      months    = 1
      signum    = '-'
      years     = 0
    IMPORTING
      calc_date = lv_period.
  CALL METHOD cl_reca_date=>get_days_between_two_dates(
    EXPORTING
      id_datefrom = lv_period
      id_dateto   = so_datum-high
    RECEIVING
      rd_days     = lv_days ).
  lv_days = lv_days + 1.

  CLEAR gt_alv[].
  CLEAR gt_zes[].
  CLEAR gt_saldo[].
  ASSIGN gs_alv TO <ls_alv>.
  LOOP AT gt_alv_pers INTO DATA(wa).
    APPEND INITIAL LINE TO gt_alv ASSIGNING <ls_alv>.
    MOVE-CORRESPONDING wa TO <ls_alv>.

    "Saldo ist zuerst der akkumulierte Monatswert
    <ls_alv>-ausw = 'SALDO'.
    <ls_alv>-bemer = 'FEHLER'.
    <ls_alv>-ampel = icon_message_error.
    <ls_alv>-anzhl = -999.
    <ls_alv>-anzhl = ''.
    <ls_alv>-anzhlc = ''.



    b2_key-pernr = wa-pernr.
    b2_key-pabrj = lv_datum(4).   "Jahr
    b2_key-pabrp = lv_datum+4(2). "Monat = Periode
    b2_key-cltyp = '1'.
    IMPORT
         zes TO gt_zes
       FROM DATABASE pcl2(b2)
       ID b2_key.
    IF sy-subrc NE 0.
      continue.
    ENDIF.
    b2_key-pernr = wa-pernr.
    b2_key-pabrj = lv_period(4).   "Jahr
    b2_key-pabrp = lv_period+4(2). "Monat = Periode
    b2_key-cltyp = '1'.
    IMPORT
         saldo TO gt_saldo
       FROM DATABASE pcl2(b2)
       ID b2_key.
    IF sy-subrc NE 0.
      continue.
    ENDIF.



    " Unnötige Zeitarten entfernen und Tage entfernen
    " Es kann Löcher geben
    DELETE gt_zes WHERE ztart NE '9320' OR reday GT lv_days.
    SORT gt_zes BY reday DESCENDING.
    DELETE gt_saldo WHERE ztart NE '9320'.


*    "Abwesenheiten
*    SELECT * FROM pa2006 INTO TABLE lt_pa2006 WHERE pernr = wa-pernr
*       "AND ( begda IN so_datum OR endda IN so_datum )
*      ORDER BY begda "Damit letzter Satz im System steht
*      .
*
    LOOP AT gt_saldo INTO DATA(wa2).
      <ls_alv>-anzhl = wa2-anzhl.
      IF p_debug = 0.
        <ls_alv>-anzhlp = 0.
      ELSE.
        <ls_alv>-anzhlp = wa2-anzhl.
      ENDIF.
      <ls_alv>-bemer = 'SALDO'.
      EXIT.
    ENDLOOP.
    "Verfeinert mit den Tageswert. Höchster Tag.
    LOOP AT gt_zes INTO DATA(wa3).
      <ls_alv>-anzhl = wa3-anzhl.
      <ls_alv>-bemer = 'SALDO'.
      EXIT.
    ENDLOOP.
    IF ( <ls_alv>-anzhl GE p_anz ). "Schwellwert überschritten
      IF p_out0 = 'X'.
        <ls_alv>-ampel = 'ROT'.
      ELSE.
        <ls_alv>-ampel = '@0A@'. "Rot noch anzulegen.
      ENDIF.
    ELSE.
      IF p_out0 = 'X'.
        <ls_alv>-ampel = 'GRÜN'. "Grün bereits angelegt.
      ELSE.
        <ls_alv>-ampel = '@08@'. "Grün bereits angelegt.
      ENDIF.
    ENDIF.
    PERFORM h2hm USING <ls_alv>-anzhl CHANGING <ls_alv>-anzhlc.
    IF p_debug = 0.
      <ls_alv>-anzhld = 0.
    ELSE.
      <ls_alv>-anzhld = <ls_alv>-anzhl - <ls_alv>-anzhlp.
    ENDIF.
*    call function 'H2HM'
*    exporting
*        lv_hour = <ls_alv>-anzhl
*    importing
*        lv_hourc = <ls_alv>-anzhlc.
*
*    <ls_alv>-anzhlc = h2hm( <ls_alv>-anzhl ).
*

  ENDLOOP.

ENDFORM.
FORM h2hm
USING lv_hour TYPE any "p decimals 2
CHANGING lv_hourc TYPE any. "(8) type c.
  DATA:
    lv_int_part(5) TYPE c,
    lv_minutes(2)  TYPE n.

  CLEAR lv_hourc.
  lv_int_part = trunc(  abs( lv_hour ) ) .
  lv_minutes  = frac( abs( lv_hour ) )  * 60.
  CONCATENATE lv_int_part ':' lv_minutes INTO lv_hourc.

  IF lv_hour LT 0.
    SHIFT lv_hourc LEFT DELETING LEADING space.
    CONCATENATE '-' lv_hourc INTO lv_hourc.
  ENDIF.
ENDFORM.
FORM sort_data.
  IF p_sortn = 'X'.
    SORT gt_alv BY nachn begda.
  ELSE.
    SORT gt_alv BY pernr begda.
  ENDIF.
ENDFORM.

FORM show_dialog.

  cl_demo_output=>display( data = gt_alv name = 'Stundenanzahlen' ).


  IF 1 = 2. "Testmodus
    DATA name TYPE string.
    DATA lv_anz TYPE integer.
    "data value type data.

    cl_demo_output=>display( gt_alv_pers ).
    lv_anz = lines( gt_alv_pers ).
    cl_demo_output=>write_data( value = lv_anz name = 'Anzahl der Sätze' ).
    cl_demo_output=>display( ).
  ENDIF.

ENDFORM.

FORM show_alv.

  "Initialisierung
  DATA: lr_salv   TYPE REF TO cl_salv_table,
        lr_layout TYPE REF TO cl_salv_layout,
        ls_key    TYPE salv_s_layout_key.
  DATA: lr_functions TYPE REF TO cl_salv_functions_list.
  DATA: lr_display TYPE REF TO cl_salv_display_settings.
* Titel
  DATA: lv_titel TYPE lvc_title.
* Sortierung und Aggregation
  DATA: lr_sorts TYPE REF TO cl_salv_sorts.
  DATA: lr_aggs TYPE REF TO cl_salv_aggregations.

  DATA: lo_events    TYPE REF TO cl_salv_events_table. "HST 20190712


* ALV aufbauen,
* lr_salv zeigt danach auf das Objekt,
* gt_alv_pers ist die Tabelle, die als Info mitgegeben wird, wo die Daten zukünftig gespeichert werden.
  TRY.
      CALL METHOD cl_salv_table=>factory
        IMPORTING
          r_salv_table = lr_salv
        CHANGING
          t_table      = gt_alv.
      "HST 20190712 Beginn
      lo_events = lr_salv->get_event( ).

      SET HANDLER cl_event_handler=>on_before_salv_function FOR lo_events.
      SET HANDLER cl_event_handler=>on_after_salv_function FOR lo_events.
      SET HANDLER cl_event_handler=>on_added_function FOR lo_events.
      SET HANDLER cl_event_handler=>on_top_of_page FOR lo_events.
      SET HANDLER cl_event_handler=>on_end_of_page FOR lo_events.
      SET HANDLER cl_event_handler=>on_double_click FOR lo_events.
      SET HANDLER cl_event_handler=>on_link_click FOR lo_events.
      "HST 20190712 Ende

    CATCH cx_salv_msg .
      cl_demo_output=>display('Error' ).
  ENDTRY.

  "Die Keydaten werden gefüllt
  ls_key-report = sy-repid.
  "lr_layout zeigt auf das Layout des ALV
  lr_layout  = lr_salv->get_layout( ).
  "Layout erhält Keydaten: Program Name
  lr_layout->set_key( ls_key ).
  "Layout Speichern erlaubt (3 Werte möglich) User can save
  lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).
* Layout auf Kundenspezifisches Layout einstellen
*  IF sy-slset = 'CUS&Z_PPMDT_01'.
*    lr_layout->set_initial_layout( value = '/Z_PPMDT_TEL' ).
*  ENDIF.
  "lr_functions zeigt auf die Funktionen des ALV
  lr_functions = lr_salv->get_functions( ).
  "lr_functions einschalten
  "  lr_functions->set_default( ).      "minimal
  lr_functions->set_all( abap_true ). "Standard

  "Überschrift des Display einstellen
  CONCATENATE 'Auswertungen - Zeitraum:   ' so_datum-low ' - ' so_datum-high
  INTO lv_titel.
  lr_display = lr_salv->get_display_settings( ).
  lr_display->set_list_header( lv_titel ).
  lr_display->set_striped_pattern( abap_true ).

* Feldkatalog ändern
  DATA: lr_columns TYPE REF TO cl_salv_columns_table,
        lr_column  TYPE REF TO cl_salv_column_table.

  lr_columns = lr_salv->get_columns( ).
* lr_columns->set_optimize( abap_true ).

  TRY.

      "Aggregation einstellen Summe
      lr_aggs = lr_salv->get_aggregations( ).
      lr_aggs->set_aggregation_before_items( abap_false ).
      lr_aggs->add_aggregation(
        columnname = 'ANZHL'
        aggregation = if_salv_c_aggregation=>total ).
      IF p_outp EQ 'X'.
        lr_aggs->add_aggregation(
          columnname = 'ANZHLP'
          aggregation = if_salv_c_aggregation=>total ).
        lr_aggs->add_aggregation(
          columnname = 'ANZHLD'
          aggregation = if_salv_c_aggregation=>total ).
      ENDIF.
      "if p_debug = 1.
      "Sort einstellen
      lr_sorts = lr_salv->get_sorts( ).
      "lr_sorts->add_sort( columnname = 'NACHN' subtotal = abap_false ).
      "lr_sorts->add_sort( columnname = 'VORNA' subtotal = abap_false ).
      IF p_sortn = 'X'.
        lr_sorts->add_sort( columnname = 'NACHN' subtotal = abap_false ).
        lr_sorts->add_sort( columnname = 'VORNA' subtotal = abap_false ).
        lr_sorts->add_sort( columnname = 'PERNR' subtotal = abap_false ).
        "lr_sorts->set_compressed_subtotal( 'NACHN' ).
      ELSE.
        lr_sorts->add_sort( columnname = 'PERNR' subtotal = abap_false ).
        lr_sorts->add_sort( columnname = 'NACHN' subtotal = abap_false ).
        lr_sorts->add_sort( columnname = 'VORNA' subtotal = abap_false ).
      ENDIF.
      "endif.


      lr_column ?= lr_columns->get_column( 'PERNR' ).
      lr_column->set_output_length( '5' ).
      lr_column->set_cell_type( if_salv_c_cell_type=>hotspot ).


      lr_column ?= lr_columns->get_column( 'NACHN' ).
      lr_column->set_output_length( '20' ).

      lr_column ?= lr_columns->get_column( 'VORNA' ).
      lr_column->set_output_length( '20' ).

      lr_column ?= lr_columns->get_column( 'ANZHL' ).
      lr_column->set_short_text( 'Anz. Std.').
      lr_column->set_medium_text( 'Anzahl Std.').
      lr_column->set_long_text( 'Anzahl Stunden').
      lr_column->set_output_length( '10' ).
      lr_column->set_sign( abap_true ).

      IF p_outp EQ 'X'.
        lr_column ?= lr_columns->get_column( 'ANZHLP' ).
        lr_column->set_short_text( 'Anz.Anf.P.').
        lr_column->set_medium_text( 'Anzahl Anf. P.').
        lr_column->set_long_text( 'Anzahl Anfang Periode').
        lr_column->set_output_length( '10' ).
        lr_column->set_sign( abap_true ).

        lr_column ?= lr_columns->get_column( 'ANZHLD' ).
        lr_column->set_short_text( 'Anz.Diff.').
        lr_column->set_medium_text( 'Anzahl Diff.').
        lr_column->set_long_text( 'Anzahl Differenz').
        lr_column->set_output_length( '10' ).
        lr_column->set_sign( abap_true ).
      ENDIF.

      lr_column ?= lr_columns->get_column( 'ANZHLC' ).
      lr_column->set_short_text( 'Anz. Std.').
      lr_column->set_medium_text( 'Anzahl Std.').
      lr_column->set_long_text( 'Anzahl Stunden').
      lr_column->set_output_length( '10' ).
      lr_column->set_sign( abap_true ).
      lr_column->set_alignment( if_salv_c_alignment=>right ).

      lr_column ?= lr_columns->get_column( 'PERSK' ).
      lr_column->set_output_length( '10' ).
      lr_column->set_short_text( 'Pers.Kreis').
      lr_column->set_medium_text( 'Personenkreis').
      lr_column->set_long_text( 'Personenkreis').

      lr_column ?= lr_columns->get_column( 'AMPEL' ).
      lr_column->set_short_text( 'Status').
      lr_column->set_medium_text( 'Status').
      lr_column->set_long_text( 'Aktueller Status').
      lr_column->set_icon( abap_true ).

      lr_column ?= lr_columns->get_column( 'BEMER' ).
      lr_column->set_output_length( '20' ).
      lr_column->set_short_text( 'Bemerkung').
      lr_column->set_medium_text( 'Bemerkung').
      lr_column->set_long_text( 'Bemerkung').

      lr_columns->set_column_position( columnname = 'VORNA' position = 1 ).
      lr_columns->set_column_position( columnname = 'NACHN' position = 1 ).
      lr_columns->set_column_position( columnname = 'PERNR' position = 1 ).
      lr_columns->set_column_position( columnname = 'AMPEL' position = 1 ).

      PERFORM visible USING lr_columns 'PERSK' p_visibl.  "Personenkreis/Mitarbeitergruppe
      PERFORM visible USING lr_columns 'PERSG' p_visibl.  "Personengruppe/Mitarbeitergruppe
      PERFORM visible USING lr_columns 'ABKRS' p_visibl.  "Abrechnungskreis
      PERFORM visible USING lr_columns 'BTRTL' p_visibl.  "Teilbereich
      PERFORM visible USING lr_columns 'TEILK' p_visibl.  "Teilzeitkennzeichen
      PERFORM visible USING lr_columns 'AUSW'  abap_false."Filterauswahl
      PERFORM visible USING lr_columns 'ANZHLP' p_outp..  "Teilzeitkennzeichen
      PERFORM visible USING lr_columns 'ANZHLD' p_outp."Filterauswahl


      "lr_columns->get_count_column

    CATCH cx_salv_not_found.
      cl_demo_output=>display('Error' ).
    CATCH cx_salv_existing.
      cl_demo_output=>display('Error: Existence' ).
    CATCH cx_salv_data_error.
      cl_demo_output=>display('Error: Data' ).
  ENDTRY.

* Ausgabe
  lr_salv->display( ).
ENDFORM.

"Unterprogramm von show_alv
FORM visible
   USING
         lr_columns TYPE REF TO cl_salv_columns_table
         lv_column
         lv_visibl .
  DATA lr_column  TYPE REF TO cl_salv_column_table.

  TRY.
      lr_column ?= lr_columns->get_column( lv_column ).
      IF lv_visibl IS INITIAL.
        lr_column->set_visible( '' ).
      ELSE.
        lr_column->set_visible( abap_true ).
      ENDIF.
    CATCH cx_salv_not_found.
      cl_demo_output=>display('Error' ).
  ENDTRY.
ENDFORM.

FORM show_data.
  IF p_out0 = 'X'. "Dialog Output
    PERFORM show_dialog.
  ELSE. "ALV Output
    PERFORM show_alv.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&      FORM call_transaction
*&---------------------------------------------------------------------*
*  Call standard transactions with authority check and progress indicator
*----------------------------------------------------------------------*
"HST 20190712
FORM call_transaction USING trx TYPE tcode.
  DATA: lv_message TYPE string.
  CONCATENATE 'Opening transaction' trx '...' INTO lv_message SEPARATED BY space. "#EC NOTEXT
  CALL FUNCTION 'AUTHORITY_CHECK_TCODE'
    EXPORTING
      tcode  = trx
    EXCEPTIONS
      ok     = 0
      not_ok = 1
      OTHERS = 2.
  IF sy-subrc NE 0.
    MESSAGE e172(00) WITH trx.
  ELSE.
    CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
      EXPORTING
        text = lv_message.
    CALL TRANSACTION trx AND SKIP FIRST SCREEN.
  ENDIF.
ENDFORM.  "call transaction


FORM display_pa30 TABLES gt_alv USING row TYPE salv_de_row column TYPE salv_de_column.


  TRY.
      gs_alv  = gt_alv[ row ].

      SET PARAMETER ID: 'PER' FIELD gs_alv-pernr.

      PERFORM call_transaction USING 'PA30'.
      "BREAK-POINT.
    CATCH cx_sy_itab_line_not_found.

      cl_demo_output=>display('Einzelzeile auswählen' ).
      "cl_abap_browser=>show_html( html = VALUE #( ( 'Einzelzeile MATNR auswählen' ) ) ).
  ENDTRY.
ENDFORM.
FORM display TABLES gt_alv USING row TYPE salv_de_row column TYPE salv_de_column.
  IF column EQ 'PERNR'.
    PERFORM display_pa30 TABLES gt_alv USING row column.
  ENDIF.
ENDFORM.