Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
10,964

Recently I had trouble with and editable ALV. The problem was that when loading data via code and showing it in the editable ALV, I could not manage to force the validations on the new records. So when the user hit save, the invalid records were save to the database.

I found a workaround to this issue in the following way:

After calling the method to display the ALV, I appended a number of rows equals to the number of the new records with method "append_rows" of the alv object and immediately after that I call method "check_changed_data". Then in the method that handles the data changed, I update the new empty rows in the parameter internal table "er_data_changed->mp_mod_rows" with the new data.

I am pasting a example source code, I hope you find it helpful.

Also, you might want to look into how to update records via code, for example, if you want to display the name of a customer and you only let the user fill the customer number. In this example code, the user can fill in a cell a vendor number, and then the ALV automatically displays the vendor name in the next cell.

This is also solved in the method you define to handle the data changed. In this code example this method is called handle_data_changed. After the user modifies a cell with a vendor number, the method handle_data_changed is called and there you have to update the parameter internal table "er_data_changed->mp_mod_rows" with the vendor name, then also you need to add a row in parameters "er_data_changed->mt_mod_cells" and "er_data_changed->mt_good_cells" with the information of cells of the vendors names.

*----------------------------------------------------------------------*

*Declaring types

*----------------------------------------------------------------------*

TYPE-POOLS : slis.

TYPES: BEGIN OF ty_data.

INCLUDE  TYPE zptp_sourcing_alv2.

TYPES:   mod_type TYPE string.      " type of modification (for protocol)

TYPES:   verified(1) TYPE c.           " flag for verification

TYPES:   celltab  TYPE lvc_t_styl.

TYPES: END OF ty_data.

TYPES:

  ty_t_data    TYPE STANDARD TABLE OF ty_data WITH NON-UNIQUE DEFAULT KEY.

TYPES: BEGIN OF ty_lfa1,

        lifnr     TYPE lfa1-lifnr,

        name1     TYPE lfa1-name1,

       END OF ty_lfa1.

CLASS cl_event_handler DEFINITION DEFERRED.

*----------------------------------------------------------------------*

* Constants                                                            *

*----------------------------------------------------------------------*

CONSTANTS:

  c_back_command            TYPE sy-ucomm VALUE 'BACK',

  c_exit_command            TYPE sy-ucomm VALUE 'EXIT',

  c_plant_prefix            TYPE c        VALUE 'P',

  c_matnr(5)                TYPE c        VALUE 'MATNR',

  c_werks(5)                TYPE c        VALUE 'WERKS',

  c_ekorg(5)                TYPE c        VALUE 'EKORG',

  c_vdatu(5)                TYPE c        VALUE 'VDATU',

  c_bdatu(5)                TYPE c        VALUE 'BDATU',

  c_insert(6)               TYPE c        VALUE 'INSERT',

  c_update(6)               TYPE c        VALUE 'UPDATE',

  c_delete(6)               TYPE c        VALUE 'DELETE',

  c_check_command(5)        TYPE c        VALUE 'CHECK',

  c_save_command(4)         TYPE c        VALUE 'SAVE',

  c_vendor1_name(12)        TYPE c        VALUE 'VENDOR1_NAME',

  c_vendor2_name(12)        TYPE c        VALUE 'VENDOR2_NAME',

  c_vendor3_name(12)        TYPE c        VALUE 'VENDOR3_NAME'.

"ALV variables

DATA:

  i_alv_data            TYPE ty_t_data,

  i_alv_data_new_rec    TYPE ty_t_data,

  o_grid                TYPE REF TO cl_gui_alv_grid,

  o_cont                TYPE REF TO cl_gui_custom_container,

  i_fcat                TYPE lvc_t_fcat,

  ok_code               LIKE sy-ucomm,

  o_event_handler       TYPE REF TO cl_event_handler.

"Internal tables and work areas

DATA:

  i_zptp_sourcing         TYPE TABLE OF zptp_sourcing,

  wa_zptp_sourcing        LIKE LINE OF i_zptp_sourcing,

  wa_xord                 TYPE zptp_xord,

  wa_variant              TYPE disvariant,

  wa_alv_data             TYPE ty_data.

"variables

DATA:

  g_matnr                 TYPE mara-matnr,

  g_werks                 TYPE marc-werks,

  g_updatable             TYPE boolean.

*----------------------------------------------------------------------*

*       CLASS cl_event_handler DEFINITION

*----------------------------------------------------------------------*

