SALV Editable with Single (custom) Method

不使用按钮

找到一个被触发但在输出显示给用户之前的事件。 找到一个可以在 Grid 和 Full Screen ALV 中工作的事件。

Full Screen ALV 触发 TOP_OF_PAGE 而不是 Grid ALV,至于 Grid 没有直接的 TOP_OF_PAGE。 Full Screen ALV 在使用 O_SALV->SET_TOP_OF_LIST( ) 方法创建页面顶部时触发它。 这也会在 ALV 中显示一个标题。 对于 Grid,您需要为 CL_DD_DOCUMENT 创建一个对象,将其传递给 Grid 对象并引发事件 TOP_OF_PAGE。 没有 Grid 开始,无法分配标题,因此无法使 TOP_OF_PAGE 事件起作用。

EVENT AFTER_REFRESH

系统完成 ALV 渲染后触发事件 AFTER_REFRESH – 解析字段目录、发送到 DP(数据提供者)又名前端的数据、应用布局、创建工具栏以及所有其他与 ALV 相关的内容。 现在,如何在没有 Grid 对象的情况下捕获此事件。 因此,声明了一个事件处理程序来处理类 CL_GUI_ALV_GRID 的事件 AFTER_REFRESH。 诀窍是使用 SET EVENT HANDLER 添加 FOR ALL INSTANCES 来注册事件。

To gain an access to the underlying object and do the magic"
SET HANDLER lo_event_h->on_after_refresh
  FOR ALL INSTANCES
  ACTIVATION X.

FOR ALL INSTANCES 非常强大。 它可以为该事件所属的任何对象注册该事件,即使该对象是在注册处理程序后实例化的。 这在这种情况下非常有用,因为 Grid 对象尚未实例化。

避免无限循环陷阱

要使 Grid 可编辑,可以使用以下 REFRESH_TABLE_DISPLAY() 调用或方法 SET_READY_FOR_INPUT 调用传递 LAYOUT-EDIT = ‘X’。 问题是,这两种方法都会调用方法 SOFT_REFRESH_TABLE_DISPLAY 并引发事件 AFTER_REFRESH。 这将再次被我们的事件处理程序捕获。 事件处理程序将通过刷新使网格再次可编辑——因此进入循环。

"Deregister the event handler"
SET HANDLER me->on_after_refresh
  FOR ALL INSTANCES
  ACTIVATION space.

为避免这种情况,我们将关闭 - 更技术地取消注册事件处理程序。 使用 SET HANDLER 中的附加 ACTIVATION 空间将为我们做到这一点。

工具栏

接下来是工具栏。 工具栏中的编辑按钮无需任何额外工作即可显示,但对于 Grid,有一些特殊的逻辑会阻止它在工具栏中创建编辑按钮。 这一切都发生在方法 CL_SALV_CONTROLLER_EVENTS=> RAISE_BUILD_UIFUNCTION 中,其中只显示了几个按钮。

因此,我们将欺骗工具栏添加相同的缺失按钮。 为此,我们需要为 CL_GUI_ALV_GRID 注册事件 TOOLBAR。 使用 FOR ALL INSTANCE 也可以这样做。

"Only for GRID, would need to add the toolbar buttons"
IF io_salv->get_display_object( ) = 3.
  SET HANDLER lo_event_h->on_toolbar
    FOR ALL INSTANCES
    ACTIVATION X.
ENDIF.

使其可编辑的单一方法

不是开箱即用的单一方法,但将所有这些逻辑都包含在一个方法中。 通过在 DISPLAY 方法之前传递 ALV 对象来调用此方法,一切都完成了。

该方法将注册事件 AFTER_REFRESH 和 TOOLBAR(用于网格)。 该类还在本地类中承载事件处理程序方法。 事件处理程序将使网格可编辑并在工具栏中添加按钮。 使其可编辑的所有复杂性都隐藏并包装在此方法中。

此外,此方法将控制多个 SALV 对象的逻辑。 使用具有对象池设计模式的事件处理程序的可选参数 SENDER。

"Make grid editable: call before display"
zcl_test_np_salv_model=>set_editable( go_alv ). 

实现结果

  • Full screen ALV generated by SALV in Editable mode
  • ALV Grid generated by SALV in Editable mode
  • Multiple Grid, only one is editable

完整代码实现

CLASS ZCL_TEST_NP_SALV_MODEL DEFINITION.
  PUBLIC FINAL create public.
  PUBLIC SECTION.
    class-methods SET_EDITABLE
        importing !IO_SALV type ref to CL_SALV_TABLE .
  PROTECTED SECTION.
  PRIVATE SECTION.
    class-data o_event_h type ref to OBJECT.
ENDCLASS.

