SAP: Änderungsbelege konfigurieren und auswerten

Änderungsbelege (change documents) protokollieren in SAP die Änderung von Objekten auf Feldebene. Viele SAP-Transaktionen bieten die Auswertung der Änderungen direkt über das Menü an.
Änderungsbelege sind auch für Z-Felder in Standardtabellen und auch für selbstdefinierte Tabellen möglich.

Mit Hilfe der Änderungsbelege kannst du sehen,

  • welcher Benutzer
  • welches Feld
  • wann
  • mit welcher Transaktion geändert hat und
  • was der alte und was der neue Feldwert ist.

Wir schauen uns nun an, in welchen Tabellen die Änderungsbelege abgespeichert werden und wie du sie dort auswerten kannst.

Anschließend zeige ich Dir, wie Du Änderungsbelege auch für selbstdefinierte Felder in Standardtabellen, z.B. am Debitor, einrichten kannst. Hierzu sind lediglich die Feldeigenschaften des neuen Z-Felds richtig zu setzen.

Als letztes schauen wir uns Änderungsbelege für selbst definierte Z-Tabellen an. Auch dort kannst Du Änderungsbelege erzeugen. Allerdings musst Du dafür etwas mehr tun: Du musst das Erzeugen des Change Documents selbst anstoßen und den alten und den neuen Wert übergeben.

Beispiele für Änderungbelege

Die Änderungsbelege kannst du in vielen SAP-Standardtransaktionen direkt über das Menü aufrufen. Hier ist mein Testkunde auf einem Entwicklungssystem, auf dem ich schon eine Reihe von Änderungen gemacht habe. Die Änderungen finden sich im Menü „Umfeld“. Dort finden sie sich typischerweise auch in anderen Standardtransaktionen.

Du gelangst dann in eine Liste von geänderten Attributen, die du auch weiter aufklicken kannst.

Wenn du auf den Button „Alle Änderungen“ klickst, dann bekommst du eine Liste über alle Details zu allen Änderungen.

Man kann sich über „Umfeld/Feldänderungen“ also die Änderungen direkt ansehen. Aus Entwicklersicht ist es aber interessanter zu schauen, wie du diese Änderungen automatisch auswerten kannst. Dazu müssen wir wissen, wo die Änderungsbelege abgelegt werden.

Die Tabellen hinter den Änderungsbelegen

Rückgrat der Änderungsbelege sind die beiden Tabellen

  • CDHDR: change document header, also Kopfdaten
  • CDPOS: die einzelnen Felddaten („Positionen“)

Wenn Du z.B. einen Debitor änderst, dann änderst du meist mehrere Felder auf einmal. All diese Feldänderungen teilen sich dann einen Header/Kopfsatz.

Hier sind Kopfsätze (CDHDR) für meinen Testkunden

Die OBJECTCLASS ist hier DEBI. Wir schauen uns weiter unten noch an, wo das definiert wird. Es handelt sich hier um einen quasi beliebigen Text, den ein Entwickler bei SAP einmal festgelegt hat, und der Feldänderungen für mehrere Tabellen der Debitoren bündelt.

OBJECTID ist die Nummer des Debitors. Bei anderen Tabellen kann der Schlüssel auch anders aufgebaut sein, z.B. eine Belegnummer plus den Buchungskreis oder die VKORG. Auch das ist eine Entwicklerentscheidung, und bei SAP-Standardobjekten war es die Entscheidung der Entwickler bei SAP.

CHANGENR ist die Nummer der Änderung. Diese werden quer über alle Änderungsbelege aus einem Nummernkreis gezogen. Zu dieser Nummer im Kopfsatz können dann eine oder mehrere CDPOS-Sätze gehören.

Hier habe ich mir zu einem der Kopfsätze die einzelnen Änderungen aus CDPOS selektiert:

Der Zusammenhalt mit CDHDR erfolgt über OBJECTCLAS, OJECTID und CHANGENR.

