本系列前一篇文章 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,即容许编辑。

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

  • 69. 利用 ALV 实现增删改查系列之一:让 ALV 报表进入可编辑状态

本例残缺源代码:

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_STYLEFORM 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_CELLTABFORM 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