CLASS ZCL_TEST_NP_SALV_MODEL IMPLEMENTATION.
  "IO_SALV TYPE REF TO CL_SALV_TABLE"
  METHOD set_editable.
    DATA: lo_event_h TYPE REF TO lcl_event_handler.
    "Event handler"
    IF zcl_test_np_salv_model=>o_event_h IS NOT BOUND.
      CREATE OBJECT zcl_test_np_salv_model=>o_event_h TYPE lcl_event_handler.
    ENDIF.
    lo_event_h ?= zcl_test_np_salv_model=>o_event_h.
    APPEND io_salv TO lo_event_h->t_salv.
    "To gain an access to the underlying object and do the magic"
    SET HANDLER lo_event_h->on_after_refresh FOR ALL INSTANCES ACTIVATION X.
    "only for GRID, would need to add the toolbar buttons"
    IF io_salv->get_display_object( ) = 3.
      SET HANDLER lo_event_h->on_toolbar FOR ALL INSTANCES ACTIVATION X.
    ENDIF.
  ENDMETHOD.
ENDCLASS.
*——————————————————————--------------—-*
* Event handler ALV events
*———————————————————————---------------*
CLASS lcl_event_handler DEFINITION.
  PUBLIC SECTION.
    METHODS: on_after_refresh FOR EVENT after_refresh OF cl_gui_alv_grid
               IMPORTING
                 sender,
             on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
               IMPORTING
                 e_object
                 e_interactive
                 sender.
  DATA: t_salv TYPE STANDARD TABLE OF REF TO cl_salv_table.
ENDCLASS.                    "lcl_event_handler DEFINITION"

CLASS lcl_event_handler IMPLEMENTATION.
  METHOD on_after_refresh.
    DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
    DATA: ls_layout TYPE lvc_s_layo.
    DATA: lo_salv TYPE REF TO cl_salv_table.
    TRY .
      LOOP AT t_salv INTO lo_salv.
        lo_grid = zcl_test_np_salv_model=>get_grid( lo_salv ).
        CHECK lo_grid EQ sender.
        "Deregister the event handler"
        SET HANDLER me->on_after_refresh FOR ALL INSTANCES ACTIVATION space.
        "Set editable"
        ls_layoutedit = X.
        lo_grid->set_frontend_layout( ls_layout ).
        lo_grid->set_ready_for_input( 1 ).
      ENDLOOP.
      CATCH cx_salv_error.
    ENDTRY.
  ENDMETHOD.                    "ON_AFTER_REFRESH"
  
  METHOD on_toolbar.
    DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
    DATA: ls_layout TYPE lvc_s_layo.
    DATA: mt_toolbar TYPE ttb_button.
    DATA: ls_toolbar LIKE LINE OF mt_toolbar.
    DATA: lo_salv TYPE REF TO cl_salv_table.
    TRY .
      LOOP AT t_salv INTO lo_salv.
        lo_grid = zcl_test_np_salv_model=>get_grid( lo_salv ).
        IF lo_grid EQ sender.
          EXIT.
        ELSE.
          CLEAR lo_grid.
        ENDIF.
      ENDLOOP.
      CATCH cx_salv_msg.
        EXIT.
    ENDTRY.
    CHECK lo_grid IS BOUND.
    CHECK lo_grid->is_ready_for_input( ) = 1.
    "Toolbar Button CHECK"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_check.
    ls_toolbarquickinfo  = text053.  "Eingaben prfen"
    ls_toolbaricon        = icon_check.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Seperator"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = &&SEP01.
    ls_toolbarbutn_type  = 3.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button CUT"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_cut.
    ls_toolbarquickinfo  = text046.  "Ausschneiden"
    ls_toolbaricon        = icon_system_cut.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button COPY"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_copy.
    ls_toolbarquickinfo  = text045.  "Kopieren"
    ls_toolbaricon        = icon_system_copy.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button PASTE OVER ROW"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_paste.
    ls_toolbarquickinfo  = text047.
    ls_toolbaricon        = icon_system_paste.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button PASTE NEW ROW"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_paste_new_row.
    ls_toolbarquickinfo  = text063.
    ls_toolbaricon        = icon_system_paste.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button UNDO"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_undo.
    ls_toolbarquickinfo  = text052.  Rckgngig
    ls_toolbaricon        = icon_system_undo.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Separator"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = &&SEP02.
    ls_toolbarbutn_type  = 3.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button APPEND ROW"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_append_row.
    ls_toolbarquickinfo  = text054.  Zeile anhngen"
    ls_toolbaricon        = icon_create.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button INSERT ROW"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_insert_row.
    ls_toolbarquickinfo  = text048.  Zeile einfgen
    ls_toolbaricon        = icon_insert_row.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button DELETE ROW"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_delete_row.
    ls_toolbarquickinfo  = text049.  Zeile lschen"
    ls_toolbaricon        = icon_delete_row.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Button COPY ROW"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = cl_gui_alv_grid=>mc_fc_loc_copy_row.
    ls_toolbarquickinfo  = text051.  Duplizieren"
    ls_toolbaricon        = icon_copy_object.
    ls_toolbardisabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
    "Toolbar Separator"
    CLEAR ls_toolbar.
    ls_toolbarfunction    = &&SEP03.
    ls_toolbarbutn_type  = 3.
    APPEND ls_toolbar TO mt_toolbar.
    APPEND LINES OF mt_toolbar TO e_object->mt_toolbar.
  ENDMETHOD.                    "on_toolbar"
ENDCLASS.                    "lcl_event_handler IMPLEMENTATION"

参考链接