Ansicht
Dokumentation

CNV_INT_SCHEME_INSTANTIATE - Umstellung: Schema-Initialisierung mit Daten aus dem Generierungsprogramm

CNV_INT_SCHEME_INSTANTIATE - Umstellung: Schema-Initialisierung mit Daten aus dem Generierungsprogramm

BAL Application Log Documentation   Fill RESBD Structure from EBP Component Structure  
Diese Dokumentation steht unter dem Copyright der SAP AG.
SAP E-Book

Anmerkungen

Die Dokumentation wurde vom Funktionsbaustein SCHEME_INSTANTIATE aus dem Release 4.6A übernommen.

Die Funktionalität wurde gegenüber diesem Funktionsbaustein dahin gehend erweitert, dass nun auch durch OR oder AND zusammengesetzte Bedingungen erlaubt sind.

Funktionalität

Die Funktion SCHEME_INSTANTIATE instantiiert ein Schema mit den globalen Daten des aufrufenden Programms.

Schemata bieten eine einfache, wartbare Methode zur Generierung von Texten, insbesondere auch von ABAP-Programmen. Ein Schema ist vergleichbar mit der Angabe eines regulären Ausdrucks mit Variablen, Alternativen, Schleifen und Subschema-Aufrufen.

Mit Schemata werden Datenbesorgung im aufrufenden Programm und Syntaxdefinition im Schemaprogramm streng getrennt, so daß Änderungen der Syntax sehr einfach zu machen sind. Zudem ist die Syntax in einem Schema relativ leicht ersichtlich, im Gegensatz zu einem programmgesteuerten Zusammenbau von Zeilen mit concatenate und append.

Technik

Aus einem Schemaprogramm s wird ein Programm /1SAP1/SCMG_s generiert, das für jedes Schema in s eine Form enthält, die die Instantiierung durchführt. Das Programm wird nur bei Änderung des Schemaprogramms oder des Schema-Parsers neu generiert.

Mit dieser Technik sind Lade- und Laufzeiten von Schema-Instantiierungen sehr performant.

Auch für fehlerhafte Schemata wird eine Form generiert, die dann bei Instantiierung einen Fehler zurückliefert. Daher können alle korrekten Schemata korrekt instantiiert werden, auch wenn fehlerhafte Schemata in dem Schemaprogramm enthalten sind.

Schema-Syntax

Im folgenden werden die Default-Steuerzeichen benutzt. Diese können aber auch pro Schemaprogramm umdefiniert werden.

Schemaprogramm

Ein Schemaprogramm ist ein (mit SE38 erstellter) ABAP-Report, der ein oder mehrere Schemata enthält. Dieser Report ist vom Typ I(nclude), da Schemata nicht der ABAP-Syntax genügen.

  • Es ist günstig zusammengehörige Schemata in einem Programm zusammenzufassen, da dann nur ein Programm geladen werden muß, um diese Schemata zu instantiieren.
  • Die Länge des Namens für Schemaprogramme ist begrenzt auf 18 Zeichen (Datenelement SCHEMEPROG), da der Präfix für die daraus generierten Programme 12 Zeichen lang ist.

Schema

Ein Schema wird geklammert durch die Zeilen

       />schema_name

         ...

       />END


  • Die Klammerungszeilen dürfen keine führenden Blanks und keinen weiteren Text oder Kommentar haben.
  • 'END' ist ein reservierter Name und kann nicht als Schemaname verwendet werden.
  • Die Länge des Schemanamens ist bestimmt durch das Datenelement SCHEMENAME, z.Z. 30-stellig.

Variablen

In einem Schema können globale Variablen vom Typ C oder string (und nur die!) des aufrufenden Programms referenziert werden. Variablen im Schema werden mit '&' begrenzt:

           &varname&

Für eine Variable wird ihr Wert substituiert, wobei trailing blanks abgeschnitten werden, während führende blanks erhalten bleiben (wie bei dem ABAP-Befehl CONCATENATE).

  • Wird dem Variablennamen ein '-' vorangestellt, so wird der Wert der Variable mit lower case Konvertierung instantiiert.
    Beispiel:

           data: VAR(4) value ' cD '. "im aufrufenden Programm

          'ab&VAR&ef'  -> 'ab cDef'

          'ab&-VAR&ef' -> 'ab cdef'

Kontrollstrukturen

