Loop Loop & Loop - wie am besten eine Verschachtelung vermeiden?

Die Frage ist als "gelöst" markiert. Den entsprechend Beitrag findest du hier.

Getting started ... Alles für einen gelungenen Start.
2 Beiträge • Seite 1 von 1
2 Beiträge Seite 1 von 1

Loop Loop & Loop - wie am besten eine Verschachtelung vermeiden?

Beitrag von Sonne1234 (ForumUser / 30 / 17 / 2 ) »
Hallo zusammen,

mein Problem ist vermutlich eher konzeptioneller Natur. Nun ja, mein Code sieht zur Zeit wie folgt aus:

Code: Alles auswählen.

TYPES: BEGIN OF ty_bkpf,
         bukrs TYPE bkpf-bukrs,
         belnr TYPE bkpf-belnr,
         xblnr TYPE bkpf-xblnr,
         blart TYPE bkpf-blart,
         bldat TYPE bkpf-bldat,
         budat TYPE bkpf-budat,
         gjahr TYPE bkpf-gjahr,
         awkey TYPE bkpf-awkey,
         awtyp TYPE bkpf-awtyp,
         cpudt TYPE bkpf-cpudt,
         refsc TYPE c LENGTH 50, "Referenzschlüssel umsortiert.
       END OF ty_bkpf,

BEGIN OF ty_toa02,
         sap_object TYPE toa02-sap_object,
         object_id  TYPE toa02-object_id,
         archiv_id  TYPE toa02-archiv_id,
         arc_doc_id TYPE toa02-arc_doc_id,
         ar_object  TYPE toa02-ar_object,
         ar_date    TYPE toa02-ar_date,
       END OF ty_toa02,

BEGIN OF ty_toa01,
         mandt      TYPE toa01-mandt,
         sap_object TYPE toa01-sap_object,
         object_id  TYPE toa01-object_id,
         archiv_id  TYPE toa01-archiv_id,
         arc_doc_id TYPE toa01-arc_doc_id,
         ar_object  TYPE toa01-ar_object,
         ar_date    TYPE toa01-ar_date,
         del_date   TYPE toa01-del_date,
         reserve    TYPE toa01-reserve,
       END OF ty_toa01.

TYPES: tty_toa01         TYPE TABLE OF ty_toa01,
       tty_toa02         TYPE TABLE OF ty_toa02.

DATA: gt_bkpf          TYPE STANDARD TABLE OF ty_bkpf.
           
form f_verknuepfung

  changing p_toa02 TYPE tty_toa02
           p_toa01 TYPE tty_toa01.

Loop at p_toa02 ASSIGNING FIELD-SYMBOL(<p_toa02>).
  Loop at gt_bkpf ASSIGNING FIELD-SYMBOL(<gt_bkpf>)

    where xblnr = <p_toa02>-object_id(10).

      IF <gt_bkpf>-awtyp = 'IBKPF'.

        loop at p_toa01 ASSIGNING <p_toa01>
          where arc_doc_id = <p_toa02>-arc_doc_id.
          <p_toa01>-sap_object = 'BKPF'.
          <p_toa01>-ar_object  = 'ZFIZZZZFI'.
          <p_toa01>-object_id = <gt_bkpf>-refsc.
          modify p_toa01 from <p_toa01>.
        endloop.

      elseif <gt_bkpf>-awtyp = 'RMRP'.

        Loop at p_toa01 ASSIGNING <p_toa01>
          where arc_doc_id = <p_toa02>-arc_doc_id.
          <p_toa01>-sap_object = 'ZZZZ'.
          <p_toa01>-ar_object  = 'ZFIZZZZMM'.
          <p_toa01>-object_id = <gt_bkpf>-awkey.
          modify p_toa01 from <p_toa01>.
        endloop.

          endif.

     ENDLOOP.
     ENDLOOP.

endform.
Ich behaupte jetzt erstmal, dass am Ende das rauskommt, was ich auch möchte. Zumindest haben einzelne Tests das richtige Ergebnis geliefert.

Ich möchte die Tabelle TOA01 um Daten aus anderen internen Tabellen ergänzen. Zunächst habe ich alle Einträge aus der TOA02 in die TOA01 übernommen. Dies ist hier nicht ersichtlich. Eigentlich brauche ich aber nur das Feld ARC_DOC_ID. Alle anderen Felder werden mit anderen Informationen gefüllt. Anhand der OBJECT_ID aus der TOA02 finde ich den zugehörigen Rechnungsbeleg in der BKPF über das Feld XBLNR. Wenn in der BKPF der AWTYP = IBKPF zu diesem Rechnungsbeleg ist, kann die Zeile in der TOA01 mit festen definierten Werten ergänzt werden. SAP_OBJECT = BKPF & AR_OBJECT = ZFIZZZZFI. Die noch fehlende OBJECT_ID setzt sich dann aus mehreren Feldern der BKPF zusammen, diese habe ich zuvor bereits in dem FELD REFSC zusammengebaut.
Ich hoffe, dass grundsätzlich verständlich ist, wie sich die TOA01 aufbaut. Es ist irgendwie sehr schwer für mich das ganze in Worte zu fassen.

