abap alv触发修改事件后更新内表数据失败随笔

文章详细描述了如何在ABAP编程中处理ALV表格的选中状态问题,包括数据同步和保存,以及如何通过事件处理机制在用户操作后更新内表数据。涉及的代码片段展示了如何在FORM中处理用户选择和数据变更,以及使用CALLBACK和EVENTS进行事件注册。
摘要由CSDN通过智能技术生成

目录

一、问题展示及解决

1、出现问题:在选中sel 选择框后,根据选中行条件同步选中其他行选择框,这是成功的,但是当再次选中别的行选择框后,第一次的选择数据却变为了未选中,数据没有保存下来,如下图所示:
在这里插入图片描述
这里内表里sel字段确实是X的状态
在这里插入图片描述
但第二次选中后,发现内表里第一次选中的sel变为空了,也就是第一次的sel实际上并没有成功更新到内表中,令人百思不得齐姐

2、解决问题
有没有发现选中后,行选择颜色变了,因为设置了这个语句:

gs_layout-box_fname = 'SEL'.

该语句的优先级高于fieldcat的选择框,导致了此现象

FORM init_fieldcat .
	DATA: lv_colpos TYPE lvc_s_fcat-col_pos.
	  REFRESH gt_fieldcat.
	  CLEAR:lv_colpos,gs_fieldcat.
	
	  DEFINE m_fieldcat.
	    lv_colpos = lv_colpos + 1.
	    gs_fieldcat-col_pos   = lv_colpos.  "显示位置
	    gs_fieldcat-fieldname = &1.         "字段名
	    gs_fieldcat-coltext   = &2.         "字段描述
	    gs_fieldcat-scrtext_s = &2.         "字段描述
	    gs_fieldcat-scrtext_m = &2.         "字段描述
	    gs_fieldcat-scrtext_l = &2.         "字段描述
	    gs_fieldcat-ref_table = &3.         "参考表
	    gs_fieldcat-ref_field = &4.         "参考字段
	    gs_fieldcat-edit      = &5.         "可否编辑
	    gs_fieldcat-outputlen = &6.         "输出长度
	    gs_fieldcat-no_zero   = &7.         "前导0
	    gs_fieldcat-just      = &8.         "对齐方式 R右 C中 L左
	    gs_fieldcat-hotspot   = &9.         "热点
	
	    IF gs_fieldcat-fieldname = 'SEL'.
	        gs_fieldcat-checkbox = 'X'.
	    ENDIF.
	    IF gs_fieldcat-fieldname = 'SEL' OR
	        gs_fieldcat-fieldname = 'STATUS' OR
	        gs_fieldcat-fieldname = 'MESSAGE' OR
	        gs_fieldcat-fieldname = 'WERKS' OR
	        gs_fieldcat-fieldname = 'MATNR' OR
	        gs_fieldcat-fieldname = 'VERID' .
	      gs_fieldcat-FIX_COLUMN = 'X'.
	    ENDIF.
	    APPEND gs_fieldcat TO gt_fieldcat.
	    CLEAR gs_fieldcat.
	  END-OF-DEFINITION.
	  
	m_fieldcat 'SEL'       '选择'        ''      ''      'X' '3'   ''  'C' '' .
ENDFORM.

把报表layout级的选择框语句去掉即可
在这里插入图片描述

二、修改数据更新至内表语句

FORM user_command USING r_ucomm LIKE sy-ucomm
  rs_selfield TYPE slis_selfield.

  DATA: lv_flg TYPE char01.
  rs_selfield-refresh = 'X'.    "控制从内部表内容向ALV屏幕更新数据

  DATA: lr_grid TYPE REF TO cl_gui_alv_grid.
  IF lr_grid IS INITIAL.
    CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
      IMPORTING
        e_grid = lr_grid.
  ENDIF.

  CALL METHOD lr_grid->check_changed_data.
  rs_selfield-refresh = 'X'.
  rs_selfield-col_stable = 'X'.
  rs_selfield-row_stable = 'X'.

  CASE r_ucomm.
    WHEN 'BACK'.
      LEAVE TO SCREEN 0.
    WHEN 'EXIT'.
      LEAVE PROGRAM.

    WHEN 'ALL'.
      gs_bb-sel = 'X'.
      MODIFY gt_bb FROM gs_bb TRANSPORTING sel WHERE sel = ''.

    WHEN 'SAL'.
      gs_bb-sel = ''.
      MODIFY gt_bb FROM gs_bb TRANSPORTING sel WHERE sel = 'X'.

    WHEN 'POST'.
      PERFORM frm_send_data.
  ENDCASE.

	rs_selfield-refresh = 'X'.
  CALL METHOD lr_grid->refresh_table_display.
