ZHR_AUSW01 – Auswertung der An- und Abwesenheiten

Hier ein Programm aus eigener Feder, verwendet SALV und OO und ergibt damit ein extrem gutes Auswertungsergebnis.

Es wertet die An- und Abwesenheiten aus, hat eine Vielzahl von Auswahlmöglichkeiten, kann mit Defaultmäßigen Varianten versehen werden, etc.

Mit gesperrten und ohne gesperrten Sätzen.

REPORT zhr_ausw01 NO STANDARD PAGE HEADING.
CONSTANTS p_debug VALUE 1.  "0 Kein Debug 1 Debug
************************************************************************
* Liste Auswertung der Abwesenheiten und Anwesenheiten.
* Liste Mitarbeiter
* Liste Umbuchungen
************************************************************************
* Dipl.Ing.J.Stangl
************************************************************************
* Version 020: 20190830HST
*    Auszahlung Prämie 9322
*    Auszahlung Wäsche 9904
*
*    Stundenkorrektur  9323
*    Pausenkorrektur   9905
*
*    Stundenübertrag ohne Zeiterf.   9901
*    Stunden auszahlen ohne Zeiterf. 9902
*    +/- Stunden ohne Zeiterf.       9903
*
* Version 020: 20190902HST
*    Korrektur 9901-9903
* Version 019: 20190829HST
*    Auszahlung Überstunden 50% 9321 und Überstunden 100% 9320
*    Zeitaufzeichnung 9901-9903
* Version 018: 20190809HST
*    Krankentage alternativ Kalendertrage oder Arbeitstage
* Version 017: 20190705 HST
*    Leiharbeiter Teilzeit Vollzeit
*    Sortierung und Filterung nun zu anderen Zeitpunkt
*    Hauptprogramm umgebaut
*    Mitarbeiterlisten und An-/Abwesenheitslisten getrennt
* Version 016: 20190502 HST
*    Alle Auswertung für Sperrkennzeichen p_alle
* Version 015: 20190429 HST
*    Fehler Berechnung Arbeitstage Arzt korrigieren
*    Fehler Berechnung Dienstreise an freien Tag korrigieren
*    Fehler Berechnung Dienstgang an freien Tag korrigieren
*    Dokumentation der Unterprogramme
* Version 014: 20190424 HST
*    Krank Von Bis auf Auswertungszeitraum einschränken
*    in der Ausgabe, Korrektur F3 bei Arzt
*    Urlaub, Arbeitsunfall, Arbeitsunfall Folge wie Krank einschränken.
*    Ausgabe der Sollarbeitszeitdaten parametrisiert.
*       0690 einbauen Arbeitstage,
*       0150 und 0160 auf Arbeitstage ändern Von Bis beschränken
*    Generelle Routine für Kalendertag Rechnung und
*      Arbeitstag Rechnung
*    ALV
*    Sonstige Abwesenheiten, 0500 ergänzt
*    Berechnung Tage sonstige Abwesenheiten
* Version 013: correct_data für korrekte Urlaubsberechnungen,
*    wenn sich dieser mit dem Auswertungszeitraum nur teilw. überschneidet.
* Version 012: Krankentage Kalendertage berechnet
* Version 011: Krankentage Überschneidungen markiert
* Version 010: Kommentartext bei Pflegeurlaub inkludiert
* Version 009: Überschneidende Zeiträume Urlaub markiert
* Version 008: Gesperrte Sätze inkludiert, exkludiert, nur gesperrte
*    Sätze
* Version 007: Monatsauswahl flexibel Selektion
* Version 006: Überschneidende Zeiträume markiert.
* Version 005: Ausgeschiedene Mitarbeiter Korrektur
* Version 004: Sonstige Abwesenheiten Auswertung
* Version 003: 20190212 Korrektur der Auswahl der MA
*    Person mit einem Orgwechsel innerhalb des Zeitraums wurden nicht
*    ausgegeben.
*    Komplette Neustrukturierung
* Version 002: 20190210 Keine Differenzierung zwischen Arbeiter und
*    Angestellt mit
*    eigener Checkbox, sondern nur über Mitarbeitergruppe
*    Keinen eigenen Report Angestellte Urlaub und Arbeiter Urlaub
*      sondern nur ein Report
* Version 001: 20190201 Fertigstellung Erstversion
*
************************************************************************
* Einschränkungen
* Für gewisse Berechnungen werden zeitabhängige Infotype herangezogen.
*    Wird der Zeitraum größer als 1 Monat gewählt, so können sich die
*    Berechnungen ändern.
* Zeitraum der Infotyps nicht klar: Überschneidungen möglich
************************************************************************
* Funktionsweise:
*    Durch explizite Auswahl der Ab- / Anwesenheitsart werden die Reports
*    gefiltert.
************************************************************************
"pa2001 Abwesenheiten
*0100	Url  Urlaub                         --> Urlaub        --> Erl.
*0101	Url  Urlaub halber Tag              --> Urlaub        --> Erl.
*0150	Pfl1 Pflegefreistellung 1 Wo        --> Sonstige      --> Erl.
*0160 Pfl2 Pflegefreistellung 2 Wo        --> Sonstige      --> Erl.
*0200	Arzt Arzt                           --> Arzt          --> Erl.
*0210	BehW Behördenweg                    --> Sonstige      --> Erl.
*0220	SoU  Sonderurlaub                   --> Sonstige      --> Erl.
*0690 FSt  Freistellung                   --> Sonstige      --> Erl.
*0300	Krk  Krank                          --> Krank         --> Erl.
*0310	Krk  Krank untertägig               --> Krank         --> Erl.
*0400	Krk  Krank Arbeitsunfall            --> Krank         --> Erl.
*Fälle
*0410	Krk  Krank Folgeerkrankung (Arbeitsunfall) --> Krank  --> Erl.
*Fälle
*0500	ZA   Zeitausgleich                  --> Sonstige Abw  --> Erl
************************************************************************
"pa2002 Anwesenheiten
*0230	Schu Anwesenheit 2002 Schulung/kurs --> Sonstige Anw  --> Erl.
*0240	BerS Anwesenheit 2002 Berufsschule  --> Sonstige Anw  --> Erl.
*0250	DieR Anwesenheit 2002 Dienstreise   --> Sonstige Anw  --> Erl.
*0260	DieG Anwesenheit 2002 Dienstgang    --> Sonstige Anw  --> Erl.
************************************************************************
*pa2012
*9321 50% Überstunden
*9320 100% Überstunden


TABLES: pa0001, pa0007, pa2001, pa2002.

TYPES: BEGIN OF ty_abwanw,
         pernr TYPE persno,
         begda TYPE begda,
         endda TYPE endda,
         enduz TYPE enduz,
         beguz TYPE beguz,
         abrtg LIKE pa2001-abrtg,
         abrst TYPE jrstd,
         awart TYPE awart,
         sprps TYPE sprps,
         itxex TYPE itxex,
       END OF ty_abwanw.

DATA: gs_abwanw TYPE ty_abwanw.
DATA: gt_abwanw TYPE TABLE OF ty_abwanw.

TYPES: BEGIN OF ty_alv,
         zaehler   TYPE i,
         ampel(4)  TYPE c,     "Ampel
         pernr     TYPE persno, "Personalnummer
         nachn     TYPE pad_nachn,             "Nachname
         vorna     TYPE pad_vorna,             "Vorname
         begda     TYPE begda, "Anfangsdatum
         endda     TYPE endda, "Endedatum
         ztage     TYPE p LENGTH 5 DECIMALS 2, "Abgerechnete Tage
         zstun     TYPE p LENGTH 5 DECIMALS 2, "Abgerechnete Stunden
         grund(30) TYPE c,     "Ausewählte Liste Langtext
         persk     TYPE persk, "Mitarbeiterkreis
         persg     TYPE persg, "Mitarbeitergruppe
         abkrs     TYPE abkrs, "Abrechnungskreis
         btrtl     TYPE btrtl, "Teilbereich
         teilk     TYPE teilk, "Teilzeit
         ausw(11)  TYPE c,     "Filterauswahl
         bemer(30) TYPE c,     "Bemerkung
         schkz     TYPE schkn, "Arbeitszeitplanregel
         wkwdy     TYPE wkwdy, "Anzahl der Arbeitstage
         arbst     TYPE arbst, "Anzahl der Arbeitsstunden
         awart     TYPE awart, "Abwesenheitsart
         "itxex     TYPE itxex,"Text existiert
         sprps     TYPE sprps, "Sperrkennzeichen
       END OF ty_alv.
DATA: gt_alv_pers TYPE STANDARD TABLE OF ty_alv, "Personen
      gt_alv      TYPE STANDARD TABLE OF ty_alv, "Ausgabedaten
      gt_alv2     TYPE STANDARD TABLE OF ty_alv, "Ausgabedaten gefiltert
      "Ausgabedaten gefilterte Daten
      gs_alv      TYPE ty_alv. "Struktur zu Ausgabedaten