Meine eigentliche Frage ist jetzt aber, ob man das ganze noch schöner abbilden kann als über 3 Loops. Denn mein Bauchgefühl sagt mir, dass das ganze schon wieder Chaosprogrammierung ist ;)

Es wäre schön, wenn mir hier jemand von euch einen Tipp geben könnte. Denn eigentlich möchte ich von dem Chaos ein bisschen wegkommen :D

Danke.

Viele Grüße
Julia

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: Loop Loop & Loop - wie am besten eine Verschachtelung vermeiden?

Beitrag von DeathAndPain (Top Expert / 1933 / 252 / 410 ) »
Also das sieht schon bedeutend besser aus als das, was Du in früheren Threads geboten hast.

Die geschachtelten LOOPs sind dann und nur dann sinnvoll, wenn jeweils überhaupt mehrere Fundstellen möglich sind. In den WHERE-Klauseln vergleichst Du ja nur auf Gleichheit. Ich kenne den Inhalt Deiner Datenfelder nicht (komme aus einem anderen SAP-Modul), aber dennoch drängt sich mir der Verdacht auf, dass Du bei den beiden inneren LOOPS nur genau eine Zeile suchst bzw. zu finden erwartest. In dem Falle ist ein LOOP natürlich Overkill.

Außerdem zwei kleine formale Anmerkungen:
  • Statt dess IF-Blocks würde sich in Deinem Fall ein CASE-Block bedeutend schöner lesen.
  • Den MODIFY brauchst Du nicht; den kannst Du ersatzlos streichen, da Du bei Deinem LOOP ja (lobenswerterweise) nicht mit einer Workarea arbeitest, sondern mit einem Feldsymbol. Das Feldsymbol zeigt direkt in die interne Tabelle hinein. Änderst Du den Wert des Feldsymbols, dann änderst Du direkt die interne Tabelle! Du brauchst also kein MODIFY. Das bräuchtest Du nur, wenn Du einen LOOP INTO anstelle eines LOOP ASSIGNING machen würdest, denn dann würdest Du eine Kopie des Tabellenwertes in eine lokale Variable legen und müsstest diese nachher in die Tabelle zurückschreiben.
Wenn meine Theorie richtig ist, dass bei den beiden inneren LOOP nur jeweils (maximal) eine Fundstelle möglich ist, dann könnte man Deinen Code wie folgt verschlanken:

Code: Alles auswählen.

*&---------------------------------------------------------------------*
*& Report ZTEST6
*&---------------------------------------------------------------------*
REPORT ZTEST6.

TYPES: BEGIN OF ty_bkpf,
         bukrs TYPE bkpf-bukrs,
         belnr TYPE bkpf-belnr,
         xblnr TYPE bkpf-xblnr,
         blart TYPE bkpf-blart,
         bldat TYPE bkpf-bldat,
         budat TYPE bkpf-budat,
         gjahr TYPE bkpf-gjahr,
         awkey TYPE bkpf-awkey,
         awtyp TYPE bkpf-awtyp,
         cpudt TYPE bkpf-cpudt,
         refsc TYPE c LENGTH 50, "Referenzschlüssel umsortiert.
       END OF ty_bkpf,

BEGIN OF ty_toa02,
         sap_object TYPE toa02-sap_object,
         object_id  TYPE toa02-object_id,
         archiv_id  TYPE toa02-archiv_id,
         arc_doc_id TYPE toa02-arc_doc_id,
         ar_object  TYPE toa02-ar_object,
         ar_date    TYPE toa02-ar_date,
       END OF ty_toa02,

BEGIN OF ty_toa01,
         mandt      TYPE toa01-mandt,
         sap_object TYPE toa01-sap_object,
         object_id  TYPE toa01-object_id,
         archiv_id  TYPE toa01-archiv_id,
         arc_doc_id TYPE toa01-arc_doc_id,
         ar_object  TYPE toa01-ar_object,
         ar_date    TYPE toa01-ar_date,
         del_date   TYPE toa01-del_date,
         reserve    TYPE toa01-reserve,
       END OF ty_toa01.

TYPES: tty_toa01         TYPE TABLE OF ty_toa01,
       tty_toa02         TYPE TABLE OF ty_toa02.

DATA: gt_bkpf          TYPE STANDARD TABLE OF ty_bkpf.
           
form f_verknuepfung

  changing p_toa02 TYPE tty_toa02
           p_toa01 TYPE tty_toa01.

