利用 ALV 实现增删改查系列之二:仅让 ALV 报表某一列允许被编辑试读版

本系列前一篇文章 69. 利用 ALV 实现增删改查系列之一:让 ALV 报表进入可编辑状态,我们介绍了如何让 SAP ABAP ALV 报表进入可编辑状态。在该状态下,ALV 报表的每一行,每一列都可以被任意修改,如下图所示:

但是在实际的项目中,更常见的需求是,ALV 报表只允许部分列能够编辑。

本文介绍只将 ALV 报表的部分列设置为可编辑状态的技术实现。

先看一下实现的效果。执行报表,发现 ALV 背景色为灰色,意味着这个报表默认状态为不可编辑。点击工具栏的眼镜笔图标:

此时只有 Airfare 列可以被编辑,其他列仍然处于不可编辑状态。

下面是实现关键点介绍。

  1. 因为从本例开始,我们实际上将输出内容从逻辑上拆分成两部分,一部分可编辑,另一部分不可编辑。我们需要通过某种数据结构,告诉 ALV 框架如何区分这两部分。这个数据结构就是下图红色区域所示。其中第 11 行 INCLUDE STRUCTURE sflight 即 ALV 输出的业务数据即 sflight 数据库表的内容。第 12 行定义的 celltab 即是控制结构,该结构负责维护 ALV 某一列是否允许被编辑。

  1. 调用第 31 行 set_table_for_first_display 进行 ALV 输出时,输入参数 gs_layout 的 stylefname 字段值设置为 CELLTAB, 意思是告诉 ALV 报表框架程序,输出数据结构 gt_outtab 内表里行结构的 CELLLTAB 字段,负责控制 ALV 列的可编辑性。

  1. 在第 62 行,通过 SELECT SQL 语句,将 sflight 数据库表里的数据读取出来,写到 ALV 报表调用 set_table_for_first_display 的输出内表 gt_outtab 中。这只是完成了业务数据的读取,接下来从 68 行开始的 LOOP 循环,遍历 ALV 待输出的每一条 sflight 数据,在代码第 71 行判断,如果检测到其 seatsmax 字段值大于 300,就允许这一列的某个字段可以被编辑,反之设置成只读。

下图 72 行调用 fill_celltab 这个 subroutine,传入 RW 代表 Read & Write,可读可写。RO 的意思是 Read-Only, 只读。

那么当 seatsmax 大于 300 时,到底我们允许哪一个字段可以被编辑呢?这就得进入 fill_celltab 内部去查看。

可以看到,除了第 103 行的 PRICE 字段的编辑性,我们根据传入的 p_mode 的不同,分别进行设置之外,其他所有字段,都设置成 cl_gui_alv_grid=>mc_style_disabled 即禁用,也就是不可编辑。

如果 subroutine 传入的 p_mode 值为 RW,则 PRICE 设置为 cl_gui_alv_grid=>mc_style_enabled,即允许编辑。

本例剩下的其他逻辑,同本系列前一篇文章介绍的步骤完全一致:

本例完整源代码:

REPORT z.

DATA: ok_code            LIKE sy-ucomm,
      save_ok            LIKE sy-ucomm,
      g_container        TYPE scrfname VALUE 'ALV_CONTAINER',
      grid1              TYPE REF TO cl_gui_alv_grid,
      g_custom_container TYPE REF TO cl_gui_custom_container,
      gs_layout          TYPE lvc_s_layo.

DATA: BEGIN OF gt_outtab OCCURS 0.
        INCLUDE STRUCTURE sflight.
        DATA: celltab TYPE lvc_t_styl.
DATA: END OF gt_outtab.

CALL SCREEN 100.

MODULE pbo OUTPUT.
  SET PF-STATUS 'MAIN100'.
  SET TITLEBAR 'MAIN100'.
  IF g_custom_container IS INITIAL.
    CREATE OBJECT g_custom_container
      EXPORTING
        container_name = g_container.
    CREATE OBJECT grid1
      EXPORTING
        i_parent = g_custom_container.
    PERFORM select_data_and_init_style.

    gs_layout-stylefname = 'CELLTAB'.

    CALL METHOD grid1->set_table_for_first_display
      EXPORTING
        i_structure_name = 'SFLIGHT'
        is_layout        = gs_layout
      CHANGING
        it_outtab        = gt_outtab[].
  ENDIF.
ENDMODULE.

MODULE pai INPUT.
  save_ok = ok_code.
  CLEAR ok_code.
  CASE save_ok.
    WHEN 'EXIT'.
      PERFORM exit_program.
    WHEN 'SWITCH'.
      PERFORM switch_edit_mode.
    WHEN OTHERS.
  ENDCASE.
ENDMODULE.

FORM exit_program.
  LEAVE PROGRAM.
ENDFORM.

FORM select_data_and_init_style.
  DATA: lt_sflight TYPE TABLE OF sflight,
        ls_sflight LIKE LINE OF lt_sflight,
        lt_celltab TYPE lvc_t_styl,
        l_index    TYPE i.

  SELECT * FROM sflight INTO TABLE lt_sflight UP TO 10 ROWS.
  LOOP AT lt_sflight INTO ls_sflight.
    MOVE-CORRESPONDING ls_sflight TO gt_outtab.
    APPEND gt_outtab.
  ENDLOOP.

  LOOP AT gt_outtab.
    l_index = sy-tabix.
    REFRESH lt_celltab.
    IF gt_outtab-seatsmax GE 300.
      PERFORM fill_celltab USING 'RW'
                           CHANGING lt_celltab.
    ELSE.
      PERFORM fill_celltab USING 'RO'
                           CHANGING lt_celltab.
    ENDIF.
    INSERT LINES OF lt_celltab INTO TABLE gt_outtab-celltab.
    MODIFY gt_outtab INDEX l_index.
  ENDLOOP.
ENDFORM.                               " SELECT_DATA_AND_INIT_STYLE

FORM fill_celltab USING VALUE(p_mode)
                  CHANGING pt_celltab TYPE lvc_t_styl.
  DATA: ls_celltab TYPE lvc_s_styl,
        l_mode     TYPE raw4.

  IF p_mode EQ 'RW'.
    l_mode = cl_gui_alv_grid=>mc_style_enabled.
  ELSE. "p_mode eq 'RO'
    l_mode = cl_gui_alv_grid=>mc_style_disabled.
  ENDIF.

  ls_celltab-fieldname = 'CARRID'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'CONNID'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'FLDATE'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'PRICE'.
  ls_celltab-style = l_mode.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'CURRENCY'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'PLANETYPE'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'SEATSMAX'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'SEATSOCC'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.
  ls_celltab-fieldname = 'PAYMENTSUM'.
  ls_celltab-style = cl_gui_alv_grid=>mc_style_disabled.
  INSERT ls_celltab INTO TABLE pt_celltab.

ENDFORM.                               " FILL_CELLTAB

FORM switch_edit_mode.

  IF grid1->is_ready_for_input( ) EQ 0.
    CALL METHOD grid1->set_ready_for_input
      EXPORTING
        i_ready_for_input = 1.

  ELSE.
    CALL METHOD grid1->set_ready_for_input
      EXPORTING
        i_ready_for_input = 0.
  ENDIF.
ENDFORM.                               " SWITCH_EDIT_MODE

你可能感兴趣的:(利用 ALV 实现增删改查系列之二:仅让 ALV 报表某一列允许被编辑试读版)