Tuesday
Hi Experts,
I found some codes and wondered which is best?
1. I read before during in earlier ECC to avoid this because of headerline being obsolete in the future.
loop at s_bukrs into data(lwa_bukrs).
append lwa_bukrs-low to gt_bukrs.
endloop.
"Compared to:
gt_bukrs[] = s_bukrs[].2. Similar to above, I still some people use the longer method compare to the shorter below:
loop at <fs_bukrs> assigning <fs_range>
append value#(
sign = <fs_range>-sign
option = <fs_range>-option
low = <fs_range>-low
high = <fs_range>-high
)
to r_bukrs.
endloop.
r_bukrs[] = <fs_bukrs>[].3. Then found this one:
gt_bukrs = VALUE #( FOR lwa_bukrs IN s_bukrs ( lwa_bukrs-low ) ).
"Below is shorter...
gt_bukrs[] = s_bukrs[].In no. 3, why do we still use for if line 5 is shorter?
Appreciate your feedback on these samples.
Thank you.
Geoff
yesterday
@jeff_broodwar for sample 2, if <fs_bukrs> and r_bukrs are both ranges of BUKRS, as the loop suggests, yes, row 11 is the one I would use. "Always" needs two conditions, though.
First, row 11 replaces and the loop adds. APPEND keeps what was already in r_bukrs, and the assignment deletes it first. The ABAP documentation of the conversion rules for internal tables says it directly: "When assigning an internal table to another, the lines of the target table are deleted." If r_bukrs is empty at that point, there is no difference. If you collect values from more than one place, you need to add, and then APPEND LINES OF <fs_bukrs> TO r_bukrs does in one line what rows 1 to 9 do.
Second, the line types must be the same. Row 11 doesn't look at the component names. I tried a range of BUKRS into a range of KUNNR in my S/4HANA 2023 lab, and the syntax check gives 0 errors and 0 warnings. But the row is moved as one block of characters, by position. Reading the conversion rule for flat structures, an interval 1000 to 1999 would arrive with LOW = 10001999 and an empty HIGH. The loop with VALUE #, or CORRESPONDING #( ) as ERPClimb showed, go by name and don't have this problem. For this part I only did the syntax check, I didn't run it.
So my rule of thumb: same type and you want to replace, row 11. Same type and you want to add, APPEND LINES OF. Different types, CORRESPONDING.
Tuesday
In number 3 the short and long line are not doing the same thing.
You should also show us the definition of all the ranges and tables. Then we will be able to answer.
Tuesday
I see it the same way, asuming that the tabels are of type RANGE
the LONG version is only moving the field LOW,
while the short version in 3 is moving all columns.
If you want to move all, then use the short version in 3, as this is the most readable coding then
Tuesday
Hello,
Please see below:
data: gv_bukrs type bukrs.
data: gt_bukrs type range of bukrs.
select-options: s_bukrs for gv_bukrs.
Tuesday
Tuesday - last edited Tuesday
In my system syntax 1 and 3 are nonsens.
Look at this test program (your example 1)
result:
As you can see if the GT_BUKRS is a range of bukrs, then the code appending s_bukrs-low to gt_bukrs is nonsens.
Tuesday
In general I will always use the short version as long as it remains readable. Too many nested short notations can sometimes make the code hard to understand.
Performance is usually the same or very similar while readability improves.
Tuesday
Tt's personal taste: I use INTO when I want not to modify data, and ASSIGNING when I want... it helps (me) no know if the LOOP will change data or will not with just a glance.
The rest, is everythingn about readability: if you are not comfy with the new syntax, you can try hard to become, or just ignore them. I'm just getting used to most of the new syntax and decided to ignore some of them (like that FOR you've put in the third sample).
About the new options: if the tables are not identical, you can use CORRESPONDING to copy them without FORs.
Tuesday
Hi,
Good question. These samples look like they do the same thing, but they don’t, and that difference is the real answer here.
On your first point, the header line concern is about declaring your own tables WITH HEADER LINE. A select-option always comes with a header line, so writing s_bukrs[] is perfectly fine. That’s just how you address its body.
The catch is that gt_bukrs[] = s_bukrs[] is not the same as your loop. The loop picks only the LOW value, while the direct assignment copies the whole range row (SIGN, OPTION, LOW, HIGH). If gt_bukrs is a simple table of BUKRS, it still compiles without complaint, but you end up with values like IEQ1 instead of 1000. No error, no dump, just wrong data. I’ve seen this one slip through in real projects.
That’s also why sample 3 uses FOR even though line 5 is shorter. They give different results. The FOR builds a list of company codes; line 5 copies the range itself. The FOR is really the modern version of your first loop, not a longer way of writing line 5.
For sample 2, if both sides are ranges of the same type, just use the one-liner:
r_bukrs = s_bukrs[].The longer mapping only makes sense when the types differ. Even then, this is cleaner and safer:
r_bukrs = CORRESPONDING #( s_bukrs[] ).One more thing worth thinking about: picking only LOW from a select-option can quietly go wrong. If a user enters a range like 1000 to 1999, an exclusion, or a pattern like 1*, you lose all of that. If the field is left empty, IN means “all”, but your list ends up empty.
So in most cases I’d just keep the range and use it directly:
SELECT ... FROM bkpf
WHERE bukrs IN @s_bukrs
INTO TABLE @DATA(lt_bkpf).And if you really need an actual list of company codes, let the database resolve it:
SELECT bukrs FROM t001
WHERE bukrs IN @s_bukrs
INTO TABLE @DATA(gt_bukrs).The FOR approach is fine only when your selection screen allows single values and nothing else.
Hope that clears it up.
Regards,
ERPClimb
Tuesday - last edited Tuesday
Hi @jeff_broodwar,
Thanks for the mention. The others already showed that the short and the long lines do different things. One part is still open: why the [] is there at all.
SELECT-OPTIONS s_bukrs creates a table with a header line: two data objects with the same name, the table body and one work area. Your gt_bukrs (TYPE RANGE OF bukrs) has no header line. The ABAP Keyword Documentation (Internal Tables with a Header Line) gives the rule:
s_bukrs alone is the header line (one row). s_bukrs[] is the table.s_bukrs is already the table: LOOP AT s_bukrs, and after FOR ... IN.[] is allowed but changes nothing. A field symbol also points to only one of the two, so <fs_bukrs>[] is the same as <fs_bukrs>.So with your declarations:
gt_bukrs = s_bukrs[]. "[] only because s_bukrs has a header line
LOOP AT s_bukrs INTO DATA(ls_bukrs). "here s_bukrs is already the tableThat is why sample 3 needs no [] after IN s_bukrs, and why gt_bukrs[] = and r_bukrs[] = are the same as gt_bukrs = and r_bukrs =.
About taking only LOW (samples 1 and 3): with a range as target it gives wrong rows, as TMNielsen showed. Even into a plain TABLE OF bukrs it changes the selection: intervals (BT), excludes (E) and patterns (CP) are lost. And an empty select-option means "all": the documentation of IN range_tab says "If the ranges table is initial, the expression IN range_tab is always true". A list of LOW values from an empty select-option is just an empty list.
What I do is keep the range and use it directly in the WHERE (WHERE bukrs IN @s_bukrs). When I really need the single values, I let the database resolve the range against T001:
SELECT bukrs FROM t001 WHERE bukrs IN @s_bukrs INTO TABLE @DATA(lt_bukrs).
Wednesday
Hi Everyone,
Thank you for all your inputs, I agree to passing -low only will make data inconcistency.
Moreover, in 2nd example is it always safe to say that row 11 is the best option instead of rows 1-9?
Thank you,
Geoff
yesterday
@jeff_broodwar for sample 2, if <fs_bukrs> and r_bukrs are both ranges of BUKRS, as the loop suggests, yes, row 11 is the one I would use. "Always" needs two conditions, though.
First, row 11 replaces and the loop adds. APPEND keeps what was already in r_bukrs, and the assignment deletes it first. The ABAP documentation of the conversion rules for internal tables says it directly: "When assigning an internal table to another, the lines of the target table are deleted." If r_bukrs is empty at that point, there is no difference. If you collect values from more than one place, you need to add, and then APPEND LINES OF <fs_bukrs> TO r_bukrs does in one line what rows 1 to 9 do.
Second, the line types must be the same. Row 11 doesn't look at the component names. I tried a range of BUKRS into a range of KUNNR in my S/4HANA 2023 lab, and the syntax check gives 0 errors and 0 warnings. But the row is moved as one block of characters, by position. Reading the conversion rule for flat structures, an interval 1000 to 1999 would arrive with LOW = 10001999 and an empty HIGH. The loop with VALUE #, or CORRESPONDING #( ) as ERPClimb showed, go by name and don't have this problem. For this part I only did the syntax check, I didn't run it.
So my rule of thumb: same type and you want to replace, row 11. Same type and you want to add, APPEND LINES OF. Different types, CORRESPONDING.
| User | Count |
|---|---|
| 19 | |
| 12 | |
| 8 | |
| 6 | |
| 4 | |
| 3 | |
| 2 | |
| 2 | |
| 2 | |
| 2 |