Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

ALV changes wrong lines, if pasting line, after sort

5,624

Hi, I have a problem with the ALV Grid.

Situation:

I have an ALV Grid where every line is editable and instead of the standard Add and Remove Buttons I have my own implementation.

I want to be able to copy multiple rows. Then I want to add multiple empty rows and paste the data from the copied rows in there.

Problem:

When I copy and paste rows after I sorted the ALV Grid, the ALV changes additional lines, that I didn't want to change.

Example:

I've made a sample program using the SFLIGHT database, to recreate the problem.

Here I sorted the table by SEATSOCC. The marked entry will be the one, that will get changed unintentionally.

I copy one line.

Then I add a new line, which for some reason appears on the second index, no mater which line I choose.

Now when I paste the copied line into the empty line, the line I marked in the first picture disapears completely and instead of having the copied line twice I do have it three times.

If I do this with multiple lines it gets even weirder. The lines in green will stay as they are and the lines in red will appear 3 times.

So instead of copying all 4 lines it just copied two of those lines twice.

I tried to debug it and my handler for the DATA_CHANGED event seems to work as intended. It changed the right lines and when it was finished, the internal table looked like the output table should look like after the changes. So I assume the ALV makes this changes somewhere in the background without triggering the DATA_CHANGED event.

My code:

Program

REPORT z_sandbox.<br>
INCLUDE z_sandbox_top.
INCLUDE z_sandbox_handler.
INCLUDE z_sandbox_forms.<br>
START-OF-SELECTION.
  PERFORM init_grid.
  PERFORM read_data.
  CALL SCREEN 100.

Top Include

CLASS lcl_handler DEFINITION DEFERRED.<br>
DATA:
  gs_layout    TYPE lvc_s_layo,
  gt_fieldcat  TYPE lvc_t_fcat,
  gt_outtab    TYPE TABLE OF sflight,
  gx_grid      TYPE REF TO cl_gui_alv_grid,
  gx_container TYPE REF TO cl_gui_custom_container,
  gx_handler   TYPE REF TO lcl_handler,
  g_ucomm      TYPE syucomm.

Eventhandler

CLASS lcl_handler DEFINITION.
  PUBLIC SECTION.
    METHODS:
      refresh_grid,
      handle_toolbar
          FOR EVENT toolbar OF cl_gui_alv_grid
        IMPORTING
          !e_object,
      handle_button_event
          FOR EVENT user_command OF cl_gui_alv_grid
        IMPORTING
          !e_ucomm,
      add_entry,
      remove_entries,
      handle_data_changed
          FOR EVENT data_changed OF cl_gui_alv_grid
        IMPORTING
          !er_data_changed,
      change_data
        IMPORTING
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_carrid
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_connid
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_fldate
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_price
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_currency
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_planetype
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsmax
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsocc
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol
      change_paymentsum
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsmax_b
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsocc_b
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsmax_f
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsocc_f
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol.
ENDCLASS.<br>
CLASS lcl_handler IMPLEMENTATION.
  METHOD refresh_grid.
    DATA:
      ls_stable TYPE lvc_s_stbl.
    gx_grid->refresh_table_display(
          EXPORTING
            is_stable      = ls_stable
        ).
  ENDMETHOD.<br>
  METHOD handle_toolbar.
    DATA: l_button TYPE stb_button.
*   Add Entry
    CLEAR l_button.
    MOVE 'ADD' TO l_button-function.
    MOVE 'Add Entry' TO l_button-text.
    MOVE icon_add_row TO l_button-icon.
    MOVE abap_false TO l_button-disabled.
    MOVE 0 TO l_button-butn_type.
    APPEND l_button TO e_object->mt_toolbar.
