alv中,在条件过滤后,全选或取消全选时,会影响到所有数据(不仅仅过滤后的数据)的解决方法

本文介绍了一种在ABAP ALV表格中实现全选或取消全选功能的方法,该方法仅针对过滤后的数据进行操作,避免了影响到未过滤的数据。通过在内表中设置标志列,并利用特定的ABAP函数来实现这一功能。

alv展示数据时,有时需要全选或取消全选,对数据进行操作,一般的做法,在内表中给标志列赋值,但是,如果根据条件过滤数据后,全选或取消全选时,会影响到所有数据(不仅仅过滤后的数据),以下是解决方法:

*---------------------------------------------------------------------*
* FORM USER_COMMAND *
*---------------------------------------------------------------------*
FORM user_command USING rf_ucomm LIKE sy-ucomm
                          rs TYPE slis_selfield .           "#EC CALLED
  DATA:  wl_answer  TYPE c.
  DATAlr_grid TYPE REF TO cl_gui_alv_grid.
  DATA et_filtered    TYPE lvc_t_fidx.
  DATA:lv_tabix           TYPE sy-tabix.


  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid lr_grid.
  CALL METHOD lr_grid->check_changed_data.
  DATA:p_count TYPE i.
  rs-refresh 'X'.  "自动刷新


  CLEAR et_filtered.
  CALL METHOD lr_grid->get_filtered_entries
    IMPORTING
      et_filtered_entries et_filtered.

  CASE rf_ucomm.
    WHEN '&SALL'.
      LOOP AT result.
        lv_tabix sy-tabix.
        READ TABLE et_filtered WITH KEY table_line lv_tabix TRANSPORTING NO FIELDS.
        IF sy-subrc NE 0.
          result-chk 'X'.
          MODIFY result.
          CLEAR result.
        ENDIF.
      ENDLOOP.
    WHEN '&SCLL'.
      LOOP AT result.
        lv_tabix sy-tabix.
        READ TABLE et_filtered WITH KEY table_line lv_tabix TRANSPORTING NO FIELDS.
        IF sy-subrc NE 0.
          result-chk ''.
          MODIFY result.
          CLEAR result.
        ENDIF.
      ENDLOOP.

    WHEN '&FX11'.
      CLEAR wl_answer.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          text_question         '确定要删除所选信息吗?' "确定要删除吗?
          icon_button_1         '是' "text-035 "是
          icon_button_2         '否' "text-036 "否
          default_button        '2'
          display_cancel_button ''
          start_column          25
          start_row             6
        IMPORTING
          answer                wl_answer
        EXCEPTIONS
          text_not_found        1
          OTHERS                2.

      IF wl_answer '1'.
        CLEAR p_count.
        LOOP AT result WHERE chk 'X'.
          p_count p_count + 1.
        ENDLOOP.
        IF p_count <= 0.
          MESSAGE '请选择要删除的数据!' TYPE   'E'.
          STOP.
        ENDIF.

        PERFORM frm_del.

      ENDIF.
  ENDCASE.

  rs-refresh 'X'.
ENDFORM" USER_COMMAND

<think>我们正在讨论ABAP ALV可编辑数据更新的实现。用户需要示例代码。 在ABAP中,实现ALV可编辑并更新数据通常涉及以下步骤: 1. 定义内表结构,用于显示和编辑数据。 2. 创建ALV网格控件,并设置可编辑。 3. 实现数据修改的事件处理(例如DATA_CHANGED事件)。 4. 提供保存按钮类似机制,将修改写回数据库。 注意:ALV有两种主要形式:函数式ALV(如REUSE_ALV_GRID_DISPLAY)和面向对象的ALV(CL_GUI_ALV_GRID)。这里我们使用面向对象的ALV,因为它更灵活,更适合可编辑场景。 下面是一个简单的示例,展示如何创建一个可编辑的ALV并更新数据数据库表。 假设我们有一个数据库表ZTEST_TABLE(字段:MANDT, KEY_FIELD, VALUE_FIELD),我们将允许用户编辑VALUE_FIELD字段。 步骤: 1. 定义内表和工作区,结构同数据库表。 2. 创建屏幕(例如1000),放置一个容器控件和一个ALV网格。 3. 实例化ALV网格,设置内表数据,并启用编辑。 4. 注册事件处理程序,特别是DATA_CHANGED事件,用于验证输入。 5. 实现保存逻辑,将内表更改写回数据库。 代码示例: ```abap REPORT z_alv_editable_example. * 定义数据库表结构 TABLES: ztest_table. * 定义内表和工作区 DATA: gt_data TYPE TABLE OF ztest_table, gs_data TYPE ztest_table. * 定义ALV相关对象 DATA: go_container TYPE REF TO cl_gui_custom_container, go_grid TYPE REF TO cl_gui_alv_grid, gt_fieldcat TYPE lvc_t_fcat, gs_fieldcat TYPE lvc_s_fcat, gs_layout TYPE lvc_s_layo. * 定义事件处理类 CLASS lcl_event_handler DEFINITION. PUBLIC SECTION. METHODS: handle_data_changed FOR EVENT data_changed OF cl_gui_alv_grid IMPORTING er_data_changed. ENDCLASS. CLASS lcl_event_handler IMPLEMENTATION. METHOD handle_data_changed. " 这里可以添加数据更改的验证逻辑 " 例如,检查字段的有效性 ENDMETHOD. ENDCLASS. DATA: go_event_handler TYPE REF TO lcl_event_handler. * 选择屏幕 SELECTION-SCREEN BEGIN OF SCREEN 1000 AS WINDOW. SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. SELECTION-SCREEN END OF BLOCK b1. SELECTION-SCREEN END OF SCREEN 1000. START-OF-SELECTION. " 从数据库获取数据 SELECT * FROM ztest_table INTO TABLE gt_data. " 创建并显示ALV CALL SCREEN 1000. * 屏幕1000的PBO模块 MODULE status_1000 OUTPUT. SET PF-STATUS 'STATUS1000'. SET TITLEBAR 'TITLE1000'. " 创建容器 IF go_container IS INITIAL. CREATE OBJECT go_container EXPORTING container_name = 'CONTAINER1'. " 创建ALV网格 CREATE OBJECT go_grid EXPORTING i_parent = go_container. " 设置布局(可编辑) gs_layout-edit = 'X'. " 允许整个网格编辑 gs_layout-sel_mode = 'A'. " 选择模式 " 设置字段目录 PERFORM build_fieldcatalog. " 设置事件处理 CREATE OBJECT go_event_handler. SET HANDLER go_event_handler->handle_data_changed FOR go_grid. " 显示ALV CALL METHOD go_grid->set_table_for_first_display EXPORTING is_layout = gs_layout CHANGING it_outtab = gt_data it_fieldcatalog = gt_fieldcat. ENDIF. ENDMODULE. * 屏幕1000的PAI模块 MODULE user_command_1000 INPUT. CASE sy-ucomm. WHEN 'SAVE'. " 保存数据数据库 PERFORM save_data. WHEN 'EXIT' OR 'BACK' OR 'CANCEL'. LEAVE TO SCREEN 0. ENDCASE. ENDMODULE. * 构建字段目录 FORM build_fieldcatalog. CLEAR gt_fieldcat. " 定义KEY_FIELD字段 gs_fieldcat-fieldname = 'KEY_FIELD'. gs_fieldcat-ref_table = 'ZTEST_TABLE'. gs_fieldcat-key = 'X'. " 关键字段 APPEND gs_fieldcat TO gt_fieldcat. CLEAR gs_fieldcat. " 定义VALUE_FIELD字段,可编辑 gs_fieldcat-fieldname = 'VALUE_FIELD'. gs_fieldcat-ref_table = 'ZTEST_TABLE'. gs_fieldcat-edit = 'X'. " 可编辑 APPEND gs_fieldcat TO gt_fieldcat. CLEAR gs_fieldcat. " 其他字段同理... ENDFORM. * 保存数据 FORM save_data. " 首先,从ALV网格获取最新数据 CALL METHOD go_grid->check_changed_data. " 更新数据库 MODIFY ztest_table FROM TABLE gt_data. IF sy-subrc = 0. COMMIT WORK. MESSAGE '数据保存成功' TYPE 'S'. ELSE. ROLLBACK WORK. MESSAGE '保存失败' TYPE 'E'. ENDIF. ENDFORM. ``` 注意:以上代码是一个简化示例。实际应用中,可能需要更复杂的数据验证和错误处理。 另外,在事件处理程序`handle_data_changed`中,可以使用`er_data_changed`对象的方法来检查修改的单元格,例如: - 使用`er_data_changed->get_cell_value`获取单元格的值 - 使用`er_data_changed->modify_cell`来修改值(例如纠正错误) - 使用`er_data_changed->add_protocol_entry`记录错误消息 例如,在`handle_data_changed`方法中验证VALUE_FIELD不能为空: ```abap METHOD handle_data_changed. DATA: ls_mod_cells TYPE lvc_s_modi, lv_value TYPE string. " 遍历所有修改的单元格 LOOP AT er_data_changed->mt_mod_cells INTO ls_mod_cells. IF ls_mod_cells-fieldname = 'VALUE_FIELD'. " 获取新输入的值 CALL METHOD er_data_changed->get_cell_value EXPORTING i_row_id = ls_mod_cells-row_id i_fieldname = ls_mod_cells-fieldname IMPORTING e_value = lv_value. IF lv_value IS INITIAL. " 报告错误 CALL METHOD er_data_changed->add_protocol_entry EXPORTING i_msgid = 'E' i_msgty = 'E' i_msgno = '000' i_msgv1 = 'VALUE_FIELD不能为空' i_fieldname = ls_mod_cells-fieldname i_row_id = ls_mod_cells-row_id. ENDIF. ENDIF. ENDLOOP. ENDMETHOD. ``` 这样,当用户输入空值,会在ALV中显示错误消息。 以上示例展示了如何实现一个可编辑的ALV并更新数据库。根据实际需求,可能还需要调整字段目录、布局和事件处理逻辑。 §§相关问题§§ 1. 如何实现ALV单元格级别的验证? 2. 在ALV中如何实现下拉框(下拉列表)? 3. 如何优化ALV性能,特别是当数据量很大?</think>### ABAP ALV 可编辑数据更新实现指南 在 ABAP 中实现 ALV 可编辑数据更新需要以下关键步骤: #### 核心实现步骤 1. **定义数据结构** 创建与数据库表结构匹配的内表: ```abap DATA: gt_data TYPE TABLE OF zyour_table, " 替换为您的表名 gs_data TYPE zyour_table. ``` 2. **ALV 初始化** 使用 `CL_GUI_ALV_GRID` 创建可编辑网格: ```abap DATA: go_container TYPE REF TO cl_gui_custom_container, go_grid TYPE REF TO cl_gui_alv_grid. CREATE OBJECT go_container EXPORTING container_name = 'CC_ALV'. CREATE OBJECT go_grid EXPORTING i_parent = go_container. ``` 3. **设置编辑模式** 在布局中启用编辑: ```abap DATA: gs_layout TYPE lvc_s_layo. gs_layout-edit = 'X'. " 启用编辑模式 ``` 4. **注册数据更改事件** 实现 `DATA_CHANGED` 事件处理: ```abap CLASS lcl_event_handler DEFINITION. PUBLIC SECTION. METHODS: handle_data_changed FOR EVENT data_changed OF cl_gui_alv_grid IMPORTING er_data_changed. ENDCLASS. CLASS lcl_event_handler IMPLEMENTATION. METHOD handle_data_changed. " 此处添加数据验证逻辑 ENDMETHOD. ENDCLASS. ``` 5. **保存数据数据库** 实现保存功能: ```abap FORM save_data. CALL METHOD go_grid->check_changed_data. " 强制刷新更改 LOOP AT gt_data INTO gs_data WHERE flag = 'X'. " 假设有修改标记 MODIFY zyour_table FROM gs_data. ENDLOOP. COMMIT WORK. MESSAGE '数据已更新' TYPE 'S'. ENDFORM. ``` #### 完整示例代码 ```abap REPORT z_alv_editable_demo. TABLES: sflight. " 示例使用SAP标准表 DATA: gt_sflight TYPE TABLE OF sflight, go_grid TYPE REF TO cl_gui_alv_grid, go_container TYPE REF TO cl_gui_custom_container, gs_layout TYPE lvc_s_layo. " 事件处理类 CLASS lcl_events DEFINITION. PUBLIC SECTION. METHODS: handle_data_changed FOR EVENT data_changed OF cl_gui_alv_grid IMPORTING er_data_changed. ENDCLASS. CLASS lcl_events IMPLEMENTATION. METHOD handle_data_changed. " 简单验证示例:价格不能为负数 LOOP AT er_data_changed->mt_mod_cells ASSIGNING FIELD-SYMBOL(<mod>). IF <mod>-fieldname = 'PRICE' AND <mod>-value < 0. CALL METHOD er_data_changed->add_protocol_entry EXPORTING i_msgid = 'ZMSG' i_msgty = 'E' i_msgno = '001' i_fieldname = <mod>-fieldname i_row_id = <mod>-row_id. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. START-OF-SELECTION. SELECT * FROM sflight INTO TABLE gt_sflight UP TO 50 ROWS. CALL SCREEN 100. MODULE status_0100 OUTPUT. SET PF-STATUS 'MAIN'. SET TITLEBAR 'T100'. IF go_container IS INITIAL. " 创建容器和ALV CREATE OBJECT go_container EXPORTING container_name = 'CC_ALV'. CREATE OBJECT go_grid EXPORTING i_parent = go_container. " 设置布局 gs_layout-edit = 'X'. gs_layout-sel_mode = 'A'. " 注册事件 DATA(go_events) = NEW lcl_events( ). SET HANDLER go_events->handle_data_changed FOR go_grid. " 显示ALV CALL METHOD go_grid->set_table_for_first_display EXPORTING is_layout = gs_layout CHANGING it_outtab = gt_sflight. ENDIF. ENDMODULE. MODULE user_command_0100 INPUT. CASE sy-ucomm. WHEN 'SAVE'. PERFORM save_data. WHEN 'BACK' OR 'EXIT'. LEAVE PROGRAM. ENDCASE. ENDMODULE. FORM save_data. CALL METHOD go_grid->check_changed_data. MODIFY sflight FROM TABLE gt_sflight. IF sy-subrc = 0. COMMIT WORK. MESSAGE '数据更新成功' TYPE 'S'. ENDIF. ENDFORM. ``` #### 关键注意事项 1. **事件处理** - `DATA_CHANGED` 事件在用户修改单元格触发 - 使用 `ER_DATA_CHANGED->MT_MOD_CELLS` 获取修改记录 - 通过 `ADD_PROTOCOL_ENTRY` 添加验证错误 2. **数据保存** - 必须调用 `CHECK_CHANGED_DATA()` 方法刷新缓冲区 - 使用 `MODIFY ... FROM TABLE` 批量更新数据库 - 添加 `COMMIT WORK` 提交事务 3. **字段控制** 使用字段目录控制可编辑字段: ```abap DATA: gt_fieldcat TYPE lvc_t_fcat. gs_fieldcat-edit = 'X'. " 使特定字段可编辑 ``` #### 高级优化 1. **自动保存标记** 添加修改标志字段自动标记更改行: ```abap TYPES: BEGIN OF ty_data, mark TYPE c, " 其他字段... END OF ty_data. ``` 2. **批量操作支持** 实现全选/取消全选功能: ```abap METHOD handle_toolbar. e_object->mt_toolbar = VALUE #( ( function = 'SELECT_ALL' icon = '@2C@' quickinfo = '全选' ) ( function = 'DESELECT_ALL' icon = '@2D@' quickinfo = '取消全选' ) ). ENDMETHOD. ``` 3. **性能优化** - 使用 `SET_READY_FOR_INPUT(1)` 禁用渲染 - 大数据启用延迟滚动 [^1]: SAP 官方文档 - ALV Grid Control 编程指南 [^2]: ABAP 开发手册 - 数据持久化最佳实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChampaignWolf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值