ABAP Implicit Work Areas
This blog is intended for newer developers who might not have been exposed to the implicit work area concept in their initial training. Most of these implicit work area constructs are obsolete for general programming use and typically are forbidden syntax within ABAP Objects classes. All of this information is contained in the Online Help, but is sometimes obscured by newer syntax additions.
The ABAP Language has been around since 1983, and one of its interesting traits is that code written “back in the day” will still execute now. This backwards compatibility means we get newer, more powerful syntax elements because we don’t have to rewrite applications every time new syntax appears. But it also means there is some really old, odd-looking code still out there. We developers will run across some of these constructs when debugging. My intent is to shed some light on what these constructs are and what they do.
Way back in the 1980’s and early 1990’s, internal tables were declared using the OCCURS clause. A typical internal table definition looked like this:
DATA: BEGIN OF itab1 OCCURS 0, carrid TYPE sflight-carrid, connid TYPE sflight-connid, fldate TYPE sflight-fldate. DATA: END OF itab1.
The OCCURS clause was used to declare this structure as an internal table. The same definition without the OCCURS clause defines a structure. The number following the word OCCURS was used to declare the initial memory size of the internal table. The default value of zero was, in practice, used almost universally by ABAP developers.
The OCCURS clause also created a “HEADER LINE”, an implicit work area for the internal table. This work area created a structure in memory with the same name, row type and technical characteristics as the ITAB definition. Because of this, the ITAB was accessed without referencing a target structure:
LOOP AT itab1. WRITE: / itab1-carrid, itab1-connid, itab1-fldate. ENDLOOP.
Here, the LOOP AT is referencing each ITAB row in turn and placing that single row into the implicit work area. Since the OCCURS created the work area with the same name as the ITAB, the WRITE statements are referencing the work area fields, NOT the internal table fields. Needless to say, this can lead to confusion when we see this construct today!
Later on, ABAP was changed to allow us to reference structures when defining ITABs:
DATA: new_itab TYPE sflight OCCURS 0 WITH HEADER LINE.
This construct built an ITAB and the “WITH HEADER LINE” extension created an implicit work area.
Another place where we find an implicit work area is with SELECT-OPTIONS and RANGE tables.
The SELECT-OPTIONS keyword is still a vital part of ABAP and it manages a lot of things for us. It creates the familiar user interface that allows single or multiple selections, ranges, and wildcard searches to be used in SELECT statements and other conditionals (SELECT FROM <table name> WHERE <field name> IN <select-option name>).
It also creates an ITAB in memory. This ITAB contains four fields named SIGN, OPTION, LOW and HIGH:
In addition, the SELECT-OPTIONS keyword also builds an implicit work area for the ITAB:
Not only does the SELECT statement access this ITAB, we as developers can access this ITAB for our own purposes. To do this we need to distinguish between the body of the ITAB and the implicit work area.
In figure 2, note the debugger shows the table name SO_CARR is suffixed with brackets, versus Figure 3. The brackets indicate that we are looking at the body of the internal table; without brackets, we are looking at the implicit work area.
This is not unique to SELECT-OPTIONS; any of the above internal tables with an implicit work area uses brackets to reference the body of the ITAB and no brackets to reference a structure. An example is:
IF so_carr IS NOT INITIAL.
This would check to see if the body ITAB is empty or if it contains values. In this particular example, we are looking at the user interface SO_CARR, and we can determine whether or not the user entered any values in the SELECT-OPTION for this field. This would be helpful if we need to edit those values before we perform the SQL SELECT statement (to constrain the search for performance reasons, for example).
The obsolete RANGES keyword operates in the same manner, but does not create a user interface. Since there is no user interface, we need to add entries programmatically.
rg_date-sign = 'I'. rg_date-option = 'EQ'. rg_date-low = sy-datum. APPEND rg_date TO rg_date.
Note that we are APPENDing the implicit work area (no brackets) to the ITAB body (with brackets).
We could also get fancy and do something like this:
rg_date = 'IBT2019010120190228'. APPEND rg_date TO rg_date.
This would make the complete row entry in two commands.
The result of the two APPENDs would be:
Now we can use this ITAB in a conditional or an SQL statement.
One last implicit work area is the TABLES statement. The TABLES statement comes in three flavors, but only the first is still legitimate syntax
The first flavor is only for module pool programming and is the only legitimate use of TABLES in new code. Here, the TABLES statement is used as a communication path to pass data from the ABAP variables to the screen fields (this is an over-simplification; see the online help for details).
The second flavor uses the TABLES statement as a target work area for an SQL SELECT:
TABLES: sflight. SELECT * FROM sflight. WRITE: / sflight-carrid, sflight-connid, sflight-fldate. ENDSELECT.
This syntax is copying each row of the database table SFLIGHT into the implicit work area SFLIGHT in our program’s memory, then writing three fields from that implicit work area. Today, we would explicitly code a target in the SQL SELECT statement.
The third flavor is:
This allowed a developer to have two work areas for the same table. This was used often in update programs to hold the original values of a record being changed. A different use was “what-if” processing, where two different versions of a record could be held to compare before and after values. Today, we would create two identical structures with separate names.
I hope this sheds some light on an obscure (but important) point and that you will find it helpful the next time you are debugging some ancient code!
Nice blog post, Loyd.
I still can see mates still using these constructions (which sometimes drives me mad) and it's incredible how there are still people for who is hard to understand the concept of the header line.
Nostalgia is good but I prefer to use modern sentences anyhow.
In my experience I find that 90-95% of ABAP programmers not only understand the concept of header lines in internal tables but still use them in the new code they write every day.
I wish that was not true, but it is.
Are you sure ??
The majority of companies I go to explicitly specify that tables with header lines are NOT to be used in their programming spec.
It may vary from country to country but I stand my statement, based on what I see.
Header lines are still all over the place and being used in new code.
Consider that ABAP OO came out with 4.6C in the year 2000 and at that point people should have started migrating to methods over FORM routines and then the header line problem would go away forever.
Almost 20 years on and people are still using FORM routines as a matter of course - hence the need for a rule to not use a header line - with no sign of stopping. It does not help that people still look to standard SAP code as an example of what to do, and for historical reasons that is riddled with header lines.
It is in fact even worse. To this day still some ABAP programmers do not even use procedural programming, no FORM routines, just all the code in a huge blob after START-OF-SELECTION.
I must admit that I have never seen monolithic programming like you mention. You're right about FORM's though but until that is enforced it won't happen. The place where I am currently working does enforce that though and everything must be in classes.
I saw some code recently that was "developed" in October 2018. It does have a FORM that contains over 4000 lines of code.
And it's badly written. I suggested to the powers that be that it never sees the light of day.
Maybe not 90% but probably a good half. It seems to be an uphill battle. ABAP guideline says one thing but then people find ways to ignore it. I believe 100% compliance is achieved only when management is 100% on board with it and anyone who can't agree just has to be removed from the team (and same applies to any external consultants). This is easier said than done, unfortunately.
Also it's not just the old foggies who are doing this. I've seen some developers in their early 30s that must have had no more than 2 years of ABAP experience writing such code. Someone must have told them this is the right way in ABAP and they just went with it. And I agree that large amounts of old-fashioned code in SAP standard are not helping.
Good blog Loyd, informative.
You could add the infotypes statement which also creates an internal table with header line.
It is especially worth mentioning the *SFLIGHT flavour i've had numerous consultant who were bewildered when they encountered it in SAP standard.
Kind regards, Rob Dielemans
Rob, I totally forgot about infotypes 🙁 That is my error and I appreciate you correcting my omission and adding infotypes to the discussion!
Nice overview of this topic.
I'm happy that SAP made the decision, that for ABAP Objects it's forbidden. Still lot of SAP standard code or all legacy z-code is full of this prehistoric syntax 🙁
BTW you could also use instead of this
the new ABAP syntax (if you are already in 7.50 system):
Thanks, Peter. I know there is a whole world of new syntax being discussed in these forums, but I have no personal experience with those versions.
And I appreciate you taking the time to add your knowledge to the discussion!
It's easy to shock new or old programmers on how SAP views implicit work areas today, if you show them SLIN and explicitly check for "obsolete statements"....specially if you apply to a program they know works properly (evil face).