DATA: gv_ausw(11) TYPE c.
DATA: gv_titel(40) TYPE c.


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
'1388'. "'2243'. "'1615'. "'1341'.
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_btrtl FOR pa0001-btrtl.
"Teilbereich 0003 Lamprechtshausen 0001 Wien
SELECT-OPTIONS: so_teilk FOR pa0007-teilk NO-DISPLAY. "Teilzeitkraft
PARAMETERS :
  p_voll  RADIOBUTTON GROUP g11,
  p_teil  RADIOBUTTON GROUP g11,
  p_vo_te RADIOBUTTON GROUP g11 DEFAULT 'X'.

SELECT-OPTIONS: so_zterf FOR pa0007-zterf NO-DISPLAY.
"Zeiterfassung 1 aktiv 0 inaktiv


PARAMETERS:
  p_zterf TYPE xfeld AS CHECKBOX DEFAULT ''. "Zeiterfassung Checkbox.

"Zeitraum
SELECTION-SCREEN END OF BLOCK per.
SELECTION-SCREEN BEGIN OF BLOCK dat WITH FRAME TITLE text-002.
PARAMETERS:
  p_vorm  RADIOBUTTON GROUP g12 USER-COMMAND uc1,  "Bis 15. dieses Mmonats
  p_nachm RADIOBUTTON GROUP g12,                   "Ab 16. dieses Monats
  p_belm  RADIOBUTTON GROUP g12 DEFAULT 'X'.       "Beliebige Auswahl Vorbelegung


"SELECT-OPTIONS: so_datum FOR sy-datum OBLIGATORY NO-EXTENSION.
SELECT-OPTIONS: so_datum FOR sy-datum MODIF ID id1.
"Ohne Verwendung ???
PARAMETERS: p_factid TYPE wfcid DEFAULT 'AT' NO-DISPLAY.
SELECTION-SCREEN END OF BLOCK dat.

"Mitarbeiterlisten
SELECTION-SCREEN BEGIN OF BLOCK opt WITH FRAME TITLE text-030.
SELECTION-SCREEN BEGIN OF BLOCK optson WITH FRAME TITLE text-031.
PARAMETERS p_mit1  TYPE xfeld AS CHECKBOX DEFAULT abap_false. "Mitarbeiterliste 1
SELECTION-SCREEN END OF BLOCK optson.

"An-/Abwesenheitslisten
SELECTION-SCREEN BEGIN OF BLOCK optanz WITH FRAME TITLE text-033.
SELECTION-SCREEN COMMENT /1(50) text-101.
*selection-screen begin of line.
*selection-screen position 20.
PARAMETERS:
  p_sonst  TYPE xfeld AS CHECKBOX DEFAULT abap_true, "Abwesenheiten Sonstige
  p_abwkra TYPE xfeld AS CHECKBOX DEFAULT abap_true. "Abwesenheiten krankenstand
SELECTION-SCREEN BEGIN OF BLOCK krank WITH FRAME TITLE text-006.
PARAMETERS:
  p_kranka RADIOBUTTON GROUP g3 DEFAULT 'X', "Krank Arbeitstage
  p_krankk RADIOBUTTON GROUP g3.             "Krank Kalendertage
SELECTION-SCREEN END OF BLOCK krank.
PARAMETERS:
  p_abwarz TYPE xfeld AS CHECKBOX DEFAULT abap_true, "Abwesenheiten Arzt
  p_urlaub TYPE xfeld AS CHECKBOX DEFAULT abap_true, "Abwesenheiten Urlaub
  p_sonab  TYPE xfeld AS CHECKBOX DEFAULT abap_false. "Abwesenheiten Sonstige andere
SELECTION-SCREEN COMMENT /1(60) text-103.
PARAMETERS:
  p_sonan  TYPE xfeld AS CHECKBOX DEFAULT abap_false. "Anwesenheiten Sonstige andere
*selection-SCREEN END OF LINE.
SELECTION-SCREEN COMMENT /1(60) text-102.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT /1(60) text-104.
PARAMETERS:
  p_alle   TYPE xfeld AS CHECKBOX DEFAULT abap_false. "Anwesenheiten Sonstige alle

"An-/Abwesenheitsarten
"paramters:
"p_anw type  xfeld as checkbox default abap_true. 'Anwesenheiten
SELECTION-SCREEN SKIP.
SELECTION-SCREEN COMMENT /1(60) text-105.
SELECT-OPTIONS: so_awart FOR pa2001-awart. "Ab-/Anwesenheitsart
SELECTION-SCREEN END OF BLOCK optanz.

"Auszahlung/Überstundenlisten
SELECTION-SCREEN BEGIN OF BLOCK optaus WITH FRAME TITLE text-034.
PARAMETERS:
  p_ausueb TYPE xfeld AS CHECKBOX DEFAULT abap_true, "Auswertungen/Überstunden 50%
  p_ausue2 TYPE xfeld AS CHECKBOX DEFAULT abap_true. "Auswertungen/Überstunden 100%
SELECTION-SCREEN SKIP.
PARAMETERS:
  p_auspra TYPE xfeld AS CHECKBOX DEFAULT abap_true, "Auswertungen/Überstunden Prämie
  p_auswae TYPE xfeld AS CHECKBOX DEFAULT abap_true. "Auswertungen/Überstunden Wäsche
SELECTION-SCREEN END OF BLOCK optaus.
SELECTION-SCREEN BEGIN OF BLOCK optohn WITH FRAME TITLE text-035.
PARAMETERS:
  p_ohnueb TYPE xfeld AS CHECKBOX DEFAULT abap_true, "Übertrag Std.
  p_ohnaus TYPE xfeld AS CHECKBOX DEFAULT abap_true, "Auszahlung Std.
  p_ohnmeh TYPE xfeld AS CHECKBOX DEFAULT abap_true. "Plus/Minus Std.
SELECTION-SCREEN END OF BLOCK optohn.
SELECTION-SCREEN END OF BLOCK opt.

"Sortierung/Summierung
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_sprmit RADIOBUTTON GROUP g121 DEFAULT 'X', "Mit gesperrten
  p_sprohn RADIOBUTTON GROUP g121,              "Ohne gesperrte
  p_sprnur RADIOBUTTON GROUP g121 .             "Nur gesperrte
SELECTION-SCREEN SKIP.
PARAMETERS:
  p_visibl TYPE xfeld AS CHECKBOX DEFAULT abap_false, "0007 Felder sichtbar
  p_sum    AS CHECKBOX DEFAULT 'X'.

SELECTION-SCREEN END OF BLOCK sort.

"Ausgabe
SELECTION-SCREEN BEGIN OF BLOCK outp WITH FRAME TITLE text-005.
PARAMETERS:
  p_outdia RADIOBUTTON GROUP g5 , "DEFAULT 'X', "Dialog Output
  p_outalv RADIOBUTTON GROUP g5 DEFAULT 'X',    "ALV Output
  "20190424 HST Anfang
  p_vari   TYPE slis_vari. "Variante
"20190424 HST Ende

SELECTION-SCREEN END OF BLOCK outp.


SELECTION-SCREEN END OF BLOCK all.

DATA lt_pa0007 TYPE TABLE OF pa0007."AZP (zterf Aktiv)
DATA lt_pa0000 TYPE TABLE OF pa0000."Maßnahmen (stat3 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 ty_abwanw."Abwesenheiten
DATA lt_pa2002 TYPE TABLE OF ty_abwanw."Abwesenheiten
DATA lt_pa2012 TYPE TABLE OF pa2012."Abwesenheiten

"DATA lt_pa2001 TYPE TABLE OF pa2001."Abwesenheiten
"DATA lt_pa2002 TYPE TABLE OF pa2002."Anwesenheiten


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.



INITIALIZATION. "Ladung der Initialwerte vor der ersten Anzeige

  IF p_debug  = 1.
    CLEAR: p_sonst, p_abwkra, p_abwarz, p_urlaub, p_sonab, p_sonan, p_alle.
    "p_sonab = 'X'.
    "p_sonan = 'X'.
    "p_alle = 'X'.
    "p_mit1 = 'X'.
    "p_abwkra = 'X'.
    p_ausueb = 'X'.
    p_ausue2 = 'X'.
    p_auspra = 'X'.
    p_auswae = 'X'.
    p_ohnueb = 'X'.
    p_ohnaus = 'X'.
    p_ohnmeh = 'X'.
    CLEAR so_pernr[].
    "so_pernr-low = '1388'.
    "APPEND so_pernr.
    CLEAR so_datum[].
    "Testbelegung
    MOVE '20190116' TO so_datum-low.
    MOVE '20190215' TO so_datum-high.
    MOVE '20190304' TO so_datum-low.
    MOVE '20190304' TO so_datum-high.
    MOVE '20180401' TO so_datum-low.
    MOVE '20190430' TO so_datum-high.
    so_datum-sign = 'I'.
    so_datum-option = 'BT'.
    APPEND so_datum.
    MODIFY SCREEN.
  ELSE.
    PERFORM date_vorm.
  ENDIF.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_vari.
  PERFORM f4_alv_variant CHANGING p_vari.

