CL_SALV_TREE is a very useful class to print information on the output screen in the form of a tree.
We can view similar kind of information grouped under nodes and can have option to have limited or full access to them.
The tabular view enables us to navigate through the data in an informative kind of way.
In this blog, we shall discuss about many small useful events for the CL_SALV_TREE and also some tricks to use them for our own desired functionalities such as Sorting, Filtering and Deleting and most importantly, REFRESH.
We would try to populate the data dynamically on to the CL_SALV_TREE which makes it more interesting!
Here we shall use our program to generate a tree which can be used as a directory explorer similar to that of AL11 transaction.
Looks impressive, doesn’t it?
Well, its very simple.
I have used two main function modules to fetch the directory and file data :
You need to filter the directories from the files and I have used my own made logic for that.
Now, for the initial display, we need to display an empty table of the same type of the table that we want to have in the output.
Now, we need to add the parent node, which is the root directory( p_file )
lo_nodes = go_tree->get_nodes( ). lv_text = CONV #( p_file ). TRY. *--- Add the root node lo_node = lo_nodes->add_node( related_node = ' ' relationship = cl_salv_nodes=>if_salv_c_node_relation~parent text = lv_text visible = abap_true expander = abap_true folder = abap_true ). CATCH cx_salv_msg. " MESSAGE s001(icl) WITH lv_text. ENDTRY.
Now, we will set the screen PF STATUS
*--- Set PF status Adding all the functions required go_tree->set_screen_status( EXPORTING report = sy-repid " ABAP Program: Current Master Program pfstatus = 'PF_STATUS' " Screens, Current GUI Status set_functions = go_tree->c_functions_all " ALV: Data Element for Constants ).
Now comes the interesting part of dynamically populating the data on to the SALV Tree Structure.
We would use an OOPS approach to the program for the functionality and use several events for the same.
Now we would assign each method for event handling on the SALV_TREE.
Now we would trigger the empty expand node event so as to populate the data under the node.
TRY. lo_nodes = go_tree->get_nodes( ). lo_node = lo_nodes->get_node( node_key = node_key ). CATCH cx_salv_msg. FREE : lo_nodes,lo_node. ENDTRY. ls_datarow = lo_node->get_data_row( ). ASSIGN ls_datarow->* TO <lfs_rowdata>. *--- If the root node is clicked then the address comes from the parameters IF <lfs_rowdata>-address IS NOT INITIAL. lv_file = <lfs_rowdata>-address. ELSE. lv_file = p_file. ENDIF. me->md_directory_open( iv_file = lv_file ). me->md_create_node( iv_key = node_key ).
The directory open method contains the two methods to populate the data in the internal table.
Now we will populate the nodes dynamically using the create node method.
*--- Create the sub nodes after expansion LOOP AT lt_main INTO ls_main. *--- Differentiate the files from the folders IF ls_main-filtyp = TEXT-003. lv_text = ls_main-name. TRY. lo_node = lo_nodes->add_node( related_node = lv_key relationship = cl_gui_column_tree=>relat_last_child data_row = ls_main text = lv_text visible = abap_true expander = 'X' folder = 'X' ). CATCH cx_salv_msg. " FREE lo_node. ENDTRY. ELSE. lv_text = ls_main-name. TRY. lo_node = lo_nodes->add_node( related_node = lv_key relationship = cl_gui_column_tree=>relat_last_child data_row = ls_main text = lv_text visible = abap_true expander = ' ' folder = ' ' ). CATCH cx_salv_msg. " FREE lo_node. ENDTRY. ENDIF. ENDLOOP.
This will complete the preliminary directory explorer using CL_SALV_TREE.
Now, we will explore more about the events and their usefulness.
ON_EXPAND_EMPTY : – This method will allow us to populate the nodes whenever an empty node is expanded and thus saving the data under that node.
ON_USER_COMMAND : – This event will handle all the functions that set the value of sy-ucomm in the output screen.
I have used this method to trigger the buttons put in the PF_STATUS of the SALV_TREE.
Now to the more interesting tricks for salv : –
1 . SORTING
I have implemented the function of sorting the elements under a selected folder in the following way : –
TRY. lo_sels = go_tree->get_selections( ). lo_item = lo_sels->get_selected_item( ). IF lo_item IS NOT INITIAL. lo_node_parent = lo_item->get_node( ). lo_key = lo_node_parent->get_key( ). lt_childr = lo_node_parent->get_children( ). ELSE. MESSAGE i303(42). ENDIF. *--- Getting the childrens of the selected node and then deleting them and creating them again with the sorted data LOOP AT lt_childr ASSIGNING <ls_childr>. ls_datarow = <ls_childr>-node->get_data_row( ). <ls_childr>-node->delete( ). ASSIGN ls_datarow->* TO <lfs_rowdata>. APPEND <lfs_rowdata> TO lt_main. ENDLOOP. CATCH cx_salv_msg. FREE <ls_childr>. ENDTRY. me->md_create_node( iv_key = lo_key ).
I have used the following logic to filter the elements under a particular node. You can filter the last expanded node too which shall be discussed later.
TRY. lo_sels = go_tree->get_selections( ). lo_item = lo_sels->get_selected_item( ). IF lo_item IS NOT INITIAL. lo_node_parent = lo_item->get_node( ). lt_childr = lo_node_parent->get_children( ). ELSE. MESSAGE i303(42). ENDIF. LOOP AT lt_childr ASSIGNING <ls_childr>. ls_datarow = <ls_childr>-node->get_data_row( ). ASSIGN ls_datarow->* TO <lfs_rowdata>. IF <lfs_rowdata>-name NP iv_filters. <ls_childr>-node->delete( ). ENDIF. ENDLOOP. CATCH cx_salv_msg. FREE lo_nodes. ENDTRY.
This is the most easiest one!
TRY. lo_nodes = go_tree->get_nodes( ). lo_nodes->delete_all( ). CATCH cx_salv_error. FREE lo_nodes. ENDTRY. me->md_display_initial( ).
The display initial method again initializes the SALV with an empty tree and repeats the whole processing and returns the tree to its initial state.
I have implemented many more functionalities and will be sharing them in the future.
Hope this helps 🙂