Codeschnipsel - 4AP.de - ABAP Syntaxbeispiele: verschiedene Codeschnipsel
(kopieren erlaubt aber auf eigene Gefahr :-))
Einige kleinere Codeschnipsel:
* mostly coded by Thorsten Neubüser - www.4ap.de
Arbeiten mit einem Makro um sich viele redundante Codingzeilen zu sparen:
DATA: rt_werks TYPE RANGE OF marc-werks,
rs_werks LIKE LINE OF rt_werks.
Makro definieren:
DEFINE fill_rt_werks. "TN2010
move: 'I' to rs_werks-sign,
'EQ' to rs_werks-option,
&1 to rs_werks-low.
append rs_werks to rt_werks. clear rs_werks.
END-OF-DEFINITION. "TN2010
Dann das Makro aufrufen:
fill_rt_werks: '01', '03', '06', '07', '09', '20', '21'.
* LCHR-Feld auslesen = lange Zeichenfolge ab 256 Stellen
* um ein Feld vom Datentyp LCHR (long Char) auszulesen muss unbedingt auch die Länge des Feldes mitermittelt werden
DATA: lv_addrnumber TYPE kna1-adrnr,
lv_persnumber TYPE knvk-prsnr,
lv_uri_length TYPE adr12-uri_length,
" INT2 Länge 5
lv_uri_addr TYPE adr12-uri_addr.
" LCHR Länge 2048
* in der ADR12 steht die URL für HTTP-Post wenn in Kundenstammdaten eingepflegt
* URL aus Kundenstamm auslesen
IF p_url IS INITIAL.
* Adressnummer besorgen
SELECT SINGLE adrnr FROM kna1 CLIENT SPECIFIED
INTO lv_addrnumber
WHERE mandt = sy-mandt
AND kunnr = p_kunnr.
* Personennummer besorgen
SELECT prsnr FROM knvk CLIENT SPECIFIED
INTO lv_persnumber
WHERE mandt = sy-mandt
AND kunnr = p_kunnr
AND abtnr = 'ANS5'
AND pafkt = '5'.
* URL auslesen
SELECT SINGLE uri_length " Länge muss mitausgelesen werden
uri_addr " sonst lv_uri_addr leer!
FROM adr12 CLIENT SPECIFIED
INTO (lv_uri_length, lv_uri_addr)
WHERE client = sy-mandt
AND addrnumber = lv_addrnumber
AND persnumber = lv_persnumber
AND date_from = '00010101'
AND consnumber = '1'.
* AND uri_addr NE ''. " funzt nicht, da LCHR - Feld
IF sy-subrc = 0.
IF lv_uri_addr NE ''.
p_url = lv_uri_addr.
EXIT. " URL gefunden
ENDIF. " lv_uri_addr ne ''
ENDIF.
ENDSELECT. " prsnr FROM knvk
ELSE. " p_url IS INITIAL
IF p_url NS 'http' OR p_url NS 'HTTP'.
MESSAGE i000(zz) WITH 'Bitte korrekte / vollständige URL angeben'(e01).
EXIT.
ENDIF. " p_url NS 'http' OR p_url NS 'HTTP'
ENDIF. " p_url IS INITIAL
* Debug-Schleife: um eine Batch-Prozess über die SM50 o.ä. debuggen zu
* können. In der SM50-Transaktion sieht man dann die Berarbeitungszeit hochlaufen.
* Diesen Dialogprozess markiern und über den Menubefehl (Administration - Programm - debuggen) das Debuggen starten.
* Auch für per RFC angestoßene Fubaus etc.
* das Coding ist eher Trivial.
data: debug. " ACHTUNG! nur in Absprache auskommentieren
while debug is initial. " der WERT von debug muss geändert werden!
* nur mal so zum Spaß und natürlich zum Testen
endwhile. " debug is initial
Wenn man keine Werte im System ändern darf, aber die SM50 darf // die sichere Methode:
*** Debug-Schleife für xx Sekunden offen halten
IF sy-datum < '20140521'. " Tagesdatum + 1 Tag, falls man mal das Auskommentieren vergisst :-)
DATA: time TYPE sy-uzeit.
GET TIME. " aktuelle, sekundengenaue Zeit holen
time = sy-uzeit + 30. " Zahlenwert = Wartezeit in Sekunden
WHILE sy-uzeit < time.
GET TIME. " aktuelle, sekundengenaue Zeit holen
ENDWHILE.
ENDIF. " sy-datum < '...'
Das Coding oben dient auch dazu einige Sekunden auch den Verbucher zu warten // wenn das z.B. ein Workflow-Prozess ist.
Das Abwarten bekommt man natürlich auch mit der Anweisung WAIT UP TO sec SECONDS. hin. ABER: dabei wird immer ein COMMIT WORK ausgelöst, was nicht immer gewünscht ist.
* Materialnummer mit führenden Nullen auffüllen // DIRTY!! geht nur für rein numerische MATNR!!!
* bei allen Anderen OVERLAY benutzen
UNPACK LV_MATNR TO LV_MATNR.
* sauberes Auffüllen der Materialnummer mit Nullen
IF ms_ta_data-out-matnr NA sy-abcde.
OVERLAY ms_ta_data-out-matnr WITH '000000000000000000'.
ENDIF. " ms_ta_data-out-matnr NA sy-abcde
Immer wieder in der Hilfe nicht gefunden
Bestimmen / Berechnen der Länge einer Zeichenkette / eines String - Stringlänge
DATA: int TYPE i,
word1(20) TYPE c VALUE '12345'.
word2(20) TYPE c.
word3(20) TYPE c VALUE ' 4 '.
int = strlen( word1 ). WRITE int.
int = strlen( word2 ). WRITE / int.
int = strlen( word3 ). WRITE / int.
Die Ergebnisse sind 5, 0 bzw. 4.
* einige wenige 'harte' Selektionsoptionen abfragen
SELECT * FROM knvp
APPENDING CORRESPONDING FIELDS OF TABLE it_knvp
FOR ALL ENTRIES IN it_kunnr
WHERE kunnr = it_kunnr-kunnr
AND parvw IN ('AG', 'WE', 'ZW').
...
( eshop = 'X' AND eshop_datum <= sy-datum )
OR ( eshop = 'A' AND eshop_datum >= sy-datum )
OR ( eshop = 'B' AND eshop_datum > sy-datum ) AND
* führende Nullen entfernen
SHIFT ME21_REENR LEFT DELETING LEADING '0'.
* übersetzungsfähiges Textelement 'intelligent' anlegen
write: 'nach dem Schreiben auf die Nummer doppelklicken'(023),
'legt diesen Text als übersetzungsfähigen Text an'(024).
* Kopfzeile in itab einfügen
insert itab index 1.
* Mengeneinheit ISO-Umwandlung von 'ST' in 'PCE' etc, benutzt für IDOCs
* es kommen Stück = ST aus der MARA, egal welche Anmeldesprache!!! Basismengeneinheit
* das IDOC will aber PCE sehen, da englisch angemeldet bzw. englisches System
data: lv_meins TYPE mara-meins.
* Conversion ISO-Code
SELECT SINGLE ISOCODE FROM t006 CLIENT SPECIFIED
into lv_meins
WHERE mandt = sy-mandt
AND msehi = lv_meins.
* 'intelligenter' SPLIT
DATA: ii_split TYPE TABLE OF string.
DATA: ww_split TYPE string.
* Initialize
REFRESH: ii_split.
CLEAR: ww_line.
* Split line
SPLIT w_file-string AT ',' INTO TABLE ii_split.
* Transfer fields
LOOP AT ii_split INTO ww_split.
CASE sy-tabix.
WHEN 1.
ww_line-gcp_matnr = ww_split.
WHEN 2.
ww_line-gcp_qty = ww_split.
WHEN 3.
ww_line-dat00 = ww_split.
WHEN 4.
ww_line-co_matnr = ww_split.
WHEN 5.
ww_line-co_qty = ww_split.
WHEN 6.
ww_line-unit = ww_split.
WHEN 7.
ww_line-stor_loc = ww_split.
WHEN 8.
ww_line-revlv = ww_split.
WHEN OTHERS.
ENDCASE. " sy-tabix
ENDLOOP. " AT ii_split INTO ww_split
* Sichten bei der MM02 oder MM03 abschalten / Call Transaction
ELSEIF r_ucomm = '&IC1'.
READ TABLE t_daten INDEX rs_selfield-tabindex.
CASE rs_selfield-fieldname.
WHEN 'MATNR'.
IF NOT rs_selfield-value IS INITIAL.
SET PARAMETER ID 'MAT' FIELD rs_selfield-value.
* Sichtenauswahl abschalten
SET PARAMETER ID 'MM5' FIELD ' '.
CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN.
ENDIF.
ENDCASE. " rs_selfield-fieldname
ENDIF. " sy-ucomm = 'DOWN'
* 10 Sekunden auf Verbuchung warten! ACHTUNG lastet System aus!
* Sie sollten wissen was Sie tun, bevor Sie das einbauen!
DATA: ZEIT LIKE SY-UZEIT.
clear zeit.
GET TIME FIELD ZEIT.
ZEIT = ZEIT + 10.
DO.
GET TIME.
IF SY-UZEIT GT ZEIT.
EXIT.
ENDIF.
ENDDO.
Oder ganz kurz:
WAIT UP TO 10 SECONDS.
* Anzahl Monate auf Datum addieren,
* davon dann Monatsletzten ermitteln:
PARAMETERS: p_month TYPE t691f-wswin.
DATA:
l_date TYPE sy-datum,
l_month TYPE t691f-wswin.
l_date = sy-datlo.
WRITE: 'Actual:', l_date.
l_month = p_month + 1.
DO l_month TIMES.
l_date+06(02) = 28.
l_date = l_date + 4.
ENDDO.
l_date+06(02) = 1.
l_date = l_date - 1.
WRITE: 'New:', l_date.
Oft braucht man am Ende eine Zeile noch ein Zeilenvorschub (LF/CR) um z.B. bei der Ausgabe von CSV-Dateien sie später auch lesbar zu gestalten und auch um die Sätze sauber zu trennen. Oder man braucht ein Hochkommate ' das man in einen String concatenaten kann. Für diese sehr ähnlichen Probleme gibt es mehrere verschiedene Lösungen, je nach System und Verständnis ausprobieren:
* at the end of each downloaded line / Windows, alte Systeme DATA: BEGIN OF final, * line_sep type C value ';', cr TYPE x VALUE '0D', " carriage return = 013 dec lf TYPE x VALUE '0A', " line feed = 010 dec END OF final,
############
* für dynamische Programmierung (subroutine-pool) und anderes
* NICHT-Unicode-Syteme haben es leicht:
HOCHKOMMA TYPE X VALUE '27'. " hex27 = dec39 = '
* für Unicode-Systeme ist das ein wenig aufwändiger
data:
hochkomma TYPE c,
wert type i value 39, " hex27 = dec39 = '
lv_hk(2) type x.
FIELD-SYMBOLS: <hk> type x.
ASSIGN hochkomma TO <hk> CASTING.
lv_hk = Wert.
<hk> = lv_hk. " so, jetzt steht in hochkomma ein Hochkomma also '
################
* GANZ richtig definiert heutzutage
* um die noch vorhandenen CRs austauschen zu können
DATA:
lv_replace TYPE c,
lv_ascii TYPE i VALUE 13, " dec-13 = hex-0D also ein 'CR'
lv_hex(2) TYPE x.
FIELD-SYMBOLS: <lv_fs> TYPE x.
ASSIGN lv_replace TO <lv_fs> CASTING.
lv_hex = lv_ascii.
<lv_fs> = lv_hex. " so, jetzt steht in lv_replace der ASCII-Wert drin
* dann klappt auch der folgende Replace
REPLACE ALL OCCURRENCES OF lv_replace IN ev_content WITH ''.
######################
* um die Codierung '$!$' in einen Zeilenumbruch umwandeln zu können
DATA:
old_lf(3) TYPE c VALUE '§!§', " old LINE FEED
new_lf TYPE ABAP_CR_LF value cl_abap_char_utilities=>cr_lf. " new LF
########
CONCATENATE syntax lv_help_string ` ` '''' lv_value ''''
INTO syntax. "#EC NOTEXT
* dabei erzeugt ` ` einen BLANK und '''' ein Hochkomma
#########
DATA: line_feed(1) TYPE c VALUE CL_ABAP_CHAR_UTILITIES=>CR_LF.
#######
ASCII-HEX-Umwandlung unter http://www.goascii.de/ (Javascript erforderlich)
sonstige 'Sonderzeichen' in CL_ABAP_CHAR_UTILITIES
-
HORIZONTAL_TAB Constant Public Type ABAP_CHAR1 Zeichen "horizontaler Tabulator-Stop"
-
VERTICAL_TAB Constant Public Type ABAP_CHAR1 Zeichen "vertikaler Tabulator-Stop"
-
NEWLINE Constant Public Type ABAP_CHAR1 Zeichen "neue Zeile" CR_LF Constant Public Type
-
ABAP_CR_LF Zeichenpaar "Wagenrücklauf u. Zeilenvorschub"
-
FORM_FEED Constant Public Type ABAP_CHAR1 Zeichen "Seitenvorschub"
-
BACKSPACE Constant Public Type ABAP_CHAR1 Zeichen "Backspace"
-
SPACE_STR Static Attribute Private Type STRING String mit Whitespace-Zeichen
-
SPACE_STR_LANGU Static Attribute Private Type LANGU Sprachkennzeichen zu SPACE_STR
Für dynamische Tabellendefinition: siehe auch bei wer-weiss-was [http://www.wer-weiss-was.de/theme129/article1119117.html#].
* Nachrichtenklasse '00' zum Ausgeben diversen Fehlermeldungen
* ohne Zwischenräume [ &1&2&3&4 ]
message i001(00) with
'maximal bis 50 Character werden je Textfeld ausgegeben'(001)
'X2' 'x3' 'X4'.
* mit Zwischenräumen [ &1 &2 &3 &4 ]
message i398(00) with 'x1' 'X2' 'x3' 'X4'.
*
**** Lesen der Klassifikation 'BEZEICHNUNG'
* Hinweis: es gibt mehrere Klassifikationen, die im Text 'Bezeichnung' haben, die jeweils passende soll gelesen werden
CLEAR: lv_atinn.
SELECT atinn FROM cabnt CLIENT SPECIFIED
INTO lv_atinn
WHERE mandt = sy-mandt
AND spras = sy-langu
AND atbez = 'BEZEICHNUNG'.
CALL FUNCTION 'CLFM_GET_AUSP_FROM_BUFFER'
EXPORTING
object = lv_object
classytpe = '001'
key_date = sy-datum
* PTABLE = PTABLE
* OBJECT_IS_CUOBJ = ' '
* MAFID = 'O'
atinn = lv_atinn
* I_NO_DB_SELECT = ' '
* I_WITH_DEL_AUSP = ' '
TABLES
exp_ausp = lt_exp_ausp.
CLEAR: ls_exp_ausp.
READ TABLE lt_exp_ausp INTO ls_exp_ausp INDEX 1.
lv_bezeichnung = ls_exp_ausp-atwrt.
IF NOT lv_bezeichnung IS INITIAL.
EXIT.
ENDIF. " NOT lv_bezeichnung IS INITIAL
ENDSELECT. " atinn FROM cabnt
Concatenate mit Berücksichtigung von Blanks:
CONCATENATE
' LGNUM = ''' ms_user-warehouse ''''
' and MATNR = ''' ms_ta_data-out-matnr ''''
' and WERKS = ''' ms_user-plant ''''
' and LGTYP = ''' ms_user-STORAGE_TYPE ''''
' and LETYP = ''' ms_ta_data-out-VRKME ''''
INTO lv_where RESPECTING BLANKS.
Name der Variable ist erst zur Laufzeit bekannt:
DATA:
lv_fieldname TYPE char30.
FIELD-SYMBOLS:
<lv_fieldvalue> TYPE any.
CLEAR: lv_fieldname.
CONCATENATE 'WA_ORDER_ITEMS_OUT-' 'NET_VALUE1' INTO lv_fieldname.
ASSIGN (lv_fieldname) TO <lv_fieldvalue>.
MOVE <lv_fieldvalue> TO wa_cartentry-kzwi2.
AUTHORITY-Check
* Berechtigungsverprobung
DATA: p_auth_classname TYPE aqs_clsna VALUE
'CL_QUERY_TAB_ACCESS_AUTHORITY',
l_oref TYPE REF TO object.
IF iref IS INITIAL.
CREATE OBJECT l_oref
TYPE
(p_auth_classname).
iref ?= l_oref.
ENDIF.
CALL METHOD iref->access_authority_begin.
CALL METHOD iref->tab_access_authority
EXPORTING
table = 'ZPPTABCD'
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE s316(aq) WITH 'ZPPTABCD'.
LEAVE LIST-PROCESSING.
ENDIF.
CALL METHOD iref->access_authority_end
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE s317(aq).
LEAVE LIST-PROCESSING.
ENDIF.
***************
* *
* T T *
* N *
* *
* `---´ *
* *
***************