5 1 1 1 1 1 Rating 100% (3 Votes)
Attachments:
Access this URL (http://abapblog.com/files/nugg/ZAB_MASS_REPLACE.nugg)ZAB_MASS_REPLACE.nugg
When using editable ALV mass replace function is needed very often, but when it comes to creating it you have to choose which from the not so perfect possibilities you should use. You can create a screen or selection-screen with all possible fields which can be used in the function (not good when you have a lot of editable fields), you can create dynamic program and submit it (not good as then you switch to the screen of generated) or you can create a FM to call selection-screen in separate task (disadvantage is that user can click on original window and hide your popup). I've used all of these possibilities but when you'd like to reuse them then third one (FM to call dynamic selection-screen in separate task) seems the best. 
 
First of all the question is why do we need separate task to call it? Well, when you call dynamic selection-screen (with parameters like (variable) ) for the first time the output is ok, but the second time you do it in the same runtime of transaction or program then the length, type and F4 help are just like for the field generated for the firs time. This is because the generated selection screen is kept in memory an called each time with same parameters, nevertheless the change of "variable". The way to omit it is to call this selection-screen in new task. This will force SAP to regenerate selection-screen each time.
Bellow I'll explain how to create such FM or in fact Function Group which will allow you to call mass replace function from any program using cl_gui_alv_gird.  Result of the work will be like that:

 
1) You'll have to create or use existing FG to be able to use such FM. I prefer to create own FG for ALV functions which you can reuse after.
 
The example shown bellow allows to show use maximum 10 columns from ALV grid in replace function but you can allow more if needed. As parameters are created dynamically I used macros to not repeat the same part of code. Macro add_param_descr changes description of the parameters and "WITH" separator (text element S02). Macro add_ss_line adds line for selection screen with parameter description, parameter from, "WITH" separator and parameter to. Macro change_parametr_type is setting proper dictionary type for our parameters.
Event at selection-screen output is responsible here for hiding unnecessary field on screen. 

datag_par01_type type char255.
datag_par02_type type char255.
datag_par03_type type char255.
datag_par04_type type char255.
datag_par05_type type char255.
datag_par06_type type char255.
datag_par07_type type char255.
datag_par08_type type char255.
datag_par09_type type char255.
datag_par10_type type char255.
datag_wait type c.
datagt_rsparams type rsparams_tt.
datagt_fcat_mass type lvc_t_fcat.
datagt_mass_sel_columns type lvc_t_col.
datag_fieldname type string.
datag_okcode type sy-ucomm.
field-symbols<fcat> type lvc_s_fcat.
field-symbols<any> type any.