Loop at p_toa02 ASSIGNING FIELD-SYMBOL(<p_toa02>).
  ASSIGN gt_bkpf[ xblnr = <p_toa02>-object_id(10) ] TO FIELD-SYMBOL(<gt_bkpf>).
  CHECK SY-SUBRC = 0. " Wenn der ASSIGN auf die Nase gefallen ist, weil es die Zeile gar nicht gibt, mit dem LOOP AT p_toa02 weitermachen

  CASE <gt_bkpf>-awtyp.
    WHEN 'IBKPF'.
      ASSIGN p_toa01[ arc_doc_id = <p_toa02>-arc_doc_id ] TO <p_toa01>.
      CHECK SY-SUBRC = 0. " Wenn der ASSIGN auf die Nase gefallen ist, weil es die Zeile gar nicht gibt, mit dem LOOP AT p_toa02 weitermachen

      <p_toa01>-sap_object = 'BKPF'.
      <p_toa01>-ar_object  = 'ZFIZZZZFI'.
      <p_toa01>-object_id = <gt_bkpf>-refsc.

    WHEN 'RMRP'.
      ASSIGN p_toa01[ arc_doc_id = <p_toa02>-arc_doc_id ] TO <p_toa01>.
      <p_toa01>-sap_object = 'ZZZZ'.
      <p_toa01>-ar_object  = 'ZFIZZZZMM'.
      <p_toa01>-object_id = <gt_bkpf>-awkey.

  ENDCASE.
Endloop.
endform.
Wie gesagt, geht das deswegen, weil Du nur auf Gleichheit prüfst. In dem Moment, in dem Deine WHERE-Bedingung auch eine Ungleichheit oder sonstige Bedingung enthält (z.B. WHERE A > B), gibt es zum LOOP leider keine Alternative, auch wenn Du genau weißt, dass Du nur (maximal) eine Fundstelle haben wirst. Dann kannst Du aber zumindest dadurch optimieren, dass Du am Ende des Codes innerhalb des LOOPs den Befehl EXIT. schreibst, damit er gar nicht erst weiter nach Fundstellen sucht, sondern den LOOP direkt verlässt.

Außerdem gefällt mir nicht, dass Du weiterhin mit Standardtabellen arbeitest. Dadurch zwingst Du den ABAP-Interpreter, die Tabelle jedesmal Zeile für Zeile von Anfang bis Ende zu durchsuchen! Das ist so, als wenn ich Dich bitten würde, mir aus dem Telefonbuch die Person mit der Telefonnummer 1234567890 herauszusuchen. Da das Telefonbuch nicht nach Telefonnummern sortiert ist, kannst Du Dir überlegen, wie lange Du daran sitzen würdest. Bitte ich Dich hingegen, mir die Nummer von Grunz, Edelbert herauszusuchen, wirst Du sicherlich bedeutend schneller ein Ergebnis liefern.

Dem ABAP-Compiler geht es nicht anders. Welchen Tabellenschlüssel Du verwenden solltest, wird sofort offenkundig, wenn man Deinen Code anschaut, nämlich den, mit dem Du in Deinem WHERE (bzw. ich in meinem ASSIGN) suchst.

gt_bkpf müsste beispielsweile wie folgt definiert sein:

Code: Alles auswählen.

DATA gt_bkpf TYPE HASHED TABLE OF ty_bkpf WITH UNIQUE KEY xblnr.
Wenn dieselbe xblnr zweimal in gt_bkpf vorkommen kann, dann geht das so nicht. Dann würdest Du schreiben:

Code: Alles auswählen.

DATA gt_bkpf TYPE SORTED TABLE OF ty_bkpf WITH NON-UNIQUE KEY xblnr.
Beides wird die Laufzeit Deines Programms drastisch reduzieren! Entsprechend solltest Du auch p_toa01 umdefinieren.

Wie sagte mal jemand hier im Forum so schön (es war Ralf): "Eine Standardtabelle ist keine Tabelle, sondern eine Liste." Formal mag seine Aussage nicht korrekt sein, inhaltlich ist sie es durchaus. In dem Moment, in dem Du vorhast, in einer Tabelle zu suchen, sollte diese unbedingt sortiert oder gehasht sein. Ausnahmen gelten allenfalls, wenn Du mit Sicherheit vorhersagen kannst, dass die Tabelle nie mehr als ca. 10 Einträge enthalten wird.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
Sonne1234


Seite 1 von 1

Vergleichbare Themen

14
Antw.
3952
Views
Zweifachen Loop vermeiden
von Barney » 14.01.2015 10:52 • Verfasst in ABAP® für Anfänger
4
Antw.
3749
Views
LOOP in einem LOOP
von Bjuti » 10.09.2013 15:18 • Verfasst in ABAP® für Anfänger
39
Antw.
7977
Views
Loop
von Kai999 » 27.07.2017 16:15 • Verfasst in ABAP® für Anfänger
34
Antw.
7099
Views
ein loop
von user2008 » 19.07.2017 10:50 • Verfasst in ABAP® für Anfänger
52
Antw.
10139
Views
LOOP AT
von cuncon » 01.02.2018 09:28 • Verfasst in ABAP® für Anfänger

Über diesen Beitrag


Die Frage ist als "gelöst" markiert. Den entsprechend Beitrag findest du hier.

Unterstütze die Community und teile den Beitrag für mehr Leser und Austausch

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.

Unbeantwortete Forenbeiträge

aRFC im OO-Kontext
vor 4 Wochen von ralf.wenzel 1 / 1517
Hilfe bei SWEC/SWE2
letzen Monat von retsch 1 / 8130