In Schemata können Bedingungen, Schleifen und Subschema-Aufrufe definiert werden. Eine Kontrollstruktur hat die Form:

         {x$control$ ... $ ....  ....  }

wobei x angibt, um welche Kontrollstruktur es sich handelt und die einzelnen Bestandteile der Kontrollstruktur durch das Separatorzeichen '$' getrennt sind. 'Control' ist der kontrollierende Ausdruck.

Die Anzahl der Bestandteile hängt von der jeweiligen Kontrollstruktur ab - sie muß aber strikt eingehalten werden, auch wenn bestimmte Teile leer sind. Ansonsten ist die Syntax des Schemas fehlerhaft.

  • Bei der Instantiierung werden die steuernden Elemente ausgewertet, produzieren aber keinerlei Ausgabe, auch keine Blanks.
  • Innerhalb von '{x$control$' darf kein Zeilenvorschub erfolgen.

Conditional

Ein Conditional hat die Form:

           {C$condition$then$else}

'Condition' kann eine einfache Variable sein. Dies hat die Bedeutung von 'not(variable is initial)'. Der 'then'-Teil wird instantiiert, wenn die Variable nicht initial ist; ansonsten der 'else'-Teil.

Beispiel:

           {C$sy-subrc$error$ok} -> 'error', falls sy-subrc <> 0
                                 -> 'ok'   , falls sy-subrc = 0

'Condition' kann auch ein einfacher Ausdruck der Form 'a op b' sein, wobei 'a' eine Variable und 'b' eine Variable, ein String oder eine integer ist. 'Op' muß eine höchstens zweistellige ABAP-Operation sein, z.B. =, <, LE, CA, ... . Vor und nach 'op' muß ein Blank stehen.

Beispiel:

           data: a value 'D', b value 'D'.
           {C$a = b   $eq$neq}      -> 'eq'
           {C$a &lt;&gt; 'D'$neq D $eq D} -> 'eq D'

  • Mit diesem Konstrukt läßt sich auch 'if ... elseif ...' abbilden:

           {C$sy-subrc = 0$ok${C$sy-subrc = 4$warning$error}}

  • Sowohl 'then' als auch 'else'-Teile können leer sein. Es müssen aber auf jeden Fall alle Separatoren angegeben sein:

           {C$condition$then$} bzw. {C$condition$$else}.

Table Loop

Eine Table Loop hat die Form:

          {T$table$pre1$pre$main$post$postn} oder

          {T$table WHERE condexpr$pre1$pre$main$post$postn}

Dabei ist 'table' der Name einer internen Tabelle des aufrufenden Programms. Diese Tabelle muß dort global sein und eine Kopfzeile haben.

'Condexpr' ist ein einfacher Ausdruck der Form 'f op b', wobei f der Name eines Feldes von 'table' ist und 'op' und 'b' wie bei bei Conditional beschrieben sind.

Es wird über diese Tabelle geloopt und folgende Ausgabe produziert:

           'pre1mainpost'  für die 1.Zeile
           'premainpost'   für die 2. - (n-1). Zeile
           'premainpostn'  für die n. Zeile

Beispiel:

          {T$fieldtab$DATA: $
                $fieldtab-fieldname like ... $,$.}
      ->  DATA: field1 like ... ,
                field2 like ... ,
                field3 like ... .

Sollen nur die Schlüsselfelder berücksichtigt werden, so könnte die Table Loop wie folgt aussehen

            {T$fieldtab WHERE key = 'X'$DATA: $ ...  }

  • Achtung: Die Nicht-Existenz der Tabelle im aufrufenden Programm führt zu der Ausnahme 'TABLE_NOT_EXISTS'.
  • Hat die Tabelle keinen (passenden) Eintrag, so ist das Ergebnis des Table Loops leer.
  • Hat die Tabelle genau einen (passenden) Eintrag, so ist das Ergebnis: 'pre1mainpostn'.
  • In den Teilen pre1, pre, post, postn können auch Variablen und sogar Kontrollstrukturen benutzt werden. In allen Teilen haben die Variablen die Werte des aktuellen Schleifendurchlaufs. Die Verwendung von Variablen oder Kontrollstrukturen in post kostet allerdings etwa 20% Performance.

Function Loop

Eine Function Loop hat die Form:

          {F$function$pre1$pre$main$post$postn}

Dabei ist 'function' eine im aufrufenden Programm definierte Form mit einem Parameter 'CHANGING TYPE I'. Diese Form setzt in jedem Durchlauf die im Schema verwendeten Variablen neu.

