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