CLASS cl_event_handler DEFINITION FINAL.

  PUBLIC SECTION.

    CLASS-DATA:

      data_changed_error  TYPE i,        " error flag

      protocol_tab        TYPE ty_t_data.  " protocol of changes since last save

    METHODS handle_toolbar

      FOR EVENT toolbar OF cl_gui_alv_grid

        IMPORTING

          e_object

          e_interactive ##needed.

    METHODS handle_user_command

      FOR EVENT user_command OF cl_gui_alv_grid

        IMPORTING

          e_ucomm.

    METHODS handle_data_changed

      FOR EVENT data_changed OF cl_gui_alv_grid

        IMPORTING

          er_data_changed.

    METHODS protocol_add

      IMPORTING

        im_tabix        TYPE i

        im_data_changed TYPE REF TO cl_alv_changed_data_protocol.

    METHODS wrong_dates

      IMPORTING

        im_tabix        TYPE i

        im_data_changed TYPE REF TO cl_alv_changed_data_protocol.

    METHODS required_field

      IMPORTING

        im_tabix        TYPE i

        im_data_changed TYPE REF TO cl_alv_changed_data_protocol

        im_fieldname    TYPE lvc_fname.

ENDCLASS.                    "cl_event_handler DEFINITION

*----------------------------------------------------------------------*

*  MODULE pbo_0100 OUTPUT

*----------------------------------------------------------------------*

MODULE pbo_0100 OUTPUT.

  PERFORM f_alv_init.

ENDMODULE.                    "pbo_0100 OUTPUT

*----------------------------------------------------------------------*

*  MODULE pai_0100 INPUT

*----------------------------------------------------------------------*

MODULE pai_0100 INPUT.

  PERFORM f_user_command.

ENDMODULE.                    "pai_0100 INPUT

*----------------------------------------------------------------------*

*       CLASS cl_event_handler IMPLEMENTATION

*----------------------------------------------------------------------*

CLASS cl_event_handler IMPLEMENTATION.

*&---------------------------------------------------------------------*

*&      METHOD handle_toolbar

*&---------------------------------------------------------------------*

  METHOD handle_toolbar.

    FIELD-SYMBOLS:

      <fs_button> TYPE stb_button.

    IF g_updatable EQ abap_true.

*     replace the standard function 'check' with own one

      READ TABLE e_object->mt_toolbar ASSIGNING <fs_button>

        WITH KEY function = cl_gui_alv_grid=>mc_fc_check. " '&CHECK'.

      "QA note: small table and internal of alv object, not sorting is necesary

      <fs_button>-function = 'CHECK'.

    ENDIF.

  ENDMETHOD.                    "handle_toolbar

*&---------------------------------------------------------------------*

*&      METHOD handle_user_command

*&---------------------------------------------------------------------*

  METHOD handle_user_command.

*   force PAI processing with user function as ok_code

    cl_gui_cfw=>set_new_ok_code( e_ucomm ).

  ENDMETHOD.                    "handle_user_command

*&---------------------------------------------------------------------*

*&      METHOD handle_data_changed

*&---------------------------------------------------------------------*

*&      validate changes against duplicate keys and collect the protocol

*&      of the changes for further db update or transport of changes

*&---------------------------------------------------------------------*

  METHOD handle_data_changed.

    DATA:

      l_wa_row          TYPE lvc_s_moce,

      l_wa_cell         TYPE lvc_s_modi,

      l_wa_mod_cell     TYPE lvc_s_modi,

      l_wa_data         TYPE ty_data,

      l_wa_data2        TYPE ty_data,

      lv_tabix          TYPE i,

      lv_tabix2         TYPE i,

      lv_new            TYPE i.

    FIELD-SYMBOLS:

      <ft_data>       TYPE ty_t_data,

      <fs_cell>       TYPE lvc_s_modi.

    ASSIGN er_data_changed->mp_mod_rows->* TO <ft_data>.

    "If there are initial records that don't exist in database to be inserted in grid

    IF i_alv_data_new_rec IS NOT INITIAL.

      LOOP AT i_alv_data_new_rec

        INTO wa_alv_data.

        MODIFY <ft_data>

          FROM wa_alv_data

          INDEX sy-tabix.

      ENDLOOP.

      REFRESH i_alv_data_new_rec.

    ENDIF.

*     consider present error messages from standard data checks

    IF lines( er_data_changed->mt_protocol ) = 0.

      data_changed_error = 0.

    ELSE.

      data_changed_error = 1.

    ENDIF.

*      "Fill additional information

    PERFORM f_vendors_name CHANGING <ft_data>.

    LOOP AT <ft_data>

      INTO wa_alv_data.

      lv_tabix = sy-tabix.

      CLEAR l_wa_mod_cell.

      READ TABLE er_data_changed->mt_mod_cells INTO l_wa_cell WITH KEY tabix = lv_tabix.

      IF sy-subrc EQ 0.

        l_wa_mod_cell-fieldname = c_vendor1_name.

        l_wa_mod_cell-row_id = l_wa_cell-row_id.

        l_wa_mod_cell-tabix = lv_tabix.

        APPEND l_wa_mod_cell TO er_data_changed->mt_mod_cells.

        APPEND l_wa_mod_cell TO er_data_changed->mt_good_cells.

        l_wa_mod_cell-fieldname = c_vendor2_name.

        APPEND l_wa_mod_cell TO er_data_changed->mt_mod_cells.

        APPEND l_wa_mod_cell TO er_data_changed->mt_good_cells.

        l_wa_mod_cell-fieldname = c_vendor3_name.

        APPEND l_wa_mod_cell TO er_data_changed->mt_mod_cells.

        APPEND l_wa_mod_cell TO er_data_changed->mt_good_cells.

      ENDIF.

    ENDLOOP.