Die Form wird zunächst mit = 1 aufgerufen. Bei jedem weiteren Aufruf wird um 1 erhöht. Die Form selbst kann intern ebenfalls erhöhen und so zurückgeben. Die Schleife wird beendet, wenn die Form = 0 zurückgibt.

  • Die Anmerkungen bei table loop gelten analog für function loop.
  • Function loop kann z.B. benutzt werden, wenn selektiv nur für bestimmte Einträge einer Tabelle Ausgabe produziert werden soll:

       form next_entry changing idx type i.
         loop at tab from idx where .... .   " start search from idx
           idx = sy-tabix.    " set idx to found entry
           exit.              " at next call idx is incremented by 1
         endloop.
         if sy-subrc &lt;&gt; 0.
           idx = 0.           " no entry found, set idx=0 to end loop
         endif.
       endform.

  • Ohne Selektion auf der Tabelle ist die Table Loop zu bervorzugen, da nur etwa 60% der Laufzeit der Function Loop benötigt wird.

Subscheme Call

Ein Subscheme Call hat die Form:

          {S$scheme}

Dabei ist 'scheme' der Name eines Schemas im gleichen Schemaprogramm. An der Stelle, an der der Subscheme Call steht, wird das angegebene Schema instantiiert.

Dabei wird das instantiierte Subschema so weit eingerückt, wie der Aufruf selbst. Beginnt eine Zeile des Subschemas mit dem Kommentarzeichen '*', so bleibt dies an erster Zeilenposition.

Beginnt die Zeile des Subschema-Aufrufs mit '*', so beginnen alle Zeilen des instantiierten Subschemas ebenfalls mit '*'.

Beispiele: siehe Schemaprogramm SCHEME_SAMPLE, das mit dem Report SCHEME_TEST zu instantiieren ist.

Weitere Features

Kommentare

Da Schemata geklammert sind, können Zeilen zwischen den Schemata als Kommentar benutzt werden.

Innerhalb eines Schemas können Kommentarzeilen eingestreut werden, die mit '*:' beginnen müssen. Sonstige mit '*' beginnende Zeilen werden normal instantiiert, um auch ABAP-Kommentare ins Ergebnis generieren zu können.

Kommentare am Zeilenende beginnen mit '":'. Der Rest der Zeile wird dann nicht in die Instantiierung übernommen.

Groß-/Kleinschreibung

Da der ABAP-Editor eine upper case Konvertierung vornimmt, ist die Möglichkeit vorgesehen, dies zu umgehen. Dazu muß die Zeile mit '"%' beginnen. Für den ABAP-Editor ist dies Kommentar und die Kleinschreibung bleibt erhalten. Der Schema-Instantiierer überliest diese Zeichen.

Wird ein Editor ohne Konvertierung benutzt (ab 4.6A), so ist diese Kennzeichnung nicht mehr notwendig.

Fortsetzungszeile und Einrückung

Um mehrere Zeilen eines Schemas auf eine Instantiierungszeile abzubilden, sind die Schemazeilen mit dem Zeichen '\' abzuschließen. Damit entfällt der folgende Zeilenvorschub in der Instantiierung der Schemazeile.

  • Dies wird benötigt, wenn durch Kontrollstrukturen oder lange Variablennamen das Schema für eine instantiierte Zeile nicht auf eine Schemazeile paßt.

Um das Schema leserlicher zu gestalten, gibt es auch die Möglichkeit, Zeilen einzurücken, ohne daß die Einrückung in das Ergebnis übernommen wird. Dazu beginnt man die Zeile nach der Einrückung mit '\'.

  • Dies ist insbesondere nützlich um Fortsetzungszeilen einzurücken.

Beispiel:

          "%       This is a long text over several \
          "%       \lines which is idented in the scheme.

Fluchtsymbol

Das Zeichen '#' dient als Fluchtsymbol und maskiert die Bedeutung der Zeichen '{}$&#&'

Beispiel:

          control: #{x#$...#}. Variable: #&var#&'. Escape: ##.'

       -> 'control: {x$...}. Variable: &var&. Escape: #.'

  • Ansonsten wird '#' in Schemazeilen einfach überlesen.
  • Die Bedeutung anderer Zeichen wird nicht maskiert. Insbesondere dürfen Zeichen, die am Zeilenanfang stehen müssen, nicht durch das Fluchtsymbol von dieser Position verdrängt werden.