AT SELECTION-SCREEN OUTPUT.  "Ladung der Werte nach jeder Veränderung

  LOOP AT SCREEN.
    "Datumsgruppe Selektion
    IF screen-group1 = 'ID1'.
      "Nur die Werte, die sich durch andere Werte verändern können, werden
      "untersucht, und verändert
      IF p_vorm EQ 'X'.
        PERFORM date_vorm.
        MODIFY SCREEN. "Aktualisierung des Screens
      ENDIF.
      IF p_nachm EQ 'X'.
        PERFORM date_nachm.
        MODIFY SCREEN. "Aktualisierung des Screens
      ENDIF.
    ENDIF.

  ENDLOOP.
*  IF 1 = 0.
*    "Testbelegung
*    MOVE '20190116' TO so_datum-low.
*    MOVE '20190215' TO so_datum-high.
*    MOVE '20190304' TO so_datum-low.
*    MOVE '20190304' TO so_datum-high.
*    MOVE '20180116' TO so_datum-low.
*    MOVE '20190515' TO so_datum-high.
*    so_datum-sign = 'I'.
*    so_datum-option = 'BT'.
*    APPEND so_datum.
*    MODIFY SCREEN.
*
*  ENDIF.



START-OF-SELECTION.
  "Hauptprogramm
  " Initialisierung
  " Sammlung der Personen
  " Sammlung der Daten
  " Sortierung der Daten
  " Ausgabe der verschiedenen Auswertungen
  PERFORM initial.
  PERFORM collect_pers.
  "PERFORM sort_data. "show_dialog_sort Nur noch Teil von show_dialog.
  "PERFORM collect_data. "Nun Teil von show_data_main.
  "PERFORM filter_data "Nun Teil von show_data.

  "Mitarbeiterauswertungen vorher, dann Struktur löschen.
  IF p_mit1 IS NOT INITIAL.
    PERFORM show_data_main_mit.
  ENDIF.
  IF  NOT (
      p_sonst  IS INITIAL
  AND p_abwkra IS INITIAL
  AND p_abwarz IS INITIAL "20190424 HST ergänzt
  AND p_urlaub IS INITIAL
  AND p_sonan  IS INITIAL
  AND p_sonab  IS INITIAL
  AND p_alle   IS INITIAL
  AND p_mit1   IS INITIAL
  AND p_ausueb IS INITIAL
  AND p_ausue2 IS INITIAL
  AND p_auspra IS INITIAL
  AND p_auswae IS INITIAL
  AND p_ohnueb IS INITIAL
  AND p_ohnaus IS INITIAL
  AND p_ohnmeh IS INITIAL
    ).
    PERFORM show_data_main.
  ENDIF.


  "show_data_main
  " collect_data
  "  collect_data_kalender 0300 Krank, 0400 Arbeitsunfall, 0410: Kalendertage
  "  collect_time 0200 Arzt, 0250 Dienstgang, 0260 Dienstreise: Tage Korrektur
  "  collect_text 0220 Sonder: Test Zusatz
  "  collect_data_arbeit 0150 Pfl Wo1, 0160 Pfl Wo2 , 0690 Freistellung: Arbeits
  "    correct_data_arbeit
  "  show_data
  "    filter_data pro Auswertung
  "    show_dialog
  "      show_dialog_sort pro Auswertung
  "    show_alv_mit
  "    show_alv
  "      visible
FORM show_data_main_mit.
  PERFORM collect_data_mit.
  IF p_mit1 = 'X'.
    gv_titel = 'Mitarbeiter'.
    gv_ausw = 'MIT1'.
  ENDIF.

  PERFORM show_data.
  CLEAR gt_alv[].
ENDFORM.

FORM show_data_main.
  PERFORM collect_data.

  IF p_sonst = 'X'.
    gv_ausw = 'SONSTIGE'.
    gv_titel = 'Sonstige'.
    PERFORM show_data.
  ENDIF.
  IF p_sonan = 'X'.
    gv_ausw = 'SONSTIGEABW'.
    gv_titel = 'Sonstige Abwesenheiten'.
    PERFORM show_data.
  ENDIF.
  IF p_sonan = 'X'.
    gv_ausw = 'SONSTIGEANW'.
    gv_titel = 'Sonstige Anwesenheiten'.
    PERFORM show_data.
  ENDIF.
  IF p_abwkra = 'X'.
    gv_ausw = 'KRANK'.
    gv_titel = 'Krankenstand'.
    PERFORM show_data.
  ENDIF.
  IF p_abwarz = 'X'.
    gv_ausw = 'ARZT'.
    gv_titel = 'Arzt'.
    PERFORM show_data.
  ENDIF.
  IF p_urlaub = 'X'.
    gv_titel = 'Urlaub'.
    gv_ausw = 'URLAUB'.
    PERFORM show_data.
  ENDIF.
  IF p_ausueb = 'X'.
    gv_titel = 'Auszahlung Überstunden 50%'.
    gv_ausw = 'AUSUEB'.
    PERFORM show_data.
  ENDIF.
  IF p_ausue2 = 'X'.
    gv_titel = 'Auszahlung Überstunden 100%'.
    gv_ausw = 'AUSUE2'.
    PERFORM show_data.
  ENDIF.
  IF p_auspra = 'X'.
    gv_titel = 'Auszahlung Prämie (EUR)'.
    gv_ausw = 'AUSPAE'.
    PERFORM show_data.
  ENDIF.
  IF p_auswae = 'X'.
    gv_titel = 'Auszahlung Wäsche (EUR)'.
    gv_ausw = 'AUSWAE'.
    PERFORM show_data.
  ENDIF.
  IF p_ohnmeh = 'X' OR p_ohnueb = 'X' OR p_ohnmeh = 'X'.
    gv_titel = 'Ohne Zeiterfassung'.
    gv_ausw = 'OHNEZEIT'.
    PERFORM show_data.
  ENDIF.
  IF p_alle = 'X'.
    gv_titel = 'Alle Anwesenheiten und Abwesenheiten'.
    "gv_ausw is initial.
    CLEAR gv_ausw.
    PERFORM show_data.
  ENDIF.

  CLEAR gt_alv[].
ENDFORM.

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.

  CLEAR so_teilk.
  IF p_voll EQ 'X'.
    so_teilk-sign = 'I'.
    so_teilk-option = 'EQ'.
    APPEND so_teilk.
  ENDIF.
  IF p_teil EQ 'X'.
    so_teilk-sign = 'I'.
    so_teilk-option = 'EQ'.
    so_teilk-low = 'X'.
    APPEND so_teilk.
  ENDIF.

  IF    p_sonst  IS INITIAL
    AND p_abwkra IS INITIAL
    AND p_abwarz IS INITIAL "20190424 HST ergänzt
    AND p_urlaub IS INITIAL
    AND p_sonan  IS INITIAL
    AND p_sonab  IS INITIAL
    AND p_alle   IS INITIAL
    AND p_mit1   IS INITIAL
    AND p_ausueb IS INITIAL
    AND p_ausue2 IS INITIAL
    AND p_auspra IS INITIAL
    AND p_auswae IS INITIAL
    AND p_ohnueb IS INITIAL
    AND p_ohnaus IS INITIAL
    AND p_ohnmeh IS INITIAL
    .
    MESSAGE 'Die Auswahl einer Liste wäre zumindest nötig.' TYPE 'E'.
  ENDIF.

ENDFORM.

