Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Recently, I received a request to create a report structured in an ALV Tree. I'm a fairly novice ABAP developer and this was the first time I had to create something of this nature. Along the way, I bumped into a few pain points for which information is either scarce or non-existent. Now, I feel compelled to share what I learned in the process - maybe this will help someone else in the future.

First off, I created my program using ABAP's class cl_gui_alv_tree. There's a series of great sample programs that will help you get started in no time, they cover pretty much everything you'll ever need with this class. All of them seem to start with bcalv_tree_## (where ## is replaced by numbers or words, e.g. bcalv_tree_01) so you can always search for that term and see what comes up. A somewhat comprehensive list can be found here: Abap ALV Tree - A Complete Example Code. The basics are covered by the "01" through "06" programs of that family and they are thoroughly documented, so pay attention to the comments.

When you're creating a tree, it's essential to have some kind of structure sorted the way you will be presenting the ALV. Personally, I think this is not trivial as it will either make your job a lot easier or a lot harder. My choice was to use a flat table with all the data I needed there, plus a explicit column to define it's hierarchy level and the row's node ID (the way I did it, each row defined a node). You can also use deep structures to store and handle your data, I didn't go this way so I could minimize the number of loops in my code - this came at the expense of larger tables, but it also allowed me to create simpler methods.

The code samples provided will show some hard-coding but that's just for clarity, that's a practice you should avoid.

On to the issues I faced: expanding an ALV tree and coloring specific ALV tree cells.

Problem #1: Automatically expanding the entire ALV tree.

Sadly, there's no easy out-of-the-box way to do this (or at least I couldn't find any) so I had to research this quite a bit. The cl_gui_tree has two methods related to this task (EXPAND_NODE and EXPAND_NODES) but neither expands the whole tree, so how do we solve this? First, you need the node key assigned by the ADD_NODE method to each of your nodes (I added a column to my source table where I kept that ID, so it made things easier); with that, I proceeded to create this method:

  METHOD me_expand_tree.

    DATA: w_node_key TYPE lvc_nkey,

       it_keys    TYPE lvc_t_nkey.

    FIELD-SYMBOLS <fs_data> TYPE y_data.

    LOOP AT it_data

      ASSIGNING <fs_data>.

      CLEAR w_node_key.

*"Check if the current node has children

      CALL METHOD ob_alv_tree->get_first_child

        EXPORTING

          i_node_key       = <fs_data>-node_key

        IMPORTING

          e_child_node_key = w_node_key.

*"If there are, append parent's key to table

      IF w_node_key IS NOT INITIAL.

        APPEND <fs_data>-node_key TO it_keys.

      ENDIF.

    ENDLOOP.

  UNASSIGN <fs_data>.

*"Expand ALV tree

    CALL METHOD io_alv_tree->expand_nodes( it_node_key = it_keys ).

  ENDMETHOD.

To save some space, I didn't add the exception handling portion of the methods called here to but you should, otherwise your program will be vulnerable to runtime errors.

What this method does is go through the ALV data and check each node to verify if it has children. Check that by using the GET_FIRST_CHILD method. Caveat: use a variable to store the returned child node key and then check if that variable is empty (filled = there are children, empty = there aren't), sy-subrc won't help here since it will show 1 whether the node has children or not.

For the ones that do have at least one child, their node key should be added to the it_keys table and then sent to the EXPAND_NODES method. It's extremely important to guarantee that a particular node has leafs, if it doesn't and you pass it to the class' method to be expanded, your program will trigger a short dump when the tree is sent to the front end:

This was a particularly cumbersome error as it wasn't triggered directly by my code, everything went through "fine"... I suspected an issue with the nodes with no children and researched in that direction, fortunately, another forum user also encountered the same problem and documented it here: My favourite cryptic ST22 dumps around CL_GUI_ALV_TREE.

The method I provided can be adjusted to expand only a specific level (or levels) of your tree. Since you define the hierarchy yourself, then you will know which nodes you want to get expanded.

There's one "bug" I haven't quite fixed yet: when you expand the tree, your container will navigate to the end of the tree, so your user will need to scroll back to the top manually. If I get a fix, I will update this post.

Problem #2: Coloring specific ALV tree cells (single cells, not entire rows).

Now, this one really didn't have an answer, I found tons of posts asking the same question but every answer was people either talking about the ALV grid or flat out saying it couldn't be done. Luckily, another dev dropped a hint right here Coloring of ROWS in ALV tree which pointed to a sample program from the family I mentioned above, it's the bcalv_tree_itemlayout.

That program allows the user to manually colorize a particular cell, but I needed that to happen automatically depending on the values of the cell in question. So how did I do it? With this method:

  METHOD me_colorize.

    DATA: it_color TYPE lvc_t_laci

      e_color  TYPE lvc_s_laci.

    FIELD-SYMBOLS <fs_data> TYPE y_data.

    LOOP AT it_data

      ASSIGNING <fs_data>.


*"Condition 1 to be checked for <fs_data>

      IF condition_1.

*"Set cell color as GREEN

        MOVE: field_name  TO e_color-fieldname,

                    6                          TO e_color-style,

        'X'        TO e_color-u_style.


*"Condition 2 to be checked for <fs_data>

      ELSEIF condition_2.

*"Set cell color as ORANGE

        MOVE: field_name TO e_color-fieldname,

                   10                       TO e_color-style,

        'X'         TO e_color-u_style.


*"All other cases

      ELSE.

*"Set cell color as RED

        MOVE: field_name TO e_color-fieldname,

                    5                        TO e_color-style,

        'X'         TO e_color-u_style.

      ENDIF.

      APPEND e_color TO it_color.

*"Modify node

      CALL METHOD ob_alv_tree->change_node

        EXPORTING

          i_node_key     = <fs_data>-node_key

          i_outtab_line  = <fs_data>

          it_item_layout = it_color.

      FREE: ce_color,

       it_color.

    ENDLOOP.

  ENDMETHOD.

Again, remember to add the exception handling portion for the methods you call.

The magic here happens thanks to the CHANGE_NODE method. It needs the node key, the line where your data is and the color parameters (which include the specific structure component to be colored, defined above by field_name). Once you provide all that information, a single cell will be granted the color you chose.

I think it's possible to add the color when you initially create the node with the ADD_NODE method, since it also has a parameter for it_item_layout, I didn't do it that way because of the particularities of my requirement.

Though there's no info about possible color codes you can use (or at least none that I could find - all I got was for the ALV grid and the ones for the tree are different) feel free to experiment, that's how I landed on the colors I needed.

There you go, those two things are pretty simple once you know how to get them done, but the getting there was quite difficult and required a bunch of research time, which I hope this post saves you :smile: .

16 Comments