*   Remove Entry
    CLEAR l_button.
    MOVE 'REMOVE' TO l_button-function.
    MOVE 'Remove Entry' TO l_button-text.
    MOVE icon_remove_row TO l_button-icon.
    MOVE abap_false TO l_button-disabled.
    MOVE 0 TO l_button-butn_type.
    APPEND l_button TO e_object->mt_toolbar.
  ENDMETHOD.<br>
  METHOD handle_button_event.
    CASE e_ucomm.
      WHEN 'ADD'.
        me->add_entry( ).
      WHEN 'REMOVE'.
        me->remove_entries( ).
    ENDCASE.
  ENDMETHOD.<br>
  METHOD add_entry.
    DATA:
          ls_line TYPE sflight.
    APPEND ls_line TO gt_outtab.
    me->refresh_grid( ).
  ENDMETHOD.<br>
  METHOD remove_entries.
    DATA:
      lt_sel_rows TYPE lvc_t_row.
    gx_grid->get_selected_rows(
      IMPORTING
        et_index_rows = lt_sel_rows    " Indizes der selektierten Zeilen
    ).
*   Rows need to be deleted in descending order
    SORT lt_sel_rows DESCENDING BY index.
    LOOP AT lt_sel_rows INTO DATA(ls_sel_row).
      DELETE gt_outtab INDEX ls_sel_row-index.
    ENDLOOP.
    me->refresh_grid( ).
  ENDMETHOD.<br>
  METHOD handle_data_changed.
    DATA:
      ls_row_no TYPE lvc_s_roid,
      ls_row_id TYPE lvc_s_row,
      ls_col_id TYPE lvc_s_col,
      ls_stable TYPE lvc_s_stbl.
    gx_grid->get_current_cell(
      IMPORTING
        es_row_id = ls_row_id
        es_col_id = ls_col_id
        es_row_no = ls_row_no
    ).
    me->change_data( er_data_changed ).
    me->refresh_grid( ).
    gx_grid->set_current_cell_via_id(
      EXPORTING
        is_row_id    = ls_row_id
        is_column_id = ls_col_id
        is_row_no    = ls_row_no
    ).
  ENDMETHOD.<br>
  METHOD change_data.
    LOOP AT ix_data_changed->mt_mod_cells INTO DATA(ls_mod_cell).
      CASE ls_mod_cell-fieldname.
        WHEN 'CARRID'.
          me->change_carrid(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'CONNID'.
          me->change_connid(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'FLDATE'.
          me->change_fldate(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'PRICE'.
          me->change_price(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'CURRENCY'.
          me->change_currency(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'PLANETYPE'.
          me->change_planetype(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSMAX'.
          me->change_seatsmax(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSOCC'.
          me->change_seatsocc(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'PAYMENTSUM'.
          me->change_paymentsum(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSMAX_B'.
          me->change_seatsmax_b(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSOCC_B'.
          me->change_seatsocc_b(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSMAX_F'.
          me->change_seatsmax_f(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSOCC_F'.
          me->change_seatsocc_f(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
      ENDCASE.
    ENDLOOP.
  ENDMETHOD.<br>
  METHOD change_carrid.
    DATA:
          l_value   TYPE sflight-carrid.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-carrid = l_value.
  ENDMETHOD.<br>
  METHOD change_connid.
    DATA:
          l_value   TYPE sflight-connid.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-connid = l_value.
  ENDMETHOD.<br>
  METHOD change_fldate.
    DATA:
          l_value   TYPE sflight-fldate.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-fldate = l_value.
  ENDMETHOD.<br>
  METHOD change_price.
    DATA:
          l_value   TYPE sflight-price.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-price = l_value.
  ENDMETHOD.<br>
  METHOD change_currency.
    DATA:
          l_value   TYPE sflight-currency.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-currency = l_value.
  ENDMETHOD.<br>
  METHOD change_planetype.
    DATA:
          l_value   TYPE sflight-planetype.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-planetype = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsmax.
    DATA:
          l_value   TYPE sflight-seatsmax.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsmax = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsocc.
    DATA:
          l_value   TYPE sflight-seatsocc.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsocc = l_value.
  ENDMETHOD.<br>
  METHOD change_paymentsum.
    DATA:
          l_value   TYPE sflight-paymentsum.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-paymentsum = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsmax_b.
    DATA:
          l_value   TYPE sflight-seatsmax_b.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsmax_b = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsocc_b.
    DATA:
          l_value   TYPE sflight-seatsocc_b.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsocc_b = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsmax_f.
    DATA:
          l_value   TYPE sflight-seatsmax_f.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsmax_f = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsocc_f.
    DATA:
          l_value   TYPE sflight-seatsocc_f.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsocc_f = l_value.
  ENDMETHOD.
ENDCLASS.

Forms and modules

FORM init_grid.
  PERFORM build_fieldcat.
  PERFORM build_layout.
  CREATE OBJECT gx_container
    EXPORTING
      container_name              = 'ALV_GRID'
    EXCEPTIONS
      cntl_error                  = 1
      cntl_system_error           = 2
      create_error                = 3
      lifetime_error              = 4
      lifetime_dynpro_dynpro_link = 5.
  IF sy-subrc <> 0.
    MESSAGE 'Error initializing Container' TYPE 'E'.
  ENDIF.
  CREATE OBJECT gx_grid
    EXPORTING
      i_parent          = gx_container
    EXCEPTIONS
      error_cntl_create = 1
      error_cntl_init   = 2
      error_cntl_link   = 3
      error_dp_create   = 4.
  IF sy-subrc <> 0.
    MESSAGE 'Error initializing Grid' TYPE 'E'.
  ENDIF.
  CREATE OBJECT gx_handler.
  SET HANDLER gx_handler->handle_toolbar FOR gx_grid.
  SET HANDLER gx_handler->handle_button_event FOR gx_grid.
  SET HANDLER gx_handler->handle_data_changed FOR gx_grid.
ENDFORM.<br>
FORM read_data.
  SELECT * FROM sflight INTO TABLE gt_outtab WHERE connid = 17.
ENDFORM.<br>
FORM set_table.
  gx_grid->set_table_for_first_display(
      EXPORTING
        is_layout                     = gs_layout
      CHANGING
        it_outtab                     = gt_outtab
        it_fieldcatalog               = gt_fieldcat
      EXCEPTIONS
        invalid_parameter_combination = 1
        program_error                 = 2
        too_many_lines                = 3
    ).
  IF sy-subrc <> 0.
    MESSAGE 'Error calling Grid' TYPE 'E'.
  ENDIF.
  gx_grid->set_ready_for_input( ).
  gx_grid->register_edit_event(
    EXPORTING
      i_event_id = cl_gui_alv_grid=>mc_evt_modified ).
ENDFORM.<br>
FORM build_fieldcat.
  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name       = 'SFLIGHT'
    CHANGING
      ct_fieldcat            = gt_fieldcat
    EXCEPTIONS
      inconsistent_interface = 1
      program_error          = 2.
  IF sy-subrc <> 0.
    MESSAGE 'Error building Fieldcat' TYPE 'I' DISPLAY LIKE 'W'.
  ENDIF.
  LOOP AT gt_fieldcat ASSIGNING FIELD-SYMBOL(<ls_fieldcat>).
    <ls_fieldcat>-edit = abap_true. "Every field should be editable
  ENDLOOP.
ENDFORM.<br>
FORM build_layout.
  gs_layout-sel_mode = 'A'. "Multi row selection
ENDFORM.<br>
*&---------------------------------------------------------------------*
*&      Module  STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'STATUS'.
  PERFORM set_table.
ENDMODULE.<br>
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
  CASE g_ucomm.
    WHEN '&F15' OR '&F03' OR '&F15'.
      LEAVE PROGRAM.
  ENDCASE.
ENDMODULE.

I hope somebody can help me to solve my problem.

Hi, I have a problem with the ALV Grid.

Situation:

I have an ALV Grid where every line is editable and instead of the standard Add and Remove Buttons I have my own implementation.

I want to be able to copy multiple rows. Then I want to add multiple empty rows and paste the data from the copied rows in there.

Problem:

When I copy and paste rows after I sorted the ALV Grid, the ALV changes additional lines, that I didn't want to change.

Example:

I've made a sample program using the SFLIGHT database, to recreate the problem.

Here I sorted the table by SEATSOCC. The marked entry will be the one, that will get changed unintentionally.

I copy one line.

Then I add a new line, which for some reason appears on the second index, no mater which line I choose.

Now when I paste the copied line into the empty line, the line I marked in the first picture disapears completely and instead of having the copied line twice I do have it three times.

If I do this with multiple lines it gets even weirder. The lines in green will stay as they are and the lines in red will appear 3 times.

So instead of copying all 4 lines it just copied two of those lines twice.

I tried to debug it and my handler for the DATA_CHANGED event seems to work as intended. It changed the right lines and when it was finished, the internal table looked like the output table should look like after the changes. So I assume the ALV makes this changes somewhere in the background without triggering the DATA_CHANGED event.

My code:

Program

REPORT z_sandbox.<br>
INCLUDE z_sandbox_top.
INCLUDE z_sandbox_handler.
INCLUDE z_sandbox_forms.<br>
START-OF-SELECTION.
  PERFORM init_grid.
  PERFORM read_data.
  CALL SCREEN 100.

Top Include

CLASS lcl_handler DEFINITION DEFERRED.<br>
DATA:
  gs_layout    TYPE lvc_s_layo,
  gt_fieldcat  TYPE lvc_t_fcat,
  gt_outtab    TYPE TABLE OF sflight,
  gx_grid      TYPE REF TO cl_gui_alv_grid,
  gx_container TYPE REF TO cl_gui_custom_container,
  gx_handler   TYPE REF TO lcl_handler,
  g_ucomm      TYPE syucomm.

Eventhandler

CLASS lcl_handler DEFINITION.
  PUBLIC SECTION.
    METHODS:
      refresh_grid,
      handle_toolbar
          FOR EVENT toolbar OF cl_gui_alv_grid
        IMPORTING
          !e_object,
      handle_button_event
          FOR EVENT user_command OF cl_gui_alv_grid
        IMPORTING
          !e_ucomm,
      add_entry,
      remove_entries,
      handle_data_changed
          FOR EVENT data_changed OF cl_gui_alv_grid
        IMPORTING
          !er_data_changed,
      change_data
        IMPORTING
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_carrid
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_connid
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_fldate
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_price
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_currency
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_planetype
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsmax
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsocc
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol
      change_paymentsum
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsmax_b
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsocc_b
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsmax_f
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol,
      change_seatsocc_f
        IMPORTING
          !is_mod_cell     TYPE lvc_s_modi
          !ix_data_changed TYPE REF TO cl_alv_changed_data_protocol.
ENDCLASS.<br>
CLASS lcl_handler IMPLEMENTATION.
  METHOD refresh_grid.
    DATA:
      ls_stable TYPE lvc_s_stbl.
    gx_grid->refresh_table_display(
          EXPORTING
            is_stable      = ls_stable
        ).
  ENDMETHOD.<br>
  METHOD handle_toolbar.
    DATA: l_button TYPE stb_button.
*   Add Entry
    CLEAR l_button.
    MOVE 'ADD' TO l_button-function.
    MOVE 'Add Entry' TO l_button-text.
    MOVE icon_add_row TO l_button-icon.
    MOVE abap_false TO l_button-disabled.
    MOVE 0 TO l_button-butn_type.
    APPEND l_button TO e_object->mt_toolbar.
*   Remove Entry
    CLEAR l_button.
    MOVE 'REMOVE' TO l_button-function.
    MOVE 'Remove Entry' TO l_button-text.
    MOVE icon_remove_row TO l_button-icon.
    MOVE abap_false TO l_button-disabled.
    MOVE 0 TO l_button-butn_type.
    APPEND l_button TO e_object->mt_toolbar.
  ENDMETHOD.<br>
  METHOD handle_button_event.
    CASE e_ucomm.
      WHEN 'ADD'.
        me->add_entry( ).
      WHEN 'REMOVE'.
        me->remove_entries( ).
    ENDCASE.
  ENDMETHOD.<br>
  METHOD add_entry.
    DATA:
          ls_line TYPE sflight.
    APPEND ls_line TO gt_outtab.
    me->refresh_grid( ).
  ENDMETHOD.<br>
  METHOD remove_entries.
    DATA:
      lt_sel_rows TYPE lvc_t_row.
    gx_grid->get_selected_rows(
      IMPORTING
        et_index_rows = lt_sel_rows    " Indizes der selektierten Zeilen
    ).
*   Rows need to be deleted in descending order
    SORT lt_sel_rows DESCENDING BY index.
    LOOP AT lt_sel_rows INTO DATA(ls_sel_row).
      DELETE gt_outtab INDEX ls_sel_row-index.
    ENDLOOP.
    me->refresh_grid( ).
  ENDMETHOD.<br>
  METHOD handle_data_changed.
    DATA:
      ls_row_no TYPE lvc_s_roid,
      ls_row_id TYPE lvc_s_row,
      ls_col_id TYPE lvc_s_col,
      ls_stable TYPE lvc_s_stbl.
    gx_grid->get_current_cell(
      IMPORTING
        es_row_id = ls_row_id
        es_col_id = ls_col_id
        es_row_no = ls_row_no
    ).
    me->change_data( er_data_changed ).
    me->refresh_grid( ).
    gx_grid->set_current_cell_via_id(
      EXPORTING
        is_row_id    = ls_row_id
        is_column_id = ls_col_id
        is_row_no    = ls_row_no
    ).
  ENDMETHOD.<br>
  METHOD change_data.
    LOOP AT ix_data_changed->mt_mod_cells INTO DATA(ls_mod_cell).
      CASE ls_mod_cell-fieldname.
        WHEN 'CARRID'.
          me->change_carrid(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'CONNID'.
          me->change_connid(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'FLDATE'.
          me->change_fldate(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'PRICE'.
          me->change_price(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'CURRENCY'.
          me->change_currency(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'PLANETYPE'.
          me->change_planetype(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSMAX'.
          me->change_seatsmax(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSOCC'.
          me->change_seatsocc(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'PAYMENTSUM'.
          me->change_paymentsum(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSMAX_B'.
          me->change_seatsmax_b(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSOCC_B'.
          me->change_seatsocc_b(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSMAX_F'.
          me->change_seatsmax_f(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
        WHEN 'SEATSOCC_F'.
          me->change_seatsocc_f(
            EXPORTING
              is_mod_cell     = ls_mod_cell
              ix_data_changed = ix_data_changed
        ).
      ENDCASE.
    ENDLOOP.
  ENDMETHOD.<br>
  METHOD change_carrid.
    DATA:
          l_value   TYPE sflight-carrid.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-carrid = l_value.
  ENDMETHOD.<br>
  METHOD change_connid.
    DATA:
          l_value   TYPE sflight-connid.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-connid = l_value.
  ENDMETHOD.<br>
  METHOD change_fldate.
    DATA:
          l_value   TYPE sflight-fldate.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-fldate = l_value.
  ENDMETHOD.<br>
  METHOD change_price.
    DATA:
          l_value   TYPE sflight-price.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-price = l_value.
  ENDMETHOD.<br>
  METHOD change_currency.
    DATA:
          l_value   TYPE sflight-currency.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-currency = l_value.
  ENDMETHOD.<br>
  METHOD change_planetype.
    DATA:
          l_value   TYPE sflight-planetype.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-planetype = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsmax.
    DATA:
          l_value   TYPE sflight-seatsmax.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsmax = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsocc.
    DATA:
          l_value   TYPE sflight-seatsocc.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsocc = l_value.
  ENDMETHOD.<br>
  METHOD change_paymentsum.
    DATA:
          l_value   TYPE sflight-paymentsum.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-paymentsum = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsmax_b.
    DATA:
          l_value   TYPE sflight-seatsmax_b.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsmax_b = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsocc_b.
    DATA:
          l_value   TYPE sflight-seatsocc_b.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsocc_b = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsmax_f.
    DATA:
          l_value   TYPE sflight-seatsmax_f.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsmax_f = l_value.
  ENDMETHOD.<br>
  METHOD change_seatsocc_f.
    DATA:
          l_value   TYPE sflight-seatsocc_f.
    CALL METHOD ix_data_changed->get_cell_value
      EXPORTING
        i_row_id    = is_mod_cell-row_id
        i_fieldname = is_mod_cell-fieldname
      IMPORTING
        e_value     = l_value.
    READ TABLE gt_outtab ASSIGNING FIELD-SYMBOL(<ls_entry>) INDEX is_mod_cell-row_id.
    <ls_entry>-seatsocc_f = l_value.
  ENDMETHOD.
ENDCLASS.

Forms and modules

FORM init_grid.
  PERFORM build_fieldcat.
  PERFORM build_layout.
  CREATE OBJECT gx_container
    EXPORTING
      container_name              = 'ALV_GRID'
    EXCEPTIONS
      cntl_error                  = 1
      cntl_system_error           = 2
      create_error                = 3
      lifetime_error              = 4
      lifetime_dynpro_dynpro_link = 5.
  IF sy-subrc <> 0.
    MESSAGE 'Error initializing Container' TYPE 'E'.
  ENDIF.
  CREATE OBJECT gx_grid
    EXPORTING
      i_parent          = gx_container
    EXCEPTIONS
      error_cntl_create = 1
      error_cntl_init   = 2
      error_cntl_link   = 3
      error_dp_create   = 4.
  IF sy-subrc <> 0.
    MESSAGE 'Error initializing Grid' TYPE 'E'.
  ENDIF.
  CREATE OBJECT gx_handler.
  SET HANDLER gx_handler->handle_toolbar FOR gx_grid.
  SET HANDLER gx_handler->handle_button_event FOR gx_grid.
  SET HANDLER gx_handler->handle_data_changed FOR gx_grid.
ENDFORM.<br>
FORM read_data.
  SELECT * FROM sflight INTO TABLE gt_outtab WHERE connid = 17.
ENDFORM.<br>
FORM set_table.
  gx_grid->set_table_for_first_display(
      EXPORTING
        is_layout                     = gs_layout
      CHANGING
        it_outtab                     = gt_outtab
        it_fieldcatalog               = gt_fieldcat
      EXCEPTIONS
        invalid_parameter_combination = 1
        program_error                 = 2
        too_many_lines                = 3
    ).
  IF sy-subrc <> 0.
    MESSAGE 'Error calling Grid' TYPE 'E'.
  ENDIF.
  gx_grid->set_ready_for_input( ).
  gx_grid->register_edit_event(
    EXPORTING
      i_event_id = cl_gui_alv_grid=>mc_evt_modified ).
ENDFORM.<br>
FORM build_fieldcat.
  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name       = 'SFLIGHT'
    CHANGING
      ct_fieldcat            = gt_fieldcat
    EXCEPTIONS
      inconsistent_interface = 1
      program_error          = 2.
  IF sy-subrc <> 0.
    MESSAGE 'Error building Fieldcat' TYPE 'I' DISPLAY LIKE 'W'.
  ENDIF.
  LOOP AT gt_fieldcat ASSIGNING FIELD-SYMBOL(<ls_fieldcat>).
    <ls_fieldcat>-edit = abap_true. "Every field should be editable
  ENDLOOP.
ENDFORM.<br>
FORM build_layout.
  gs_layout-sel_mode = 'A'. "Multi row selection
ENDFORM.<br>
*&---------------------------------------------------------------------*
*&      Module  STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'STATUS'.
  PERFORM set_table.
ENDMODULE.<br>
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
  CASE g_ucomm.
    WHEN '&F15' OR '&F03' OR '&F15'.
      LEAVE PROGRAM.
  ENDCASE.
ENDMODULE.

I hope somebody can help me to solve my problem.

5 REPLIES 5
Read only

abo
Active Contributor
5,450

pro-tip: to avoid the html elements in the code (span and so on), switch back to display mode before copying.

Read only

thkolz
Contributor
0 Likes
5,450

Once I build a class ZCL_ALV myself.

This is what I found in my code. Maybe it helps you...

*--------------------------------------------------------------------
* Get outtab
*--------------------------------------------------------------------
ASSIGN me->t_outtab->* TO <fs_outtab>.
CHECK sy-subrc IS INITIAL.

*--------------------------------------------------------------------
* Create mod row table
*--------------------------------------------------------------------
ASSIGN ir_data_changed->mp_mod_rows->* TO <fs_mod_table>.<br>  CHECK sy-subrc IS INITIAL.

*--------------------------------------------------------------------
* Create key structure (only key fields)
*--------------------------------------------------------------------
CREATE DATA l_key TYPE HANDLE me->gr_key_structdescr.
ASSIGN l_key->* TO <fs_key>.
CHECK sy-subrc IS INITIAL.

IF me->t_modified_rows IS INITIAL.
* Table has not been created yet => Create it
  CREATE DATA me->t_modified_rows TYPE HANDLE me->gr_tabledescr.
ENDIF.
ASSIGN me->t_modified_rows->* TO <fs_modified_rows>.

*--------------------------------------------------------------------
* This code is obsolete, because issues occured when table was sorted
* and the lines were changed afterwards.
* Then the row ID in table <fs_modified_rows> was not up-to-date
*--------------------------------------------------------------------
Read only

Sandra_Rossi
Active Contributor
5,450

Thanks for the demo. I don't have time to investigate right now, but did you investigate the modification via the method MODIFY_CELL of parameter ER_DATA_CHANGED to see if it's the same error?

Read only

0 Likes
5,450

Using the MODIFY_CELL method actually solves the problem and also makes the code cleaner, because it gets rid of a lot of duplicate code, that really bothered me. Thank you very much!

In case somebody with the same problem stumbles upon this with the same problem, here is what my CHANGE_DATA method looks like now:

METHOD change_data.
DATA l_value TYPE lvc_value.
LOOP AT ix_data_changed->mt_mod_cells INTO DATA(ls_mod_cell).
CALL METHOD ix_data_changed->get_cell_value
EXPORTING
i_row_id = ls_mod_cell-row_id
i_fieldname = ls_mod_cell-fieldname
IMPORTING
e_value = l_value.
ix_data_changed->modify_cell(
EXPORTING
i_row_id = ls_mod_cell-row_id
i_tabix = ls_mod_cell-tabix
i_fieldname = ls_mod_cell-fieldname
i_value = l_value
).
ENDLOOP.
ENDMETHOD.

It's important to use the GET_CELL_VALUE method instead of just passing LS_MOD_CELL-VALUE to the MODIFY_CELL method. Because the GET_CELL_VALUE method converts the value into a format ABAP can work with. In the mod cell the value has the display format from ALV. For numbers this can be in a format like 1.234,56 which might cause errors or alter data, because ABAP interprets it wrong.

So just use the GET_CELL_VALUE method to retrieve the value and you should be safe.

Read only

0 Likes
5,450

Sandra Rossi solved the problem in the comments.