Hier wurden also zwei Felder gleichzeitig geändert, beide aus der Tabelle KNA1 (Kunden-Kopfdaten). Einmal die Straße und zum zweiten ein Z-Feld mit einer Versionsnummer.

Zu beiden Feldänderungen sind der alte und der neue Wert aufgeführt.

Die Schlüsselwerte des Kopfsatzes finden sich auch im Tabellenschlüssel der Positionsdaten.

Mit diesem Wissen kannst Du dir dann eigene Datenbankabfragen schreiben, die speziell nach Änderungen eines bestimmten Felds im Kunden suchen.

CDPOS ist eine Clustertabelle!

Achtung: die Tabelle CDPOS ist eine Clustertabelle. Clustertabellen sind darauf optimiert, große Datenmengen zu speichern, die aber nur selten gelesen werden. Die Daten werden hierzu komprimiert in der Datenbank abgelegt.

Clustertabellen haben gewisse technische Einschränkungen. Insbesondere kannst du sie nicht in einem Join verwenden.

Das ist schade, denn wenn du Änderungen in einem bestimmten Zeitbereich suchst (CDHDR), die bestimmte Felder betreffen (Feldname aus CDPOS), dann wäre ein Join von CDHDR auf CDPOS ja die erste Idee.

Meist wirst du deine Suche über einen Zeitbereich einschränken wollen. In diesem Fall geht es leider nicht anders: die erste Abfrage geht über alle Änderungen in CDPOS zur gewünschten OBJECTCLAS (hier „DEBI“) im Zeitbereich. Mit diesem großen Sack von Daten kannst du dann in CDPOS nach Änderungen deines Lieblingsfelds suchen.

Änderungsbelege für neue Felder an SAP-Standardobjekten einrichten: Datenelement fitmachen

Für viele Standardbelege hat SAP die Änderungsbelege schon für dich eingerichtet. Wenn du daran etwas ändern willst, dann lautet deine Aufgabe wahrscheinlich, ein neues Z-Feld anzuschließen.

Als Beispiel betrachte ich ein neues Feld auf der Tabelle KNVV, es soll ZZEMAIL_SPERRE heißen. Es hält fest, dass der Debitor nicht per E-Mail beworben werden will.

Hier ist die Definition des zugehörigen Datenelements ZEMAIL_SPERRE:

Wichtig ist an dieser Stelle die Checkbox „Änderungsbeleg“, sie findet sich auf dem Karteireiter „Zusatzeigenschaften“. Änderungsbelege zu einem Feld lassen sich nur dann erzeugen, wenn im zugrundeliegenden Datenelement diese Feldeigenschaft angekreuzt ist.

Nach dem Ändern ist das Aktivieren der Änderung besonders wichtig. Bitte prüfe das nach. Es wurde schon mehrfach berichtet, dass ein einfaches Aktivieren des Datenelements nach Ankreuzen dieser Checkbox nicht ausgereicht hatte. Das Datenelement verblieb auf „inaktiv“, und dann funktionieren die Änderungsbelege nicht. Also: so lange aktivieren, bis diese Änderung tatsächlich aktiv ist.

Konfiguration der Änderungsbelege

Wenn du eigene Z-Tabellen mit Änderungsbelegen ausstatten willst, oder wenn du wissen willst, die die OBJECTCLAS zu einer SAP-Standardtabelle lautet, dann brauchst du

  • die Transaktion SCDO, in der dies festgelegt wird und
  • die Tabelle TCDOB, in der SCDO seine Daten ablegt.

Die Transaktion SCDO ist unhandlich, denn sie verlangt in Eingangsdialog schon den Namen der OBJECTCLAS. Schauen wir lieber in die Tabelle TCDOB und suchen wir den TABNAME KNVV, das ist eine Tabelle, in der VKORG-spezifische Daten eines Debitors abgelegt werden. (KNA1, den Stammsatz gibt es nur einmal. Aber in der KNVV hat der Debitor/Kunde für jede VKORG einen Datensatz, in der er angelegt wurde.)

