ABAP中AT NEW、AT LAST、ATFIRST、AT END OF、ON CHANGE OF使用,叠加SUM.语句

ABAP中AT NEW、AT LAST、ATFIRST、AT END OF、ON CHANGE OF使用,叠加SUM.语句 一、AT NEW 、AT END OF1.1、语法AT NEW F. 代码段.. ENDAT. F是内表的一个字段以f为分组条件在每组的第一条记录时执行时执行其中的代码段。 AT END OF F. 代码段.. ENDAT.F是内表的一个字段以f为分组条件在每组的最后一条记录时执行时执行其中的代码段。 例如第一条记录f’1000’col2’AAA1’col31第二条记录f’1000’col2’AAA2’col32第三条记录f’2000’col2’AAA2’col33第四条记录f’2000’col2’AAA2’col34第五条记录f’2000’col2’AAA3’col35第六条记录f’3000’col2’AAA3’col36AT NEW col1以f为分组条件在每组的第一条记录时执行在上述例子里会在在第一条第三条第六条记录时会执行。AT END OF col1以f为分组条件在每组的最后一条记录时执行在上述例子里会在在第二条第五条第六条记录时会执行。1.2、使用条件一般在loop中使用; 要提前对内表进行排序sort; Loop不能加where条件; 在at 和 endat之间不能再使用loop语法。1.3、例子REPORT ZMMR_CK_TEST2 . TYPES:BEGIN OF TY_TEST, NAME(3) TYPE C, PRODUCT TYPE C, SALES TYPE I, END OF TY_TEST. DATA:FLAG TYPE C, MARK TYPE C. DATA:I_TEST TYPE TABLE OF TY_TEST, W_TEST TYPE TY_TEST. DATA:I_TEST2 TYPE TABLE OF TY_TEST, I_TEST3 TYPE TABLE OF TY_TEST. W_TEST-NAME 001. W_TEST-PRODUCT A. W_TEST-SALES 10. APPEND W_TEST TO I_TEST. W_TEST-NAME 001. W_TEST-PRODUCT B. W_TEST-SALES 20. APPEND W_TEST TO I_TEST. W_TEST-NAME 002. W_TEST-PRODUCT A. W_TEST-SALES 20. APPEND W_TEST TO I_TEST. W_TEST-NAME 002. W_TEST-PRODUCT B. W_TEST-SALES 30. APPEND W_TEST TO I_TEST. W_TEST-NAME 002. W_TEST-PRODUCT C. W_TEST-SALES 60. APPEND W_TEST TO I_TEST. W_TEST-NAME 003. W_TEST-PRODUCT A. W_TEST-SALES 30. APPEND W_TEST TO I_TEST. CLEAR:W_TEST. SORT I_TEST BY NAME PRODUCT . LOOP AT I_TEST INTO W_TEST. AT NEW NAME. FLAG X. ENDAT. IF FLAG X. APPEND W_TEST TO I_TEST2. CLEAR:FLAG . ENDIF. AT END OF NAME. MARK X. ENDAT. IF MARK X. APPEND W_TEST TO I_TEST3. CLEAR:MARK. ENDIF. CLEAR:W_TEST. ENDLOOP. WRITE: 原始数据. LOOP AT I_TEST INTO W_TEST. WRITE:/ W_TEST-NAME, , W_TEST-PRODUCT, W_TEST-SALES. CLEAR:W_TEST. ENDLOOP. WRITE:/ . WRITE:/ 结果如下. WRITE:/ AT NEW 用法. LOOP AT I_TEST2 INTO W_TEST. WRITE:/ W_TEST-NAME, , W_TEST-PRODUCT, W_TEST-SALES. CLEAR:W_TEST. ENDLOOP. WRITE:/ . WRITE:/ AT END OF 用法. LOOP AT I_TEST3 INTO W_TEST. WRITE:/ W_TEST-NAME, , W_TEST-PRODUCT, W_TEST-SALES. CLEAR:W_TEST. ENDLOOP.执行结果显示如下截图然后我们按照nameproduct排序。最然name是唯一关键字段但name排在第一位所以这里product加入排序并不影响也是为了后面结果能更直观的显示出来。排序后我们loop内表第一行001 A 10 。这时进入at new 的代码段因为这里name 001是新的一个name如上代码。我们给flag赋值X这样执行一条插入语句将此行插入到结构完全一样的内表I_TEST2中然后clear 标记字不要忘记clear。loop第二行001 B 20 。这次不会进入at new中的代码段了因为name还是001没变。但是这次会进入at end of中的代码段因为下一行的name是002也就是前面说到的下一行即将变化时。这样我们将此行append到I_TEST3中。后面我就不多说了总之以key字段为唯一标准。这样我们在统计内表中数据时就可以根据不同key字段进行统计。再提一点我们上面的代码中为何用到两个标记位(其实一个就够了为了看起来条理清晰)flagmark。因为当进入at 。。endat中的时候工作区中的值除了key字段其他字段会全部变为默认值字符型字段值全变为*数值全部变为0而当跳出AT … END AT.语法块后工作区内容恢复原样如图由于这种特性我们不将插入语句或赋值语句写在at endat之中而是通过标记变量的方式解决因为影响的只是工作区中的内容。二、AT FIRST、AT LAST在at语法中工作区的内容会变为*但指针不会3. AT FIRST. 代码段.. ENDAT. 内表的第一行时执行。4. AT LAST. 代码段.. ENDAT. 内表的最后一行时执行。上面这两种用法就比较简单易懂了。一个是在loop的第一行时进入调用另一个是最后一行时。而且不用对Loop进行排序也没有key字段。三:ON CHANGE OF FIELD . ENDON.先看标准的语法ON CHANGE OF dobj [OR dobj1 [OR dobj2] ... ].statement_block1[ELSE.statement_block2]ENDON.EffectThe statements ON CHANGE OF and ENDON, which are forbidden in classes, define a control structure that can contain two statement blocks:statement_block1 and statement_block2. AfterON CHANGE OF, any number of data objects dobj1, dobj2... of any data type can be added, linked byOR.The first time a statement ON CHANGE OF is executed, the first statement blockstatement_block1 is executed if at least one of the specified data objects is not initial. The first statement block is executed for each additional execution of the same statementON CHANGE OF, if the content of one of the specified data objects has been changed since the last time the statementON CHANGE OF was executed. The optional second statement blockstatement_block2 after ELSE is executed if the first statement block is not executed.For each time the statement ON CHANGE OF is executed, the content of all the specified data objects is saved as an auxiliary variable internally in the global system. The auxiliary variable is linked to this statement and cannot be accessed in the program. The auxiliary variables and their contents are retained longer than the lifetime of procedures. An auxiliary variable of this type can only be initialized if its statementON CHANGE OF is executed while the associated data object is initial.NoteThis control structure is particularly prone to errors and should be replaced by branches with explicitly declared auxiliary variables.例子*---------------------------------------------------------------------* * Report ZTXYY_111106 *---------------------------------------------------------------------* * *---------------------------------------------------------------------* REPORT ZTXYY_111106. DATA : BEGIN OF TAB OCCURS 0, ID TYPE CHAR01, NAME TYPE CHAR10, END OF TAB. DATA : NUM TYPE I. TAB-ID 1. TAB-NAME A001. APPEND TAB. TAB-ID 1. TAB-NAME A002. APPEND TAB. TAB-ID 2. TAB-NAME A002. APPEND TAB. TAB-ID 2. TAB-NAME A002. APPEND TAB. NUM 0 . LOOP AT TAB. ON CHANGE OF TAB-ID . NUM NUM 1. ENDON. ENDLOOP. WRITE : / NUM. NUM 0 . LOOP AT TAB. ON CHANGE OF TAB-ID OR TAB-NAME. NUM NUM 1. ENDON. ENDLOOP. WRITE : / NUM. 原文链接https://blog.csdn.net/zhongguomao/article/details/62037711结果用途1/7背景由于AT NEW field会判断field和它前面的所有字段而ON CHANGE OF没有这个要求所以后者就有了登上舞台的空间。2/7正常情况现在有一个内表GT_TAB包括一个字段FIELD1内容如下行FIELD1的值112132LOOP GT_TAB时ON CHANGE OF GT_TAB-FIELD1会在第一和第三行被触发。3/7非正常情况GT_TAB内容如下行FIELD1的值1121没有疑问第一次LOOP GT_TAB时ON CHANGE OF GT_TAB-FIELD1会在第一行被触发。可是如果第二次LOOP呢答案是不会触发ON CHANGE OF。而且即便你清空GT_TAB的内表或工作区再重新赋值都没有用。4/7示例说明为此我做了一个示例包含的功能如下(连续的两次循环时内表的值都是无重复的我们重点关注第二次循环是否触发ON CHANGE OF的情况)操作内表是否触发构建新内表首次循环全局内表触发第二次循环全局内表不触发清空内表后重新赋值并循环全局内表不触发清空工作区后重新循环全局内表不触发清空内表工作区后重新赋值并循环全局内表不触发free内表后重新赋值并循环全局内表不触发调用FORM循环局部内表局部内表触发再次调用FORM循环局部内表局部内表不触发换一个FORM2同名局部内表局部内表触发再次调用FORM2循环局部内表局部内表不触发这是一个比较隐蔽的坑因为在某些情况下我们不能预知GT_TAB-FIELD1会不会一定都是多个值的。如果某一次循环的时候我们判断的字段没有重复值那么下次循环的时候如果内表中的首条记录恰巧与我们上一次循环的值相同ON CHANGE OF就不会被触发。而且不管是全局变量还是局部变量都有这样的情况。5/7示例代码有兴趣的同学可以自己修改代码以测试一下这样的情况1、首次循环内表中是1 1两条数据2、再次循环内表中是1 2 两条数据REPORT ztest_abap_ll. SELECTION-SCREEN PUSHBUTTON /10(40) clear1 USER-COMMAND clear1. SELECTION-SCREEN SKIP 1. SELECTION-SCREEN PUSHBUTTON /10(40) clear2 USER-COMMAND clear2. SELECTION-SCREEN SKIP 1. SELECTION-SCREEN PUSHBUTTON /10(40) clear3 USER-COMMAND clear3. SELECTION-SCREEN SKIP 1. SELECTION-SCREEN PUSHBUTTON /10(40) create USER-COMMAND create. SELECTION-SCREEN SKIP 1. SELECTION-SCREEN PUSHBUTTON /10(40) loop1 USER-COMMAND loop1. SELECTION-SCREEN SKIP 1. SELECTION-SCREEN PUSHBUTTON /10(40) loop2 USER-COMMAND loop2. SELECTION-SCREEN SKIP 1. SELECTION-SCREEN PUSHBUTTON /10(40) loop3 USER-COMMAND loop3. *SELECTION-SCREEN SKIP 1. *SELECTION-SCREEN PUSHBUTTON /10(40) loop3 USER-COMMAND loop4. TYPES:BEGIN OF ty_tab, field1 TYPE string, END OF ty_tab, tyt_tab TYPE TABLE OF ty_tab. DATA: gt_tab TYPE tyt_tab WITH HEADER LINE, g_msg TYPE string, g_msgty TYPE c. INITIALIZATION. clear1 清空内表. clear2 清空工作区. clear3 FREE内表. create 向内表中插入两条数据. loop1 循环全局内表. loop2 全局内表放入局部内表后再循环. loop3 全局内表放入另一个FORM的同名局部内表后再循环. AT SELECTION-SCREEN. CASE sy-ucomm. WHEN CLEAR1. CLEAR: gt_tab[]. WHEN CLEAR2. CLEAR: gt_tab. WHEN CLEAR3. free: gt_tab. WHEN CREATE. 插入两条数据 gt_tab-field1 1. APPEND gt_tab. APPEND gt_tab. WHEN LOOP1. PERFORM loop1. WHEN LOOP2. PERFORM loop2. WHEN LOOP3. PERFORM loop3. ENDCASE. FORM loop1. LOOP AT gt_tab. ON CHANGE OF gt_tab-field1. g_msg 当前索引 sy-tabix 触发了ON CHANGE OF. g_msgty S. ELSE. g_msg 当前索引 sy-tabix 没有触发ON CHANGE OF. g_msgty E. ENDON. MESSAGE g_msg TYPE I DISPLAY LIKE g_msgty. ENDLOOP. ENDFORM. FORM loop2. DATA: lt_tab TYPE tyt_tab WITH HEADER LINE. lt_tab[] gt_tab[]. LOOP AT lt_tab. ON CHANGE OF lt_tab-field1. g_msg 当前索引 sy-tabix 触发了ON CHANGE OF. g_msgty S. ELSE. g_msg 当前索引 sy-tabix 没有触发ON CHANGE OF. g_msgty E. ENDON. MESSAGE g_msg TYPE I DISPLAY LIKE g_msgty. ENDLOOP. ENDFORM. FORM loop3. DATA: lt_tab TYPE tyt_tab WITH HEADER LINE. lt_tab[] gt_tab[]. LOOP AT lt_tab. ON CHANGE OF lt_tab-field1. g_msg 当前索引 sy-tabix 触发了ON CHANGE OF. g_msgty S. ELSE. g_msg 当前索引 sy-tabix 没有触发ON CHANGE OF. g_msgty E. ENDON. MESSAGE g_msg TYPE I DISPLAY LIKE g_msgty. ENDLOOP. ENDFORM.6/7原因分析根据F1里的说明可以看到对于ON CHANGE OF的事件在系统里是有一个类似于帮助变量的东西在支撑的而且这个帮助变量的生命周期是比我们的FORM、FUNCTION等代码块的周期更长的。F1里面没有提到的是它的生命周期与全局变量的生命周期谁更长。不过实践证明了除非程序退出否则这个帮助变量是不会消失的。7/7如何规避个人觉得用ON CHANGE OF不如自己定义一个变量记录一下上次循环的值当本次的值与上次不一致时即形同ON CHANGE OF的事件。如下DATA: l_field1 type string.loop at gt_tab.if l_field1 gt_tab-field1.形同ON CHANGE OFelse.l_field1 gt_tab-field1.endif.endloop.ABAPON CHANGE OF的坑释疑の语法 ON CHANGE OF-CSDN博客