*     1. collect the deleted rows (no checks needed)

    LOOP AT er_data_changed->mt_deleted_rows INTO l_wa_row.

      READ TABLE i_alv_data INTO l_wa_data INDEX l_wa_row-row_id.

*        "QA note: Not using binary search, in order to not interfere with current sorting of table

      l_wa_data-mod_type = 'DELETE'.

      APPEND l_wa_data TO protocol_tab.

    ENDLOOP.

*     2. collect the 'old' changed rows (no changes on key fields)

    LOOP AT <ft_data> INTO l_wa_data

      WHERE verified = abap_true.

      l_wa_data-mod_type = 'UPDATE'.

      APPEND l_wa_data TO protocol_tab.

    ENDLOOP.

*     3. check the new rows against the old, verified rows (verified once, which means keys are correct

*    "and we can find them in the alv table )

    LOOP AT <ft_data> INTO l_wa_data

      WHERE verified NE abap_true.

      lv_tabix = sy-tabix.

      ADD 1 TO lv_new.

      READ TABLE i_alv_data TRANSPORTING NO FIELDS

        WITH KEY ekorg = l_wa_data-ekorg

                 vdatu = l_wa_data-vdatu

                 bdatu = l_wa_data-bdatu.

*        "QA note: Not using binary search, in order to not interfere with current sorting of table

      CHECK sy-subrc = 0.

*      data_changed_error = 1.

      CALL METHOD protocol_add

        EXPORTING

          im_tabix        = lv_tabix

          im_data_changed = er_data_changed.

    ENDLOOP.

*     4. check the new rows among themselves

    IF lv_new > 1.

      LOOP AT <ft_data> INTO l_wa_data

        WHERE verified NE abap_true.

        lv_tabix = sy-tabix.

        LOOP AT <ft_data> INTO l_wa_data2

          WHERE verified NE abap_true.

          lv_tabix2 = sy-tabix.

          CHECK lv_tabix2 <> lv_tabix.

          CHECK l_wa_data2-ekorg = l_wa_data-ekorg

            AND l_wa_data2-vdatu = l_wa_data-vdatu

            AND l_wa_data2-bdatu = l_wa_data-bdatu.

*          data_changed_error = 1.

          CALL METHOD protocol_add

            EXPORTING

              im_tabix        = lv_tabix

              im_data_changed = er_data_changed.

          CALL METHOD protocol_add

            EXPORTING

              im_tabix        = lv_tabix2

              im_data_changed = er_data_changed.

        ENDLOOP.

      ENDLOOP.

    ENDIF.

*      "Other validations

    LOOP AT <ft_data> INTO l_wa_data

      WHERE verified NE abap_true.

      lv_tabix = sy-tabix.

      IF l_wa_data-vdatu IS INITIAL.

        CALL METHOD required_field

          EXPORTING

            im_tabix        = lv_tabix

            im_data_changed = er_data_changed

            im_fieldname    = 'VDATU'.

      ENDIF.

      IF l_wa_data-bdatu IS INITIAL.

        CALL METHOD required_field

          EXPORTING

            im_tabix        = lv_tabix

            im_data_changed = er_data_changed

            im_fieldname    = 'BDATU'.

      ENDIF.

      IF l_wa_data-ekorg IS INITIAL.

        CALL METHOD required_field

          EXPORTING

            im_tabix        = lv_tabix

            im_data_changed = er_data_changed

            im_fieldname    = 'EKORG'.

      ENDIF.

      IF l_wa_data-vdatu GT l_wa_data-bdatu.

        CALL METHOD wrong_dates

          EXPORTING

            im_tabix        = lv_tabix

            im_data_changed = er_data_changed.

      ENDIF.

    ENDLOOP.

*     5. last aktivities in event DATA_CHANGED

    LOOP AT <ft_data> INTO l_wa_data

      WHERE verified NE abap_true.

      lv_tabix = sy-tabix.

*      "looking for a modified cell of row

      READ TABLE er_data_changed->mt_mod_cells INTO l_wa_cell WITH KEY tabix = sy-tabix.

*        "QA note: Not using binary search, in order to not interfere with current sorting of table

      CHECK sy-subrc EQ 0.

      "looking for errors of this record

      READ TABLE er_data_changed->mt_protocol TRANSPORTING NO FIELDS WITH KEY row_id = l_wa_cell-row_id.

*        "QA note: Not using binary search, in order to not interfere with current sorting of table

      CHECK sy-subrc <> 0.

*       if there are no errors

*       collect new rows

      l_wa_data-mod_type = 'INSERT'.

      APPEND l_wa_data TO protocol_tab.

*       Disable key fields

      LOOP AT er_data_changed->mt_good_cells ASSIGNING <fs_cell>

        WHERE tabix = lv_tabix.

        READ TABLE i_fcat TRANSPORTING NO FIELDS WITH KEY fieldname = <fs_cell>-fieldname

                                                           key       = abap_true.

*        "QA note: Not using binary search, in order to not interfere with current sorting of table

        CHECK sy-subrc = 0.

        <fs_cell>-style = cl_gui_alv_grid=>mc_style_disabled.

      ENDLOOP.

    ENDLOOP.

  ENDMETHOD.                    "handle_data_changed

*&---------------------------------------------------------------------*

*&      METHOD protocol_add

*&---------------------------------------------------------------------*

  METHOD protocol_add.

    DATA:

      l_wa_cell       TYPE lvc_s_modi,

      l_wa_fcat       TYPE lvc_s_fcat,

      lv_string     TYPE string,

      lv_msgv1      TYPE symsgv,

      lv_msgv2      TYPE symsgv,

      l_wa_roid_front TYPE lvc_s_roid,

      lv_row_id     TYPE i.

    LOOP AT im_data_changed->mt_mod_cells INTO l_wa_cell

      WHERE tabix = im_tabix.

*     report only key fields

      READ TABLE i_fcat INTO l_wa_fcat WITH KEY fieldname = l_wa_cell-fieldname.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

      CHECK l_wa_fcat-key = abap_true.

*     report only once

      READ TABLE im_data_changed->mt_protocol TRANSPORTING NO FIELDS

        WITH KEY fieldname = l_wa_cell-fieldname

                 row_id    = l_wa_cell-row_id.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

      CHECK sy-subrc <> 0.

*     map the row id between frontend and internal tables for the message

      READ TABLE im_data_changed->mt_roid_front INTO l_wa_roid_front

        WITH KEY row_id = l_wa_cell-row_id.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

      lv_row_id = sy-tabix.

      lv_msgv1 = 'Row &1:'(005).

      lv_string = lv_row_id.

      REPLACE SUBSTRING '&1' IN lv_msgv1 WITH lv_string.

      lv_msgv2 = 'Duplicate key with value "&1"'(006).

      lv_string = l_wa_cell-value.

      REPLACE SUBSTRING '&1' IN lv_msgv2 WITH lv_string.

      data_changed_error = 1.

      CALL METHOD im_data_changed->add_protocol_entry

        EXPORTING

          i_msgid     = '0K'

          i_msgno     = '000'

          i_msgty     = 'E'

          i_msgv1     = lv_msgv1

          i_msgv2     = lv_msgv2

          i_fieldname = l_wa_cell-fieldname

          i_row_id    = l_wa_cell-row_id.    " pass the row id without mapping here

    ENDLOOP.

  ENDMETHOD.                    "protocol_add

*&---------------------------------------------------------------------*

*&      METHOD required_field

*&---------------------------------------------------------------------*

  METHOD required_field.

    DATA:

      l_wa_cell     TYPE lvc_s_modi,

      lv_string     TYPE string,

      lv_msgv1      TYPE symsgv,

      lv_msgv2      TYPE symsgv,

      l_wa_roid_front TYPE lvc_s_roid,

      lv_row_id     TYPE i.

    READ TABLE im_data_changed->mt_mod_cells

      INTO l_wa_cell

      WITH KEY tabix = im_tabix

               fieldname = im_fieldname.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

    IF sy-subrc EQ 0.

*     map the row id between frontend and internal tables for the message

      READ TABLE im_data_changed->mt_roid_front

        INTO l_wa_roid_front

        WITH KEY row_id = l_wa_cell-row_id.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

      IF sy-subrc EQ 0.

        lv_row_id = sy-tabix.

        lv_msgv1 = 'Row &1:'(005).

        lv_string = lv_row_id.

        REPLACE SUBSTRING '&1' IN lv_msgv1 WITH lv_string.

        lv_msgv2 = 'Please fill this field'(007).

        data_changed_error = 1.

        CALL METHOD im_data_changed->add_protocol_entry

          EXPORTING

            i_msgid     = '0K'

            i_msgno     = '000'

            i_msgty     = 'E'

            i_msgv1     = lv_msgv1

            i_msgv2     = lv_msgv2

            i_fieldname = l_wa_cell-fieldname

            i_row_id    = l_wa_cell-row_id.    " pass the row id without mapping here

      ENDIF.

    ENDIF.

  ENDMETHOD.                    "required_field

*&---------------------------------------------------------------------*

*&      METHOD wrong_dates

*&---------------------------------------------------------------------*

  METHOD wrong_dates.

    DATA:

      l_wa_cell       TYPE lvc_s_modi,

      lv_string       TYPE string,

      lv_msgv1        TYPE symsgv,

      lv_msgv2        TYPE symsgv,

      l_wa_roid_front TYPE lvc_s_roid,

      lv_row_id       TYPE i.

    READ TABLE im_data_changed->mt_mod_cells

      INTO l_wa_cell

      WITH KEY tabix = im_tabix

               fieldname = 'VDATU'.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

    IF sy-subrc EQ 0.

*     map the row id between frontend and internal tables for the message

      READ TABLE im_data_changed->mt_roid_front

        INTO l_wa_roid_front

        WITH KEY row_id = l_wa_cell-row_id.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

      IF sy-subrc EQ 0.

        lv_row_id = sy-tabix.

        lv_msgv1 = 'Row &1:'(005).

        lv_string = lv_row_id.

        REPLACE SUBSTRING '&1' IN lv_msgv1 WITH lv_string.

        lv_msgv2 = 'Initial date can not be greater than end date'(008).

        data_changed_error = 1.

        CALL METHOD im_data_changed->add_protocol_entry

          EXPORTING

            i_msgid     = '0K'

            i_msgno     = '000'

            i_msgty     = 'E'

            i_msgv1     = lv_msgv1

            i_msgv2     = lv_msgv2

            i_fieldname = l_wa_cell-fieldname

            i_row_id    = l_wa_cell-row_id.    " pass the row id without mapping here

      ENDIF.

    ENDIF.

    READ TABLE im_data_changed->mt_mod_cells

      INTO l_wa_cell

      WITH KEY tabix = im_tabix

               fieldname = 'BDATU'.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

    IF sy-subrc EQ 0.

*     map the row id between frontend and internal tables for the message

      READ TABLE im_data_changed->mt_roid_front

        INTO l_wa_roid_front

        WITH KEY row_id = l_wa_cell-row_id.

*      "QA note: Not using binary search, in order to not interfere with current sorting of table,

*      "and is a small table

      IF sy-subrc EQ 0.

        lv_row_id = sy-tabix.

        lv_msgv1 = 'Row &1:'(005).

        lv_string = lv_row_id.

        REPLACE SUBSTRING '&1' IN lv_msgv1 WITH lv_string.

        lv_msgv2 = 'Initial date can not be greater than end date'(008).

        CALL METHOD im_data_changed->add_protocol_entry

          EXPORTING

            i_msgid     = '0K'

            i_msgno     = '000'

            i_msgty     = 'E'

            i_msgv1     = lv_msgv1

            i_msgv2     = lv_msgv2

            i_fieldname = l_wa_cell-fieldname

            i_row_id    = l_wa_cell-row_id.    " pass the row id without mapping here

      ENDIF.

    ENDIF.

  ENDMETHOD.                    "wrong_dates

ENDCLASS.                    "cl_event_handler IMPLEMENTATION

*&---------------------------------------------------------------------*

*&      Form  F_GET_DEFAULT_VARI

*&---------------------------------------------------------------------*

*       Get Default Variant

*----------------------------------------------------------------------*

FORM f_get_default_vari .

  CLEAR:wa_variant.

  wa_variant-report = sy-repid.

  CALL FUNCTION 'REUSE_ALV_VARIANT_DEFAULT_GET'

    EXPORTING

      i_save     = 'A'

    CHANGING

      cs_variant = wa_variant

    EXCEPTIONS

      not_found  = 2.

  IF sy-subrc NE 0.

    CLEAR wa_variant-variant.

  ENDIF.

ENDFORM.                    " F_GET_DEFAULT_VARI

*&---------------------------------------------------------------------*

*&      Form  f_fieldcat_create

*&---------------------------------------------------------------------*

FORM f_fieldcat_create.

  FIELD-SYMBOLS:

    <fs_fcat> TYPE lvc_s_fcat.

  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'

    EXPORTING

      i_structure_name = 'ZPTP_SOURCING_ALV2'

    CHANGING

      ct_fieldcat      = i_fcat.

  LOOP AT i_fcat ASSIGNING <fs_fcat>.

    IF g_updatable EQ abap_true.

      IF   <fs_fcat>-fieldname NE c_vendor1_name"'vendor1_name'

       AND <fs_fcat>-fieldname NE c_vendor2_name"'vendor2_name'.

       AND <fs_fcat>-fieldname NE c_vendor3_name."'vendor3_name'.

        <fs_fcat>-edit = abap_true.

      ENDIF.

    ENDIF.

    IF   <fs_fcat>-fieldname = c_matnr"'MATNR'

      OR <fs_fcat>-fieldname = c_werks."'WERKS'.

      <fs_fcat>-no_out = abap_true.

    ENDIF.

*   key fields

    IF   <fs_fcat>-fieldname = c_matnr"'MATNR'

      OR <fs_fcat>-fieldname = c_werks"'WERKS'

      OR <fs_fcat>-fieldname = c_ekorg"'EKORG'

      OR <fs_fcat>-fieldname = c_vdatu"'VDATU'

      OR <fs_fcat>-fieldname = c_bdatu."'BDATU'.

      <fs_fcat>-key = abap_true.

    ELSE.

      <fs_fcat>-key = ''.

    ENDIF.

  ENDLOOP.

ENDFORM.                    "f_fieldcat_create

*&---------------------------------------------------------------------*

*&      Form  f_data_key_readonly_set

*&---------------------------------------------------------------------*

FORM f_data_key_readonly_set USING    fp_fcat TYPE lvc_t_fcat

                           CHANGING fp_data TYPE ty_t_data.

  DATA:

    lt_style TYPE lvc_t_styl,

    l_wa_style TYPE lvc_s_styl,

    l_wa_fcat  TYPE lvc_s_fcat.

  FIELD-SYMBOLS:

    <fs_data> TYPE ty_data.

* the following construct works well for function 'copy row' (MC_FC_LOC_COPY_ROW)

* (the style of the whole row is not copied and the key fields are open for change)

* first deactivate complete row for edit

  l_wa_style-style = cl_gui_alv_grid=>mc_style_disabled.

  INSERT l_wa_style INTO TABLE lt_style.

  LOOP AT fp_fcat INTO l_wa_fcat

    WHERE NOT key = abap_true.

*   then activate non-key fields that should be editable

    IF   l_wa_fcat-fieldname NE c_vendor1_name"'vendor1_name'

     AND l_wa_fcat-fieldname NE c_vendor2_name"'vendor2_name'.

     AND l_wa_fcat-fieldname NE c_vendor3_name."'vendor3_name'.

      l_wa_style-fieldname = l_wa_fcat-fieldname.

      l_wa_style-style = cl_gui_alv_grid=>mc_style_enabled.

      INSERT l_wa_style INTO TABLE lt_style.

    ENDIF.

  ENDLOOP.

  LOOP AT fp_data ASSIGNING <fs_data>.

    <fs_data>-celltab = lt_style.

  ENDLOOP.

ENDFORM.                    "f_data_key_readonly_set

*&---------------------------------------------------------------------*

*&      Form  f_data_verified_set

*&---------------------------------------------------------------------*

FORM f_data_verified_set CHANGING fp_data TYPE ty_t_data.

  FIELD-SYMBOLS:

    <fs_data> TYPE ty_data.

  LOOP AT fp_data ASSIGNING <fs_data>

    WHERE verified NE abap_true.

    <fs_data>-verified = abap_true.

  ENDLOOP.

ENDFORM.                    "f_data_verified_set

*&---------------------------------------------------------------------*

*&      Form  f_data_change_post_processing

*&---------------------------------------------------------------------*

FORM f_data_change_post_processing CHANGING fp_data TYPE ty_t_data.

* check all rows as verified

  PERFORM f_data_verified_set CHANGING fp_data.

* deactivate edit mode of key fields

  PERFORM f_data_key_readonly_set USING    i_fcat

                                CHANGING fp_data.

* refresh ALV grid from internal table

  CALL METHOD o_grid->refresh_table_display.

ENDFORM.                    "f_data_change_post_processing

*&---------------------------------------------------------------------*

*&      Form  f_data_save

*&---------------------------------------------------------------------*

FORM f_data_save.

  DATA:

    l_wa_data    TYPE ty_data,

    l_wa_db_data TYPE zptp_sourcing.

  LOOP AT cl_event_handler=>protocol_tab INTO l_wa_data.

*    "Global values

    l_wa_db_data-matnr = g_matnr.

    l_wa_db_data-werks = g_werks.

*    "Updated values

    l_wa_db_data-ekorg    = l_wa_data-ekorg.

    l_wa_db_data-vdatu    = l_wa_data-vdatu.

    l_wa_db_data-bdatu    = l_wa_data-bdatu.

    l_wa_db_data-vendor1  = l_wa_data-vendor1.

    l_wa_db_data-vendor2  = l_wa_data-vendor2.

    l_wa_db_data-vendor3  = l_wa_data-vendor3.

    l_wa_db_data-text     = l_wa_data-text.

    CASE l_wa_data-mod_type.

      WHEN c_insert."'INSERT'.

        INSERT zptp_sourcing FROM l_wa_db_data.

      WHEN c_update."'UPDATE'.

        UPDATE zptp_sourcing FROM l_wa_db_data.

      WHEN c_delete."'DELETE'.

        DELETE zptp_sourcing FROM l_wa_db_data.

    ENDCASE.

  ENDLOOP.

  COMMIT WORK.

  MESSAGE s010 WITH 'Data saved'(001).

ENDFORM.                    "f_data_save

*&---------------------------------------------------------------------*

*&      Form  f_alv_init

*&---------------------------------------------------------------------*

FORM f_alv_init.

  DATA:

    l_wa_layout TYPE lvc_s_layo.

  IF o_cont IS INITIAL.

    SET TITLEBAR 'ZZSOURCING'.

    IF g_updatable EQ abap_true.

      SET PF-STATUS 'ZZSOURCING'.

    ELSE.

      SET PF-STATUS 'ZZSOURCING'

        EXCLUDING c_save_command.

    ENDIF.

    CREATE OBJECT o_cont

      EXPORTING

        container_name = 'CONT1_0100'.

    CREATE OBJECT o_grid

      EXPORTING

        i_parent = o_cont.

    CREATE OBJECT o_event_handler.

    SET HANDLER o_event_handler->handle_toolbar      FOR o_grid.

    SET HANDLER o_event_handler->handle_user_command FOR o_grid.

    SET HANDLER o_event_handler->handle_data_changed FOR o_grid.

    l_wa_layout-stylefname = 'CELLTAB'.

    l_wa_layout-val_data = 'C'.

    CALL METHOD o_grid->set_table_for_first_display

      EXPORTING

        is_layout       = l_wa_layout

        is_variant      = wa_variant

        i_save          = 'A'

      CHANGING

        it_fieldcatalog = i_fcat

        it_outtab       = i_alv_data.

    CALL METHOD o_grid->register_edit_event

      EXPORTING

        i_event_id = cl_gui_alv_grid=>mc_evt_enter.

*    "add rows that don't exist in data base to grid

    IF i_alv_data_new_rec IS NOT INITIAL.

      CALL METHOD o_grid->append_rows

        EXPORTING

          i_row_count = lines( i_alv_data_new_rec ).

      CALL METHOD o_grid->check_changed_data.

    ENDIF.

  ENDIF.

ENDFORM.                    "f_alv_init

*&---------------------------------------------------------------------*

*&      Form  f_user_command

*&---------------------------------------------------------------------*

FORM f_user_command.

  DATA:

    l_v_ans                 TYPE c.

  CALL METHOD cl_gui_cfw=>dispatch.

  CASE ok_code.

    WHEN c_exit_command OR

         c_back_command.

      IF g_updatable EQ abap_true.

*       1. synchronize the internal table

        CALL METHOD o_grid->check_changed_data.

*       2. if the data was changed

        "If there are changes, ask wheter user wants to save

        IF NOT cl_event_handler=>protocol_tab IS INITIAL.

          PERFORM f_confirm_if_user_wants_save CHANGING l_v_ans.

          CASE l_v_ans.

            WHEN 'J'.

*             3. if there are no duplicated keys

              IF cl_event_handler=>data_changed_error = 0.

*               post processing after successful synchronization

                PERFORM f_data_change_post_processing CHANGING i_alv_data.

*          *     save the delta changes in database

                PERFORM f_data_save.

*          *     clear the protocol

                CLEAR cl_event_handler=>protocol_tab.

              ENDIF.

            WHEN OTHERS.

              SET SCREEN 0.

              LEAVE SCREEN.

          ENDCASE.

        ELSE.

          SET SCREEN 0.

          LEAVE SCREEN.

        ENDIF.

      ELSE.

        SET SCREEN 0.

        LEAVE SCREEN.

      ENDIF.

    WHEN c_check_command."'CHECK'.

      IF g_updatable EQ abap_true.

*       1. synchronize the internal table and check against duplicate keys

        CALL METHOD o_grid->check_changed_data.

*       2. if there are no duplicated keys

        IF cl_event_handler=>data_changed_error = 0.

*         post processing after successful synchronization

          PERFORM f_data_change_post_processing CHANGING i_alv_data.

          MESSAGE i010 WITH 'There are no data inconsistencies'(004).

        ENDIF.

      ENDIF.

    WHEN c_save_command."'SAVE'.

      IF g_updatable EQ abap_true.

*       1. synchronize the internal table

        CALL METHOD o_grid->check_changed_data.

*       2. if there are no duplicated keys

        IF cl_event_handler=>data_changed_error = 0.

*         post processing after successful synchronization

          PERFORM f_data_change_post_processing CHANGING i_alv_data.

*         3. if the data was changed

          IF NOT cl_event_handler=>protocol_tab IS INITIAL.

*           save the delta changes in database

            PERFORM f_data_save.

*           clear the protocol

            CLEAR cl_event_handler=>protocol_tab.

          ELSE.

            MESSAGE i010 WITH 'There is no data to update'(003).

          ENDIF.

        ENDIF.

      ENDIF.

  ENDCASE.

  CLEAR ok_code.

ENDFORM.                    "f_user_command

*&---------------------------------------------------------------------*

*&      Form  f_confirm_if_user_wants_save

*&---------------------------------------------------------------------*

FORM f_confirm_if_user_wants_save    CHANGING fp_ans TYPE c.

  DATA: lv_ans.

  CALL FUNCTION 'POPUP_TO_CONFIRM_DATA_LOSS'

    EXPORTING

      defaultoption = 'J'

      titel         = 'Data has changed'(010)

      start_column  = 25

      start_row     = 6

    IMPORTING

      answer        = lv_ans.

  fp_ans = lv_ans.

ENDFORM.                    "f_confirm_if_user_wants_save

*&---------------------------------------------------------------------*

*&      Form  F_REFRESH_GLOBAL_DATA

*&---------------------------------------------------------------------*

FORM f_refresh_global_data .

  IF NOT o_cont IS INITIAL.

    CALL METHOD o_cont->free.

  ENDIF.

  CALL METHOD cl_gui_cfw=>flush.

  CLEAR:

    cl_event_handler=>data_changed_error,

    o_grid,

    o_cont,

    o_event_handler,

    ok_code,

    wa_zptp_sourcing,

    wa_xord,

    wa_variant,

    wa_alv_data,

    g_matnr,

    g_werks,

    g_updatable

      .

  REFRESH:

    i_alv_data,

    i_alv_data_new_rec,

    i_fcat,

    i_zptp_sourcing,

    cl_event_handler=>protocol_tab.

ENDFORM.                    " F_REFRESH_GLOBAL_DATA

*&---------------------------------------------------------------------*

*&      Form  F_LOCK_TABLE

*&---------------------------------------------------------------------*

FORM f_lock_table .

  CALL FUNCTION 'ENQUEUE_EZPTP_SOURCING'

    EXPORTING

      matnr          = g_matnr

      werks          = g_werks

    EXCEPTIONS

      foreign_lock   = 1

      system_failure = 2

      OTHERS         = 3.

  IF sy-subrc NE 0.

    g_updatable = space.

    MESSAGE i010 WITH 'Sourcing information for this material'(002)

                       'and plant is currently being edited'(009).

  ELSE.

    g_updatable = abap_true.

  ENDIF.

ENDFORM.                    " F_LOCK_TABLE

*&---------------------------------------------------------------------*

*&      Form  F_REMOVE_LOCK

*&---------------------------------------------------------------------*

FORM f_remove_lock .

  IF g_updatable EQ abap_true.

    CALL FUNCTION 'DEQUEUE_EZPTP_SOURCING'

      EXPORTING

        matnr = g_matnr

        werks = g_werks.

  ENDIF.

ENDFORM.                    " F_REMOVE_LOCK

*&---------------------------------------------------------------------*

*&      Form  F_VENDORS_NAME

*&---------------------------------------------------------------------*

*       Find vendors name

*----------------------------------------------------------------------*

*      <--FP_I_ALV_DATA  Internal table vendors information

*----------------------------------------------------------------------*

FORM f_vendors_name  CHANGING fp_data TYPE ty_t_data.

  FIELD-SYMBOLS:

    <fs_data> TYPE ty_data.

  DATA:

    l_i_lfa1  TYPE TABLE OF ty_lfa1,

    l_wa_lfa1 TYPE ty_lfa1.

  IF fp_data[] IS NOT INITIAL.

    SELECT lifnr

           name1

      FROM lfa1

      INTO TABLE l_i_lfa1

      FOR ALL ENTRIES IN fp_data

      WHERE lifnr EQ fp_data-vendor1

         OR lifnr EQ fp_data-vendor2

         OR lifnr EQ fp_data-vendor3.

    IF sy-subrc EQ 0.

      SORT l_i_lfa1

        BY lifnr.

    ELSE.

      REFRESH l_i_lfa1.

    ENDIF.

  ENDIF.

  LOOP AT fp_data ASSIGNING <fs_data>.

    READ TABLE l_i_lfa1

      INTO l_wa_lfa1

      WITH KEY lifnr = <fs_data>-vendor1

      BINARY SEARCH.

    IF sy-subrc EQ 0.

      <fs_data>-vendor1_name = l_wa_lfa1-name1.

    ELSE.

      CLEAR <fs_data>-vendor1_name.

    ENDIF.

    READ TABLE l_i_lfa1

      INTO l_wa_lfa1

      WITH KEY lifnr = <fs_data>-vendor2

      BINARY SEARCH.

    IF sy-subrc EQ 0.

      <fs_data>-vendor2_name = l_wa_lfa1-name1.

    ELSE.

      CLEAR <fs_data>-vendor2_name.

    ENDIF.

    READ TABLE l_i_lfa1

      INTO l_wa_lfa1

      WITH KEY lifnr = <fs_data>-vendor3

      BINARY SEARCH.

    IF sy-subrc EQ 0.

      <fs_data>-vendor3_name = l_wa_lfa1-name1.

    ELSE.

      CLEAR <fs_data>-vendor3_name.

    ENDIF.

  ENDLOOP.

ENDFORM.                    " F_VENDORS_NAME

2 Comments