Skip to Content
Author's profile photo Timo John

How to fetch *nicely* 2 values from ITAB-Row?

I started this already via Twitter how to fetch or map two values from an internal table if you are not interested in the whole line

Input:     lt_vbpa   (just an internal table with some more columns )


target:     lv_kunn  (two fields to be filled … needed for next method or something.

               lv_land1

Of cause there are lots of solutions, we could make a list out of it, but key is to have FAST, short an understandable code

80s style:

Read Table lt_vbpa assigning <fs>  Key …

lv_kunnr = <fs>-kunnr.

lv_land1  = <fs>-land1.

New >7.40

lv_kunnr = lt_vbpa[ parvw = “WE” ]-kunnr

lv_land1  = lt_vbpa[ parvw = “WE” ]-land1

* but worse 2 read operations in ITAB performance issue in mass processing.

Via Twitter I did receive some Ideas:

New >7.40 feat. Uwe Fetzer

Read Table ltvbpa assigning <fs>  Key …

assign lt_vbpa[ parvw = “WE” ] to <fs>.

lv_kunnr = <fs>-kunnr.

lv_land1  = <fs>-land1.

* Nicer, one read on the itab only, but still tree lines of code

Solution by Enno Wulff

* Also nicer but quite some coding overhead… and again with the performance issue of two reads.

I still do not see a great Idea to do this in a nice way in two lines of code (pls. no #Macros, or two statemts in one line ideas …)

Thanks for the two of you for your Ideas!

Assigned Tags

      39 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      How about using a LET expression?

      3 lines of code, but still 1 expression. Does it give me the brownie points 😉

      TYPES:

        BEGIN OF ty_carrier_monthly_stats,

          total_price  TYPE sflight-price,

          avg_seatsocc TYPE sflight-seatsocc,

        END OF ty_carrier_monthly_stats.

      DATA(lv_date_begin) = sy-datum - 30.

      SELECT

          DISTINCT carrid AS carrier,

          SUM( price ) AS total_price,

          AVG( seatsocc ) AS avg_seats_occ

        FROM sflight

        INTO TABLE @DATA(carriers)

        WHERE fldate BETWEEN @lv_date_begin AND @sy-datum

        GROUP BY carrid

        ORDER BY carrier.

      cl_demo_output=>display(

          data = VALUE ty_carrier_monthly_stats(

                  LET lh = VALUE #( carriers[ carrier = 'LH' ] OPTIONAL ) IN

                  total_price  = lh-total_price

                  avg_seatsocc = lh-avg_seats_occ

                )    " Text  oder Daten

      ).

      PS - I cannot see the solution from Enno Wullf, maybe you should post the lines of code.

      Author's profile photo Timo John
      Timo John
      Blog Post Author

      I do not really see the advantage here, using the VALUE operator makes not really sense as I just want these two values... But for other questions it is nice code, wehre you have to get used to.

      Author's profile photo Former Member
      Former Member

      I just want these two values.

      TBH, my solution is similar to Enno Wulff's. Instead of using 2 separate variables, i have packed them as fields in a structure.

      Having said that my solution cannot be used anyway if you want 2 separate variable, because you cannot use VALUE operator to construct value of variables. 😐

      Author's profile photo Former Member
      Former Member

      I don't have any 7.4 system to try it, but cannot you use something like:

      DATA(ls_customer) = NEW ty_customer( CORRESPONDING #( lt_vbpa[ parvw = p_parvw ] MAPPING kunnr = kunnr land1 = land1 ).

      ?

      Author's profile photo Enno Wulff
      Enno Wulff

      Why do you insist of using two separate variables (lv_kunnr, lv_land1)??

      Adapt Uwes code with DATA instead of FIELD-SYMBOL and use the given structure:

      data(ls_vbpa) = lt_vbpa[ parvw = 'WE' ].

         write: / 'Customer:', ls_vbpa-kunnr,

                / 'Country: ', ls_vbpa-land1.

      Author's profile photo Sandra Rossi
      Sandra Rossi

      Is it really possible in another language to write it shorter? In ABAP, I really don't see how we could do it in less than 3 lines because we need to access the line of the internal table first, so that it can be used to setup the 2 fields.

      Author's profile photo Arseni Gallardo
      Arseni Gallardo

      types: BEGIN OF ty_needed_values,

                  kunnr type kunnr,

                  land1 type land1,

              END OF ty_needed_values.

      data: l_needed_values type ty_needed_values.

      Read Table lt_vbpa assigning <fs>  Key ...

      MOVE-CORRESPONDING <fs> TO l_:needed_values.

      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      The actual 80s style:

      READ itab INTO wa BINARY SEARCH.

      Not sure if it's just some kind of academic exercise, but IMHO in this odd quest to stuff as much code as possible in as few lines as possible we are starting to lose readability.

      Author's profile photo Loyd Enochs
      Loyd Enochs

      Jelena, I agree with you wholeheartedly.

      Certainly there is good reason to take advantage of new additions to the language when new functionality comes with it, but the headlong rush to adopt new syntax just because it is the bright shiney new thing is not merited.

      It should be remembered that OO was developed to be reusable and to allow the building of complex programs by assembling components, not writing from scratch.

      How much of THAT is happening these days outside of software houses like SAP??

      Code readability is already going extinct and we're heading back to the bad old days of trying to read assembly language code, IMHO.

      Author's profile photo Timo John
      Timo John
      Blog Post Author

      Hello, thank you for your comments. I see coding in such a N-Angle with the - sometimes - conflicting targets: - speed of development (e.g. write only code ) - maintainability      (e.g.: comments vs. whole history of 10 projects in code ) - readability          ( find the right spot in coding ) - reusability - execution time So I think it's good from time to time to think about coding style. Yes, I agree it's some kind of an academic discussion if you need 2 or 3 lines. In a Dynpro transaction I would go for the two lines approach, cause no body will notice the performance difference there. + read + maintain In mass processing of orders performance is key so the three lines version is best.

      Author's profile photo Former Member
      Former Member

      Hi Jelena,

      but IMHO in this odd quest to stuff as much code as possible in as few lines as possible we are starting to lose readability.

      Unfortunately i have to disagree on this one with you.

      I don't understand why is this piece of code

      data = VALUE ty_carrier_monthly_stats(

                       LET lh = VALUE #( carriers[ carrier = 'LH' ] OPTIONAL ) IN

                       total_price  = lh-total_price

                       avg_seatsocc = lh-avg_seats_occ

                )

      is deemed to be unreadable? 😕

      Tbh, i am often at cross-roads when to stop using functional expressions. Hence i often end up asking questions like this Cleaner syntax for filling up internal tables with VALUE?.

      BR,

      Suhas

      PS - It's kinda addictive when you start using the functional ABAP 😳

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      +1

      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      It's not that it's unreadable, it is not easily translated to plain English (which is understood by humans). E.g. when I see READ TABLE... INTO... I don't even need to reach for Help. In fact, I don't even need to know ABAP.

      But take the other example: "VALUE". Hm, so what am I doing here? Am I assigning value to something? Where is a verb? Oh, there it is - LET. Uhm, let what? Let there be light? What goes where here? And then there is another VALUE, two sets of parenthesis and square brackets, dear lord...

      It might be just a matter of what one is used to (e.g. when I was in University, Java did not exist and mainframes ruled the world) as such syntax is typical for languages like C & Co. But since ABAP is rather business oriented I came to appreciate that it can read like plain English. Even a functional consultant can look at ABAP code that we call "80s style" (e.g. in a short routine) and still understand what's going on in general. I doubt they'd have the same success with VALUE... LET. Not that we need to "dumb it down" intentionally but I hope you see the point.

      Author's profile photo Former Member
      Former Member

      Not that we need to "dumb it down" intentionally but I hope you see the point.

      ABAP used to be verbose, no denying the fact. If one wrote the ABAP statements with good in-source comments, one could in fact read the source code like a story.

      IMHO whether to use old, verbose ABAP syntax or the new, compact, geekier 😎 syntax is a matter of one's taste. Both the syntaxes will continue to co-exist in the ABAP ecosystem and the developer has to pick what suits his/her taste.

      Author's profile photo Loyd Enochs
      Loyd Enochs

      If one gets to pick.  More and more I see clients requiring "geeky" code, not because they are moving headlong into Webdynrpo or Fiori or mobility apps, but because it is "the new shiny thing" and someone's performance goal (and bonus) is to implement new shiny things.

      How much money are companies willing to spend on consultants to indulge their whims?

      Again, new for the sake of a noticable gain is wonderful.  New for the sake of novelty is not a sound business decision.

      Just my free opinion and worth everything you paid for it 😆 .

      Author's profile photo Custodio de Oliveira
      Custodio de Oliveira

      Sorry, never seen such thing. Actually, quite the opposite: customers often don't want "the new shiny thing", even when it's proved to be way better than the old thing, because they are afraid they will not have people who knows the new thing when they need to maintain it.

      just my free opinion/experience anyway 😉

      Author's profile photo Kiran K
      Kiran K

      "and someone's performance goal (and bonus) is to implement new shiny things"-


      Exactly.

      K.Kiran.

      Author's profile photo Former Member
      Former Member

      "and someone's performance goal (and bonus) is to implement new shiny things"

      And what about people who want to learn new things? Let's not generalize 😉

      Author's profile photo Kiran K
      Kiran K

      Agree 🙂

      Author's profile photo Paul Hardy
      Paul Hardy

      I think he is being sarcastic ... obviously that line of code is not readable by a human....

      This whole argument is crazy to me - surely success is judged not by how compact you can make your code, but rather by how easy it is for someone coming after you, or even yourself six months on, to be able to look at the code and know what is going on?

      To my mind the more the code reads like plain English (sorry non-English speakers) the closer you are to that goal. The more it reads like VALUE x LET y OPTIONAL z OPTIONAL z LET x = y the further you are away from that goal, even if such a statement does the same thing as twenty lines of readable code.

      Since 95% of development is changing and enhancing existing programs you have to be able to look at the code and work out what it does in a hurry. If you have to guess, something is seriously wrong.

      I thought the whole reason we used "fourth generation" languages as opposed to machine code was so that we could read the code?

      Author's profile photo Łukasz Pęgiel
      Łukasz Pęgiel

      Paul,

      if you're working with it daily, then it's readable. But that's sure that with new syntax you have to be careful not to do a mess, as then you'd probably need to put a huge comment to what you're doing inside such one very complex syntax. And in my opinion code should be self-explanatory.

      Cheers

      Author's profile photo Former Member
      Former Member

      I think he is being sarcastic ... obviously that line of code is not readable by a human....

      Hi Paul,

      No, i'm not.

      Never have i mentioned that expression-based ABAP is better than verbose ABAP.


      The trick is to strike the correct balance between the two. IMO what matters the most is that the code is clean and easy to understand.

      Let me take the liberty of adding to your statement,

      obviously that line of code is not readable by a human... who has not worked with expression-based ABAP

      BR,

      Suhas

      PS - For the scepticals please read the response from Horst Keller here How much ABAP740 (read: functional ABAP programming) is too much?

      Author's profile photo Paul Hardy
      Paul Hardy

      I don't actually think the argument is to do with expression based ABAP vs pre 7.40 ABAP, or even about ABAP at all, but rather programming languages in general.

      As Horst says there have been obscure and/or misleading statements in ABAP for a long while.

      I think we all want the same thing. Code where it is clear what is going on to anyone who looks at it, not just the programmers but anyone else who looks at it, and much as programmers may hate it, lots of other people, like business analysts, look at your code.

      Robert Martin spends a great deal of his time talking about this subject, even more important in the version of Java he was using at the time, which has far less key words than we are used to in ABAP world.

      To me, being able to understand a line of code, and that line of code being "readable" are two separate things.

      I could see a regular expression, and I know what it means, but I could not honestly describe it as "readable" in the same way something like "REPLACE ALL OCCURENCES OF '&V1' IN message_text WITH dynamic_value" would be readable because it looks almost like a normal sentence.

      I am able to read the new "exotic" ABAP commands with no problem at all, I have to concentrate a bit harder, but not the end of the world. However I cannot help but be reminded of a book on website design called "Don't Make Me Think".

      If a block of code is 10% of the size, but it takes you longer to work out what is happening than the equivalent full size block of readable code, how have you made life for your colleagues (and you) any better?

      This whole concept is fascinating to me, as you can tell, and since it is sort of off topic for this blog I will shortly write a blog of my own about this, presenting a whole bunch f examples and arguments which people can then shoot down in the comments.

      Cheersy Cheers

      Paul

      Author's profile photo Former Member
      Former Member

      This whole concept is fascinating to me, as you can tell, and since it is sort of off topic for this blog I will shortly write a blog of my own about this

      Now that you have mentioned it, eagerly waiting for the blog to be published 😀

      Author's profile photo Paul Hardy
      Paul Hardy
      Author's profile photo Horst Keller
      Horst Keller

      Another way around, also "English" ABAP has its problems.

      • Statement GET spfli. Do you understand from that what id does? (no, it does not get SPFLI ...)
      • Statement SET LANGUAGE, no it does not set the language ...
      • AT SELECTION-SCREEN OUTPUT, beware!
      • ...

      Shows a general problem of verbose statements. Same for variable names. Meanings may change but but the names stay.

      Author's profile photo Horst Keller
      Horst Keller

      PS: Here's another one.

      ... text+2(10) ...

      ... substring( val = text off = 2 len = 10 ) ...

      What is old what is new?

      What is understandable and what isn't 😉

      Author's profile photo Former Member
      Former Member

      Horst Keller wrote:

      What is understandable and what isn't 😉

      Schrödinger's ABAP-expression: Is it understandable or is it not? 😀

      Author's profile photo Horst Keller
      Horst Keller

      I have a PhD in physics, but I have to admit that I never fully understood that dang cat discussion ...

      Author's profile photo Former Member
      Former Member

      Hi Enno, Hi Uwe,

      In your solution(s) you missed the fact that the table expression can give a CX_SY_ITAB* exception if the line is not found. You have to either handle the exception or use the addition OPTIONAL/DEFAULT with the VALUE operator.

      BR,

      Suhas

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      Hi Suhas,

      Ok, if we want to be pedantic today 😉 : in the original example the IF <fs> IS ASSIGNED is missing...

      Author's profile photo Former Member
      Former Member

      if we want to be pedantic today

      Lol, of course not 🙂

      My poor colleagues have to face it everyday though. I drag up ABAP help at the drop of the hat.

      Author's profile photo Timo John
      Timo John
      Blog Post Author

      But to be honest we also have to check sy-subrc in the other way as well. Maybe I should take that into account in the statements. Cause I see an other advantage of the Uwe Fetzer solution:

      try

      *Business Code of interest...

      assign lt_vbpa[ parvw = "WE" ] to <fs>.

      lv_kunnr = <fs>-kunnr.

      lv_land1  = <fs>-land1.

      * more Business code ..

      catch CX_SY_ITAB* ...

      * Boring dump protection ...

      end try.

      you can have more clear separation of interesting and boring code:

      Compare 80ts stuff:

      Read Table lt_vbpa assigning <fs>  Key ...  "Business Code

      if sy-subrc <> 0.                                                      "Boring

        * Error handling                                                       "Boring

      end if.                                                                      "Boring

      lv_kunnr = <fs>-kunnr.                                          "Business Code

      lv_land1  = <fs>-land1.                                         "Business Code

      you mix things up which I think, create code that is hard to read.

      Author's profile photo Former Member
      Former Member

      If you use ASSIGN with table expressions CX_SY_ITAB* exception won't be raised. Instead SY-SUBRC is set to 4. (refer: table_exp - Table Expressions - ABAP Keyword Documentation)

      In fact, if you use ASSIGN-construct with table expression, the code will look similar to the READ TABLE

      ASSIGN itab[...] TO FIELD-SYMBOL(<wa>)

      IF sy-subrc = 0.

      ...

      ELSE.

      ...

      ENDIF.

      vs

      READ TABLE itab WITH KEY ... ASSIGNING FIELD-SYMBOL(<wa>)

      IF sy-subrc = 0.

      ...

      ELSE.

      ...

      ENDIF.

      Cause I see an other advantage of the Uwe Fetzer solution

      I don't quite understand the rationale, sorry! 😕

      Author's profile photo Juwin Pallipat Thomas
      Juwin Pallipat Thomas

      If you just need 2 fields returned back and not the whole line, you may use TRANSPORTING addition with READ statement:

      read table customers into data(customer) transporting kunnr land1 with key kunnr = 'ABCD'.


      Thanks,

      Juwin.

      Author's profile photo Łukasz Pęgiel
      Łukasz Pęgiel

      If we take the idea of Enno Wulff to use structure instead of two separate fields then it could be done in one shot:

          types: begin of ty_customer,

                   kunnr type vbpa-kunnr,

                   land1 type vbpa-land1,

                 end of ty_customer.

          data(lt_vbpa) = value vbpa_tab( 

                                           (  parvw = 'WE' kunnr = '111111' land1 = 'DE')

                                           (  parvw = 'AG' kunnr = '111111' land1 = 'DE')

                                         ).
      data(customer) = corresponding ty_customer( lt_vbpa[ parvw = 'WE' ] ).

      But with two separate fields I'd prefer assign lt_vbpa[ xx ] to field-symbol(<x>). solution.

      Author's profile photo Horst Keller
      Horst Keller

      I prefer the Fetzer way (well, the first line of it):

      assign lt_vbpa[ parvw = "WE" ] to FIELD-SYMBOL(<fs>).


      Jelena ( 😉 ) would write it as


      READ TABLE lt_vbpa WITH KEY parvw = "WE"  ASSIGNING FIELD-SYMBOL(<fs>).


      Both do exactly the same! ->Question of taste which to use (as Suhas said).


      You set a pointer to the table line.


      The field symbol is structured. No need to declare a special structure with the two components, or?


      Now you can simply use <fs>-kunnr and <fs>-land1 at any operand position.


      Normally no need for


      lv_kunnr = <fs>-kunnr.

      lv_land1  = <fs>-land1.


      (as long as you do not need to prevent overriding the values by write accesses).


      That's a bit the problem of this question "How to fetch nicely", as Sandra has pointed out already.

      Author's profile photo Jacques Nomssi Nzali
      Jacques Nomssi Nzali

      Hello Horst,

      can I propose extending the DEFAULT / OPTIONAL value specified within the construction operators VALUE or REF to the CORRESPONDING operator?

      This would enable code like:


      data(customer) = CORRESPONDING

                              ty_customer( lt_vbpa[ parvw = 'WE' ]  OPTIONAL ).

      best regards,

      JNN

      Author's profile photo Horst Keller
      Horst Keller

      Sure ...