Kommentarzeichen der Zielsprache

Dieses einstellbare Zeichen, mit Default '*' für die Generierung von ABAP-Programmen, wird sonderbehandelt bei der Einrückung von Subschemata und beim automatischen Zeilenumbruch.

Falls eine Subschema-Zeile mit diesem Zeichen beginnt, bleibt es auch bei Einrückung an 1. Stelle stehen - die Einrückung findet hinter diesem Zeichen statt.

Muß eine instantiierte Zeile umgebrochen werden und hat diese Zeile das Kommentarzeichen an 1. Position, so haben auch die Folgezeilen dieses Zeichen an 1. Stelle.

Automatischer Zeilenumbruch

Wird eine instantiierte Zeile zu lang, so wird ein automatischer Zeilenumbruch gemacht, so daß die Zeilen in RESULT_TAB passen.

Ein Umbruch findet statt bei space oder, wenn dies nicht möglich ist, vor '({[' oder nach ',.)]}'. Dabei wird space durch linefeed ersetzt, bei den anderen Zeichen wird linefeed davor bzw. danach eingefügt.

Beispiel:

          {t$fieldtab$DATA:$$ fieldtab-fieldname like ... $,$.}

       -> DATA: field1 like ... , field2 like ... , ... ,

          field5 like ... , ...

  • Alle Folgezeilen werden so weit eingerückt wie die Originalzeile.
  • Ist die Originalzeile eine Kommentarzeile, so sind auch alle Folgezeilen Kommentarzeilen.
  • Fehlerfall: Kann die Zeile nicht an den angegebenen Zeichen umgebrochen werden und ist die Zeile keine Kommentarzeile, so wird die Ausnahme FORCED_LINESPLIT gesetzt. Die Instantiierung wird aber auf jeden Fall vollständig durchgeführt und in RESULT_TAB zurückgegeben.
  • Eine instantiierte Zeile darf vor dem Umbruch bis zu 8000 Zeichen lang werden (Feld SCINSTLINE-TEXT).

Steuerzeichen

Hier der Überblick über die Default-Steuerzeichen für Schemata

   Zeichen   Bedeutung                          Länge   Anmerkung

      #    Fluchtsymbol                           1        3

      />   Schemadefinition-Anfang                2        1

      

      {    Kontrollstruktur-Anfang                1        3

      }    Kontrollstruktur-Ende                  1        3

      $    Kontrollstruktur-Separator             1        3

      &    Variablenbegrenzer                     1        3

      -    Kleinschreibung von Variablen          1        2

      \    Linefeed-Escape, Ident-Escape          1        4

      *:   Kommentarzeile                         2        1

      ":   Restzeilenkommentar                    2

      "%   Zeile mit Kleinschreibung              2        1

      *    Kommentarzeichen der Zielsprache       1        5

      !    Eingabevariable im interaktiven Modus  1        2, 6

      "!   Zeile nur für interaktiven Modus       2        1, 6

Anmerkungen

  1. Zeichen wirkt nur am Zeilenanfang
  2. Zeichen wirkt nur innerhalb von Variablen vor dem Variablennamen.
  3. Zeichen kann mit Fluchtsymbol maskiert werden.
  4. Zeichen wirkt nur am Zeilenende und als erstes Zeichen nach beliebig vielen Spaces.
  5. Zeichen hat keine Sonderrolle in Schemata, aber bei der Instantiierung.
  6. Wird zur Zeit noch nicht benutzt, aber bei syntaktischer Analyse schon berücksichtigt.

Kommt es zu Konflikten mit dem Schemainhalt, so können die Steuerzeichen in dem Schemaprogramm auch umdefiniert werden. Dazu wird in der 1. Zeile ab der 1. Spalte angegeben:

           :SET # />

Nach :SET werden alle oder ein Anfangsstück der Steuerzeichen in der oben angegebenen Reihenfolge und Länge(!) angegeben. Blanks werden entfernt und der String wird der Delimeter-Leiste (siehe Dictionary-Struktur SCMDELIMA) zugewiesen. Für die am Ende fehlenden Steuerzeichen wird weiter der Default benutzt. Um die Sonderbehandlung des Kommentarzeichens der Zielsprache abzuschalten, ist dort 'N' anzugeben.

Schemagesteuerte Generierung