define add_param_descr.
  concatenate 'P_DESC' &1 into g_fieldname.
  assign (g_fieldnameto <any>.
  if sy-subrc eq 0.
    <any> &2.
  endif.
  concatenate 'P_WITH' &1 into g_fieldname.
  assign (g_fieldnameto <any>.
  if sy-subrc eq 0.
    <any> text-s02.
  endif.
  concatenate 'P_CLEA' &1 into g_fieldname.
  assign (g_fieldnameto <any>.
  if sy-subrc eq 0.
    <any> text-s03.
  endif.
end-of-definition.

define change_parametr_type.
  dataf_type type string.
  concatenate 'G_PAR' &1 '_TYPE' into g_fieldname.
  concatenate &2 '-' &3 into f_type.
  assign (g_fieldnameto <any>.
  if sy-subrc eq 0.
    <any> f_type.
  endif.
end-of-definition.


*--------------------------------------------------------------------*
* begin of selection screens
*--
define add_ss_line.
  selection-screen begin of line.
  selection-screen comment 1(14p_clea&1.
  parametersp_parc&1 as checkbox user-command p_parc&1.
  selection-screen comment 18(10p_desc&1.
  parametersp_parf&1 like (g_par&1_typelower case.
  selection-screen comment 77(6p_with&1.
  parametersp_part&1 like (g_par&1_typelower case.

  "selection-screen comment 51(10) p_with&1.
  selection-screen end of line.
end-of-definition.



"mass replace ss
selection-screen begin of screen 1001.
add_ss_line01020304050607080910.
selection-screen end of screen 1001.



at selection-screen output.
  if sy-dynnr eq 1001.
    perform set_ss_status.
    loop at screen.
      if screen-name cp '*P_*01*' and g_par01_type is initial.
        clearp_parf01p_part01.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*02*' and g_par02_type is initial.
        clearp_parf02p_part02.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*03*' and g_par03_type is initial.
        clearp_parf03p_part03.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*04*' and g_par04_type is initial.
        clearp_parf04p_part04.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*05*' and g_par05_type is initial.
        clearp_parf05p_part05.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*06*' and g_par06_type is initial.
        clearp_parf06p_part06.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*07*' and g_par07_type is initial.
        clearp_parf07p_part07.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*08*' and g_par08_type is initial.
        clearp_parf08p_part08.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*09*' and g_par09_type is initial.
        clearp_parf09p_part09.
        screen-active 0.
        modify screen.
      endif.
      if screen-name cp '*P_*10*' and g_par10_type is initial.
        clearp_parf10p_part10.
        screen-active 0.
        modify screen.
      endif.
      if screen-name+0(6eq 'P_PARF'
        concatenate 'P_PARC' screen-name+6(2into g_fieldname.
        assign (g_fieldnameto <any>.
        if sy-subrc eq and <any> is not initial.
          assign (screen-nameto <any>.
          if sy-subrc eq 0.
            clear <any>.
          endif.
          screen-input 0.
          modify screen.
        elseif sy-subrc eq 0.
          screen-input 1.
          modify screen.
        endif.
      endif.
    endloop.
  endif.


  if sy-dynnr eq 1001.
    g_okcode sy-ucomm.
    clear sy-ucomm.
    case g_okcode.
      when 'ENTER'.
        " return.

      when 'CANCEL'.
        clearp_parf01p_parf02p_parf03p_parf04p_parf05p_parf06p_parf07p_parf08p_parf09p_parf10,
        p_part01p_part02p_part03p_part04p_part05p_part06p_part07p_part08p_part09p_part10
        .
      when 'P_PARC01' or 'P_PARC02' or 'P_PARC03' or 'P_PARC04' or 'P_PARC05' or 'P_PARC06' or 'P_PARC07' or 'P_PARC08' or
      'P_PARC09' or 'P_PARC10'.

    endcase.
  endif.

2) As we need only confirm and cancel buttons I will need a form to hide other standard buttons for modal window (set_ss_status). We can do this using FM RS_SET_SELSCREEN_STATUS and passing proper function code (GET, SPOS, NONE for variant, check and info button). We need also need a form which will be called at end of task for our FM (ss1001_call_end).This form will retrieve results from FM called in separate task using statement receive results from function.

form set_ss_status.
  dataft_exclude type standard table of rsexfcode.
  datafs_exclude like line of ft_exclude.
  if sy-dynnr eq 1001.

    "Exclude functions which are not used from modal SS
    fs_exclude-fcode 'GET'.
    append fs_exclude to ft_exclude.
    fs_exclude-fcode 'SPOS'.
    append fs_exclude to ft_exclude.
    fs_exclude-fcode 'NONE'.
    append fs_exclude to ft_exclude.


    call function 'RS_SET_SELSCREEN_STATUS'
      exporting
        p_status  space
        p_program 
sy-repid
      tables
        p_exclude ft_exclude.


  endif.

endform.                    "set_ss_status

*&---------------------------------------------------------------------*
*&      Form  ss1001_call_end
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->TASKNAME   text
*----------------------------------------------------------------------*
form ss1001_call_end using taskname.

  receive results from function 'Z_AB_CALL_SS_1001'
  importing
    et_rsparams       gt_rsparams.

  g_wait space.

endform.                    "ss1001_call_end

3) We need two FM , one which will be displaying selection-screen in separate task and second which will be called from ALV.
 
First function needs two import parameter, which are tables of selected columns in ALV grid (LVC_T_COL) and fieldcatalog of ALV (LVC_T_FCAT). This FM adds proper selection-screen lines on a base of fieldcatalog and selected columns, then it displays selection-screen 1001. After pressing button "Confirm" or "Cancel" using FM RS_REFRESH_FROM_SELECTOPTIONS I'm retrieving table with parameters and its values, this table will be exported to the FM which will be called from ALV. In case of pressing "Cancel" button it will return parameters without values as then they are cleared after pressing "Cancel" button.

function z_ab_call_ss_1001.
*"--------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IT_MASS_SEL_COLUMNS) TYPE  LVC_T_COL
*"     VALUE(IT_FCAT_MASS) TYPE  LVC_T_FCAT
*"  EXPORTING
*"     VALUE(ET_RSPARAMS) TYPE  RSPARAMS_TT
*"--------------------------------------------------------------------
  field-symbols<col> like line of it_mass_sel_columns.
  dataft_mass_sel_columns like it_mass_sel_columns.
  dataf_num(2type n.


  ft_mass_sel_columns it_mass_sel_columns.
  loop at it_fcat_mass assigning <fcat>.
    read table ft_mass_sel_columns[] with key fieldname <fcat>-fieldname transporting no fields." binary search.
    if sy-subrc eq 0.
      add to f_num.
      add_param_descrf_num <fcat>-scrtext_s.
      change_parametr_typef_num <fcat>-ref_table <fcat>-ref_field.
    endif.
  endloop.

  call selection-screen 1001 starting at 1 1.

  call function 'RS_REFRESH_FROM_SELECTOPTIONS'
    exporting
      curr_report           sy-repid
* IMPORTING
*   SP                    = SP
    tables
      selection_table       et_rsparams
   
exceptions
     not_found             1
     no_report             2
     others                3
            .
  if sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  endif.


endfunction.

 
4) Last needed FM is the one which will be called directly from ALV. As import parameter we need cl_gui_alv_grid object and as a changing parameter we need out output table to be able to update it directly. 
Firstly after calling this FM from ALV we need to get fieldcatalog with method ( get_frontend_fieldcatalog ) and then get selected columns ( get_selected_columns ). We will pass this to the FM from 3rd point but only in case user has at least one free session available. We can check that with FM RM_FREE_SESSION_CHECK. If the check is successful the we call FM from 3rd point starting new task and performing ss1001_call_end funtion at end of task. Once we get RSPARAMS table we can use it to replace values in output table. If at least one field was changed then we have to refresh ALV with refresh_table_display method.
 

function z_ab_mass_replace_alv.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IO_GRID) TYPE REF TO  CL_GUI_ALV_GRID
*"  CHANGING
*"     REFERENCE(CT_OUTTAB) TYPE  STANDARD TABLE
*"----------------------------------------------------------------------

  dataft_rsparams type rsparams_tt.
  dataf_lines type i.
  dataf_num(2type n.
  dataf_index type i.
  dataf_field type string.
  dataf_changed type flag.
  dataf_tabix type i.
  dataft_filtered type lvc_t_fidx.
  dataft_selected_rows type lvc_t_roid.
  datafs_layout type lvc_s_layo.
  dataf_space like line of ft_rsparams.
  field-symbols<paramsf> like line of ft_rsparams.
  field-symbols<paramst> like line of ft_rsparams.
  field-symbols<paramsc> like line of ft_rsparams.
  field-symbols<out> type any.
  field-symbols<col> like line of gt_mass_sel_columns.
  field-symbols<value> type lvc_s_modi-value.
  field-symbols<stylet> type lvc_t_styl.
  field-symbols<style> type lvc_s_styl.


  if io_grid->is_ready_for_input( ) eq 0.
    message s001(00display like 'W' with 'Grid should be in edit mode in order to use this function!'.
    return.
  endif.

  io_grid->get_frontend_layout(
    importing
      es_layout fs_layout    " Layout
  ).

  "get fieldcat and selected columns
  io_grid->get_frontend_fieldcatalog(
  importing
    et_fieldcatalog gt_fcat_mass[]
    
).

  io_grid->get_filtered_entries(
      importing
        et_filtered_entries ft_filtered
           
).

  io_grid->get_selected_rows(
      importing
*        et_index_rows = et_index_rows    " Indexes of Selected Rows
        et_row_no     =  ft_selected_rows
    
).

  io_grid->get_selected_columns(
  importing
    et_index_columns gt_mass_sel_columns[]
    
).

  sort ft_selected_rows by row_id.

  "remove not editable fields
  delete gt_fcat_mass where edit eq abap_false.
  if gt_fcat_mass[] is initial.
    message s001(00display like 'W' with 'No editable fields in the grid'.
    return.
  endif.
  sort gt_fcat_mass by fieldname.

  loop at gt_mass_sel_columns assigning <col>.
    f_tabix sy-tabix.
    read table gt_fcat_mass with key fieldname <col>-fieldname transporting no fields binary search.
    if sy-subrc ne 0.
      delete gt_mass_sel_columns index f_tabix.
    endif.
  endloop.
  if sy-subrc eq 0.
    if gt_mass_sel_columns[] is initial.
      message s001(00display like 'W' with 'Please select editable fields only'.
      return.
    endif.
  endif.




  if gt_mass_sel_columns[] is initial.
    message s001(00display like 'W' with 'Please select at least one column!'.
    return.
  endif.
  describe table gt_mass_sel_columns lines f_lines.
  if f_lines gt 10.
    message s001(00display like 'W' with 'Maximum number of columns in mass change function is 10'.
    return.
  endif.

  loop at gt_mass_sel_columns[] assigning <col>.
    data f_fieldname type string.
    concatenate 'G_' <col>-fieldname into f_fieldname.
    assign (f_fieldnameto <any>.
    if sy-subrc eq 0.
      <any> 'X'.
      read table gt_fcat_mass with key fieldname <col>-fieldname assigning <fcat> binary search.
      if sy-subrc eq 0.
        concatenate 'PD' <col>-fieldname into f_fieldname.
        assign (f_fieldnameto <any>.
        if sy-subrc eq 0.
          <any> <fcat>-scrtext_s.
        endif.
      endif.
    endif.
  endloop.


  refresh gt_rsparams[].
  sort gt_fcat_mass by col_pos.
  call function 'RM_FREE_SESSION_CHECK'
    exceptions
      no_free_session 1
      others          2.
  if sy-subrc eq 0.
    g_wait abap_true.
    call function 'Z_AB_CALL_SS_1001'
      destination 'NONE'
      starting new task 'ZABMASSR'
      performing ss1001_call_end on end of task
      exporting
        it_mass_sel_columns gt_mass_sel_columns
        it_fcat_mass        
gt_fcat_mass.
  else.
    message s001(00display like 'W' with 'No more free sessions. Close one window.'.
    return.
  endif.
  wait until g_wait eq space.

  sort gt_rsparams by selname.
  clear f_num.
  dataf_row type i.
  dataft_delta type lvc_t_modi.
  datafs_delta type lvc_s_modi.
  ft_rsparams[] gt_rsparams[].
  sort ft_rsparams by selname.
  clear f_num.
  loop at gt_fcat_mass assigning <fcat>.
    read table gt_mass_sel_columns[] with key fieldname <fcat>-fieldname transporting no fields." binary search.
    if sy-subrc eq 0.
      add to f_num.
      concatenate 'P_PARC' f_num into f_field.
      read table ft_rsparams assigning <paramsc> with key selname f_field binary search.
      if sy-subrc ne 0.
        assign f_space to <paramsc>.
      endif.
      concatenate 'P_PARF' f_num into f_field.
      read table ft_rsparams assigning <paramsf> with key selname f_field binary search.
      if sy-subrc eq 0.
        concatenate 'P_PART' f_num into f_field.
        read table ft_rsparams assigning <paramst> with key selname f_field binary search.
        if sy-subrc eq and <paramsf>-low ne <paramst>-low  or <paramsc>-low eq abap_true ).
          loop at ct_outtab assigning <out>.
            f_row sy-tabix.
            if ft_filtered[] is not initial.
              read table ft_filtered with key table_line f_row transporting no fields.
              if sy-subrc eq 0.
                continue.
              endif.
            endif.
            if ft_selected_rows[] is not initial.
              read table ft_selected_rows with key row_id f_row transporting no fields binary search.
              if sy-subrc ne 0"only selected rows can be changed.
                continue.
              endif.
            endif.
            assign component <fcat>-fieldname of structure <out> to <any>.
            if sy-subrc eq and <any> eq <paramsf>-low or <paramsc>-low eq abap_true ).
              "check if field is not disabled in row :)
              if fs_layout-stylefname is not initial.
                assign component fs_layout-stylefname of structure <out> to <stylet>.
                if sy-subrc eq 0.
                  read table <stylet> with key fieldname <fcat>-fieldname assigning <style>.
                  if sy-subrc eq and <style>-style eq cl_gui_alv_grid=>mc_style_disabled.
                    "do not change that cell as it's not editable.
                    continue.
                  endif.
                endif.
              endif.

              <any> <paramst>-low.
              clear fs_delta.
              fs_delta-fieldname <fcat>-fieldname.
              fs_delta-row_id    f_row.
              fs_delta-value <paramst>-low.
              append fs_delta to ft_delta.

              f_changed abap_true.
            endif.
          endloop.
        endif.
      endif.
    endif.
  endloop.

  if f_changed eq abap_true.
    sy-ucomm 'MASSREPL'.
    io_grid->set_delta_cells(
      exporting
        it_delta_cells  ft_delta    " Delta Table
        i_modified      abap_true    " Modified
        i_frontend_only abap_true   " Update only at Frontend
    ).
    sy-ucomm space.
    io_grid->check_changed_data( ).
  endif.


endfunction.

Now you can call FM Z_AB_MASS_REPLACE_ALV and get different parameters in the popup if you select different column in ALV grid.
 
Demo report (please create screen 0100 with custom container called 'CC_0100', add gui status with at least function 'MASS_REPLA' )

report  zab_mass_replace_demo.


dataok_code type sy-ucomm.

databegin of gs_spfli.
        include structure spfli.
datastyles type lvc_t_styl,
     end of gs_spfli.
datagt_spfli like standard table of gs_spfli.
datago_cc type ref to cl_gui_custom_container.
datago_alv type ref to cl_gui_alv_grid.
datags_layout type lvc_s_layo.
datagt_fieldcat type lvc_t_fcat.
datag_row type i.
datag_field type i.
datags_style type lvc_s_styl.
field-symbols<spfli> like gs_spfli.
field-symbols<fcat> type lvc_s_fcat.

select up to 250 rows into corresponding fields of table gt_spfli
  
from spfli.

call function 'LVC_FIELDCATALOG_MERGE'
  exporting
*   i_buffer_active        = i_buffer_active    " Buffer active
    i_structure_name       'SPFLI' " Structure name (structure, table, view)
*   i_client_never_display = 'X' " Hide client fields
    i_bypassing_buffer     abap_true    " Ignore buffer while reading
*   i_internal_tabname     = i_internal_tabname    " Table Name
  changing
    ct_fieldcat            gt_fieldcat    " Field Catalog with Field Descriptions
  exceptions
    inconsistent_interface 1
    program_error          2
    others                 3.
if sy-subrc eq 0.

  loop at gt_fieldcat assigning <fcat>.
    if <fcat>-key is initial.
      if sy-tabix mod eq 0.
        <fcat>-edit abap_true.
      endif.
    endif.
  endloop.
  loop at gt_spfli assigning <spfli>.
    g_row sy-tabix.
    g_field 0.
    loop at gt_fieldcat assigning <fcat> where edit eq abap_true.
      add to g_field.
      if g_row mod eq and g_field mod eq ).
        clear gs_style.
        gs_style-fieldname <fcat>-fieldname.
        gs_style-style cl_gui_alv_grid=>mc_style_disabled.
        insert gs_style into table <spfli>-styles.
      endif.
    endloop.
  endloop.

endif.


call screen 0100.

module status_0100 output.
  set pf-status 'STATUS_0100'.
  set titlebar 'TITLE_0100'.
  if go_cc is initial.

    create object go_cc
      
exporting
        container_name              'CC_0100'
      exceptions
        cntl_error                  1
        cntl_system_error           2
        create_error                3
        lifetime_error              4
        lifetime_dynpro_dynpro_link 5
        others                      6.
    if sy-subrc eq 0.
      create object go_alv
        
exporting
          i_parent          go_cc
        
exceptions
          error_cntl_create 1
          error_cntl_init   2
          error_cntl_link   3
          error_dp_create   4
          others            5.
      if sy-subrc eq 0.
        gs_layout-stylefname 'STYLES'.
        go_alv->set_table_for_first_display(
          exporting
            i_structure_name              'SPFLI'
            is_layout                     gs_layout
          
changing
            it_outtab                     gt_spfli
            it_fieldcatalog               
gt_fieldcat
          
exceptions
            invalid_parameter_combination 1
            program_error                 2
            too_many_lines                3
            others                        4
               ).
        if sy-subrc eq 0.

          go_alv->register_edit_event(
            exporting
              i_event_id cl_gui_alv_grid=>mc_evt_modified  " Event ID
            exceptions
              error      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.
        endif.
      endif.
    endif.
  endif.

endmodule.

module user_command_0100 input.
  case ok_code.
    when 'BACK' or 'END' or 'EXIT'.
      leave program.
    when 'MASS_REPLA'.
      call function 'Z_AB_MASS_REPLACE_ALV'
        exporting
          io_grid   go_alv    " ALV List Viewer
        changing
          ct_outtab gt_spfli.    " ALV List Viewer
  endcase.
endmodule.

EnjoY!