"Sammlung der Personen
FORM collect_pers.
  "Selektion der Grundtabelle lt_pa über PA0007
  "Sammeln der Daten PA0000, PA0001, PA0002, PA0007 über diese MA.
  "Anreichern der Struktur gs_alv_pers
  "Plausibilitätscheck
  "Anhängen an die Ausgabetabelle gt_alv_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.
  "Erste Filterung ist die Zeiterfassung, ob die notwendig ist,
  " je nach Selektion
  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.
    "for all entries in lt_pa  darf nicht leer sein, sonst werden alle Sätze genommen.

    "Auswahl der Maßnahmen 3 Beschäftigt im besagtem Zeitraum
    "Delta sind Personen, die gekündigt wurden und wieder angestellt wurden.
    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
    )
    ).
    "Vorige Selektion waren unabh. vom Beschäftigung
    "Vorige Selektion waren MA, die vor dem Zeitraum Ende angefangen
    " und nach dem Zeitraum Ende aufgehört haben, nicht aber MA, die vor
    " dem Zeitraum Ende aufgehört haben.
    "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
    "Es wird auf jeden Fall ein Satz mit langer Laufzeit
    " im besten Fall 31.12.9999 gewählt.
    "Delta wäre, wenn die Auswertung für eine weit zurückliegende
    " Vergangenheit wäre, dann wäre die aktuelle Org. Zugehörigkeit
    SELECT * FROM pa0001 AS a INTO TABLE lt_pa0001
    FOR ALL ENTRIES IN lt_pa "Darf ja nicht leer sein.
    WHERE pernr = lt_pa-pernr
    AND a~persk IN so_persk "Personenkreis Angestelle und Arbeiter
    AND a~persg IN so_persg
    AND a~abkrs IN so_abkrs
    AND a~btrtl IN so_btrtl
    AND a~begda LT so_datum-high"LE so_datum-low
    AND a~endda GE so_datum-high.

    "Auswahl der Namens- und Adressdaten im besagtem Zeitraum
    "Delta wäre, wenn die Auswertung für eine weit zurückliegende
    " Vergangenheit wäre, dann wäre die aktuelle Adresse
    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 AS a INTO TABLE lt_pa0007
    FOR ALL ENTRIES IN lt_pa
    WHERE pernr = lt_pa-pernr
    AND zterf IN so_zterf
    AND teilk IN so_teilk
    "Insert Anfang HST 20190328
    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
      )
    ).
    "Insert Ende HST 20190328

    "Delete Anfang HST 20190328
    "Vorige Selektion waren MA, die vor dem Zeitraum Ende angefangen
    " und nach dem Zeitraum Ende aufgehört haben, nicht aber MA, die vor
    " dem Zeitraum Ende aufgehört haben.
    "AND begda LT so_datum-high"LE so_datum-low
    "AND endda GE so_datum-high.
    "Delete Ende HST 20190328
  ELSE.
    EXIT.
  ENDIF.

  "Durchgehen aller MA mit der Personalnummerntabelle lt_pa
  "Ergänzung um Maßnahme        0000 Begin Datum Ende Datum
  "Ergänzung um Adresse         0002 Nachname Vorname
  "Ergänzung um Personalkreis   0001
  "Ergänzung um Sollarbeitszeit 0007
  "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>). "0007
    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.
      gs_alv-arbst = <pa0007>-arbst.
      gs_alv-schkz = <pa0007>-schkz.
      gs_alv-wkwdy = <pa0007>-wkwdy.
      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.
"Sammlung der Daten
"  Wird für alle Auswertungen einmalig aufgerufen
"Fall 1: Mitarbeiterliste
"Durchgehen der MA.
"Durchgehen der Grundtabelle gt_alv_pers
"Anhängen der Struktur ls_alv an die Tabelle gt_alv.
FORM collect_data_mit.

  DATA gv_text(30) TYPE c.
  FIELD-SYMBOLS: <ls_alv> TYPE ty_alv.

  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>.
  ENDLOOP.
ENDFORM.
"Sammlung der Daten
"  Wird für alle Auswertungen einmalig aufgerufen
"Fall 2: An- Abwesenheitsliste
"Durchgehen der Grundtabelle gt_alv_pers
"Lesen der Abwesenheiten PA2001.
"Anreichern der Struktur ls_alv.
"Anhängen der Struktur ls_alv an die Tabelle gt_alv.
"Lesen der Abwesenheiten PA2002.
"Anreichern der Struktur ls_alv.
"Anhängen der Struktur ls_alv an die Tabelle gt_alv.
FORM collect_data.

  "Fall 1: Mitarbeiterliste
  "Durchgehen der MA.
  "Durchgehen der Grundtabelle gt_alv_pers
  "Anhängen der Struktur ls_alv an die Tabelle gt_alv.


  DATA gv_text(30) TYPE c.
  FIELD-SYMBOLS: <ls_alv> TYPE ty_alv.

  ASSIGN gs_alv TO <ls_alv>.
  LOOP AT gt_alv_pers INTO DATA(wa).
    "*****************************************************************************
    "2012 Umbuchungen
    SELECT pernr, subty, begda, endda, anzhl FROM pa2012 INTO CORRESPONDING FIELDS OF TABLE @lt_pa2012 WHERE pernr = @wa-pernr
      AND ( ( begda IN @so_datum )
      OR ( endda IN @so_datum  )
      OR  ( begda LT @so_datum-low AND endda GT @so_datum-high ) )
      "AND subty IN ('9320', '9321') 20190902HST
    .
    IF sy-subrc = 0.
      LOOP AT lt_pa2012 ASSIGNING FIELD-SYMBOL(<pa2012>).
        APPEND INITIAL LINE TO gt_alv ASSIGNING <ls_alv>.
        MOVE-CORRESPONDING wa TO <ls_alv>.
        MOVE <pa2012>-begda TO <ls_alv>-begda.
        MOVE <pa2012>-endda TO <ls_alv>-endda.
        MOVE <pa2012>-anzhl TO <ls_alv>-zstun.
        MOVE <pa2012>-subty TO <ls_alv>-awart.
        CASE <pa2012>-subty.

          WHEN '9320'.
            MOVE 'AUSBEZ. ÜBERST. 100%' TO <ls_alv>-grund.
            MOVE 'AUSUE2' TO <ls_alv>-ausw.
          WHEN '9321'.
            MOVE 'AUSBEZ. ÜBERST. 50%' TO <ls_alv>-grund.
            MOVE 'AUSUEB' TO <ls_alv>-ausw.
          WHEN '9322'.
            MOVE 'AUSBEZ. PRÄMIE (EUR)' TO <ls_alv>-grund.
            MOVE 'AUSPRA' TO <ls_alv>-ausw.
          WHEN '9904'.
            MOVE 'AUSBEZ. WÄSCHE (EUR)' TO <ls_alv>-grund.
            MOVE 'AUSWAE' TO <ls_alv>-ausw.
