SMEN_BUFFC - falsches menu_level

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

SMEN_BUFFC - falsches menu_level

Beitrag von defaultuser (ForumUser / 1 / 0 / 0 ) »
Ich habe ein SAP ABAP Programm geschrieben, um Favoriten zu verwalten. Per Selektionsbildschirm kann ein Benutzer einen Report mit Namen als Favorit unter den Favoriten speichern. Es laesst sich auch ein Report einem Ordner unterordnen, wenn dieser vorher im SAP per GUI erstellt wurde. Dies kann der Benutzer durch den Transaktionscode `/n` und dann rechtsklick auf 'Favoriten' -> 'Ordner einfuegen' tun.

Nun funktioniert das meiste, es gibt nur ein kleineres Problem. Wenn ich die ersten Reports in dem Favoriten Ordner durch mein Programm erstelle, und dann danach einen Ordner per SAP-GUI erstelle, wird der Wert der Spalte `menu_level` von den beiden Eintraegen auf `2` gesetzt. Jedoch sollte dieser `1` betragen, da sich der Ordner und der Report shortcut in dem Root Ordner, also im ersten Level befinden.

Das ganze passiert nicht, wenn ich damit anfange einen Ordner zu erstellen und im Nachhinein per meinem Programm die Reports einfuege. Dabei bleibt das menu_level mit dem Wert `1` korrekt.

Hat jemand eine Idee, was das Problem ist, und wie ich dieses beheben kann?
Hier ist mein aktueller, vollstaendiger code:

Code: Alles auswählen.

TYPE-POOLS: vrm.

DATA: ls_smen_buffc     TYPE smen_buffc,
      lv_max_object_id  TYPE smen_buffc-object_id,
      lv_max_sort_order TYPE smen_buffc-sort_order,
      lt_folders        TYPE TABLE OF smen_buffc,
      ls_folder         TYPE smen_buffc,
      lt_vrm_values     TYPE vrm_values,
      ls_vrm_value      TYPE LINE OF vrm_values.

CLASS lcl_menu_level DEFINITION.
  PUBLIC SECTION.
    METHODS: get_menu_level IMPORTING parent_id         TYPE smen_buffc-parent_id
                            RETURNING VALUE(menu_level) TYPE i.
ENDCLASS.

CLASS lcl_menu_level IMPLEMENTATION.
  METHOD get_menu_level.
    DATA lv_parent_id TYPE smen_buffc-parent_id.
    lv_parent_id = parent_id.
    menu_level = 1.

    WHILE lv_parent_id <> 1.
      SELECT SINGLE parent_id INTO lv_parent_id FROM smen_buffc WHERE object_id = lv_parent_id.
      IF sy-subrc = 0.
        menu_level = menu_level + 1.
      ELSE.
        EXIT.
      ENDIF.
    ENDWHILE.
  ENDMETHOD.
ENDCLASS.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS: p_user   TYPE sy-uname DEFAULT sy-uname,
            p_report TYPE extdreport OBLIGATORY,
            p_desc   TYPE char100sm OBLIGATORY,
            p_folder TYPE smen_buffc-text AS LISTBOX VISIBLE LENGTH 30.
SELECTION-SCREEN END OF BLOCK b1.

INITIALIZATION.
  SELECT * FROM smen_buffc INTO TABLE lt_folders WHERE uname = p_user AND reporttype = space.

  LOOP AT lt_folders INTO ls_folder.
    ls_vrm_value-key   = ls_folder-object_id.
    ls_vrm_value-text  = ls_folder-text.
    APPEND ls_vrm_value TO lt_vrm_values.
  ENDLOOP.

  CALL FUNCTION 'VRM_SET_VALUES'
    EXPORTING
      id     = 'P_FOLDER'
      values = lt_vrm_values.

AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN.
    IF screen-name = 'P_USER'.
      screen-input = 0.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.