ENDFORM. "USER_COMMAND

三、change事件注册demo

1、alv REUSE_ALV_GRID_DISPLAY_LVC展示函数注册并监听修改事件

DATA: gs_setting  TYPE lvc_s_glay.
DATA: gs_event  type slis_alv_event,
      gt_events type table of slis_alv_event.

FORM frm_display .
  gs_setting-edt_cll_cb = 'X'.                "参数回调
  "注册CALLER_EXIT事件,在CALLER_EXIT事件中注册其他事件
  CLEAR: gs_event  ,gt_events[].
  gs_event-name = 'DATA_CHANGED'.                                   "设置注册的事件
  gs_event-form = 'FRM_DATA_CHANGE'.                             "设置响应事件的FORM
  APPEND gs_event TO gt_events.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid
      i_callback_pf_status_set = 'PF_STATUS_SET'
      i_callback_user_command  = 'USER_COMMAND'
      it_events                = gt_events[]
      is_layout_lvc            = gs_layout
      it_fieldcat_lvc          = gt_fieldcat
      i_grid_settings          = gs_setting               "设置参数回调,屏幕修改值,自动保存到ALV 内表
*     I_DEFAULT                = 'X'
      i_save                   = 'A'
    TABLES
      t_outtab                 = gt_alv[]
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.
form frm_data_change  using rr_data_changed type ref to  cl_alv_changed_data_protocol.

  data: l_name     type char20,
        lw_stable  type lvc_s_stbl,
        ls_cells   type lvc_s_modi.
  data: l_grid     type ref to cl_gui_alv_grid.    "用来获取最新值
  data l_message   type char100.
  data:lv_change_flag(1).
*设置ALV刷新时的焦点,避免每次刷新都自动跳到第一列
  lw_stable-row = 0.
  lw_stable-col = 0.

* 取当前ALV信息
  call function 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    importing
      e_grid = l_grid.

  loop at rr_data_changed->mt_mod_cells into ls_cells.               "读取被修改了的单元格
    read table gt_alv  into gw_alv index ls_cells-row_id.   "读取修改行号
    case ls_cells-fieldname.
       when 'SEL'.
        gw_alv-sel = ls_cells-value.

      when others.
    endcase.

    modify gt_alv from gw_alv  index ls_cells-row_id .

  endloop.

  call method l_grid->refresh_table_display
    exporting
      is_stable = lw_stable.                  "刷新ALV

endform.   

2、事件类方式注册修改change事件
(1)、事件类定义及实现

*----------------------------------------------------------------------*
*       CLASS lcl_event_receiver IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_event_receiver DEFINITION.
  PUBLIC SECTION.
    DATA: ucomm TYPE sy-ucomm.

    METHODS handle_data_changed FOR EVENT data_changed OF cl_gui_alv_grid
      IMPORTING er_data_changed.

    METHODS handle_data_changed_finished FOR EVENT data_changed_finished OF cl_gui_alv_grid
      IMPORTING e_modified et_good_cells sender.

  PRIVATE SECTION.
ENDCLASS.
*----------------------------------------------------------------------*
*       CLASS lcl_event_receiver IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_event_receiver IMPLEMENTATION.
  METHOD handle_data_changed.      "修改前触发
*    PERFORM frm_when_changed USING er_data_changed.
  ENDMETHOD.                    "handle_data_changed

  METHOD handle_data_changed_finished.   "修改后触发
    PERFORM frm_finished_changed USING e_modified et_good_cells.
  ENDMETHOD.                    "handle_data_changed_finished

ENDCLASS.                    "lcl_event_receiver IMPLEMENTATION

DATA: event_receiver TYPE REF TO lcl_event_receiver.

*& INITIALIZATION/选择屏幕前初始化                                     *
*&---------------------------------------------------------------------*
INITIALIZATION.
**&---屏幕初始化

(2)、事件绑定alv

*&---------------------------------------------------------------------*
*&      Form  FRM_DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_GT_DD  text
*----------------------------------------------------------------------*
FORM frm_display .

  gs_setting-edt_cll_cb = 'X'.                  "参数回调
  "注册CALLER_EXIT事件,在CALLER_EXIT事件中注册其他事件
  CLEAR: gt_events,gt_events[].
  gt_events-name = 'CALLER_EXIT'.                                   "设置注册的事件
  gt_events-form = 'FRM_EVENTS_CALLER'.                             "设置响应事件的FORM
  APPEND gt_events.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid
      i_callback_pf_status_set = 'PF_STATUS_SET'
      i_callback_user_command  = 'USER_COMMAND'
      it_events                = gt_events[]
      is_layout_lvc            = gs_layout
      it_fieldcat_lvc          = gt_fieldcat
      i_grid_settings          = gs_setting               "设置参数回调,屏幕修改值,自动保存到ALV 内表