*    Stundenübertrag ohne Zeiterf.   9901
*    Stunden auszahlen ohne Zeiterf. 9902
*    +/- Stunden ohne Zeiterf.       9903
          WHEN '9901'.
            MOVE 'ÜBERTRAG' TO <ls_alv>-grund.
            MOVE 'OHNEZEIT' TO <ls_alv>-ausw.
          WHEN '9902'.
            MOVE 'AUSZAHLUNG STD.' TO <ls_alv>-grund.
            MOVE 'OHNEZEIT' TO <ls_alv>-ausw.
          WHEN '9903'.
            MOVE '+/- STUNDEN' TO <ls_alv>-grund.
            MOVE 'OHNEZEIT' TO <ls_alv>-ausw.
          WHEN OTHERS.
            MOVE 'UNASSIGNED' TO <ls_alv>-grund.
            MOVE 'UNASSIGNED' TO <ls_alv>-ausw.
        ENDCASE.

      ENDLOOP.
    ENDIF.
    "*****************************************************************************
    "2001 Abwesenheiten
    SELECT * FROM pa2001 INTO CORRESPONDING FIELDS OF TABLE @lt_pa2001 WHERE pernr = @wa-pernr
      AND ( ( begda IN @so_datum )
      OR ( endda IN @so_datum  )
      OR  ( begda LT @so_datum-low AND endda GT @so_datum-high ) )
    AND awart IN @so_awart.
    IF sy-subrc = 0.
      LOOP AT lt_pa2001 ASSIGNING FIELD-SYMBOL(<pa2001>).
        "Anlage eines neuen Satzes mit Grundwerten
        APPEND INITIAL LINE TO gt_alv ASSIGNING <ls_alv>.
        MOVE-CORRESPONDING wa TO <ls_alv>.
        MOVE <pa2001>-begda TO <ls_alv>-begda.
        MOVE <pa2001>-endda TO <ls_alv>-endda.
        MOVE <pa2001>-abrst TO <ls_alv>-zstun.
        MOVE <pa2001>-abrtg TO <ls_alv>-ztage.
        MOVE <pa2001>-awart TO <ls_alv>-awart.
        "Vorarbeiten für ausgewertete Abw.
        CASE <pa2001>-awart.
          WHEN '0300' OR '0310' OR '0200' OR '0210' OR '0220'
            OR '0100' OR '0101' OR '0150' OR '0160' OR '0400'
            OR '0410' OR '0690'
            .
        ENDCASE.
        "Korrektur der Grundwerte des neuen Satzes
        CASE <pa2001>-awart.
          WHEN 'SONST'.
          WHEN '0300'. "KRANK Kalendertage
            MOVE 'KRANK' TO <ls_alv>-grund.
            MOVE 'KRANK' TO <ls_alv>-ausw.
            IF p_krankk = 'X'.
              PERFORM collect_data_kalender USING <pa2001> CHANGING <ls_alv>.
            ELSE.
              PERFORM collect_data_arbeit USING <pa2001> CHANGING <ls_alv>.
            ENDIF.
          WHEN '0310'. "KRANK
            MOVE 'KRANKUNTERT.' TO <ls_alv>-grund.
            MOVE 'KRANK' TO <ls_alv>-ausw.
          WHEN '0400'. "Arbeitsunfall Kalendertage
            MOVE 'ARBEITSUNF.' TO <ls_alv>-grund.
            MOVE 'KRANK' TO <ls_alv>-ausw.
            IF p_krankk = 'X'.
              PERFORM collect_data_kalender USING <pa2001> CHANGING <ls_alv>.
            ELSE.
              PERFORM collect_data_arbeit USING <pa2001> CHANGING <ls_alv>.
            ENDIF.
          WHEN '0410'. "Arbeitsunfall Foleeerkr. Kalendertage
            MOVE 'FOLGEERK.ARB.UNF.' TO <ls_alv>-grund.
            MOVE 'KRANK' TO <ls_alv>-ausw.
            IF p_krankk = 'X'.
              PERFORM collect_data_kalender USING <pa2001> CHANGING <ls_alv>.
            ELSE.
              PERFORM collect_data_arbeit USING <pa2001> CHANGING <ls_alv>.
            ENDIF.
          WHEN '0200'.           "ARZT
            MOVE 'ARZT' TO <ls_alv>-ausw.
            MOVE 'ARZT' TO <ls_alv>-grund.
            "Fehler von Arzt korrigieren.
            "Abrechnungstage sind bei Arzt derzeit 0,5 fix.
            "Hier die tatsächlichen Ist Stunden heranziehen.
            PERFORM collect_time USING <pa2001> CHANGING <ls_alv>.
          WHEN '0210'.           "BEHÖRDENWEG
            MOVE 'BEHÖRDE' TO <ls_alv>-grund.
            MOVE 'SONSTIGE' TO <ls_alv>-ausw.
          WHEN '0220'.           "SONDERURLAUB
            MOVE 'SONDERURLAUB' TO <ls_alv>-grund.
            IF <pa2001>-itxex = 'X'.
              CLEAR gv_text.
              PERFORM collect_text
                USING
                          <pa2001>-pernr
                          '2001'
                          <pa2001>-awart
                          <pa2001>-begda
                          <pa2001>-endda
                          CHANGING gv_text.
              MOVE gv_text TO <ls_alv>-bemer.
            ENDIF.
            MOVE 'SONSTIGE' TO <ls_alv>-ausw.
          WHEN '0150'.           "PFLEGEFREISTELLUNG 1.Wo
            MOVE 'PFLEGEFR. 1.WO' TO <ls_alv>-grund.
            MOVE 'SONSTIGE' TO <ls_alv>-ausw.
            PERFORM collect_data_arbeit USING <pa2001> CHANGING <ls_alv>.
          WHEN '0160'.           "PFLEGEFREISTELLUNG 2.Wo
            MOVE 'PFLEGEFR. 2.WO' TO <ls_alv>-grund.
            MOVE 'SONSTIGE' TO <ls_alv>-ausw.
            PERFORM collect_data_arbeit USING <pa2001> CHANGING <ls_alv>.
          WHEN '0690'.           "FREISTELLUNG
            MOVE 'FREISTELLUNG' TO <ls_alv>-grund.
            MOVE 'SONSTIGE' TO <ls_alv>-ausw.
            PERFORM collect_data_arbeit USING <pa2001> CHANGING <ls_alv>.
          WHEN '0100'. "URLANG und URLARB
            MOVE 'URLAUB' TO <ls_alv>-ausw.
            MOVE 'URLAUB' TO <ls_alv>-grund.
            PERFORM collect_data_arbeit USING <pa2001> CHANGING <ls_alv>.
          WHEN '0101'. "URLANG und URLARB
            MOVE 'URLHALBT.' TO <ls_alv>-grund.
            MOVE 'URLAUB' TO <ls_alv>-ausw.
          WHEN '0500'. "ZEITAUSGLEICH
            MOVE 'ZEITAUSGLEICH' TO <ls_alv>-grund.
            MOVE 'SONSTIGEABW' TO <ls_alv>-ausw.
            CLEAR <ls_alv>-ztage.
          WHEN OTHERS.
            MOVE 'SONSTIGEABW' TO <ls_alv>-ausw.
            MOVE <pa2001>-awart TO <ls_alv>-grund.
        ENDCASE.
        "Korrektur des Beginndatums und des Endedatums in den Auswertungen
        "Nur bei mehrtägigen
        CASE <pa2001>-awart.
          WHEN '0150' "Pflegefreistellung 1.Wo
            OR '0160' "Pflegefreistellung 2.Wo
            OR '0300' "Krank
            OR '0220' "Sonderurlaub
            OR '0100' "Urlaub
            OR '0400' "Arbeitsunfall
            OR '0410' "Arbeitsunfall Folgeerk.
            OR '0690' "Freistellung
            .
            IF <pa2001>-begda LT so_datum-low.
              MOVE so_datum-low TO <ls_alv>-begda. "Korrektur Beginndatum
            ENDIF.
            IF <pa2001>-endda GT so_datum-high.
              MOVE so_datum-high TO <ls_alv>-endda. "Korrektur Enddatum
            ENDIF.
        ENDCASE.

        "Gesperrte An-/Abwesenheiten Info ergänzen
        IF <pa2001>-sprps = 'X'.
          CONCATENATE <ls_alv>-grund ' SPERRKENNZEICHEN' INTO <ls_alv>-grund.
          MOVE 'X' TO <ls_alv>-sprps.
        ENDIF.
      ENDLOOP.
    ENDIF.
    "*****************************************************************************
    "2002 Anwesenheiten
    SELECT * FROM pa2002 INTO CORRESPONDING FIELDS OF TABLE @lt_pa2002 WHERE pernr = @wa-pernr
    AND ( ( begda IN @so_datum )
    OR ( endda IN @so_datum  )
    OR  ( begda LT @so_datum-low AND endda GT @so_datum-high ) )
    AND awart IN @so_awart.
    IF sy-subrc = 0.
      LOOP AT lt_pa2002 ASSIGNING FIELD-SYMBOL(<pa2002>).
        "      LOOP AT lt_pa2002 ASSIGNING field-symbol (<pa2002>).
        APPEND INITIAL LINE TO gt_alv ASSIGNING <ls_alv>.
        MOVE-CORRESPONDING wa TO <ls_alv>.
        MOVE <pa2002>-begda TO <ls_alv>-begda.
        MOVE <pa2002>-endda TO <ls_alv>-endda.
        MOVE <pa2002>-abrtg TO <ls_alv>-ztage.
        MOVE <pa2002>-abrst TO <ls_alv>-zstun.
        MOVE <pa2002>-awart TO <ls_alv>-awart.
        CASE <pa2002>-awart.
          WHEN '0230' OR '0240' OR '0250' OR '0260'.
        ENDCASE.
        CASE <pa2002>-awart.
*0230	Schu Anwesenheit 2002 Schulung/kurs --> SonstigeAnw     --> Erl.
*0240	BerS Anwesenheit 2002 Berufsschule  --> SonstigeAnw     --> Erl.
*0250	DR Anwesenheit 2002 Dienstreise     --> SonstigeAnw     --> Erl.
*0260	DG Anwesenheit 2002 Dienstgange     --> SonstigeAnw     --> Erl.
          WHEN '0230'. "Ohne Uhrzeit
            MOVE 'SONSTIGEANW' TO <ls_alv>-ausw.
            MOVE 'SCHULUNG/KURS' TO <ls_alv>-grund.
          WHEN '0240'."Ohne Uhrzeit
            MOVE 'SONSTIGEANW' TO <ls_alv>-ausw.
            MOVE 'BERUFSSCHULE' TO <ls_alv>-grund.
          WHEN '0250'. "Ohne Uhrzeit
            MOVE 'SONSTIGEANW' TO <ls_alv>-ausw.
            MOVE 'DIENSTREISE' TO <ls_alv>-grund.
            "Fehler von Dientreise an Feiertagen/Sonntagen korrigieren
            IF <ls_alv>-zstun = 0.
              PERFORM collect_time USING <pa2002> CHANGING <ls_alv>.
            ENDIF.
          WHEN '0260'. "Dienstgang Tatsächliche Stunden
            MOVE 'SONSTIGEANW' TO <ls_alv>-ausw.
            MOVE 'DIENSTGANG' TO <ls_alv>-grund.
            "Fehler von Dientgang an Feiertagen/Sonntagen korrigieren
            IF <ls_alv>-zstun = 0.
              PERFORM collect_time USING <pa2002> CHANGING <ls_alv>.
            ENDIF.
          WHEN OTHERS.
            MOVE 'SONSTIGEANW' TO <ls_alv>-ausw.
            MOVE <pa2002>-awart TO <ls_alv>-grund.
        ENDCASE.
        IF <pa2002>-sprps = 'X'.
          CONCATENATE <ls_alv>-grund ' SPERRKENNZEICHEN'
            INTO <ls_alv>-grund.
          MOVE 'X' TO <ls_alv>-sprps.
        ENDIF.
      ENDLOOP.
    ENDIF.

  ENDLOOP.
