Refresh ALV GRID and keep position and current cell – ABAP
When using the CL_GUI_ALV_GRID in edit mode or after changing the internal table, refreshing the grid with refresh_table_display may cause the cursor or scroll to reset, confusing the user. To avoid this, the following methods can help retain the scroll position and current cell:
get_scroll_info_via_id: Retrieve current scroll info. get_current_cell: Get the current cell to retain cursor position. get_selected_rows / get_selected_cells_id: Capture selected rows/cells. refresh_table_display: Refresh the grid. set_selected_cells_id / set_selected_rows: Restore selected rows/cells. set_scroll_info_via_id: Restore scroll position. set_current_cell_via_id: Set the cursor back.

CL_GUI_ALV_GRID
When you use CL_GUI_ALV_GRID in edit mode, or you change your internal table used to display data on ALV grid it may happen that after refreshing the grid using refresh_table_display your cursor or scroll goes to the beginning of the grid. User feels little lost in such situation, but there is an easy solution for that.
data: is_stable type lvc_s_stbl. is_stable-row = 'X'. is_stable-col = 'X'. "or is_stable = 'XX'. grid->refresh_table_display(   exporting     is_stable      =   is_stable   " With Stable Rows/Columns *    i_soft_refresh =   i_soft_refresh  " Without Sort, Filter, etc.   exceptions     finished       = 1     others         = 2 ). if sy-subrc <> 0. * message id sy-msgid type sy-msgty number sy-msgno *            with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. endif.
So to keep scroll position and current cell we will need to use  following methods of CL_GUI_ALV_GRID:
get_scroll_info_via_id
– gets current scroll informationget_current_cell
       – gets current cell, we will use that data to set the cursor at the endget_selected_rows
     – gets selected rowsget_selected_cells_id
 – if we didn’t select any rows, we check for the selected cell information>refresh_table_display
 – then simple refresh of gridset_selected_cells_id
  – after refresh it’s time to set back all information, so set selected cellset_selected_rows
     – or set selected rows (depending on what we received at the beginning)set_scroll_info_via_id
 – set scroll position backset_current_cell_via_id
– set cursor back.
There is no special coding here, just standard ALV
grid methods used in proper order.
Method definition, Importing parameters:
I_SOFTÂ TYPE CHAR01Â DEFAULT 'X'Â I_SET_CURRENTÂ TYPE CHAR01Â DEFAULT SPACEÂ I_SET_SELECTEDÂ TYPE CHAR01Â DEFAULT SPACE
Changing parameters:
GRIDÂ TYPE REF TO CL_GUI_ALV_GRID
Implementation of the code:
method grid_refresh_and_keep_position.   data: es_row_no  type lvc_s_roid.   data: es_row_info  type lvc_s_row.   data: es_col_info  type lvc_s_col.   data: fes_row_no  type lvc_s_roid.   data: fes_row_id  type lvc_s_row.   data: fes_col_id  type lvc_s_col.   data: mt_cells type lvc_t_ceno.   data: mt_rows type lvc_t_row.   grid->get_scroll_info_via_id(   importing     es_row_no   = es_row_no     es_row_info = es_row_info     es_col_info = es_col_info     ).   grid->get_current_cell(     importing *        e_row     = e_row *        e_value   = e_value *        e_col     = e_col       es_row_id = fes_row_id       es_col_id = fes_col_id       es_row_no = fes_row_no          ).   grid->get_selected_rows(   importing     et_index_rows = mt_rows *            et_row_no     = et_row_no     ).   if mt_rows[] is initial.     grid->get_selected_cells_id(     importing  et_cells = mt_cells ).   endif.   grid->refresh_table_display( i_soft_refresh = i_soft ).   if i_set_selected eq 'X'.     if mt_cells[] is not initial.       grid->set_selected_cells_id( it_cells = mt_cells   ).     else.       grid->set_selected_rows(       it_index_rows            = mt_rows *        it_row_no                = it_row_no *        is_keep_other_selections = is_keep_other_selections       ).     endif.   endif.   grid->set_scroll_info_via_id(   is_row_info = es_row_info   is_col_info = es_col_info   is_row_no   = es_row_no   ).   if i_set_current eq 'X'.     grid->set_current_cell_via_id( is_row_id = fes_row_id                                     is_column_id = fes_col_id                                     is_row_no = fes_row_no ).   endif.   refresh: mt_rows[], mt_cells[]. endmethod.
Source
https://www.abapblog.com/articles/tricks/22-refresh-alv-grid-and-keep-position-and-current-cell