请教一个abap事件AT SELECTION-SCREEN的问题。。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教一个abap事件AT SELECTION-SCREEN的问题。。相关的知识,希望对你有一定的参考价值。

我在程序里面定义了AT SELECTION-SCREEN的判断条件:
AT SELECTION-SCREEN.
IF ftr <> 'y'.
RETURN.
ENDIF.
START-OF-SELECTION.
WRITE / 'START-OF-SELECTION事件'.
END-OF-SELECTION.
WRITE / 'END-OF-SELECTION事件'.

为什么我点了执行按钮(F8),ftr <> 'y'这个条件也符合,可是后面的START-OF-SELECTION和END-OF-SELECTION还是执行了,STOP也不行。怎样才能返回原来的屏幕不执行下面的两个事件。
谢谢回答!

F8是执行程序,而你所说的返回原来的屏幕应该是选择屏幕吧,

AT SELECTION-SCREEN. 相当于选择屏幕的PAI,用来响应屏幕元素的输入,当你按F8执行程序的时候,是不会触发PAI事件的
选择屏幕的作用在于为程序输入一些限制条件什么的,AT SELECTION-SCREEN.只能响应屏幕元素,当你按F8时,(一般意义上讲)是选择屏幕条件输入完成,需要正式进入程序逻辑的执行了,选择屏幕代码的执行优先级高于 START-OF-SELECTION.事件,所以会优先出现输入屏幕,按F8后,会把选择屏幕的输入送到程序中,执行后面的代码追问

是点了工具栏上那个执行按钮,不是按了F8,会执行AT SELECTION-SCREEN的。。然后我想在里面判断,不符合条件就不执行,就是说不执行START-OF-SELECTION中的代码,怎么做才好?

追答

执行按钮的快捷键就是F8,当你执行按执行按钮后,程序会从START-OF-SELECTION执行,
你可以给屏幕添加一个按钮来代替执行按钮,然后把START-OF-SELECTION中的代码写到PAI中,如下
添加BUTTON的代码如下,添加到前面
SELECTION-SCREEN PUSHBUTTON /1(20) button USER-COMMAND go.
判断变成
IF ftr 'y'.
RETURN.
ELSE.
MESSAGE ''START-OF-SELECTION事件' TYPE 'I'.
ENDIF.
下面是初始化Button显示文本。
INITIALIZATION.
button = '执行'.
另外要告诉你的是,WRITE是打印,即是说程序执行完成后的打印(WRITE后程序就结束了),在屏幕上操作是不能用WRITE语句的,所心我用了MESSAGE抛出你要的信息

追问

不管是F8快捷键还是点那个执行按钮,AT SELECTION-SCREEN事件都是会执行的,大哥。。然后才是START-OF-SELECTION,不信你写个最简单的选择屏幕程序,随便放几个按钮上面,测试一下就知道了!

追答

你说的对,我之前是说错了,执行程序是会触发PAI事件
是我理解错你的需求了,不想执行程序的话,你可以让选择屏幕抛出'E'类型的Message,这样程序就因为报出Error类型的message会停留在选择屏幕上
即是说将你的代码中的RETURN,换成一个类似如下的Message语句(E类型)

MESSAGE ' ftr y ' TYPE 'E' .

参考技术A This statement defines event blocks for different events selscreen_event that are triggered by the ABAP runtime environment during selection screen processing.

RETURN.
Effect
This statement ends the current processing block immediately. It can appear at any point in a processing block and ends this block irrespective of the statement block or control structure in which the block appears.

AT SELECTION-SCREEN是一个block 你在里面return 都只是退出当前这个block 不会退出整个程序,会继续执行后面的block,如果你把return换成LEAVE TO TRANSACTION SY-TCODE.会看到不同的效果。

在这里 如果你需要后面不执行 可以通过ftr的值在start-of-selection 和 end-of-selection里面做判断追问

先谢谢你的回答!我觉得如果在start-of-selection 和 end-of-selection里判断的话,那AT SELECTION-SCREEN这个事件就没发挥好它的作用,让程序多走了一步不该走的。。我想的效果是某个值不符合条件,就返回选择屏幕让用户重新选择输入,目前只知道message这种方式。。

追答

AT SELECTION-SCREEN 里面本来就只处理选择屏幕相关事宜 它的作用就是这个 你要强加一些 然后处理起来不方便也没辙

你直接在start-of-selection里面 check一下有问题吗
而且 LEAVE TO TRANSACTION SY-TCODE 是会跳出程序 重新进入这个程序
完全能满足你输入不符合条件 重新进入选择屏幕的要求
但是从没见人在at selection screen里面写这些东西

追问

好的,明白了,谢谢!

参考技术B 用message
message 'your message' type 'E'.追问

除了这种方式呢。。

ABAP: AT ... ENDAT的使用

在ABAP报表程序中,经常会涉及到内表字段的统计。而统计一般会以一个或多个Key字段为节点,统计其他某些数值类型字段。这里我们就会用到AT<level>.. ENDAT。

这里<LEVEL>包括: 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 ZTEST NO STANDARD PAGE HEADING.

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:/ '结果如下:'.
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 。废话不多说,大家自行掌握,欢迎探讨交流。

以上是关于请教一个abap事件AT SELECTION-SCREEN的问题。。的主要内容,如果未能解决你的问题,请参考以下文章

菜鸟请教:abap开发释放请求是啥意思?

请教一下,ABAP都有哪些特性和优点呢?

请教ABAP调用FTP函数的问题

请教一下ABAP 程序跑出来是空值

ABAP: AT ... ENDAT的使用

ABAP: AT ... ENDAT的使用