ENDFORM.
"Unterprogramm von collect_data
"Auswertung nach Kalendertagen (Für Krankheit
"Korrektur der Zeiträume und Fehler von SAP Abrechnung
"Sollkorrketur
FORM collect_data_kalender
  USING ls_pa2001 TYPE ty_abwanw
  CHANGING ls_alv TYPE ty_alv.


  "DATA: lv_abrtg LIKE pa2001-abrtg.
  DATA: lv_abrtg TYPE f, lv_zstun TYPE f.

  IF ls_pa2001-begda LT so_datum-low.
    IF ls_pa2001-endda GT so_datum-high."Vor und nach Zeitraum
      lv_abrtg = so_datum-high - so_datum-low + 1.
      CONCATENATE ls_alv-grund ' VORH. NACHH.' INTO ls_alv-grund.
    ELSE.                              "vor betrachteten Zeitraum
      lv_abrtg = ls_pa2001-endda - so_datum-low + 1.
      CONCATENATE ls_alv-grund ' BEREITS VORHER' INTO ls_alv-grund.
    ENDIF.
  ELSE.
    IF ls_pa2001-endda GT so_datum-high. "nach betrachteten Zeitraum
      lv_abrtg = so_datum-high - ls_pa2001-begda + 1.
      CONCATENATE ls_alv-grund ' AUCH NACHHER' INTO ls_alv-grund.
    ELSE.                              "im betrachteten Zeitraum
      lv_abrtg = ls_pa2001-endda - ls_pa2001-begda + 1.
    ENDIF.
  ENDIF.
  "Durchschnittliche Arbeitsstunden tgl.
  ls_alv-zstun = lv_abrtg * ls_alv-arbst.
  MOVE lv_abrtg TO ls_alv-ztage.

ENDFORM.

"Unterprogramm von collect_data
"Auswertung nach tatsächlicher Uhrzeit (Für Dienstreisen
"Korrektur der Zeiträume und Fehler von SAP Abrechnung
"Istkorrketur
FORM collect_time
  USING ls_pa2001 TYPE ty_abwanw
  CHANGING ls_alv TYPE ty_alv.

  "Abgerechnete Stunden zstun an Feiertagen ist gleich 0,
  " hier die tatsächliche Uhrzeit wählen

  "Tatsächliche Uhrzeit eintragen
  DATA lv_tims TYPE t.
  lv_tims = ls_pa2001-enduz - ls_pa2001-beguz.
  "Umwandlung tims in decimal.
  ls_alv-zstun = lv_tims+0(2) + ( lv_tims+2(2) / 60 ).
  IF ls_alv-arbst NE 0.
    ls_alv-ztage = ls_alv-zstun / ls_alv-arbst.
  ELSE.
    DATA lv_text(80) TYPE c.
    CONCATENATE ls_alv-pernr ' ' ls_alv-awart ' ' ls_alv-begda ' ' ls_alv-endda INTO lv_text RESPECTING BLANKS.
    MESSAGE i534(0u) WITH lv_text ls_alv-zstun ls_alv-arbst .
  ENDIF.
  "Deckelung max. 1 Tag.
  IF ls_alv-ztage GT 1.
    ls_alv-ztage = 1.
  ENDIF.


ENDFORM.
"Unterprogramm von collect_data
"Auswertung nach Arbeitstagen
"Korrektur der Zeiträume und Fehler von SAP Abrechnung
FORM collect_data_arbeit
    USING ls_pa2001 TYPE ty_abwanw
  CHANGING ls_alv TYPE ty_alv.


  DATA: lv_begda TYPE begda.
  DATA: lv_endda TYPE endda.

  "Folgende Felder werden nur in ls_alv neu berechnet und rückgeschrieben,
  " wenn der Zeitraum verändert wird.
  DATA: lv_abrst TYPE f.
  DATA: lv_abrtg TYPE f. "Richtiger Type
  "DATA: lv_abrtg LIKE pa2001-abrtg.

  IF ls_pa2001-begda LT so_datum-low.
    IF ls_pa2001-endda GT so_datum-high.  "Vor und nach Zeitraum
      CONCATENATE ls_alv-grund ' VORH. NACHH.' INTO ls_alv-grund.
    ELSE.                              "vor betrachteten Zeitraum
      CONCATENATE ls_alv-grund ' BEREITS VORHER' INTO ls_alv-grund.
    ENDIF.
  ELSE.
    IF ls_pa2001-endda GT so_datum-high. " nach betrachteten Zeitraum
      CONCATENATE ls_alv-grund ' AUCH NACHHER' INTO ls_alv-grund.
    ELSE.                              "im betrachteten Zeitraum
    ENDIF.
  ENDIF.


  "Wenn Datumsbereich korrigiert werden muss, dann Neuberechnung
  IF ls_pa2001-begda LT so_datum-low OR ls_pa2001-endda GT so_datum-high.
    "Korrektur des Datumsbereichs
    CLEAR: lv_begda, lv_endda.
    lv_begda = ls_pa2001-begda.
    lv_endda = ls_pa2001-endda.
    IF ls_pa2001-begda LT so_datum-low.
      lv_begda = so_datum-low.
    ENDIF.
    IF ls_pa2001-endda GT so_datum-high.
      lv_endda = so_datum-high.
    ENDIF.
    PERFORM correct_data_arbeit
      USING
                ls_pa2001-pernr
                '2001'
                ls_pa2001-awart
                lv_begda
                lv_endda
                CHANGING lv_abrst lv_abrtg.
    MOVE lv_abrst TO ls_alv-zstun. "Korrigierte Stunden
    MOVE lv_abrtg TO ls_alv-ztage. "Korrigierte Tage
  ELSE.
    lv_begda = ls_pa2001-begda.
    lv_endda = ls_pa2001-endda.
    PERFORM correct_data_arbeit
      USING
                ls_pa2001-pernr
                '2001'
                ls_pa2001-awart
                lv_begda
                lv_endda
                CHANGING lv_abrst lv_abrtg.
    MOVE lv_abrst TO ls_alv-zstun. "Korrigierte Stunden
    MOVE lv_abrtg TO ls_alv-ztage. "Korrigierte Tage

  ENDIF.
ENDFORM.

"Unterprogramm von collect_data_arbeit
"Berechnung von lv_abrst und lv_abrtg.
FORM correct_data_arbeit
  USING
      lv_pernr
      lv_infty
      lv_subty
      lv_begda
      lv_endda
  CHANGING lv_abrst lv_abrtg.
  DATA lt_ptpsp TYPE TABLE OF ptpsp.

  CLEAR: lv_abrst, lv_abrtg.

  "lt_ptpsp beinhaltet Tages AZP, Sollabrechnungsstunden, Feiertaginfo
  CALL FUNCTION 'HR_PERSONAL_WORK_SCHEDULE'
    EXPORTING
      pernr         = lv_pernr
      begda         = lv_begda
      endda         = lv_endda
    TABLES
      perws         = lt_ptpsp
    EXCEPTIONS
      error_occured = 1
      abort_occured = 2
      OTHERS        = 3.

  IF sy-subrc = 0.
    LOOP AT lt_ptpsp ASSIGNING FIELD-SYMBOL(<ls_ptpsp>).
      IF <ls_ptpsp>-tprog = 'FREI'. "Frei - Kein Urlaub etc. nötig
        CONTINUE.
      ENDIF.
      IF <ls_ptpsp>-ftkla = 1. "Feiertag - Kein Urlaub etc. nötig
        CONTINUE.
      ENDIF.
      IF <ls_ptpsp>-ftkla = 0. "Normaler Arbeitstag
        lv_abrst = lv_abrst + <ls_ptpsp>-stdaz.
        lv_abrtg = lv_abrtg + 1.
        CONTINUE.
      ENDIF.
      IF <ls_ptpsp>-ftkla = 2. "Weihnachten, Silvester
        lv_abrst = lv_abrst + <ls_ptpsp>-stdaz / 2.
        lv_abrtg = lv_abrtg + 1 / 2.
        CONTINUE.
      ENDIF.
    ENDLOOP.

  ENDIF.
ENDFORM.


"Sortierung der Daten
" Wird nach der Sammlung der Daten durch collect_data aufgerufen
"  einmalig für alle Daten
"  Nur für Dialogausgabe
FORM show_dialog_sort.
  "Sortierung des ALV
  IF lines( gt_alv2 ) = 0.
    EXIT.
  ENDIF.
  IF gv_ausw = 'MIT1'.
    IF p_sortn = 'X'.
      SORT gt_alv2 BY teilk nachn vorna pernr begda.
    ELSE.
      SORT gt_alv2 BY teilk pernr nachn vorna begda.
    ENDIF.

  ELSE.
    IF p_sortn = 'X'.
      SORT gt_alv2 BY nachn vorna pernr begda.
    ELSE.
      SORT gt_alv2 BY pernr nachn vorna begda.
    ENDIF.
  ENDIF.
ENDFORM.


"Filter der Daten bzgl. gesperrte und nicht gesperrte Sätze
" Unterpgrogramm von show_data
FORM filter_data.

  FIELD-SYMBOLS: <ls_alv> TYPE ty_alv..

  IF lines( gt_alv ) = 0.
    EXIT.
  ENDIF.
  CLEAR gt_alv2[].

  "Abbildung des Sperrschlüssels
  DATA lt_sprps TYPE RANGE OF sprps.
  DATA ls_sprps LIKE LINE OF lt_sprps.
  IF p_sprnur = 'X'. "Nur gesperrte Sätze
    ls_sprps-sign = 'I'.
    ls_sprps-option = 'EQ'.
    ls_sprps-low = 'X'.
    APPEND ls_sprps TO lt_sprps.
  ENDIF.
  IF p_sprohn = 'X'. "Ohne gesperrte Sätze
    ls_sprps-sign = 'E'.
    ls_sprps-option = 'EQ'.
    ls_sprps-low = 'X'.
    APPEND ls_sprps TO lt_sprps.
  ENDIF.
  IF p_sprmit = 'X'. "Mit gesperrten Sätzen
    CLEAR lt_sprps.
  ENDIF.

  LOOP AT gt_alv INTO DATA(wa) WHERE sprps IN lt_sprps.
    "Alle Daten bei alle und bei Mitarbeiterlisten
    IF gv_ausw = wa-ausw OR gv_ausw IS INITIAL OR gv_ausw = 'MIT1'.
      APPEND INITIAL LINE TO gt_alv2 ASSIGNING <ls_alv>.
      MOVE-CORRESPONDING wa TO <ls_alv>.
    ENDIF.
  ENDLOOP.
ENDFORM.

"Show Data
"Filtern der Daten
"Ausgabe als Dialogfenster odeer als ALV
FORM show_data.
  "Für jede Gruppe ein anderer Filter
  "Input gt_alv
  "Outpu gt_alv2

  PERFORM filter_data.
  IF p_outdia = 'X'. "Dialog Output
    PERFORM show_dialog.
  ELSE. "ALV Output
    IF gv_ausw = 'MIT1'.
      PERFORM show_alv_mit.
    ELSE.
      PERFORM show_alv.
    ENDIF.
  ENDIF.

ENDFORM.


"Ausgabe als Dialog
"Unterprogramm von show_data
FORM show_dialog.

  IF gt_alv2[] IS INITIAL.
    EXIT.
  ENDIF.
  PERFORM show_dialog_sort.

  "cl_demo_output=>display( gv_ausw ).

  cl_demo_output=>display( gt_alv2 ).


  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.

"Ausgabe als ALV
"Unterprogramm von show_data
FORM show_alv_mit.

  "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.
* Spalten Feldkatalog ändern
  DATA: lr_columns TYPE REF TO cl_salv_columns_table,
        lr_column  TYPE REF TO cl_salv_column_table.
* Variant
  DATA: lf_variant TYPE slis_vari.


  "Rücksprung wenn die Daten leer sind.
  IF gt_alv2[] IS INITIAL.
    EXIT.
  ENDIF.

* 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_alv2.
    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 gv_titel ` - 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 ).

  TRY.

      "Sort einstellen
      lr_sorts = lr_salv->get_sorts( ).
      lr_sorts->add_sort( columnname = 'TEILK' subtotal = abap_true ).
      IF p_sortn = 'X'.
        lr_sorts->add_sort( columnname = 'NACHN' subtotal = abap_false ).
        lr_sorts->add_sort( columnname = 'VORNA' 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.

      "Aggregation einstellen
      lr_aggs = lr_salv->get_aggregations( ).
      "lr_aggs->add_aggregation( 'TEILK' ).
      lr_aggs->set_aggregation_before_items( abap_true ).


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

      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( 'PERNR' ).
      lr_column->set_output_length( '5' ).

      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( 'TEILK' ).
      lr_column->set_output_length( '10' ).

      PERFORM visible USING lr_columns 'PERSK' abap_true.  "Personenkreis/Mitarbeitergruppe
      PERFORM visible USING lr_columns 'PERSG' abap_true.  "Personengruppe/Mitarbeitergruppe
      PERFORM visible USING lr_columns 'ABKRS' abap_true.  "Abrechnungskreis
      PERFORM visible USING lr_columns 'BTRTL' abap_true.  "Teilbereich
      PERFORM visible USING lr_columns 'TEILK' abap_true.  "Teilzeitkennzeichen
      PERFORM visible USING lr_columns 'SCHKZ' abap_true.  "Arbeitszeitplan
      PERFORM visible USING lr_columns 'WKWDY' abap_true.  "Arbeitstage pro Woche
      PERFORM visible USING lr_columns 'ARBST' abap_true.  "Arbeitsstunden pro Tag
      PERFORM visible USING lr_columns 'AUSW'  abap_false. "Filterauswahl
      PERFORM visible USING lr_columns 'AWART' abap_false. "An-/Abwesenheitsart
      PERFORM visible USING lr_columns 'SPRPS' abap_false. "Sperrkennzeichen
      PERFORM visible USING lr_columns 'BEGDA' abap_false."
      PERFORM visible USING lr_columns 'ENDDA' abap_false."
      PERFORM visible USING lr_columns 'ZTAGE' abap_false."
      PERFORM visible USING lr_columns 'ZSTUN' abap_false."
      PERFORM visible USING lr_columns 'GRUND' abap_false."
      PERFORM visible USING lr_columns 'BEMER' abap_false."


      lr_columns->set_count_column( 'ZAEHLER').

      lr_columns->set_column_position( columnname = 'PERSK' position = 1 ).
      lr_columns->set_column_position( columnname = 'AUSW'  position = 1 ).
      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 ).

**   set initial Layout

      "lf_variant = '/AUSDRUCK'.
      lf_variant = p_vari. "20190424 Variante
      lr_layout->set_initial_layout( lf_variant ).


    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' ).
    CATCH cx_salv_msg.
      cl_demo_output=>display('Error' ).
  ENDTRY.

* Ausgabe
  lr_salv->display( ).
ENDFORM.


"Ausgabe als ALV
"Unterprogramm von show_data
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.
* Spalten Feldkatalog ändern
  DATA: lr_columns TYPE REF TO cl_salv_columns_table,
        lr_column  TYPE REF TO cl_salv_column_table.
* Variant
  DATA: lf_variant TYPE slis_vari.


  "Rücksprung wenn die Daten leer sind.
  IF gt_alv2[] IS INITIAL.
    EXIT.
  ENDIF.

* 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_alv2.
    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 gv_titel ` - 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 ).

  TRY.

      "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_true ).
        "lr_sorts->set_compressed_subtotal( 'NACHN' ).
      ELSE.
        lr_sorts->add_sort( columnname = 'PERNR' subtotal = abap_true ).
        lr_sorts->add_sort( columnname = 'NACHN' subtotal = abap_false ).
        lr_sorts->add_sort( columnname = 'VORNA' subtotal = abap_false ).
      ENDIF.

      "Aggregation einstellen Summe
      lr_aggs = lr_salv->get_aggregations( ).
      lr_aggs->set_aggregation_before_items( abap_false ).
      lr_aggs->add_aggregation( 'ZTAGE' ).
      lr_aggs->add_aggregation( 'ZSTUN' ).


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

      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( 'PERNR' ).
      lr_column->set_output_length( '5' ).

      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( 'BEGDA' ).
      lr_column->set_short_text( 'Beginn').
      lr_column->set_medium_text( 'Beginn Datum').
      lr_column->set_long_text( 'Beginn Datum').

      lr_column ?= lr_columns->get_column( 'ENDDA' ).
      lr_column->set_short_text( 'Ende').
      lr_column->set_medium_text( 'Ende Datum').
      lr_column->set_long_text( 'Ende Datum').

      IF p_auspra = 'X' OR p_auswae = 'X'.
        lr_column ?= lr_columns->get_column( 'ZSTUN' ).
        lr_column->set_short_text( 'EUR').
        lr_column->set_medium_text( 'EUR').
        lr_column->set_long_text( 'EUR').
        PERFORM visible USING lr_columns 'ZTAGE' abap_false.
      ELSE.
        lr_column ?= lr_columns->get_column( 'ZTAGE' ).
        lr_column->set_short_text( 'Tage').
        lr_column->set_medium_text( 'Anzahl Tage').
        lr_column->set_long_text( 'Anzahl Tage').

        lr_column ?= lr_columns->get_column( 'ZSTUN' ).
        lr_column->set_short_text( 'Stunden').
        lr_column->set_medium_text( 'Anzahl Stunden').
        lr_column->set_long_text( 'Anzahl Stunden').
      ENDIF.


      lr_column ?= lr_columns->get_column( 'GRUND' ).
      lr_column->set_short_text( 'Grund').
      lr_column->set_medium_text( 'Grund').
      lr_column->set_long_text( 'Grund').

      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').

      "20190424 HST Anfang
      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 'SCHKZ' p_visibl.  "Arbeitszeitplan
      PERFORM visible USING lr_columns 'WKWDY' p_visibl.  "Arbeitstage pro Woche
      PERFORM visible USING lr_columns 'ARBST' p_visibl.  "Arbeitsstunden pro Tag
      "PERFORM visible USING lr_columns 'AWART' p_visibl.
      PERFORM visible USING lr_columns 'AUSW'  abap_false."Filterauswahl
      PERFORM visible USING lr_columns 'SPRPS' abap_false."Sperrkennzeichen
      PERFORM visible USING lr_columns 'ZAEHLER' abap_false."Sperrkennzeichen
      "20190424 HST Ende

*      lr_column ?= lr_columns->get_column( 'AUSW' ).
*      lr_column->set_visible( '' ).
*
*      lr_column ?= lr_columns->get_column( 'SPRPS' ).
*      lr_column->set_visible( '' ).
*

*     lr_column ?= lr_columns->get_column( 'MENG1' ).
*     lr_column->set_short_text( 'Abw.Tg.S.').
*     lr_column->set_medium_text( 'Abw.Tg.Skonto').
*     lr_column->set_output_length( '10' ).
*     lr_column->set_sign( abap_true ).

** Zusatzinfo ausblenden
*     IF p_zusatz IS INITIAL.
*       lr_column ?= lr_columns->get_column( 'ZFBDT' ).
*       lr_column->set_visible( '' ).
*       lr_column ?= lr_columns->get_column( 'ZBD1T' ).
*       lr_column->set_visible( '' ).
*       lr_column ?= lr_columns->get_column( 'ZBD2T' ).
*       lr_column->set_visible( '' ).
*       lr_column ?= lr_columns->get_column( 'ZBD1P' ).
*       lr_column->set_visible( '' ).
*       lr_column ?= lr_columns->get_column( 'ZBD2P' ).
*       lr_column->set_visible( '' ).
*     ENDIF.

      "lr_columns->set_column_position( columnname = 'PERSK' position = 1 ).
      lr_columns->set_column_position( columnname = 'AUSW'  position = 1 ).
      lr_columns->set_column_position( columnname = 'BEMER' position = 1 ).
      lr_columns->set_column_position( columnname = 'GRUND' position = 1 ).
      lr_columns->set_column_position( columnname = 'ZSTUN' position = 1 ).
      lr_columns->set_column_position( columnname = 'ZTAGE' position = 1 ).
      lr_columns->set_column_position( columnname = 'ENDDA' position = 1 ).
      lr_columns->set_column_position( columnname = 'BEGDA' position = 1 ).
      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 ).

      "lr_columns->get_count_column

**   set initial Layout

      "lf_variant = '/AUSDRUCK'.
      lf_variant = p_vari. "20190424 Variante
      lr_layout->set_initial_layout( lf_variant ).


    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' ).
    CATCH cx_salv_msg.
      cl_demo_output=>display('Error' ).
  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.


"Lesen der Zusatztexte
"Unterprogramm von collect_data
" Zusatztext bei gewissen Bewegungsarten
" Das Makro rp-imp-c1-tx liest den Zusatztext
FORM collect_text
  USING
      lv_pernr
      lv_infty
      lv_subty
      lv_begda
      lv_endda
  CHANGING gv_text.
*  PARAMETERS: pernr LIKE pa2001-pernr,
*              infty LIKE pa2001-infty,
*              subty LIKE pa2001-subty,
*              endda LIKE pa2001-endda,
*              begda LIKE pa2001-begda.
*  tables: pa2001.
  TABLES: pcl1.

  DATA: tx-key LIKE pskey.
  DATA: BEGIN OF text-version,
          nummer TYPE x VALUE '02',
        END OF text-version.
  DATA: BEGIN OF ptext OCCURS 200.
  DATA:  line(78).
  DATA: END OF ptext.
  "DATA: key1 LIKE pcl1-srtfd.

*  DATA: key2 LIKE pcl1-srtfd.
*  DATA: final_key LIKE pcl1-srtfd.
*  DATA: blank(7).
*  DATA: blank1(3).
  FIELD-SYMBOLS <wa> TYPE any.
*  IF lv_subty IS INITIAL.
*    CONCATENATE lv_pernr lv_infty INTO key1.
*    CONCATENATE lv_endda lv_begda '000' INTO key2.
*    CONCATENATE key1 key2 INTO final_key SEPARATED BY blank.
*  ELSE.
**-- if with subtypes
*    CONCATENATE lv_pernr lv_infty lv_subty INTO key1.
*    CONCATENATE lv_endda lv_begda '000' INTO key2.
*    CONCATENATE key1 key2 INTO final_key SEPARATED BY blank1.
*  ENDIF.
*  MOVE final_key TO tx-key.

  IF lv_subty IS INITIAL.
    CONCATENATE lv_pernr lv_infty      '       ' lv_endda lv_begda '000'
    INTO tx-key RESPECTING BLANKS.
  ELSE.
    CONCATENATE lv_pernr lv_infty lv_subty '   ' lv_endda lv_begda '000'
    INTO tx-key RESPECTING BLANKS.
  ENDIF.

  rp-imp-c1-tx.

  READ TABLE ptext ASSIGNING <wa>. "Erste Zeile lesen.
  gv_text = <wa>(30).

*  LOOP AT ptext.
*     READ TABLE ptext ASSIGNING <wa>.
*    WRITE:/ ptext.
*  ENDLOOP.

ENDFORM.

"F4 Hilfe für Varianten
"   Unterprogramm für Selektion
FORM f4_alv_variant  CHANGING p_variant LIKE p_vari.
  DATA:variant  TYPE disvariant.
  DATA: lv_exit TYPE c.

  variant-report = sy-repid.
  "variant-handle = '0001'.
  variant-username = sy-uname.
  CALL FUNCTION 'REUSE_ALV_VARIANT_F4'
    EXPORTING
      is_variant    = variant
      i_save        = 'A'
    IMPORTING
      es_variant    = variant
      e_exit        = lv_exit
    EXCEPTIONS
      not_found     = 1
      program_error = 2
      OTHERS        = 3.

  IF sy-subrc NE 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ELSE.
    IF lv_exit EQ space.
      p_vari = variant-variant.
    ENDIF.
  ENDIF.

  "CHECK sy-subrc = 0.
  "p_variant = variant-variant.
ENDFORM.                    " f4_alv_variant

"Selektionszeitraum nach hinten korrigieren
"Unterprogramm in der Initialisierung
"Datum nach jetzigen Monat
FORM date_nachm.

  CLEAR so_datum[].
  "Vorbelegung Datum
  so_datum-sign = 'I'.
  so_datum-option = 'BT'.

  "Aktueller Monat 16 bis nächster Monat 15
  CONCATENATE sy-datum(6) '15' INTO so_datum-low.
  CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
    EXPORTING
      date      = so_datum-low
      days      = 0
      months    = 1
      signum    = '+'
      years     = 0
    IMPORTING
      calc_date = so_datum-high.
  "High ist nun richtig, Low muss noch korrigiert werden
  CONCATENATE sy-datum(6) '16' INTO so_datum-low.

  APPEND so_datum.
ENDFORM.

"Selektionszeitraum nach vorne korrigieren
"Unterprogramm in der Initialisierung
"Datum vor jetzigen Monat
FORM date_vorm.

  CLEAR so_datum[].
  "Vorbelegung Datum
  so_datum-sign = 'I'.
  so_datum-option = 'BT'.
  "Voriger Monat 16 bis aktueller Monat 15
  CONCATENATE sy-datum(6) '16' INTO so_datum-high.
  CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
    EXPORTING
      date      = so_datum-high
      days      = 0
      months    = 1
      signum    = '-'
      years     = 0
    IMPORTING
      calc_date = so_datum-low.
  "Low ist nun richtig, High muss noch korrigiert werden
  CONCATENATE sy-datum(6) '15' INTO so_datum-high.
  APPEND so_datum.


  "MODIFY SCREEN.

ENDFORM.