ABAP 的TABLE CONTROL实践积累

时间:2023-01-31 04:52:58

TABLE CONTROL 是一个结构,

假设我们定义的TC名称为  ZTEST_TC (具体结构参照:SCXTAB_CONTROL)

那么我们定义ZTEST_TC-CURENT_LINE ,ZTEST_TC-LINES 等等都有意义,我们可以将其理解为一个DEEP STRUCTURE.

        General TC attributes: |                      Column attributes

 1.FIXED_COLS LINES TOP_LINE CURRENT_LINE.... | COLS   INDEX SELECTED VISLENGTH INVISIBLE..

                                                |

 2.                                           SCREEN   

                                                

 3. NAME GROUP1 ... GROUP4 REQUIRED INPUT OUTPUT INTENSIFIED..INVISIBLE LENGTH ACTIVE DISPLAY_3D VALUE_HELP REQUEST...

 1是一个整体的TABLE CONTROL结构

 2是 ZTEST_TC-COLS的结构内容 也就是我们经常用的LOOP AT SCREEN. ... ENDLOOP.

 3.是SCREEN结构的属性。

那么这些有什么用呢?

一、现在需求如下(我在实际项目中接触到的实例):

通过选择屏幕,将数据库表A的内容显示出来,A有一个审批字段,如果这个审批字段是对勾(CHAR4 (ICON_D) 类型字段 存储内容: @01@ 就自然被系统装换成对勾显示了 ),那么这些数据在TABLE CONTROL中试灰色的,新添加的没有被审批的数据,就可以修改。

拿导航生成代码为例:PBO

我自定义TC输出内表名称为 T_ZTEST 工作区 WA_ZTEST

 PROCESS BEFORE OUTPUT.
*&SPWIZARD: PBO FLOW LOGIC FOR TABLECONTROL 'ZTEST_TC'

  MODULE ZTEST_TC_CHANGE_TC_ATTR.
*&SPWIZARD: MODULE ZTESTTC_CHANGE_COL_ATTR.
  LOOP AT   T_ZTEST
       INTO WA_ZTEST
       WITH CONTROL ZTEST_TC
       CURSOR ZTEST_TC-CURRENT_LINE .
    MODULE ZTEST_TC_GET_LINES.
*&SPWIZARD:   MODULE ZTESTTC_CHANGE_FIELD_ATTR
  ENDLOOP.
  MODULE STATUS_8000.

 

 最开始接触ABAP的时候,看到有这样的一个LOOP语句我发蒙了。除了在PBO里面,在其他地方使用不了的。

在这里,我们将 我们在屏幕的上显示的数据 每一行LOOP 进工作区中WA_TEST.

WITH CONTROL ZTEST_TC 说明了这个LOOP的过程是要和TC绑定LOOP的 CURSOR ZTEST_TC-CURRENT_LINE 。通过我上面罗列的结构为基础,我们进去 MODULE ZTEST_TC_GET_LINES中,添加一段代码:

LOOP AT SCREEN.

IF SCREEN-NAME CS 'WA_ZTEST' AND WA_ZTEST-STATUS EQ '@01@'.

IF SY-SUBRC EQ 0.

SCREEN-INPUT EQ 0.

MODIFY SCREEN.

ENDIF.

ENDIF

 CURSOR 是光标在控件中的位置,这时候光标所处的位置为,LOOP的当前行的数据。

 整个逻辑如下: 首先 我们LOOP 内表一条数据,然后和TC绑定.随后LOOP AT SCREEN. 这个时候,TC只会操作CURRENT_LINE这行的属性。如果这行的标识位为 mailto:‘@01@’那么就会不能输入(整行变灰色),如果没有标示位,则正常。由于CURSOR的作用,TC的每行属性是逐行操作的。

二、如何得到TC中更新的数据.(TC-> TABLE CONTROL)