*     I_DEFAULT                = 'X'
      i_save                   = 'A'
    TABLES
      t_outtab                 = gt_bb[]
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  frm_events_caller
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->LS_DATA    text
*----------------------------------------------------------------------*
FORM frm_events_caller USING ls_data TYPE slis_data_caller_exit.        "ls_data形参
  DATA: lr_grid TYPE REF TO cl_gui_alv_grid.
  IF lr_grid IS INITIAL.
    CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
      IMPORTING
        e_grid = lr_grid.
  ENDIF.

  "如果call ALV未设置参数回调参数I_GRID_SETTINGS,需要注册EDIT事件
*  CALL METHOD go_grid->register_edit_event
*    EXPORTING
*      i_event_id = cl_gui_alv_grid=>mc_evt_modified.

  CREATE OBJECT event_receiver.
  SET HANDLER event_receiver->handle_data_changed FOR lr_grid.
  SET HANDLER event_receiver->handle_data_changed_finished FOR lr_grid.

ENDFORM.                    "frm_events_caller

(3)、触发事件业务逻辑实现form块

*&---------------------------------------------------------------------*
*&      Form  frm_when_changed
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PR_DATA_CHANGED  text
*----------------------------------------------------------------------*
FORM frm_when_changed  USING    pr_data_changed TYPE REF TO cl_alv_changed_data_protocol.


*  DATA: ls_mod_cells TYPE lvc_s_modi.
*
*  DATA lt_errormsg TYPE tsmesg.
*  DATA ls_errormsg LIKE LINE OF lt_errormsg.
*  CLEAR:lt_errormsg[], ls_errormsg.
*
*
* IF pr_data_changed->mt_mod_cells IS NOT INITIAL.
*    READ TABLE pr_data_changed->mt_mod_cells INTO ls_mod_cells INDEX 1.
*    IF sy-subrc EQ 0.
*      ls_errormsg-msgty = 'S'.
*      ls_errormsg-arbgb = 'Z001'.
*      ls_errormsg-txtnr =  '001'.
*      ls_errormsg-msgv1 = |行:{ ls_mod_cells-row_id }值即将被改变|.
*      APPEND ls_errormsg TO lt_errormsg.
*
*      IF lt_errormsg[] IS NOT INITIAL.
*        CALL FUNCTION 'FB_MESSAGES_DISPLAY_POPUP'
*          EXPORTING
*            it_smesg        = lt_errormsg[]
*          EXCEPTIONS
*            no_messages     = 1
*            popup_cancelled = 2
*            OTHERS          = 3.
*      ENDIF.
*    ENDIF.
*
*  ENDIF.
ENDFORM.                    "frm_when_changed
*&---------------------------------------------------------------------*
*&      Form  frm_finished_changed
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PV_MODIFIED    text
*      -->PT_GOOD_CELLS  text
*----------------------------------------------------------------------*
FORM frm_finished_changed  USING    pv_modified
                                    pt_good_cells TYPE lvc_t_modi.

  DATA: ls_mod_cells TYPE lvc_s_modi.
  DATA: lw_stable  TYPE lvc_s_stbl.

*设置ALV刷新时的焦点,避免每次刷新都自动跳到第一列
  lw_stable-row = 0.
  lw_stable-col = 0.

  IF pt_good_cells  IS NOT INITIAL.
    READ TABLE pt_good_cells INTO ls_mod_cells INDEX 1.
    IF sy-subrc EQ 0.
      READ TABLE gt_bb INTO gs_bb INDEX ls_mod_cells-row_id.
      IF sy-subrc = 0.
        MODIFY gt_bb FROM gs_bb TRANSPORTING sel WHERE matnr = gs_bb-matnr
                                                 AND   werks = gs_bb-werks.
      ENDIF.
    ENDIF.
  ENDIF.

  DATA: lr_grid TYPE REF TO cl_gui_alv_grid.
  IF lr_grid IS INITIAL.
    CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
      IMPORTING
        e_grid = lr_grid.
  ENDIF.

  "Refresh ALV display
  CALL METHOD lr_grid->refresh_table_display
    EXPORTING
      is_stable = lw_stable.                  "刷新ALV

ENDFORM.                    "frm_finished_changed

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值