Für die schemagesteuerte Generierung benötigt man 2 Programme - das Schemaprogramm und ein Treiberprogramm. Das Treiberprogramm stellt die in dem Schemaprogramm verwendeten Variablen, Tabellen und Funktionen zur Verfügung und ruft dann die Schema-Instantiierung auf. Der Aufbau eines Treiberprogramms ist weiter unten beschrieben.

Vorgehen

  • Die benötigten Schemata in einem Schemaprogramm erstellen. Eine Möglichkeit besteht darin, zunächst ein lauffähiges Programm für ein fixes Beispiel zu erstellen und dann die generischen Teile mit Schemasyntax zu generalisieren.
  • Parallel dazu fügt man in das Treiberprogramm die von dem Schema benötigten Variablen, Tabellen und Funktionen ein.
  • Das erstellte Schemaprogramm mit dem Report SCHEME_TEST im Modus 'symbolische Instantiierung' überprüfen.
    Dabei werden die eventuell vohandenen Syntaxfehler ausgegeben und das Layout läßt sich anhand der symbolischen Instantiierung überprüfen. Der Wert für die Conditions und die Anzahl der Durchläufe für Loops läßt sich variieren. Zumindest sollten auch die Extremfälle 0 und 1 geprüft werden.
  • Dann das Treiberprogramm zusammen mit dem Schemaprogramm prüfen.
    Dabei kann man zunächst auch den Baustein DD_SCHEME_TEST statt SCHEME_INSTANTIATE aufrufen, wobei die zusätzlichen Parameter dieses Bausteins nicht versorgt werden. Dieser gibt dann das Ergebnis und Fehlermeldungen auf den Bildschirm aus.

Fehler

Alle Ausnahmen setzen die System-Variablen, um die Fehlermeldung über MESSAGE auszugeben.

Die Ausnahmen SYNTAX_ERROR und GENERATE_ERROR lassen sich meist vermeiden, wenn das Schemaprogramm vorher mit dem Report SCHEME_TEST geprüft wird.

Aufrufendes Programm

Für ein Schemaprogramm gibt es normalerweise ein Treiberprogramm, das die notwendigen Daten besorgt und für die Instantiierung bereit stellt.

Dieses Programm sieht im Aufbau etwa wie folgt aus:

        ** global variables usable in schemes

        data: var1, ..., varn.

        ** global tables usable in table loops of schemes

        data: tab1 type table of ... with header line,

              ...

              tabm type table of ... with header line.

        ** functions used in function loops of schemes

        form fct1 changing idx type i.   ...   endform.

          ...

        form fctk changing idx type i.   ...   endform.

        ** variables for scheme instantiation

        data: thisprog   like sy-repid,

              schemeprog type schemeprog value 'myschemes',

              scheme     type schemename,

              result_tab type abapprog.

        **** for each scheme S in schemeprog a form instantiate_S

        form instantiate_S using ... .

        * 1. set global variables and tables used in S

          ...

        * 2. call instantiation

          thisprog = sy-repid. "important to fix value of sy-repid here

          scheme   = 'S'.

          refresh result_tab.

          call function 'SCHEME_INSTANTIATE'

               exporting

                  calling_prog   = thisprog

                  scheme_program = schemeprog

                  scheme_name    = scheme

               tables

                  result_tab.

               exceptions

                 when others     = 8.

          if sy-subrc &lt;&gt; 0.

             MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO

                     WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.

          endif.

        * 3. use result_tab

          ...

        endform.

Beispiel

Beispiele sind in dem Report SCHEME_SAMPLE, fehlerhafte Beispiele in SCHEME_ERROR zu finden.

Diese Beispiele wie auch selbstgeschriebene Schemaprogramme lassen sich testen mit dem Report SCHEME_TEST.





Parameter

CALLING_PROGRAM
RESULT_TAB
SCHEME_NAME
SCHEME_PROGRAM

Ausnahmen

FORCED_LINESPLIT
GENERATE_ERROR
NO_AUTHORITY
SCHEMEPROG_NOT_FOUND
SCHEME_NOT_FOUND
SCHEME_SYNTAX_ERROR
TABLE_NOT_EXISTS

Funktionsgruppe

CNV_BASIS_SCHEME

Fill RESBD Structure from EBP Component Structure   CPI1466 during Backup  
Diese Dokumentation steht unter dem Copyright der SAP AG.

Length: 33479 Date: 20240523 Time: 124851     sap01-206 ( 290 ms )