ABAP: AT ... ENDAT的使用

本文详细介绍了ABAP中AT...ENDAT的四种用法,特别是AT NEW和AT END OF的区别。通过实例说明如何在内表循环中进行数据统计,并解释了在不同情况下的执行时机。此外,还提到了内表排序和工作区值的变化,以及在统计中可能用到的collect关键字。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考博客:https://blog.csdn.net/sunnyonly1992/article/details/51682978

在ABAP报表程序中,经常会涉及到内表字段的统计。而统计一般会以一个或多个Key字段为节点,统计其他某些数值类型字段。这里我们就会用到AT… ENDAT。
这里包括: new , first , last , end of .
使用前提:一般在loop中使用,要提前对内表进行排序sort,排序的主键为统计时用到的节点(比如,按销售组织统计,节点为vkorg),Loop不能加where条件,在at 和 endat之间不能再使用loop语法。
那下面我们简单介绍一下四种用法:

1.AT NEW F.
    代码段..
ENDAT.

f是内表的一个字段,当内表中f字段以及f左边的任何字段内容发生变化时,执行其中的代码段。

2. AT END OF F.
        代码段..
    ENDAT.

当f字段以及f左边字段内容即将发生变化时,执行代码段。
上面这两种用法,看似很相近,但是 at new 是新变化的时候执行,也就是有变化的新一行loop进工作区时执行。而 at end of 则是下一行即将变化时执行,也就是有变化新一行的前一行loop时执行。
所以这里容易混淆,我们做个简单的例子更好理解区分。

REPORT z_zhangm_052.

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.

  AT FIRST.
    WRITE:/,'loop的第一行时,进入调用',sy-uzeit.
    wait up to 3 seconds.  "停留3秒
  ENDAT.

  AT LAST.
    WRITE:/,'loop最后一行时,进入调用',sy-uzeit.
  ENDAT.

ENDLOOP.



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.

执行结果显示如下截图:
在这里插入图片描述
这里写图片描述

通过上面的代码和最终结果,我们应该更加清晰这两种用法的区别,在统计之前,我们的内表I_TEST中有6条数据:
这里写图片描述
然后我们按照name,product排序。最然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字段进行统计。

再提一点,我们上面的代码中为何用到两个标记位(其实一个就够了,为了看起来条理清晰):flag,mark。

因为当进入at …endat中的时候,工作区中的值除了key字段,其他字段会全部变为默认值,字符型字段值全变为*,数值全部变为0:
这里写图片描述
而当跳出AT … END AT.语法块后,工作区内容恢复原样:
这里写图片描述
如图,由于这种特性,我们不将插入语句或赋值语句写在at endat之中,而是通过标记变量的方式解决,因为影响的只是工作区中的内容。
上面讲述了两种常用的,还有两种比较简单,我们不做例子代码,简单描述下:

   3.  AT FIRST.
       代码段..
  ENDAT.
4. AT LAST.
  代码段..
ENDAT.

上面这两种用法,就比较简单易懂了。一个是在loop的第一行时,进入调用;另一个是最后一行时。而且不用对Loop进行排序,也没有key字段。

在sap报表开发过程中,可能会经常用到at end of 和 at new.希望通过这篇博文能让大家对这两种用法更好的理解。
对于内表的统计,有时我们还会用到collect。后面我们会简单介绍下。
如果看我前面博文《将Excel导入SAP中》的朋友可能会注意到,代码中就使用了at end of 。废话不多说,大家自行掌握,欢迎探讨交流。

<think>好的,我现在需要解决用户在ABAP开发中遇到的可执行语句数量超出限制的问题。首先,我需要回忆一下ABAP中的相关限制。ABAP程序中的可执行语句数量确实有一个上限,通常是几千条,具体取决于系统版本和配置。当超过这个限制时,用户会收到错误信息,比如“Number of executable statements exceeds limit of xxxx”。 接下来,我需要考虑常见的解决方案。用户可能已经尝试过直接减少代码行数,但效果有限。这时候应该考虑模块化编程,将代码拆分成子程序、函数模块或者类方法。例如,把重复的逻辑提取到函数模块中,这样主程序中的可执行语句就会减少。 另外,使用宏(Macros)也是一个方法。虽然宏在ABAP中不推荐过度使用,但在某些情况下,可以用宏来简化重复的代码块,从而减少可执行语句的数量。需要注意宏的维护性和可读性可能较差,所以需要谨慎使用。 性能方面,用户可能没有意识到某些语句的执行效率问题。比如,循环内的数据库访问或频繁的字符串操作会增加执行次数。优化这些部分,比如使用更高效的SQL查询或缓存数据,可以减少执行次数,从而间接减少语句数量。 还有,检查程序是否包含冗余代码或调试语句。有时候开发过程中遗留的测试代码或者重复的逻辑会增加语句数量,清理这些部分可以释放空间。 此外,ABAP的包含程序(Include Programs)可以用来分割代码。将部分代码移到包含程序中,主程序通过INCLUDE语句引用,这样每个包含程序单独计算语句数量,可能绕过单个程序的限制。 如果以上方法仍不足够,可能需要与BASIS团队沟通,调整系统参数。不过,这通常需要管理员权限,并且可能涉及系统稳定性,因此需要谨慎操作。 最后,需要考虑用户的实际情况,比如代码结构是否复杂,是否有未使用的功能模块可以移除。建议用户先进行代码分析,使用ABAP的代码审查工具查找冗余部分,逐步优化结构。 需要验证这些方法的有效性,比如拆分代码后是否真的减少了主程序中的可执行语句数量,或者使用宏是否会导致其他问题。同时,提醒用户在修改代码前进行备份,避免引入新的错误。</think>在ABAP中,当可执行语句数量超出系统限制时,可通过以下步骤解决: ### 解决方案步骤 1. **代码模块化重构** 将重复逻辑封装为函数模块(SE37)或类方法(SE24),例如将循环处理或数据转换代码独立为子程序: ```abap FORM process_data USING p_data TYPE ty_table. "业务逻辑 ENDFORM. ``` 2. **使用宏简化重复代码** 将频繁出现的语句组合定义为宏(注意不超过16行限制): ```abap DEFINE set_field. &1 = &2. CONDENSE &1. END-OF-DEFINITION. ``` 3. **包含程序拆分** 通过`INCLUDE`将代码分割到多个子程序(每个包含程序单独计数): ```abap INCLUDE zinclude_program1. INCLUDE zinclude_program2. ``` 4. **性能优化** - 避免在循环内执行SELECT查询,改为一次性读取数据到内表 - 使用`LOOP AT ... GROUP BY`代替多层嵌套循环 - 用`FIELD-SYMBOLS`代替工作区操作 5. **系统参数调整(需BASIS支持)** 修改`rdisp/max_extprog_size`参数值,提升程序容量限制(默认值通常为8-16MB)[^1]。 ### 关键优化示例 原始代码: ```abap LOOP AT it_data ASSIGNING <data>. SELECT single kunnr INTO <data>-kunnr FROM kna1 WHERE name1 = <data>-name. ENDLOOP. ``` 优化后: ```abap SELECT kunnr, name1 INTO TABLE @DATA(lt_kna1) FROM kna1 FOR ALL ENTRIES IN @it_data WHERE name1 = @it_data-name. LOOP AT it_data ASSIGNING <data>. READ TABLE lt_kna1 WITH KEY name1 = <data>-name ASSIGNING FIELD-SYMBOL(<kna1>). IF sy-subrc = 0. <data>-kunnr = <kna1>-kunnr. ENDIF. ENDLOOP. ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值