您的位置:首页 > 其它

ABAP 的TABLE CONTROL实践积累

2009-08-14 08:01 169 查看
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> - 1.
ENDIF.
*&SPWIZARD: set new cursor line *
L_LINE = L_SELLINE - <TC>-TOP_LINE + 1.

*&SPWIZARD: insert initial line *
INSERT INITIAL LINE INTO <TABLE> INDEX L_SELLINE.

一些ABAP的动态操作,可复用性代码都是这么写的。

FIELD-SYMBOLS <TC> TYPE CXTAB_CONTROL.

ASSIGN (P_TC_NAME) TO <TC>.

充分说明了 我自定义的TC 是一个结构。我将我自定义的TC名称,这时候声明一个引用,也就是TC的别名。

然后我就可以使用<TC>进行操作了。

插入操作和当前自己的光标位置相关,然后

INSERT INITIAL LINE INTO <TABLE> INDEX L_SELLINE.

SET CURSOR FIELD L_SELLINE.

觉得还是有点复杂吧,但是能看明白,却说不明白。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: