zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle Thema ist als GELÖST markiert

Alles rund um die Sprache ABAP®: Funktionsbausteine, Listen, ALV
7 Beiträge • Seite 1 von 1
7 Beiträge Seite 1 von 1

zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle

Beitrag von sonicalcatharsis (ForumUser / 4 / 0 / 0 ) » 11.09.2020 12:53
Hallo zusammen,

ich habe da eine Anforderung, dir mir etwas Kopfzerbrechen bereitet. Es geht grob um Berichtserstellung im HR-Zeitkontext.

Tabelle in Kontenform wird im BW angenommen, d.h. Z_EMPLOYEE Z_DATE ZEITART Z_STUNDEN

Für jede Zeitart kommen nun Werte mit, dabei sollen 2 bestimmte Zeitarten ( Z01 und Z02) von Z03 abgezogen bzw addiert werden. Ich habe mir überlegt die Tabelle zu Gruppieren - nach DATE und EMPLOYEE, da innerhalb jedes Tages und Mitarbeiters ja die Berechnung stattfinden soll. Bin aber ehrlich gesagt komplett überfragt, wie ich den Wert Z_STUNDEN von Zeitart Z01 mit dem Wert Z_STUNDEN von Zeitart Z03 in Verbindung bringen soll bzw. ob es nicht besser wäre, die Tabelle erstmal in eine Kennzahlenform zu mappen und die Berechnungen über direkt adressierbare Felder je Datensatz durchführen zu können.

Hat irgendjemand nen Tipp oder so? Ich verzeifel hier gerade ein bisschen...

Vielen Dank im Voraus


Re: zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle

Beitrag von MrBojangles (Specialist / 366 / 3 / 28 ) » 14.09.2020 11:45
Hallo,
ich bin sicher, dass die Top-Trickser dieses Forums das mit wenigen Befehlen hinkriegen würden.

Aus Gründen der Übersichtlichkeit und der einfacheren Weiterverarbeitkeit (eben für Berechnungen und auch zur zeilenweise Ausgabe bspw. in einem ALV) würde ich genauso vorgehen:
...ob es nicht besser wäre, die Tabelle erstmal in eine Kennzahlenform zu mappen und die Berechnungen über direkt adressierbare Felder je Datensatz durchführen zu können.
Voraussetzung hierbei ist natürlich, dass die Anzahl (und Verwendung) der vorkommenden verschiedenen Zeitarten klar definiert ist.
Weiterhin viel Freude mit SAP...
Cheers
MrB.

Re: zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle

Beitrag von DeathAndPain (Top Expert / 1436 / 156 / 329 ) » 14.09.2020 12:35
Um ehrlich zu sein, habe ich die Anforderung noch nicht wirklich verstanden (und das, obwohl ich HCM-ler bin). Ich formuliere mal, was ich verstanden zu haben glaube:
  • Schlüssel der internen Tabelle ist Z_EMPLOYEE Z_DATE ZEITART. (Ist der Schlüssel eigentlich eindeutig, oder könnte ein Mitarbeiter an einem Tag z.B. auch zwei Sätze mit Zeitart Z1 haben?)
  • Für jeden Mitarbeiter Z_EMPLOYEE (warum eigentlich nicht PERNR?) und jeden Tag Z_DATE gibt es je einen Datensatz für die Zeitarten Z1, Z2 und Z3. (Müssen an jedem Tag alle drei Zeitarten vorkommen?)
  • Für jeden Mitarbeiter Z_EMPLOYEE und jeden Tag Z_DATE soll die Z_STUNDEN-Zahl von Z1 von Z3 abgezogen und die von Z2 zu Z3 addiert werden. Wo soll das Ergebnis abgelegt werden? Soll einfach der Wert von Z3 in der Tabelle verändert werden?
Fragen über Fragen. In Fällen wie diesen wäre es sehr hilfreich, wenn Du ein kleines Beispiel mit ein paar Datenzeilen und dem gewünschten Ergebnis liefern könntest. Das sagt mehr als tausend Worte!

Re: zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle

Beitrag von sonicalcatharsis (ForumUser / 4 / 0 / 0 ) » 14.09.2020 13:48
Hello,

ich habe mal ein beispiel angehangen mit den Grundinformationen, die aus der Quelltabelle mitkommen und auf die es ankommt.
Schlüssel der internen Tabelle ist Z_EMPLOYEE Z_DATE ZEITART. (Ist der Schlüssel eigentlich eindeutig, oder könnte ein Mitarbeiter an einem Tag z.B. auch zwei Sätze mit Zeitart Z1 haben?)
..schüssel der Tabelle ist PERNR (hatte mich vertan) und der Kalendertag -> Schüssel ist nicht eindeutig, jedoch kommt jede Zeitart pro Tag nur einmal mit.
Für jeden Mitarbeiter Z_EMPLOYEE und jeden Tag Z_DATE soll die Z_STUNDEN-Zahl von Z1 von Z3 abgezogen und die von Z2 zu Z3 addiert werden. Wo soll das Ergebnis abgelegt werden? Soll einfach der Wert von Z3 in der Tabelle verändert werden?
...genau so in etwas ist es gedacht. Abgelegt werden die modifizierten Datensätze in einer neuen Tabelle bzw. dem Ziel der Transformation im BW.

