您的位置:首页 > 其它

ALV data_change事件例子2

2017-10-16 22:32 1521 查看
program ztest_bcalv_edit_03.

*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

* Purpose:

* ~~~~~~~~

* In this example the user may change values of fields

* SEATSOCC (occupied seats) and/or PLANETYPE. The report checks

* the input value(s) semantically and provides protocol

* messages in case of error.

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

* To check program behavior

* ~~~~~~~~~~~~~~~~~~~~~~~~~

* Change values of the column "occupied seats" or "Planetype" or

* both (in the same line). Try to provocate errors.

* Click on the check symbol or press return to initiate checking.

* (ALV also checks input before any functions like sorting,

* filtering or doubleclick are processed. These functions are

* only active if the input does not contain any errors).

* The ALV Grid Control first checks if the input is correct

* according to DDIC-Information (Type, lenght). Then semantic

* checks are made by the application using event handler method

* HANDLE_DATA_CHANGED.

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

* Essential steps (search for '§')

* ~~~~~~~~~~~~~~~

* 1.Set status of columns PLANETYPE and SEATSOCC to editable.

* 2.Optionally restrict generic functions to 'change only'.

*   (The user shall not be able to add new lines).

* 3.Optionally register ENTER to raise event DATA_CHANGED.

*   (Per default the user may check data by using the check icon).

* 4.Define and implement event handler to handle event DATA_CHANGED.

* 5.Loop over table MT_GOOD_CELLS to check all values that are

*   valid due to checks according to information of the DDIC.

* 6.Within a check cycle:

* 6a.Get new cell value to check it using method GET_CELL_VALUE.

*    (In this case SEATSOCC).

* 6b.If the value is valid you may want to change values of

*    other cells.

* 6c.If the value is not valid create an protocol entry in

*    the application log.

* 6d.To access old values (which where not changed in this check cycle)

*    use your output table GT_OUTTAB.

* 7.Display application log if an error has occured.

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

*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

data: ok_code like sy-ucomm,

      save_ok like sy-ucomm,

      g_container type scrfname value 'BCALV_GRID_DEMO_0100_CONT1',

      g_grid  type ref to cl_gui_alv_grid,

      g_custom_container type ref to cl_gui_custom_container,

      gt_fieldcat type lvc_t_fcat,

      gs_layout type lvc_s_layo,

      g_max type i value 100.

* local class to handle semantic checks

class lcl_event_receiver definition deferred.

data: g_event_receiver type ref to lcl_event_receiver.

data: gt_outtab type table of sflight.

**************************************************************

* LOCAL CLASS Definition

**************************************************************

*§4.Define and implement event handler to handle event DATA_CHANGED.

*

class lcl_event_receiver definition.

 public section.

    methods:

      handle_data_changed

         for event data_changed of cl_gui_alv_grid

             importing er_data_changed.

 private section.

* This flag is set if any error occured in one of the

* following methods:

    data: error_in_data type c.

* Methods to modularize event handler method HANDLE_DATA_CHANGED:

    methods: check_planetype

     importing

        ps_good_planetype type lvc_s_modi

        pr_data_changed type ref to cl_alv_changed_data_protocol.

    methods: ch_new_plane_v_new_seatsocc

           importing

              psg_plane type lvc_s_modi

              psg_socc type lvc_s_modi

              ps_saplane type saplane

              pr_data_changed type ref to cl_alv_changed_data_protocol.

    methods: ch_new_plane_v_old_seatsocc

           importing

              psg_plane type lvc_s_modi

              ps_saplane type saplane

              pr_data_changed type ref to cl_alv_changed_data_protocol.

    methods: check_seatsocc

           importing

              ps_good type lvc_s_modi

              pr_data_changed type ref to cl_alv_changed_data_protocol.

*....................................................................

* This is a suggestion how you could comment your checks in each method:

*.....

* CHECK: fieldname(old/new value) !<comp> fieldname(old/new value)

* IF NOT: (What to tell the user is wrong about the input)

*......

* Remarks:

*  fieldname:       fieldname of table for the corresponding column

*  (old/new value): ckeck with value of GT_OUTTAB or MT_GOOD_CELLS.

*  !<comp>        : the value is valid if the condition <comp> holds.

*

* Example:

*  CHECK seatsocc(new) !>= seatsmax(old)

*  IF NOT: There are not enough number of seats according to this

*          planetype.

*.......................................................................

endclass.

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

class lcl_event_receiver implementation.

  method handle_data_changed.

