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>