Wir finden heraus: KNVV wird nur von der OBJECTCLAS „DEBI“ verwendet. Und wenn wir erneut in SE16 suchen, diesmal für die OBJECTCLAS DEBI, dann finden wir diesen Zoo:

All diese Tabellen gehören also aus Sicht der Änderungsbelege zusammen. Jetzt wissen wir, wie wir uns das in SCDO ansehen können und geben DEBI im Selektionsschirm an:

Und die Details sehen so aus:

Änderungsbelege für Z-Tabellen

Jetzt haben wir alles beisammen, um Änderungsbelege für eine eigene Z-Tabellen einzurichten.

Du hast also eine Z-Tabelle, sagen wir mal ZSOMETHING. Dann könnte die OBJECTCLAS dazu vielleicht ZFOOBAR heißen. Du hast sicherlich auch daran gedacht, die Datenelemente hinter den Feldern aus ZSOMETHING mit dem Flag auszustatten, dass hierzu Änderungsbelege gewünscht sind?

Dann gehtst du in die Transaktion SCDO und legst eine OBJECTCLAS ZFOOBAR an. Du definierst, dass die Tabelle ZSOMETHING von ZFOOBAR protokolliert wird. Anschließend drückst du in diesem Dialog auf „generieren“. Du wirst nach einer Funktionsgruppe gefragt, denn SAP möchte einen Funktionsbaustein für dich anlegen.

Anschließend kannst du dich per SE11 in der Tabelle TCDOB davon überzeugen, dass es dort einen neuen Eintrag gibt.

Jetzt ist nur noch die Frage, wie du die Änderungsbelege tatsächlich erzeugst. Dazu kannst du den generierten Funktionsbaustein verwenden. Ich selbst mache es aber lieber „zu Fuß“. Es läuft am Ende auf dasselbe Dreigestirn von drei Funktionsbausteinen hinaus.

Da ich ABAP-OO mag, habe ich mir eine Klasse ZCL_CHANGEDOCUMENT geschrieben. Wenn ich dort eine manuelle Änderung an der MARA protokollieren will, dann verwende ich die Methode

    CLASS-METHODS log_mara
      IMPORTING
        !is_mara_old TYPE mara
        !is_mara_new TYPE mara .


METHOD log_mara.

    DATA:
      lf_objectclass TYPE cdobjectcl,
      lf_objectid    TYPE cdobjectv,
      lf_tablename   TYPE tabname.

    lf_objectid    = is_mara_new-matnr.
    lf_objectclass = 'MATERIAL'.
    lf_tablename   = 'MARA'.

    log_generic( if_objectclass = lf_objectclass
                 if_objectid    = lf_objectid
                 if_tablename   = lf_tablename
                 is_data_new    = is_mara_new
                 is_data_old    = is_mara_old ).

  ENDMETHOD.                    "LOG_MARA

Wichtig ist hier die Angabe der Objectclass und des Tabellennamens. Der Tabellenname ist immer eine Pflichtangabe. Es ginge bei MARA auch gar nicht anders, weil die Änderungsbelege der Objectclass MATERIAL zu mehreren Tabellen möglich sind.

Außerdem gibt es ein struct mit den neuen und eines mit den alten Daten. Beide muss ich mitliefern, dann kann SAP mit seinen Standardbausteinen ermitteln, welche Felder sich tatsächlich geändert haben.

Und log_generic sieht dann so aus.

    CLASS-METHODS log_generic
      IMPORTING
        !if_objectclass TYPE cdobjectcl
        !if_objectid    TYPE cdobjectv
        !if_tablename   TYPE tabname
        !is_data_old    TYPE any
        !is_data_new    TYPE any .


  METHOD log_generic.
    CALL FUNCTION 'CHANGEDOCUMENT_OPEN'
      EXPORTING
        objectclass      = if_objectclass
        objectid         = if_objectid