BREAK-POINT.

    data: ls_good type lvc_s_modi.

   error_in_data = space.

* semantic checks

* Identify columns which were changed and check input

* against output table gt_outtab or other new input values of one row.

* Table er_data_changed->mt_good_cells holds all cells that

* are valid according to checks against their DDIC data.

* No matter in which order the input was made this table is

* ordered by rows (row_id). For each row, the entries are

* sorted by columns according to their order in the fieldcatalog

* (not the defined order using field COL_POS but the order

* given by the position of the record in the fieldcatalog).

* The order is relevant if new inputs in several columns of

* the same row are dependent. In this example,

* method 'ch_new_plane_v_new_seatsocc' needs only to be called

* once since we know that the corresponding check is already done

* when checking column PLANETYPE (see also method 'check_seatsocc').

*§5.Loop over table MT_GOOD_CELLS to check all values that are

*   valid due to checks according to information of the DDIC.

    loop at er_data_changed->mt_good_cells into ls_good.

      case ls_good-fieldname.

* check if column PLANETYPE of this row was changed

        when 'PLANETYPE'.

          call method check_planetype

                 exporting

                    ps_good_planetype = ls_good

                    pr_data_changed   = er_data_changed.

* check if column SEATSOCC of this row was changed

        when 'SEATSOCC'.

          call method check_seatsocc

                 exporting

                    ps_good         = ls_good

                    pr_data_changed = er_data_changed.

      endcase.

    endloop.

*§7.Display application log if an error has occured.

    if error_in_data eq 'X'.

       call method er_data_changed->display_protocol.

    endif.

  endmethod.

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

  method check_planetype.

*..................................................

* Overview of checks according to field PLANETYPE

* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* a) Does the Planetype exists? (check against check table SAPLANE)

* b) Are the number of seats (SEATSMAX) of the new planetype

*    sufficient to fullfill requested bookings (SEATSOCC)?

*    b1) SEATSOCC (occupied seats) also changed within

*        this check cycle.

*    b2) SEATSOCC has not changed within this cycle.

*

*...................................................

    data: l_planetype type s_planetye,

          ls_saplane type saplane,

          ls_good_seatsocc type lvc_s_modi.

* Get new cell value to check it.

* (In this case: PLANETYPE).

    call method pr_data_changed->get_cell_value

          exporting i_row_id =    ps_good_planetype-row_id

                    i_fieldname = ps_good_planetype-fieldname

          importing e_value     = l_planetype.

* existence check: Does the plane exists?

    select single * from saplane into ls_saplane where

                                     planetype = l_planetype.

    if sy-subrc ne 0.

* In case of error, create a protocol entry in the application log.

* Possible values for message type ('i_msgty'):

*

*    'A': Abort (Stop sign)

*    'E': Error (red LED)

*    'W': Warning (yellow LED)

*    'I': Information (green LED)

*
      call method pr_data_changed->add_protocol_entry

       exporting

          i_msgid = '0K' i_msgno = '000'  i_msgty = 'E'

          i_msgv1 = text-m03           "Flugzeugtyp

          i_msgv2 = l_planetype

          i_msgv3 = text-m05           "exitstiert nicht

          i_fieldname = ps_good_planetype-fieldname

          i_row_id = ps_good_planetype-row_id.


      error_in_data = 'X'.

      exit. "plane does not exit, so we're finished here!

    endif.

* Check if other relevant fields of this row have been changed, too.

    read table pr_data_changed->mt_good_cells into ls_good_seatsocc

                       with key row_id    = ps_good_planetype-row_id

                                fieldname = 'SEATSOCC'.

    if sy-subrc = 0.

      call method ch_new_plane_v_new_seatsocc

                   exporting

                    psg_plane  = ps_good_planetype

                    psg_socc   = ls_good_seatsocc

                    ps_saplane = ls_saplane

                    pr_data_changed = pr_data_changed.

    else.

      call method ch_new_plane_v_old_seatsocc

                   exporting

                    psg_plane       = ps_good_planetype

                    ps_saplane      = ls_saplane

                    pr_data_changed = pr_data_changed.

    endif.

  endmethod.                           " CHECK_PLANETYPE

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

  method ch_new_plane_v_new_seatsocc.

    data: l_seatsocc type s_seatsocc.

*§5a.Get new cell value to check it using method GET_CELL_VALUE.

* (In this case SEATSOCC).

    call method pr_data_changed->get_cell_value

           exporting i_row_id =    psg_socc-row_id

                     i_fieldname = psg_socc-fieldname

           importing e_value     = l_seatsocc.

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