gleichzeitig werden in der transformationen noch stammdaten zum mitarbeiter nachgelesen und einige andere Sachen gemacht.

Ich habe jetzt damit angefangen, den LOOP der über die Quelltabelle läuft und der eine Struktur des jeweiligen Datensatzes weitergibt mit einer Nebenschleife zu versehen, der schaut ob es in der Quelltabelle eine Zeitart gibt, die abgezogen oder hinzuaddiert werden muss. Also läuft im Endeffekt ein um die relevanten Zeitarten gefilterter "Klon" nebenher und zieht ab,wenn beide Konditionen (Zeile links enthält Zeitart die abzuziehen/zu addieren ist , Zeile rechts enthält die Zeitart, von der abgezogen werden muss)

Coding sieht folgendermaßen aus:

Code: Alles auswählen.


 <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_HR_BW_ROUT_END_ZREPTT->GET_WORKING_HOURS
* +-------------------------------------------------------------------------------------------------+
* | [<-->] CS_DATA                        TYPE        _TY_S_TG_1
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD get_working_hours.

    TYPES: BEGIN OF ty_lt_pt2,
             /bic/zgp_im01 TYPE /bic/oizgp_im01,
             calday        TYPE /bi0/oicalday,
             /bic/zreptt   TYPE /bic/oizreptt,
             dur_actual    TYPE /bi0/oidur_actual,
           END OF ty_lt_pt2.

    DATA: lt_pt2      TYPE TABLE OF ty_lt_pt2.

    IF lt_pt2 IS INITIAL.
      SELECT /bic/zgp_im01, calday, /bic/zreptt, dur_actual
          FROM /bic/lt_pt_2
          WHERE /bic/zreptt = 'Z0000002' OR /bic/zreptt = 'Z0000012'
          INTO TABLE @lt_pt2 .
    ENDIF.


    IF cs_data-/bic/zreptt = 'Z0000015'.
      LOOP AT lt_pt2 ASSIGNING FIELD-SYMBOL(<fs_pt2>).
        IF line_exists( lt_pt2[ /bic/zgp_im01 = cs_data-/bic/zgp_im01
           calday = cs_data-calday
          /bic/zreptt = 'Z0000002' ] ).
          ADD <fs_pt2>-dur_actual TO cs_data-dur_actual.
        ENDIF.
        ENDLOOP.
      ENDIF.

Aus Gründen der Übersichtlichkeit und der einfacheren Weiterverarbeitkeit (eben für Berechnungen und auch zur zeilenweise Ausgabe bspw. in einem ALV) würde ich genauso vorgehen:
...so hab ich´s jetzt auch erstmal gebaut, würde aber gern, da die Datensätze ja schon in Kontenform aus der Quelle kommen, den "zusätzlichen" Schritt umgehen.

Vielen Dank erstmal für eure Antworten und ich hoffe der Sachverhalt und was ich überhaupt möchte ist nun etwas klarer :)

so long

Re: zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle

Beitrag von sonicalcatharsis (ForumUser / 4 / 0 / 0 ) » 15.09.2020 09:36
Habe jetzt nochmal etwas dran herumgebaut, die Befüllung der "Kontrolltabelle" in den Klassenkonstruktor ausgelagert, so dass nicht jedes mal neu nachgelesen werden muss und das line_exists auf READ TABLE umgestellt. Erster Testdurchlauf wurde durchgeführt und er scheint das zu machen, was er soll :)

Code: Alles auswählen.

* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_ROUT_END_ZREPTT=>CLASS_CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
 METHOD class_constructor.

    SELECT /bic/zgp_im01, calday, /bic/zreptt, dur_actual
      FROM /bic/azgp_io1400
      INTO CORRESPONDING FIELDS OF TABLE @st_pt2.

  ENDMETHOD.




 <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ROUT_END_ZREPTT->GET_WORKING_HOURS
