
ABAP Tools - Arbeiten mit Eclipse (Tabellenvergleich)
Interne Tabellen mit dem Debugger in den ABAP Development Tools vergleichen? Mit dem neusten Feature kein Problem mehr und für viele Situationen nutzbar.
Inhaltsverzeichnis
In diesem Artikel schauen wir uns das neuste Feature für den Debugger in den ABAP Development Tools an und wie du es in deinem Alltag einsetzen kannst.
Einleitung
Die ABAP Development Tools, kurz ADT, gelten als aktueller Standard in der ABAP Entwicklung. Daher wurden die letzten Jahre auch viele Funktionen in das Plugin für Eclipse überführt, um uns als ABAP Entwickler das Leben leichter zu machen. Im aktuellen Release 2508 für das ABAP Environment und S/4HANA Public Cloud wurde nun ein neuer View zum Vergleich von Tabellen während des Debuggings ausgeliefert. In den nächsten Kapiteln testen wir das neue Feature in verschiedenen Szenarien.
Einstieg
Um den Vergleich aufzurufen, müssen wir zuerst in den Debugger kommen. Dafür müssen wir im Quellcode einen Breakpoint setzen, um das Debugging zu starten. Wie du am einfachsten dabei vorgehst und die verschiedenen Features im Debugger nutzen kannst, findst du in diesen Tutorials zum Lesen oder Schauen:
Starten
Zuerst einmal müssen wir den Vergleich im Debugger starten, dazu stehen dir aktuell mehrere Varianten zur Verfügung. Die verschiedenen Varianten findest du unten in im Link zur offiziellen Dokumentation. Hier noch einmal mit Bildern zusammengefasst.
Kontextmenü
Über das Kontextmenü im Variablenview kannst du die ersten beiden Optionen ausführen. Dazu holst du dir die Tabelle oder direkt beide Tabellen in den View. Entweder per Doppelklick beim Debuggen oder du schreibst die Variablennamen in den View. Markierst du dann beide Tabellen und rufst das Kontextmenü auf, kannst du diese dann direkt gleich miteinander vergleichen.
Das zweite Verfahren ist dann zweistufig. Dazu markierst du deine erste Tabelle und wählst den Eintrag "Prepare Comparison / Set as First Table". Der Inhalt bzw. aktuelle Zustand der Tabelle wird dann gesichert. Möchtest du es dann mit der zweiten Tabelle vergleichen, wählst du die zweite Tabelle, rufst das Kontextmenü auf und wählst "Compare with First Table", um den Vergleich zu starten.
Internal Table
Als dritte Variante steht dir der View "ABAP Internal Table (Debugger)" zur Verfügung. Hier findest du im oberen Bereich zwei Buttons, die dem Prinzip des zweistufigen Verfahrens folgen. Die erste Tabelle merken und mit dem zweiten Button den Vergleich starten.
Hinweis: Änderst du für die Tabelle im View die Sortierung, die Felder oder die Reihenfolge, dann fließen diese Einstellung ebenfalls in den Vergleich ein.
Ansicht
Der View wird geladen, sobald der Tabellenvergleich startet. Dabei wird pro Vergleich eine neue Instanz des Views erzeugt, wie die verschiedenen Reiter für den Quellcode-Editor. Auf der linken Seite findest du die erste Tabelle und auf der rechten Seite die zweite Tabelle. Wie die einzelnen Farben beim Vergleich arbeiten, findest du in der Dokumentation unten verlinkt. In diesem View werden gleiche Zeilen versteckt und nur die Unterschiede angezeigt.
In der rechten oberen Ecke findest du das Menü mit weiteren Einstellungen und Aktionen. Zuerst findest du eine Information über die gefundenen Unterschiede in der Tabelle. Wenn du mit der Maus über die Unterschiede gehst, bekommst du noch einmal die Zahlen im Detail. Mit der Navigation kannst du dann durch die verschiedenen Unterschiede springen. Daneben stehen dir noch verschiedene Ansichten und Filter zur Verfügung.
Test
In diesem Kapitel testen wir einmal die verschiedenen Funktionen und das Verhalten und Verlassen damit den Teil der Theorie.
Einfacher Vergleich
Führen wir im ersten Schritt einen einfachen Vergleich durch. Dazu erstellen wir zwei Tabellen vom Typ String. Bei der zweiten Tabelle lassen wir die "Zwei" weg und ergänzen die "Vier".
DATA(table_one) = VALUE string_table( ( `One` ) ( `Two` ) ( `Three` ) ).
DATA(table_two) = VALUE string_table( ( `One` ) ( `Three` ) ( `Four` ) ).
Im Vergleich ist gut zu erkennen, welche Zeile in der Tabelle entfernt wurde und welche neu ist. Damit ist ein einfacher Vergleich sehr gut möglich.
Standard Tabelle
Schauen wir uns einmal eine Standard Tabelle ohne definierten Schlüssel an. Dabei verändern wir zwischen den beiden Tabelle relativ viele Informationen. Grundsätzlichen passen einige der Informationen in den Zellen noch.
DATA(table_one) = VALUE table_no_key( ( rkey = 'K1'
text = `Key One`
number = 10
amount = '12.65' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K1'
text = `Key Three`
number = 19
amount = '87.06' ) ).
DATA(table_two) = VALUE table_no_key( ( rkey = 'K3'
text = `Key One`
number = 10
amount = '12.65' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K4'
text = `Key Three`
number = 15
amount = '87.06' ) ).
Die Tabelle wird nun komplett miteinander verglichen und die unterschiedlichen Zeilen in Grau markiert. Die veränderten Zellen in der Tabelle werden mit Dunkelgrau angezeigt.
Im zweiten Szenario sortieren wir die Tabelle im View "ABAP Internal Table (Debugger)" nach dem Feld RKEY aufsteigend und führen den gleichen Vergleich noch einmal durch. Die Ansicht ändert sich und es wird auf Basis des sortierten Schlüssels verglichen. Dabei werden die Änderungen auf Zellebene nicht mehr angezeigt, sondern die Zeilen als Ganzes interpretiert.
Sortierte Tabelle
Im letzten Szenario verwenden wir eine SORTED TABLE über das Feld RKEY und schauen uns das Verhalten hier im Detail noch einmal an. Wir haben hier den Schlüssel K3 entfernt, K4 neu eingefügt, aber mit ähnlichen Werten wie K3 und bei K1 haben wir den AMOUNT angepasst.
DATA(table_one) = VALUE table_sorted( ( rkey = 'K1'
text = `Key One`
number = 10
amount = '12.65' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K3'
text = `Key Three`
number = 19
amount = '87.06' ) ).
DATA(table_two) = VALUE table_sorted( ( rkey = 'K1'
text = `Key One`
number = 10
amount = '12.66' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K4'
text = `Key Four`
number = 19
amount = '87.06' ) ).
Wie sieht also nun der Vergleich der beiden Tabellen aus? Die Tabelle wird wir die sortierte Standardtabelle angezeigt. Die gelöschte Zeile und die neue Zeile wird angezeigt, sowie die Änderung im ersten Datensatz angezeigt. Das Schlüsselfeld scheint noch einmal eine spezifische Farbe zu erhalten.
Vergleichen wir zuletzt noch einmal die beiden Tabellen und blenden dazu bei der zweiten Tabelle das Feld AMOUNT aus. Der Vergleich wird weiterhin durchgeführt, allerdings erhalten wir auch eine entsprechende Fehlermeldung, sowie die Spalte wird bei der ersten Tabelle als Unterschied angezeigt.
Session
Dadurch das der Vergleich auch außerhalb der Debugging Session zur Verfügung steht, kannst du auch Vergleiche über verschiedene Session hinweg machen. Dazu benötigst du das zweistufige Verfahren, um dir in der ersten Session die Tabelle zu merken. Dann startest du eine neue Session und rufst für die zweite Tabelle den Vergleich auf. Grundsätzlich kannst du damit auch auf zwei unterschiedlichen Systemen arbeiten und so zum Beispiel verschiedene Einstellungen validieren. Wenn du den View oben prüfst, dann findest du in der Kopfzeile neben der Anzahl der Zeilen auch das System und den Mandant, sowie die Uhrzeit des Snapshots der Tabelle.
Vollständiges Beispiel
Hier findest du die Klasse die wir oben verwendet haben. Damit kannst du unsere Beispiel bei dir auf dem System nachstellen.
CLASS zcl_bs_demo_table_compare DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
TYPES: BEGIN OF structure,
rkey TYPE c LENGTH 15,
text TYPE string,
number TYPE i,
amount TYPE p LENGTH 10 DECIMALS 2,
END OF structure.
TYPES table_no_key TYPE STANDARD TABLE OF structure WITH EMPTY KEY.
TYPES table_sorted TYPE SORTED TABLE OF structure WITH UNIQUE KEY rkey.
METHODS compare_string_table
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS compare_standard_table
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS compare_sorted_table
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS compare_different_session
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS compare_method_changes
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS change_table
IMPORTING !source TYPE string_table
RETURNING VALUE(result) TYPE string_table.
METHODS get_content_table
RETURNING VALUE(result) TYPE string_table.
ENDCLASS.
CLASS zcl_bs_demo_table_compare IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
compare_string_table( out ).
compare_standard_table( out ).
compare_sorted_table( out ).
compare_different_session( out ).
compare_method_changes( out ).
ENDMETHOD.
METHOD compare_string_table.
DATA(table_one) = VALUE string_table( ( `One` ) ( `Two` ) ( `Three` ) ).
DATA(table_two) = VALUE string_table( ( `One` ) ( `Three` ) ( `Four` ) ).
IF table_one = table_two.
out->write( table_one ).
out->write( table_two ).
ENDIF.
ENDMETHOD.
METHOD compare_standard_table.
DATA(table_one) = VALUE table_no_key( ( rkey = 'K1'
text = `Key One`
number = 10
amount = '12.65' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K1'
text = `Key Three`
number = 19
amount = '87.06' ) ).
DATA(table_two) = VALUE table_no_key( ( rkey = 'K3'
text = `Key One`
number = 10
amount = '12.65' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K4'
text = `Key Three`
number = 15
amount = '87.06' ) ).
IF table_one = table_two.
out->write( table_one ).
out->write( table_two ).
ENDIF.
ENDMETHOD.
METHOD compare_sorted_table.
DATA(table_one) = VALUE table_sorted( ( rkey = 'K1'
text = `Key One`
number = 10
amount = '12.65' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K3'
text = `Key Three`
number = 19
amount = '87.06' ) ).
DATA(table_two) = VALUE table_sorted( ( rkey = 'K1'
text = `Key One`
number = 10
amount = '12.66' )
( rkey = 'K2'
text = `Key Two`
number = 112
amount = '99.00' )
( rkey = 'K4'
text = `Key Four`
number = 19
amount = '87.06' ) ).
IF table_one = table_two.
out->write( table_one ).
out->write( table_two ).
ENDIF.
ENDMETHOD.
METHOD compare_different_session.
DATA(changed) = change_table( get_content_table( ) ).
out->write( changed ).
ENDMETHOD.
METHOD compare_method_changes.
DATA(table) = get_content_table( ).
DATA(changed) = change_table( table ).
IF table = changed.
out->write( table ).
out->write( changed ).
ENDIF.
ENDMETHOD.
METHOD change_table.
result = source.
DATA(random) = cl_abap_random=>create( CONV i( cl_abap_context_info=>get_system_time( ) ) ).
DO random->intinrange( low = 0
high = 3 ) TIMES.
DATA(delete_index) = random->intinrange( low = 1
high = lines( result ) ).
DELETE result INDEX delete_index.
ENDDO.
DO random->intinrange( low = 0
high = 2 ) TIMES.
DATA(run_id) = sy-index.
DATA(change_index) = random->intinrange( low = 1
high = lines( result ) ).
result[ change_index ] = |Changed { run_id }|.
ENDDO.
ENDMETHOD.
METHOD get_content_table.
DO 26 TIMES.
INSERT substring( val = sy-abcde
off = sy-index - 1
len = 1 ) INTO TABLE result.
ENDDO.
ENDMETHOD.
ENDCLASS.
Fazit
Das neue Feature kann dich bei der Entwicklung unterstützen, vor allem wenn du über verschiedene Sessions das Ergebnis vergleichen möchtest oder um einfach nur zu sehen, was sich in einer internen Tabelle geändert hat. Damit musst du nicht mehr auf externe Tools zurückgreifen. Als Bonus ist der Vergleich von Inhalten über verschiedene Systeme noch ein netter Bonus.
Quelle:
SAP Help - Getting Started with the Table Comparison Tool
SAP Help - Comparing Internal Tables