* CHECK:  SEATSMAX(of new planetype) !>= SEATSOCC(new value)

* IF NOT: Message for wrong planetype

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

    if ps_saplane-seatsmax ge l_seatsocc.

*§5b.If the value is valid you may want to change values of

*    other cells.

      call method pr_data_changed->modify_cell

                exporting i_row_id    = psg_plane-row_id

                          i_fieldname = 'SEATSMAX'

                          i_value     = ps_saplane-seatsmax.

    else.

*§5c.If the value is not valid create an protocol entry in

*    the application log.

* Possible values for message type ('i_msgty'):

*

*    'A': Abort (Stop sign)

*    'E': Error (red LED)

*    'W': Warning (yellow LED)

*    'I': Information (green LED)

*

      call method pr_data_changed->add_protocol_entry

       exporting

          i_msgid = '0K' i_msgno = '000'  i_msgty = 'E'

          i_msgv1 = text-m03               "Flugzeugtyp

          i_msgv2 = ps_saplane-planetype

          i_msgv3 = text-m04               "hat nicht genug Sitzpl#tze

          i_fieldname = psg_plane-fieldname

          i_row_id = psg_plane-row_id.

      error_in_data = 'X'.

    endif.

  endmethod.

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

  method ch_new_plane_v_old_seatsocc.

    data: l_old_seatsocc type s_seatsocc,

          ls_outtab type sflight.

*§5d.To access old values (which where not changed in this check cycle)

*    use your output table GT_OUTTAB.

   read table gt_outtab into ls_outtab index psg_plane-row_id.

   l_old_seatsocc = ls_outtab-seatsocc.

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

* CHECK:  SEATSMAX(of new planetype) !>= SEATSOCC(old value)

* IF NOT: Message for wrong planetype

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

    if ps_saplane-seatsmax ge l_old_seatsocc.

* ok->field seatsmax can be changed

      call method pr_data_changed->modify_cell

                exporting i_row_id    = psg_plane-row_id

                          i_fieldname = 'SEATSMAX'

                          i_value     = ps_saplane-seatsmax.

    else.

      call method pr_data_changed->add_protocol_entry

       exporting

          i_msgid = '0K' i_msgno = '000'  i_msgty = 'E'

          i_msgv1 = text-m03                "Flugzeugtyp

          i_msgv2 = ps_saplane-planetype

          i_msgv3 = text-m04                 "hat nicht genug Sitzpl#tze

          i_fieldname = psg_plane-fieldname

          i_row_id = psg_plane-row_id.

      error_in_data = 'X'.

    endif.

  endmethod.

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

*&      Form  CHECK_SEATSOCC

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

*       text

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

*      -->P_LS_GOOD  text

*      -->P_ER_DATA_CHANGED  text

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

  method check_seatsocc.

    data: l_seatsocc type s_seatsocc,

          l_old_seatsmax type s_seatsmax,

          ls_outtab type sflight,

          ls_good type lvc_s_modi.

*.................................................................

* Check if the planetype has changed, too.

*.................................................................

    read table pr_data_changed->mt_good_cells into ls_good

                       with key row_id    = ps_good-row_id

                                fieldname = 'PLANETYPE'.

    if sy-subrc eq 0.

*....................................................

* remark: the check

*   seatsocc (new value) <= seatsmax (new value)

* was already handled by form 'ch_new_plane_v_new_seatsocc'.

* so we are finished here.

*.................................................

       exit.

    endif.

*.....................................................

* CHECK: seatsocc (new value) <= seatsmax (old value)

* IF NOT: Message that SEATSOCC is to high.

*.....................................................

* get new cell value of SEATSOCC.

    call method pr_data_changed->get_cell_value

          exporting i_row_id =    ps_good-row_id

                    i_fieldname = ps_good-fieldname

          importing e_value     = l_seatsocc.

* get old cell value of SEATSMAX

   read table gt_outtab into ls_outtab index ps_good-row_id.

   l_old_seatsmax = ls_outtab-seatsmax.

    if l_seatsocc > l_old_seatsmax.

      call method pr_data_changed->add_protocol_entry

        exporting

           i_msgid = '0K' i_msgno = '000'  i_msgty = 'E'

           i_msgv1 = text-m01  "Die Anzahl der belegten Pl#tze

           i_msgv2 = text-m02  "übersteigt die Kapazit#t des Flugzeugs

           i_msgv3 = ls_outtab-planetype

           i_fieldname = ps_good-fieldname

           i_row_id = ps_good-row_id.


      error_in_data = 'X'.

    endif.

  endmethod.                           " CHECK_SEATSOCC

endclass.

***************************************************************

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

*       MAIN                                                          *

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

end-of-selection.

  call screen 100.

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

*       MODULE PBO OUTPUT                                             *

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

module pbo output.

  set pf-status 'MAIN100'.

  set titlebar 'MAIN100'.

  if g_custom_container is initial.

    perform create_and_init_alv changing gt_outtab

                                         gt_fieldcat

                                         gs_layout.

  endif.

endmodule.

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

*       MODULE PAI INPUT                                              *

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

module pai input.

  save_ok = ok_code.

  clear ok_code.

  case save_ok.

    when 'EXIT'.

      perform exit_program.

    when others.

*     do nothing

  endcase.

endmodule.

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

*       FORM EXIT_PROGRAM                                             *

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

form exit_program.

  leave program.

endform.

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

*&      Form  BUILD_FIELDCAT

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

*       text

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

*      <--P_GT_FIELDCAT  text

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

form build_fieldcat changing pt_fieldcat type lvc_t_fcat.

  data ls_fcat type lvc_s_fcat.

  BREAK-POINT.

  call function 'LVC_FIELDCATALOG_MERGE'

       exporting

            i_structure_name = 'SFLIGHT'

       changing

            ct_fieldcat      = pt_fieldcat.

  loop at pt_fieldcat into ls_fcat.

    if    ls_fcat-fieldname eq 'PLANETYPE'

       or ls_fcat-fieldname eq 'SEATSOCC'.

*§1.Set status of columns PLANETYPE and SEATSOCC to editable.

      ls_fcat-edit = 'X'.

* Field 'checktable' is set to avoid shortdumps that are caused

* by inconsistend data in check tables. You may comment this out

* when the test data of the flight model is consistent in your system.

      ls_fcat-checktable = '!'.  "do not check foreign keys

      modify pt_fieldcat from ls_fcat.

    endif.

  endloop.

endform.

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

*&      Form  CREATE_AND_INIT_ALV

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

*       text

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

*      <--P_GT_OUTTAB  text

*      <--P_GT_FIELDCAT  text

*      <--P_GS_LAYOUT  text

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

form create_and_init_alv changing pt_outtab like gt_outtab[]

                                  pt_fieldcat type lvc_t_fcat

                                  ps_layout type lvc_s_layo.

  data: lt_exclude type ui_functions.

  create object g_custom_container

         exporting container_name = g_container.

  create object g_grid

         exporting i_parent = g_custom_container.

* Build fieldcat and set columns PLANETYPE and SEATSOCC

* edit enabled.

  perform build_fieldcat changing pt_fieldcat.

*§2.Optionally restrict generic functions to 'change only'.

*   (The user shall not be able to add new lines).

  perform exclude_tb_functions changing lt_exclude.

  select * from sflight into table pt_outtab up to g_max rows.

  call method g_grid->set_table_for_first_display

       exporting is_layout             = ps_layout

                 it_toolbar_excluding  = lt_exclude

       changing  it_fieldcatalog       = pt_fieldcat

                 it_outtab             = pt_outtab.

* set editable cells to ready for input

  CALL METHOD g_grid->set_ready_for_input

     EXPORTING

       I_READY_FOR_INPUT = 1.

*§3.Optionally register ENTER to raise event DATA_CHANGED.

*   (Per default the user may check data by using the check icon).

 call method g_grid->register_edit_event

               exporting

                  i_event_id = cl_gui_alv_grid=>mc_evt_enter.

  create object g_event_receiver.

  set handler g_event_receiver->handle_data_changed for g_grid.

endform.                               "CREATE_AND_INIT_ALV

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

*&      Form  EXCLUDE_TB_FUNCTIONS

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

*       text

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

*      <--P_LT_EXCLUDE  text

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

form exclude_tb_functions changing pt_exclude type ui_functions.

* Only allow to change data not to create new entries (exclude

* generic functions).

  data ls_exclude type ui_func.

  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_copy_row.

  append ls_exclude to pt_exclude.

  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_delete_row.

  append ls_exclude to pt_exclude.

  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_append_row.

  append ls_exclude to pt_exclude.

  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_insert_row.

  append ls_exclude to pt_exclude.

  ls_exclude = cl_gui_alv_grid=>mc_fc_loc_move_row.

  append ls_exclude to pt_exclude.

endform.                               " EXCLUDE_TB_FUNCTIONS
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  SAP abap alv