*       PLANNED_CHANGE_NUMBER   = ' '
*       PLANNED_OR_REAL_CHANGES = ' '
      EXCEPTIONS
        sequence_invalid = 1
        OTHERS           = 2.
    IF sy-subrc <> 0.
      MESSAGE 'Fehler beim Schreiben Änderungshistorie (Open)' TYPE 'E'.
    ENDIF.

    CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE'
      EXPORTING
*       CHANGE_INDICATOR       = 'U'
*       DOCU_DELETE            = ' '
*       DOCU_INSERT            = ' '
*       REFAREA_NEW            = ' '
*       REFAREA_OLD            = ' '
*       REFTABLENAME           = ' '
        tablename              = if_tablename
        workarea_new           = is_data_new
        workarea_old           = is_data_old
      EXCEPTIONS
        nametab_error          = 1
        open_missing           = 2
        position_insert_failed = 3
        OTHERS                 = 4.
    IF sy-subrc <> 0.
      MESSAGE 'Fehler beim Schreiben Änderungshistorie (SingleCase)' TYPE 'E'.
    ENDIF.

    CALL FUNCTION 'CHANGEDOCUMENT_CLOSE'
      EXPORTING
        date_of_change         = sy-datum
        objectclass            = if_objectclass
        objectid               = if_objectid
        tcode                  = sy-tcode
        time_of_change         = sy-uzeit
        username               = sy-uname
*       OBJECT_CHANGE_INDICATOR       = 'U'
*       PLANNED_OR_REAL_CHANGES       = ' '
*       NO_CHANGE_POINTERS     = ' '
*     IMPORTING
*       CHANGENUMBER           =
      EXCEPTIONS
        header_insert_failed   = 1
        no_position_inserted   = 2
        object_invalid         = 3
        open_missing           = 4
        position_insert_failed = 5
        OTHERS                 = 6.
    IF sy-subrc <> 0 AND sy-subrc <> 2.
      MESSAGE 'Fehler beim Schreiben Änderungshistorie (Close)' TYPE 'E'.
    ENDIF.


  ENDMETHOD.                    "LOG_MARA

Die drei Methoden gehören zusammen. Wenn sie nicht in dieser Reihenfolge aufgerufen werden, dann gibt es hässliche Sequenzfehler.

CHANGEDOCUMENT_OPEN: Dies öffnet für eine Objectclass und eine Object-ID (z.B. die Materialnummer oder einen von dir definierten Tabellenschlüssel in der Tabelle ZSOMETHING) einen Änderungsbelegskopfsatz.

Es folgen ein oder mehrere Aufrufe von CHANGEDOCUMENT_SINGLE_CASE, der eine Zeile wegschreibt. Es gibt auch den Baustein CHANGEDOCUMENT_MULTIPLE_CASE, der theoretisch Listen vergleichen kann. Den habe ich aber bisher nicht zum Leben erwecken können.) Hier ist die Tabelle anzugeben und die Daten (als strukturierten Datentyp, z.B. vom Typ MARA oder vielleicht von ZSOMETHING.

Als letztes schließt CHANGEDOCUMENT_CLOSE den Block ab.

Anschließend kannst du die Änderung dann in CDHDR und CDPOS nachschlagen.

Ein Wort zum Schluss

Bei Standard-Objectclasses werden die Standardtabellen von SAP automatisch verarbeitet. Dort ist in den jeweiligen Dialogen in der SAP-GUI schon hinterlegt, dass die Änderungsbelege erzeugt werden sollen.

Bei manuellen Updates auf SAP-Standardtabellen oder immer bei Z-Tabellen musst du das selbst machen. Nur da, wo du explizit selbst die Änderungsbelege erzeugst, wird es diese am Ende geben. Du müsstest also überall da, wo du ein update auf die Datenbank machst, dafür Sorge tragen, dass auch Änderungsbelege geschrieben werden.

Aber mit dem Wissen aus diesem Artikel funktioniert das dann auch.

Viel Spaß mit deinen eigenen Änderungsbelegen.

Mehr SAP-Tipps gibt es hier.

heiko

Dipl.-Ing. Heiko Evermann

Vorheriger Artikel