在PAI的 模板代码中加了些代码。

  LOOP AT T_ZTEST.
    CHAIN.
      FIELD WA_ZTEST-VKORG.
      FIELD WA_ZTEST-VKBUR.
      FIELD WA_ZTEST-KUNNR MODULE KUNNR_TEXT ON INPUT.
      FIELD WA_ZTEST-MATNR MODULE MATNR_TEXT ON INPUT.
      FIELD WA_ZTEST-ZYEAR.
      .......
      MODULE ZHGXS_XSJH_TC_MODIFY ON CHAIN-REQUEST.
    ENDCHAIN.

     FIELD WA_ZHGXS_XSJH-SEL
      MODULE ZHGXS_XSJH_TC_MARK ON REQUEST.

   ENDLOOP.

     

 

FIELD .... MOUDLE ...ON INPUT 就是那个字段不为空,会触发这个ON INPUT ...MODULE

当有了INPUT操作后,会触发 MODULE.... ON REQUEST(响应MODULE).  

还有:MODULE ZHGXS_XSJH_TC_MODIFY ON CHAIN-REQUEST.

这个MOUDLE的作用,在触发PAI后,要是被CHAIN。。ENDCHAIN的数据只要有改变,TC会触发这个MODULE,然后更新最新当前行的最新值。
源代码如下   MODIFY T_ZTEST
             FROM WA_ZTEST  INDEX ZTEST_TC-CURRENT_LINE.

所以我们利用这个地方,巧妙的定义一个用来存储更新数据的内表,然后

MODIFY 更新内表统计
             FROM WA_ZTEST  INDEX ZTEST_TC-CURRENT_LINE.

这样所有改变后值得数据都会在这个内表出现,

DECRIBE 内表就知道更新多少行了。

对于TC的内表,永远是操作后的数据,非常准确。

因为他的每一个PAI都要出发LOOP 并且MODIFY改变值 原来的内表.

那么就要有一个疑问了,删除行时候,会怎样呢?

假设我使用的是导航本身生成的 - (删除行)操作,那么在PAI的时候,虽然在我们看来这行数据没有了,然是,PAI的LOOP检查会触发 一个MARK 标识位的操作,然后将内表的SEL打上X。当程序流走到PAI的INSR控件触发的事件时候,将SEL = 'X'的数据从内表删除。

所以PAI 的 CHAIN只会对存在的 操作前的数据进行LOOP,不会减少内表数据。主要的精华都在于

MODULE .... ON REQUEST的控制了。

三。对一些TABLE CONTROL的经典动态代码进行分析。

   FIELD-SYMBOLS <TC>                 TYPE CXTAB_CONTROL.
   FIELD-SYMBOLS <TABLE>              TYPE STANDARD TABLE.
   FIELD-SYMBOLS <LINES>              TYPE I.
*&SPWIZARD: END OF LOCAL DATA------------------------------------------*

   ASSIGN (P_TC_NAME) TO <TC>.

*&SPWIZARD: get the table, which belongs to the tc                     *
   CONCATENATE P_TABLE_NAME '[]' INTO L_TABLE_NAME. "table body
   ASSIGN (L_TABLE_NAME) TO <TABLE>.                "not headerline

*&SPWIZARD: get looplines of TableControl                              *
   CONCATENATE 'G_' P_TC_NAME '_LINES' INTO L_LINES_NAME.
   ASSIGN (L_LINES_NAME) TO <LINES>.

*&SPWIZARD: get current line                                           *
   GET CURSOR LINE L_SELLINE.
   IF SY-SUBRC <> 0                  append line to table
     L_SELLINE <TC>-LINES 1.
*&SPWIZARD: set top line                                               *
     IF L_SELLINE <LINES>.
       <TC>-TOP_LINE L_SELLINE <LINES> 1 .
     ELSE.
       <TC>-TOP_LINE 1.
     ENDIF.
   ELSE                              insert line into table
     L_SELLINE <TC>-TOP_LINE L_SELLINE 1.
     L_LASTLINE <TC>-TOP_LINE <LINES>