START-OF-SELECTION.
  DATA: lo_menu_level TYPE REF TO lcl_menu_level.
  CREATE OBJECT lo_menu_level.

  ls_smen_buffc-uname = p_user.
  ls_smen_buffc-report = p_report.
  ls_smen_buffc-text = p_desc.
  ls_smen_buffc-reporttype = 'RE'.

  SELECT MAX( object_id ) INTO lv_max_object_id FROM smen_buffc WHERE uname = p_user.
  IF sy-subrc <> 0.
    lv_max_object_id = 0.
  ENDIF.

  IF p_folder IS INITIAL.
    ls_smen_buffc-parent_id = 1.
  ELSE.
    ls_smen_buffc-parent_id = p_folder.
  ENDIF.

  ls_smen_buffc-menu_level = lo_menu_level->get_menu_level( ls_smen_buffc-parent_id ).

  SELECT MAX( sort_order ) INTO lv_max_sort_order FROM smen_buffc WHERE uname = p_user AND parent_id = ls_smen_buffc-parent_id.
  IF sy-subrc <> 0.
    lv_max_sort_order = 0.
  ENDIF.

  ls_smen_buffc-object_id = lv_max_object_id + 1.
  ls_smen_buffc-sort_order = lv_max_sort_order + 10.

  INSERT INTO smen_buffc VALUES ls_smen_buffc.

  IF sy-subrc = 0.
    COMMIT WORK AND WAIT.
    MESSAGE 'Der Favorit wurde erfolgreich erstellt.' TYPE 'S'.
  ELSE.
    MESSAGE 'Fehler beim Einfügen der Daten.' TYPE 'E'.
  ENDIF.

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


Re: SMEN_BUFFC - falsches menu_level

Beitrag von DeathAndPain (Top Expert / 1952 / 259 / 413 ) »
Das wird damit zusammenhängen, dass es da Konsistenzabhängigkeiten geben wird und vermutlich an dieser Favoritenablage noch weitere Tabellen beteiligt sind. Ich habe mir die Tabelle SMEN_BUFFC angeschaut und Deine Gedankengänge verstanden. Der entscheidende Fehler, den Du hier machst, ist, hart in SAP-Standardtabellen zu schreiben. Das ist höchst unprofessionell und ein absolutes No-Go, denn nur die SAP kennt alle Abhängigkeiten und Zusammenhänge und kann zweifelsfrei sagen, was wie zusammenhängt und was zu beachten ist, damit ein Tabelleneintrag keine Konsistenzbedingungen in anderen Tabellen verletzt. Ich habe jetzt zwar nicht recherchiert, welche andere Tabelle das in diesem Fall wäre, aber sie muss ja eigentlich existieren, sonst wäre das von Dir beobachtete Systemverhalten nicht möglich.

Genau aus diesem Grund darf man zwar SAP-Tabellen lesen, muss sich zum Schreiben aber immer von der SAP gebotene Wege suchen, sei es ein BADI, sei es ein Funktionsbaustein oder zur Not ein programmierter Batch Input.

Wenn Du es dennoch herausfinden willst, dann solltest Du mit der Transaktion ST05 einen SQL-Trace mitschneiden, während Du in einem anderen Fenster händisch solch Favoriten anlegst. Anschließend könntest Du in dem Trace dann genau sehen, welche Datenbanktabellen wie angesprochen worden sind. Aber ganz deutlich: Auch wenn Du genau glaubst zu wissen, wie bestimmte SAP-Datenbanktabellen funktionieren, kannst Du das nie beweisen, und selbst, wenn es stimmen sollte, könnte die SAP es im nächsten Support Package schon ändern, so dass Dein Programm plötzlich Murks macht und die Datenkonsistenz zerstört. Aus diesem Grunde ist direktes Schreiben in SAP-Tabellen immer Pfusch und kann ggf. ein gutes Argument sein Dich rauszuschmeißen. Ich kann Dir nur dringend nahelegen, Dich von dieser Geisteshaltung zu lösen und zu der professionellen Einstellung zu wechseln, dass alle Änderungen an von der SAP angelegten Datenbanktabellen auch mit von der SAP bereitgestellten Mitteln erfolgen sollte.

