Recently i stumbled across a problem in the ALV Tree. When you refresh the Tree you are supposed to delete all nodes
CALL METHOD REF_TREE
->DELETE_ALL_NODES
.
and add the new Nodes after. The problem here is, that the Tree implementation does not reset the Node Key Counter. So when you had 248 Elements before the new Tree will start at Key 249(-1?).
The thing is, i wanted to have the same UI after the refresh, meaning all the expanded Nodes should be expanded again. You can read expanded Nodes with REF_TREE
->GET_EXPANDED_NODES but it will only give you a list of Keys, which are pretty worthless after the Refresh if you dont want to do complicated calculations, which might fail due to complexity.
You can later Expand the Nodes in the new tree with REF_TREE
->EXPAND_NODES. But now we need a connection between the old node keys and the new ones.
Given that you have an itab
it_data with unique keys that builds up the tree ist is possible by using that table and an extra itab
l_it_expanded with the same structure that holds the expanded data lines instead of only the node keys.
- First you read all the expanded nodes GET_EXPANDED_NODES
- Then you read the lines of your data structure into it_expanded using the node keys
- You need to save the Node Keys of the Tree in the it_data structure when you build it, so you can now find the corresponding line
- The mt_outtab of the tree would also work, but its protected in the class and i dont know how to access it. Comment if you know how
- You do your refresh now
- Your it_data contains the new data and the new nodekeys now.
- The l_it_expanded contains the old expanded data with the worthless node keys
- You can now read the new data itab using the real key tuple of your it_expanded
- Because you have the node keys saved inside the it_data after the read you kann append to a node key table to add all expanded
- Also you are able to react on changes like missing lines
- You can now use EXPAND_NODES with you node key table.
here is a code sample how i worked it out. It might be more difficult to read since we are using a framework between ALV Tree and our code.
"Tabelle für Expandierte Knoten
DATA: L_WA_OUTLINEOLD TYPE TP_T_TREE_TAB.
........
Inside a function for e.g. Text updates
"Speichern der Expandierten Knoten für Refresh
CLEAR L_WA_OUTLINEOLD.
PERFORM CUST_TREE_SAVE_EXPANDED CHANGING L_WA_OUTLINEOLD.
"Texte über Lagernummer ermitteln
PERFORM CUST_GET_TXTS_FOR_TRANSPORT USING C_WA_TREE_TAB-TKNUM.
"LayoutRefresh und Laden der Expandierten Knoten
PERFORM STD_REFRESH_SELECTION.
PERFORM CUST_TREE_EXPAND_SAVED_NODES USING L_WA_OUTLINEOLD.
The important functions here are:
*&---------------------------------------------------------------------*
*& Form CUST_TREE_SAVE_EXPANDED
*&---------------------------------------------------------------------*
* Ausgeklappte Knoten für den Refresh speichern
* Das Problem ist, dass ein Refresh alle Knoten löscht und neu
* anlegt aber die Schlüssel der Knoten einfach fortzählt.
* Deshalb sind die gespeicherten Schlüssel unbrauchbar und
* eine Verbindung muss über die Wertetupel des eigentlichen
* Tabelleninhalte geschaffen werden um die Zeilen nach dem
* neuaufbau wieder zu finden.
*----------------------------------------------------------------------*
* <--C_IT_OUTLINEOLD Tabelle mit den Realen ausgeklappten zeilen
*----------------------------------------------------------------------*
FORM CUST_TREE_SAVE_EXPANDED
CHANGING C_IT_OUTLINEOLD TYPE TP_T_TREE_TAB.
DATA: L_IT_NODES TYPE LVC_T_NKEY,
L_WA_NODE TYPE LVC_NKEY,
L_WA_OUTLINEOLD TYPE TP_TREE_TAB.
"Expandierte Knoten lesen
CALL METHOD REF_TREE->GET_EXPANDED_NODES
CHANGING
CT_EXPANDED_NODES = L_IT_NODES
EXCEPTIONS
CNTL_SYSTEM_ERROR = 1
DP_ERROR = 2
FAILED = 3
OTHERS = 4.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE 'S' NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4
DISPLAY LIKE SY-MSGTY.
ENDIF.
"Knoten in Inbhaltstabelle Übersetzen
LOOP AT L_IT_NODES INTO L_WA_NODE.
REF_TREE->GET_OUTTAB_LINE(
EXPORTING
I_NODE_KEY = L_WA_NODE " node key
IMPORTING
E_OUTTAB_LINE = L_WA_OUTLINEOLD
EXCEPTIONS
NODE_NOT_FOUND = 1
OTHERS = 2
).
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE 'S' NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4
DISPLAY LIKE SY-MSGTY.
ENDIF.
"Durch die Inhaltstabelle mit Wertetupeln wird der Bezug zu den
"neuen Knoten hergestellt
APPEND L_WA_OUTLINEOLD TO C_IT_OUTLINEOLD.
ENDLOOP.
ENDFORM. " CUST_TREE_SAVE_EXPANDED
*&---------------------------------------------------------------------*
*& Form CUST_TREE_EXPAND_SAVED_NODES
*&---------------------------------------------------------------------*
* Ausklappen der gespeicherten Tree Zeilen. Ausfühliche besch-
* reibung des Problem unter CUST_TREE_SAVE_EXPANDED.
*----------------------------------------------------------------------*
* -->F_IT_OUTLINEOLD Zeilen zum Ausklappen
*----------------------------------------------------------------------*
FORM CUST_TREE_EXPAND_SAVED_NODES
USING F_IT_OUTLINEOLD TYPE TP_T_TREE_TAB.
DATA: L_IT_NODES TYPE LVC_T_NKEY,
L_WA_NODE TYPE LVC_NKEY,
L_WA_OUTLINEOLD TYPE TP_TREE_TAB,
L_WA_TREETABNEW TYPE TP_TREE_TAB.
"Inhaltstabelle lesen und die neuen entsprechenden Knoten ausklappen
LOOP AT F_IT_OUTLINEOLD INTO L_WA_OUTLINEOLD.
READ TABLE IT_TREE_TAB
INTO L_WA_TREETABNEW
WITH KEY TKNUM = L_WA_OUTLINEOLD-TKNUM
VENUM = L_WA_OUTLINEOLD-VENUM
EXIDV = L_WA_OUTLINEOLD-EXIDV
LINETYPE = L_WA_OUTLINEOLD-LINETYPE.
IF SY-SUBRC = 0.
APPEND L_WA_TREETABNEW-NODE_KEY TO L_IT_NODES.
ENDIF.
ENDLOOP.
CALL METHOD REF_TREE->EXPAND_NODES
EXPORTING
IT_NODE_KEY = L_IT_NODES
EXCEPTIONS
FAILED = 1
CNTL_SYSTEM_ERROR = 2
ERROR_IN_NODE_KEY_TABLE = 3
DP_ERROR = 4
NODE_NOT_FOUND = 5
OTHERS = 6.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE 'S' NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4
DISPLAY LIKE SY-MSGTY.
ENDIF.
"Update der Darstellung
REF_TREE->FRONTEND_UPDATE( ).
ENDFORM. " CUST_TREE_EXPAND_SAVED_NODES
Feel free to comment, especially for better solutions for this problem. I need to add, since the framework is in between, we are not able to use other refresh functions, but i've heard that there is a different solution where you don't use DELETE_ALL_NODES but i think any solutions using the keys might be faulty due to possible changes in the structure resulting in wrong node keys for a line.