Learning new syntax ABAP 7.4 with a volte-face scenario
Recently, I encountered a unique challenge while working with a client with an old SAP system.
I had code ( ABAP 7.4 ) ready to deploy to client system but I could not use it due to lower ECC version. So, I downgraded my code syntactically as many of the operators are not supported by EHP 6.0
I am sharing few of my learnings while doing so. I hope the same can be useful for changing the code to and/or learning ABAP 7.4 as well.
This blog will cover Inline declaration of variables and field symbols, inline usage of structure, and operators such as Filter and group by.
1. LOOP-AT Statement: Inline declaration of Variable or Reference.
LOOP AT GT_DATA ASSIGNING FIELD-SYMBOL(<LS_DATA>). * Code ENDLOOP. LOOP AT GT_DATA INTO DATA(LS_DATA). * Code ENDLOOP.
First of all, if you find DATA(*) OR FIELD-SYMBOL(*) in code, it means it is inline declaration. This is not supported by old syntax. So, I declared the field symbol and as it is a LOOP-AT, type of field symbol has to be a line of the table.
Old syntax equivalent is as below.
FIELD-SYMBOLS: <LS_DATA> LIKE LINE OF GT_DATA . LOOP AT GT_DATA ASSIGNING <LS_DATA>. * Code ENDLOOP. * ORR data: LS_DATA LIKE LINE OF GT_DATA . LOOP AT GT_DATA INTO LS_DATA. * Code ENDLOOP.
Same holds true for inline declaration of Data(*) in LOOP-AT statement.
2. Inline usage of Structure | NO-DECLRATION
IF <LS_DATA>-NUM IS NOT INITIAL. APPEND VALUE #( BUKRS = <LS_DATA>-BUK BELNR = <LS_DATA>-BEL GJAHR = <LS_DATA>-YR ) TO GT_DOC. ENDIF.
Here, no structure/ work area is declare to hold values. Instead, direct assignment and then append happens.
First of all, declare a work area of type GT_DOC.
DATA: LS_DOC LIKE LINE OF GT_DOC.
Then assign 3 variables from <ls_data> to new work area and append to the table.
IF <LS_DATA>-NUM IS NOT INITIAL. LS_DOC-BUKRS = <LS_DATA>-BUK. LS_DOC-BELNR = <LS_DATA>-BEL. LS_DOC-GJAHR = <LS_DATA>-YR. APPEND LS_DOC TO GT_DOC. ENDIF.
3. Filter Operator : an Equivalent of Conditional Move-corresponding.
New syntax looks like below. As the name suggests, Usage of Filter operator is to transfer records , for which the condition holds true, from one table to another
DATA(LT_DATA) = FILTER #( GT_DATA WHERE BUKRS = CONV #( CS_DATA-BUK ) AND BELNR = CONV #( CS_DATA-BEL ) AND GJAHR = CONV #( CS_DATA-YR ) ).
Initially, I suspected that it is move-corresponding operator for work area. But, I later found out that result is a subset table of GT_Data and “where” condition filters the result set.
So, Equivalent code would look like below.
DATA: LT_DATA LIKE GT_DATA. DATA: LS_DATA LIKE LINE OF GT_DATA. DATA:LS_BUKRS TYPE BUKRS, LS_BELNR TYPE BELNR, LS_GJAHR TYPE GJAHR. LS_BUKRS = CS_DATA-BUK. LS_BELNR = CS_DATA-BEL. LS_GJAHR = CS_DATA-YR. LOOP AT GT_DATA INTO LS_DATA WHERE BUKRS = LS_BUKRS AND BELNR = LS_BELNR AND GJAHR = LS_GJAHR. APPEND LS_DATA TO LT_DATA. ENDLOOP.
4. Reduce Operator : Loop-At statement with Aggregation
Usage of Reduce operator is to aggregate value of a particular column of an internal table.
in other words, it reduces a table to single variable by aggregating.
GS_DATA-TAX = REDUCE #( INIT LV_TAX TYPE BSET-HWSTE FOR LS_DATA IN LT_DATA NEXT LV_TAX = LV_TAX + COND # ( WHEN LS_DATA-SHKZG = CS_DATA-DEBIT THEN LS_DATA-HWSTE WHEN LS_DATA-SHKZG = CS_DATA-CREDIT THEN ( LS_DATA-HWSTE * -1 ) ) ).
In above scenario, Reduce operator loops over LT_DATA and cumulatively adds HWSTE value into LV_TAX and finally assigns to GS_DATA-TAX.
For this to work in old ABAP, it would require looping over an internal table, storing record in a work area and writing an IF-ELSE ladder.
DATA: LV_TAX TYPE BSET-HWSTE. DATA: LS_DATA LIKE LINE OF LT_DATA. LOOP AT LT_DATA INTO LS_DATA. IF LS_DATA-SHKZG = CS_DATA-DEBIT. LV_TAX = LV_TAX + LS_DATA-HWSTE. ELSEIF LS_DATA-SHKZG = CS_DATA-CREDIT. LV_TAX = LV_TAX + ( LS_DATA-HWSTE * -1 ). ENDIF. ENDLOOP. GS_DATA-TAX = LV_TAX.
5. GROUP BY on an Internal Table
New Syntax supports group by operator on an internal table while looping over it.
This makes code way easier when dealing with single internal table containing both Header and Item level data.
Group-by table <LT_GRP>, which is reference to original table GT_TABLE, contains item level data of a particular header. ( Grouped by 3 parameters in below example )
LOOP AT GT_DATA INTO LS_DATA WHERE VAR1 = ABAP_TRUE AND VAR2 IS NOT INITIAL GROUP BY ( BUKRS = LS_DATA-BUKRS BELNR = LS_DATA-BELNR GJHAR = LS_DATA-GJHAR INDEX = GROUP INDEX ) ASCENDING ASSIGNING FIELD-SYMBOL(<LT_GRP>). * Code LOOP AT GROUP <LT_GRP> ASSIGNING FIELD-SYMBOL(<LS_GRP_DATA>). * Code ENDLOOP. * Code ENDLOOP.
I found this one really complex to solve.
Old syntax does not support Group-by on an internal table. So I had to find a solution for GROUP-BY.
Create a copy-table of the given table and use it is header table, while GT_TABLE would work as Item table.
I used field symbol for looping over item table, so I would be able to make changes in the GT_TABLE itself.
FIELD-SYMBOL: <LS_GRP_DATA> LIKE LINE OF GT_DATA. DATA: GT_HEADER_DATA LIKE GT_DATA. GT_HEADER_DATA = GT_DATA. SORT GT_HEADER_DATA BY BUKRS BELNR GJHAR. DELETE ADJECENT DUPLICATES FROM GT_HEADER_DATA COMPARING BUKRS BELNR GJHAR. LOOP AT GT_HEADER_DATA INTO LS_DATA WHERE VAR1 = ABAP_TRUE AND VAR2 IS NOT INITIAL. * Code LOOP AT GT_DATA ASSIGNING <LS_GRP_DATA> WHERE VAR1 = ABAP_TRUE AND VAR2 IS NOT INITIAL AND BUKRS = LS_DATA-BUKRS AND BELNR = LS_DATA-BELNR AND GJHAR = LS_DATA-GJHAR. * Code ENDLOOP. * Code ENDLOOP.
There could be many equivalent or better code remediation to GROUP BY or FILTER operators. Feel free to share your comments.
Thank you for reading this entire blog, I think this blog must have helpful to those who haven’t used ABAP 7.4 or want to migrate code to the latest syntax. This blog covered few of the challenges I faced while converting the syntax constructs such as Inline declaration, direct usage of work-area without any declaration, group-by and Filter.
I converted all the constructs of new syntax ABAP 7.4 while dealing with the client with lower version of ECC. Remaining others are VALUE , BASE, table indexing, Conditional Indexing, Advanced OSQL and many more. I will include them in my next blog.
This post is very helpful for me as I got all the old syntax to new syntax in 1 page.
Appreciate your Efforts Bro.
In Eclipse, Ctrl-1 on a variable (or field-symbol) defined inline has an option that will declare it explicitly.
For group by, did you consider using the AT NEW construct?
For reduce, I'd create a class.
For VALUE, I'd replace it with a method call, encaspulating the work area - in this way you retain some of the compactness of the VALUE statement.
Note, I use insert rather than append. This is so that if you change the table type to SORTED or HASHED, you don't have to change your code.
Very useful ! Thanks for sharing