Im übrigen möchte ich anmerken, dass es mir Bauchschmerzen bereitet zu sehen, dass selbst hier im "ABAP für Anfänger"-Forum immer wieder total antiquierter Code geboten wird, bei dem ich mich frage, wird das echt noch so von irgendwem unterrichtet, oder warum machen die Leute das?

Das fängt schon bei Deinem ersten Befehl an: Der Befehl TYPE-POOLS ist schon seit vielen Jahren veraltet und bewirkt in heutigen Releases genau gar nichts mehr! Aus Kompatibilitätsgründen meckert ABAP nicht darüber, sondern ignoriert den Befehl einfach, wenn es ihn vorfindet. Probier es aus und lösche ihn ersatzlos aus Deinem Programm. Du wirst feststellen, dass sich dadurch nichts ändert.

Und das Füllen einer internen Tabelle, bei Dir geschehen, um den FB VRM_SET_VALUES damit zu beschicken... warum sparst Du Dir nicht einfach den ganzen LOOP und schreibst modern:

Code: Alles auswählen.

  CALL FUNCTION 'VRM_SET_VALUES'
    EXPORTING
      id     = 'P_FOLDER'
      values = VALUE vrm_values( FOR <zeile> IN lt_folders ( key  = <zeile>-object_id 
                                                             text  = <zeile>-text ).
Oder noch viel schöner:

Code: Alles auswählen.

  CALL FUNCTION 'VRM_SET_VALUES'
    EXPORTING
      id     = 'P_FOLDER'
      values = CORRESPONDING vrm_values( lt_folders MAPPING key = object_id ).
Viel kürzer, viel besser lesbar, und den DATA ls_folders brauchst Du auch nicht mehr, weil Du die ganze Workarea nicht mehr brauchst.

Dafür scheinbar modern ist die objektorientierte Programmierung in Deinem Programm. Nur fragt man sich, wofür Du in diesem Programm mit Objekten hantieren möchtest. Dementsprechend erzeugst Du ja auch nur konstant ein einziges. Die Klasse verwendest Du nur, um Unterprogramme darin unterzubringen. Versteh mich nicht falsch: Methodenaufrufe sind erheblich schöner und besser lesbar als alte FORM-Aufrufe. Aber wenn Du sie nur dafür brauchst, dann wäre eine statische Klasse (DEFINITION ABSTRACT FINAL) angemessener. Dann sparst Du Dir das CREATE OBJECT, und der Leser sieht sofort, dass er sich über Objekte und deren Unterschiede keine Gedanken machen muss und Du einfach nur Unterprogramme aufrufst.

Seite 1 von 1

Vergleichbare Themen

1
Antw.
1369
Views
Upper level in MVC
von Alonso » 02.09.2005 12:30 • Verfasst in Web-Dynpro, BSP + BHTML
2
Antw.
1884
Views
Patch Level Frage
von kaim77 » 01.07.2013 10:39 • Verfasst in Sonstige Module
7
Antw.
1784
Views
SAPGUI 770 mit integrierten Patch Level 13
von beginner234A1 » 19.09.2023 06:52 • Verfasst in Basis
3
Antw.
2720
Views
CALL TRANSACTION -> falsches DYNPRO
von formcraft » 12.04.2016 13:57 • Verfasst in ABAP® für Anfänger

Aktuelle Forenbeiträge

Customizing-Transportauftrag schreiben
vor 7 Stunden von msfox 5 / 434
Daten an Tabelle binden
vor 2 Tagen von Lukas Sanders 4 / 2622
Regex in where
vor 4 Tagen von tar 8 / 1495

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.

Aktuelle Forenbeiträge

Customizing-Transportauftrag schreiben
vor 7 Stunden von msfox 5 / 434
Daten an Tabelle binden
vor 2 Tagen von Lukas Sanders 4 / 2622
Regex in where
vor 4 Tagen von tar 8 / 1495

Unbeantwortete Forenbeiträge

BUSOBJEKT zu CMIS PHIO ermitteln
vor 5 Tagen von snooga87 1 / 1019
aRFC im OO-Kontext
letzen Monat von ralf.wenzel 1 / 4207
Hilfe bei SWEC/SWE2
September 2024 von retsch 1 / 10625