* +-------------------------------------------------------------------------------------------------+
* | [<-->] CS_DATA                        TYPE        _TY_S_TG_1
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD get_working_hours.

    IF cs_data-/bic/zreptt = 'Z0000015'.

      READ TABLE st_pt2 WITH TABLE KEY
      /bic/zgp_im01 = cs_data-/bic/zgp_im01
      calday = cs_data-calday
      /bic/zreptt = 'Z0000002'
      ASSIGNING FIELD-SYMBOL(<fs_pt2_z0000002>) .

      IF sy-subrc = 0.
        ADD <fs_pt2_z0000002>-dur_actual TO cs_data-dur_actual.
      ENDIF.

      READ TABLE st_pt2 WITH TABLE KEY
           /bic/zgp_im01 = cs_data-/bic/zgp_im01
           calday = cs_data-calday
           /bic/zreptt = 'Z0000012' ASSIGNING FIELD-SYMBOL(<fs_pt2_z0000012>).

      IF sy-subrc = 0.
        SUBTRACT <fs_pt2_z0000012>-dur_actual FROM cs_data-dur_actual.
      ENDIF.

    ENDIF.

    lv_refdate = cs_data-calday.
    lv_empl = cs_data-/bic/zgp_im01.


  ENDMETHOD.


Re: zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle

Beitrag von DeathAndPain (Top Expert / 1436 / 156 / 329 ) » 15.09.2020 14:02
Hm. Die Codefragmente geben etwas Aufschluss, aber es fehlen halt doch immer noch große Teile zum Verständnis.
  • Wie ist CS_DATA typisiert? (TYPE _TY_S_TG_1 ist jetzt nicht wirklich aufschlussreich)
  • Wie ist st_pt2 typisiert (Sortierung usw.)?
  • Wo kommt CS_DATA überhaupt her? Da scheint es ja pro Mitarbeiter bereits einen Eintrag zu geben.
Das Dazulesen der Werte hast Du ja im zweiten Anlauf schon ganz gut hinbekommen, auch wenn ich da noch kosmetisches Optimierungspotenzial sehe (ASSIGN mit 7.40-Syntax statt READ TABLE oder sogar direkte Verwendung der 7.40-Notation mit OPTIONAL bei der Addition ohne Umweg über ein Feldsymbol).

Richtig schlecht ist allerdings der Teil

Code: Alles auswählen.

    lv_refdate = cs_data-calday.
    lv_empl = cs_data-/bic/zgp_im01.
am Ende der Methode: Du weist Variablen zu, die Du in der Methode gar nicht deklariert hast, die also global sein müssen (Verletzung der Kapselung, mutmaßlich mit Ausrede, dass die globalen Variablen "Attribute" und daher nicht böse seien) und deklarierst diese auch noch mit falscher ungarischer Notation als "lv_", also als lokal.

So, wie ich Dich ursprünglich verstanden hatte, wolltest Du ja eigentlich gar keine st_pt2 separat aufbauen, sondern alles direkt aus der Originaltabelle machen. Ich glaube auch, dass das möglich wäre, jedoch fehlen zu große Codeteile, um eine Lösung anbieten zu können. Ohne vollständige Information werden wir da eher nicht helfen können.

Re: zeilenübergreifende Berechnungen innerhalb Gruppe in interner Tabelle

Beitrag von sonicalcatharsis (ForumUser / 4 / 0 / 0 ) » 16.09.2020 13:26
cs_data ist die Struktur des Datenziels. In der Routine, wird die Klasse angesprochen und die Struktur um einige Informationen zum Mitarbeiter angereichert. Pro MA gibt es also schon einen Satz, nämlich den in der Datenquelle.

Die Struktur ist wie folgt (vereinfacht) aufgebaut:

PersNr.(+ Stammdaten) CALDAY CALMONTH CALYEAR ZEITART (ZREPPT) VALUE. (sortiert nach PErsNr und CALDAY)

st_pt2 ist typisiert mit PERSNR CALDAY ZREPPT VALUE (sortiert nach PERSNR & CALDAY). Sie dient als Hilfstabelle, um VALUE von der einen Zeitart dem VALUE der anderen Zeitart zu addieren oder subtrahieren.

Der Aufbau der Hilfstabelle ist in Ordnung, ich wollte nur keinen extra Datentopf im BW modellieren. Wie performant oder auch nicht die ganze Sache nun abläuft, werde ich morgen beim Probelauf mal sehen :)

Danke für die Kritik mit den Variablen in der Methode, bin noch relativ frisch dabei und manchmal achtet man nicht auf die grundlegensten Dinge..habe das jetzt korrigiert und sie als Exportparameter in der Methode deklariert.
Die anderen "kosmetischen" Vorschläge werde ich mir heute Abend mal schauen.

Seite 1 von 1

Vergleichbare Themen

FB 'TEXT_INCLUDE_REPLACE': Zeilenübergreifende Inlude-Texte
von ralf.wenzel » 28.07.2014 14:54
Problem mit interner Tabelle
von Troilus » 17.11.2007 23:09
Key Felder von interner Tabelle auf dem ALV
von thesaint » 14.07.2005 16:32
Concatenate in interner Tabelle
von wenigerABAP » 16.09.2016 12:47
Types mit interner Tabelle?
von Gast » 19.07.2005 17:43