ALV data_change事件例子2

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值