Messages消息处理
Messages
消息维护
所有的消息都是存储在T100表里的,可以使用SE91事务码来维护:
00系统消息ID(8占位符)
MESSAGE e001(00) WITH 'No local currecny maintained for company:' p_bukrs.
上面的00为系统预定义的消息类,如下:
从上面可以看出,001这条消息可以传递8个参数。
语法规则
使用全局的Message Class
以下程序定义语句后面可以加上选项:...MESSAGE-ID<id>.
这样在这些类型的的程序里可以这样来使用MESSAGE语句:
MESSAGE<t><num>[WITH<f1>... <f4>][RAISING<exc>].
REPORT zjzj_test1 MESSAGE-ID 00.
MESSAGE s002.
静态的指定Message
MESSAGE <t><nnn>(<id>) [WITH<f1>... <f4>][RAISING<exc>].
MESSAGE s002(00).
这里在语句中指定了消息ID,如果程序开头指定了消息Class,则这里也会将它覆盖,使用此语句中的消息ID。
动态的指定Message
MESSAGE ID <id> TYPE <t> NUMBER <n> [WITH<f1>...<f4>] [RAISING<exc>].
DATA: t(1) VALUE 'S',
id(2) VALUE '00',
num(3) VALUE '002'.
MESSAGE ID id TYPE t NUMBER num.
INTO msgtext 、DISPLAY LIKE dtype选项
这两个选项对于以上3个(使用全局的Message Class、静态的指定Message、动态的指定Message)都有效。
使用MESSAGE … INTO…可以很方便拼接BDC执行返回结果:
data: gt_messtab type table of bdcmsgcoll with header line .
call transaction 'VA02' using bdcdata
* MODE 'A'
mode p_runtp
update 'S'
messages into gt_messtab.
loop at gt_messtab .
message id gt_messtab-msgid type gt_messtab-msgtyp number gt_messtab-msgnr
with gt_messtab-msgv1
gt_messtab-msgv2
gt_messtab-msgv3
gt_messtab-msgv4
into l_msg.
endloop.
DATA mtext TYPE string.
CALL FUNCTION ... EXCEPTIONS error_message = 4.
IF sy-subrc = 4.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
INTO msgtext
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
INTO msgtext选项与Message Type没有关系(不管是什么类型,即使是X类型,也会将消息存入到msgtext变量中),这不像RAISING选项。
DISPLAY LIKE dtype:
对于原先就以dialog box方式显示的消息,仍然还是显示在dialog box中。
如果dtype为A或者是I类型时,E、W类型的消息(除开PBO与LOAD-OF-PROGRAM)将会在dialog box中显示。
不管dtype类型为什么,S类型的消息都会显示在状态栏中,PBO与LOAD-OF-PROGRAM中的I类型消息也是这样。
X类型消息总会引起运行时错误。
注:此种方式不会影响到消息本身的性为处理,只是改变了消息的显示类型(图标),如下面只是改变了S类型消息在状态栏中以错误图标来显示:
MESSAGE msg TYPE 'S' DISPLAY LIKE 'E'.
直接显示消息常量,不引用消息ID与消息号
MESSAGE msgtext TYPE c
MESSAGE 'aaaa' TYPE 'S'.
选项">RAISING <exc>选项:消息以异常形式抛出(是否以异常形式抛出还要看主调函数是否捕获了)
该选项对于以上4个(使用全局的Message Class、静态的指定Message、动态的指定Message、直接显示消息常量)都有效。
MESSAGE ID 'SABAPDEMOS' TYPE MESSAGE_TYPE NUMBER '777'
WITH MESSAGE_TYPE MESSAGE_PLACE MESSAGE_EVENT
RAISING MESS.
RAISING 后面接的是异常名(如下面的MESS异常),只有在Function或Class中定义的异常,才能用在RAISING选项的后面,具体使用过程如下:
当使用该选项后,并且如果在调用的地方(CALL FUNCTION或者是 CALL METHOD的地方)使用了EXCEPTION选项来捕获RAISING抛出的异常,则不再以MESSAGE的原有形式来显示消息,而是被主调捕获后进一步处理或者是程序Dump(AEIWS类型都能被捕获到,但X类型的Message不会走到被主调者捕获这一步,因为在被调程序中就宕掉了);反过来,当主调者未使用EXCEPTION选项(或者使用了但未捕获到所抛出的异常),则RAISING选项会被忽略,MESSAGE语句会按照无RAISING选项时那样运行(弹框还是在状态栏中显示、以及程序是否终止等性为)。
下面程序中,第一次调用时中会弹出消息框(因为没有使用EXCEPTIONS选项捕获),而第二次不会弹出消息框,也不会在状态栏中显示,而是被后继程序捕获后输出:
CLASS c1 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS m1 EXCEPTIONS exc1.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
MESSAGE 'Message in a Method' TYPE 'I' RAISING exc1.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
c1=>m1( ).
c1=>m1( EXCEPTIONS exc1 = 4 ).
IF sy-subrc = 4.
write: / '被捕获'.
ENDIF.
下面也不会显示错误消息,因E类型消息(注:不是异常,是消息)被error_message所捕获了:
FUNCTION ZJZJ_FUNC1.
MESSAGE id '00' TYPE 'E' NUMBER 001 WITH '1' '2'.
ENDFUNCTION.
REPORT ZJZJTEST.
CALL FUNCTION 'ZJZJ_FUNC1'
EXCEPTIONS
error_message = 4.
if sy-subrc <> 0.
WRITE: / '被捕获'.
ENDIF.
RAISING异常后,与消息相关的信息分别存储到相应系统字段中:
SY-MSGID 消息类
SY-MSGNO消息号
SY-MSGTY 消息类型
SY-MSGV1 ... SY-MSGV4 消息参数
CLASS c1 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS m1 EXCEPTIONS exc1.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
MESSAGE id '00' TYPE 'I' NUMBER 001 WITH '1' '2' RAISING exc1.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
c1=>m1( EXCEPTIONS exc1 = 4 ).
IF sy-subrc = 4.
write: / SY-MSGID.
write: / SY-MSGNO.
write: / SY-MSGTY.
write: / SY-MSGV1.
write: / SY-MSGV2.
ENDIF.
00
001
I
1
2
CALL FUNCTION[error_message]
CALL FUNCTION func ...[EXCEPTIONS[exc1= n1 exc2= n2 ...]
[others= n_others] ].
[error_message = n_error]
exc1,exc2...与OTHERS异常只能捕获到MESSAGE...RAISING选项或RAISE语句抛出的异常,即MESSAGE...RAISING与RAISE抛出的异常只能被exc1,exc2...与OTHERS异常所捕获,而error_message是无法捕获MESSAGE...RAISING与RAISE抛出的异常的。
error_message为系统内置的隐式性异常,主用来捕获那些未使用RAISING选项的A、E两类消息(注:error_message的作用是用来捕获消息的,而不是针对MESSAGE...RAISING与RAISE抛出的异常)
在主调程序中使用error_message来捕获Message请参考:在主调程序中捕获Message
MESSAGE中的RAISING<exc1...exci>抛出异常时,如果在Call Function的Exception列表中有exc1...exci或others异常,则会优先被exc1...exci或others捕获到;否则RAISING选项将直接被忽略掉,MESSAGE会被error_message所捕获(前提是在CALL FUNCTION时,加上了error_message异常,且不管MESAGGE为任何类型,此时都不会再显示MESSAGE,具体请参考在主调程序中捕获Message中的1、2两点说明):
REPORT ZJZJTEST.
CALL FUNCTION 'ZJZJ_FUNC1'
EXCEPTIONS
ERROR_MESSAGE = 5
"如果注释掉下面E类型异常捕获列表,则会输出2
"否则,像这里就会输出1
E = 4
D = 6.
if sy-subrc = 4.
WRITE: / '1'.
ENDIF.
if sy-subrc = 5.
WRITE: / '2'.
ENDIF.
RAISE语句(触发异常)
在Function Module里有两种方式触发异常(注:下面二种也只能在Function Module使用):
l RAISE <except>.
l MESSAGE..... RAISING <except>.
这些语句的作用依赖于主调程序中是否处理<except>异常。如果异常<except>或者others出现在了CALL FUNCTION语句中的EXCEPTIONS选项中,<except>异常将会被主调程序所捕获。如果主调程序没有捕获<except>异常,则:
l RAISE 语句会终止程序并且切换到debug模式
l MESSAGE ..... RAISING语句会根据message type来像MESSAGE语句那样正常显示消息(前提条件是要在CALL FUNCTION 语句中使用error_message来捕获消息)
一旦主调程序捕获了异常,以上两种触发异常的方式都会返回到主调程序,并且不会返回值(Function Module参数输出)。MESSAGE ..... RAISING语句也不会再显示消息,而是将相关的信息填充到SY-MSGID, SY-MSGTY,SY-MSGNO, and SY-MSGV1 to SY-MSGV4这些系统变量中(即使是I,S,W三种消息类型也会设置这些系统变量)
RAISE [RESUMABLE] EXCEPTION { { TYPE cx_class [EXPORTING p1 = a1 p2 = a2 ...]} | oref }.
cx_class为异常Class,EXPORTING为构造此异常类的构造参数,oref可以是已存在的异常Class引用,如:
DATA oref TYPE REF TO cx_root.
DATA:text TYPE string , result TYPE i.
TRY .
TRY.
result = 1 / 0.
CATCH cx_sy_zerodivide INTO oref.
text = oref->get_text( ).
RAISE EXCEPTION oref."捕获后继续向外层抛出,在函数里不需Exception选项,请参考下面示例(可能抛出是non-class-based exceptions,而不是class-based exceptions吧?)
ENDTRY.
CATCH cx_root INTO oref.
text = oref->get_text( ).
WRITE: / text.
ENDTRY.
RAISE EXCEPTION语句一般用来抛出基于Class的异常类class-based exceptions,而RAISE一般是直接用来抛出 non-class-based exceptions,如:
FUNCTION ZJZJ_FUNC1.
RAISE e.
ENDFUNCTION.
REPORT ZJZJTEST.
CALL FUNCTION 'ZJZJ_FUNC1'
EXCEPTIONS
OTHERS = 4.
if sy-subrc = 4.
WRITE: / '1'.
ENDIF.
RESUMABLE选项
表示可恢复的异常,可以在CATCH块里使用RESUME语句直接跳到抛出异常语句后面继续执行,RESUME后面语句不再被执,CLEANUP块也不会被执行。该选项只能用于BEFORE UNWIND类型的CATCH块中:
DATA oref TYPE REF TO cx_root.
DATA text TYPE string.
DATA i TYPE i.
TRY .
RAISE RESUMABLE EXCEPTION TYPE cx_demo_constructor
EXPORTING
my_text = sy-repid.
i = i + 1.
WRITE: / i.
CATCH BEFORE UNWIND cx_demo_constructor INTO oref .
text = oref->get_text( ).
IF i < 1.
RESUME.
ENDIF.
WRITE:/ '--'.
ENDTRY.
结果只输出 1
Message Types
X |
Exit 退出 |
Nomessageis displayed,andtheprogramterminateswitha shortdump. Programterminationswithashortdumpnormallyonlyoccurwhena runtimeerroroccurs.MessagetypeX allowsyoutoforceaprogram termination.TheshortdumpcontainsthemessageID. 消息不会显示,程序会终止并伴随着shortdump.信息。程序终止一般是由于运行时错误,但X消息允许你强迫终止程序。运行时会产生错误,屏幕显示异常的堆栈信息 |
A |
Abend 终止 |
Themessageappearsinadialogbox,andtheprogramterminates.Whentheuserhasconfirmedthemessage,controlreturnstothenext- highestareamenu. 此种消息只能以模式对话框来显示,并且会终止当应用程序。当用户确认后,控制权返回到最高层区域菜单所在屏幕,即“SAP Easy Access”初始屏幕:程序被取消 |
E |
Error 错误 |
Depending ontheprogram context, an errordialogappearsorthe programterminates. 依赖于程序上下文(可能显示在对话框中或状态栏上),显示错误对话框或者是终止程序(工具条按钮变灰,但不会中转到SAP Easy Access屏幕) |
W |
Warning 警告 |
Depending ontheprogram context, an errordialogappearsorthe programterminates. 依赖于程序上下文(可能显示在对话框中或状态栏上),显示错误对话框或者是终止程序(工具条按钮变灰,但不会中转到SAP Easy Access屏幕) |
I |
Information 消息 |
Themessageappearsinadialogbox.Oncetheuserhasconfirmedthemessage,theprogramcontinuesimmediatelyaftertheMESSAGE statement. 此种类型的消息只会出现在显示在对话框中。一旦用户确认了对话框,程序将继续执行MESSAGE语句后面的语句 |
S |
Status 状态 |
TheprogramcontinuesnormallyaftertheMESSAGEstatement,andthemessageisdisplayedinthestatusbarof thenextscreen. 程序会继续执行MESSAGE后面的语句,并且消息将显示在下一屏幕的状态栏中(如果没有下一屏幕,则显示在本屏幕的状态栏中)。程序不会被中断 |
消息显示及处理
Messages可以以模式对话框或者在屏幕的状态栏中显示,这究竟如何显示,则依赖限Messages的类型与运行时MESSAGE语句所在上下文环境。
特别是是E 与 W类型的消息,它们的行为与所在的程序上下文相关。
非屏幕PAI事件块中
适用所有不属于任何屏幕处理事件块。非屏幕处理包括以下事件块:
n PBO(PBO of screens):对话屏幕的PBO块
n The selection screen event AT SELECTION-SCREEN OUTPUT(PBO of a selection screen)选择屏幕的PBO块
n 报表程序事件块:INITIALIZATION、START-OF-SELECTION、GET、END-OF-SELECTION
n 列表事件块TOP-OF-PAGE、END-OF-PAGE
另:此节具体的各种情况下的演示,还可以通过 DEMO_MESSAGES程序(SAP自带的各种情况下的Message测试)此节的程序来演示
类型 |
Display显示 (显示在对话框中还是状态栏中) |
Processing处理(是终止程序还是继续,以及终止时返回到哪里)(注:显示及处理是不一样的) |
X |
None 不显示信息 |
Triggers a runtime error with short dump 触发运行时错误并伴随着dump |
A |
Dialogbox以对话框形式显示: |
Programterminates,andcontrolreturnstolastarea menu 并且会终止当应用程序,控制权返回到“SAP Easy Access”初始屏幕 |
E |
In PBO context,the same as type A, otherwise statusbar 在PBO块里与A类型相同(指显示方式相同,即以对话框形式显示): 否则(指那些上面除PBO以外的事件块——INITIALIZATION、START-OF-SELECTION、GET、END-OF-SELECTION、TOP-OF-PAGE、END-OF-PAGE)显示在状态栏中(此种情况贴图在右边)。 |
In PBO context like type A, otherwise,program terminates and control returns to pointfrom which the program was called 在PBO块里与A类型消息相同(指处理方式相同,即退出应用程序,并跳转到欢迎屏幕);否则,程序终止,但控制权返回到该程序被调用的地方(指界面停留在运行前的地方): |
W |
In PBO context,thes a meas type S, otherwise statusbar 在PBO里与S类型相同: 否则显示在状态栏中(此种情况贴图在右边)。 |
In PBO context like type S,otherwise,program terminates andcontrol returns to point from which the program was called 在PBO中与S类型相同 否则,程序终止,并且控制权返回到程序被调用的地方(指界面停留在调用前的地方): |
I |
In PBO context,thes a meas type S,otherwise dialogbox 在PBO里与S类型相同: 否则以对话框的形式显示(此种情况贴图在右边)。 |
Program continues processing after the MESSAGE Statement 程序会继续向下执行 |
S |
Status bar of next screen 消息会显示在下一屏幕的状态栏中(前提是有下一屏幕): 如果没有下一屏幕,则显示在当前屏幕的状态栏中(此种情况贴图在右边)。 |
Program continues processing after the MESSAGE Statement 程序会继续向下执行
|
屏幕中(对话屏幕)
会影响用户的的输入性为。屏幕处理即所有的PAI modules
另:此节具体的各种情况下的演示,还可以通过 DEMO_MESSAGES程序(SAP自带的各种情况下的Message测试)此节的程序来演示
类型 |
Display显示 (显示在对话框中还是状态栏中) |
Processing处理 (是终止程序还是继续,以及终止时返回到哪里) |
X |
None 不会显示消息 |
Triggers a runtime error with short dump 触发运行时错误并伴随着dump |
A |
Program terminates, and control returns to last area menu 并且会终止当应用程序,控制权返回到欢迎屏幕 |
|
E |
Status bar在状态栏中显示 |
PAI processing is terminated, and control returns to the current screen. All of the screen fields for which there is a FIELD or CHAIN statement are ready for input. The user must enter a new value. The system then restarts PAI processing for the screen using the new values. Error messages are not possible in POH or POV processing. Instead, a runtime error occurs. PAI处理结束,并且控制权返回到当前屏幕。MESSAGE所在的Module所属的FIELD或CHAIN所对应的字段全部可以重新输入(其他不在FIELD与CHAIN中的字段会灰掉,以及即使在其他FIELD或其他CHAIN中的字段如果通过验证了的也会灰掉。变灰就意味着验证已通过,无需才输入),且用户必须重新输入新的值。然后系统将重新对新输入的值进行PAI处理。注:Error消息将不能用在POH与POV,否则将会发生运行时错误 |
W |
Statusbar 在状态栏中显示 |
Like type E, but the user can confirm the message by pressing ENTER without having to enter new values. The system then resumes PAI processing directly after the MESSAGE statement. Warning messages are not possible in POH or POV processing. Instead, a runtime error occurs. 像类型E一样(指出弹出警告消息后,哪些屏幕字段变灰,哪些需要重新输入,这些处理相同)。但用户可以在不必输入新的值情况下按回车键继来忽略警告消息,系统会继续后面的PAI处理。 注:Warning消息将不能用在POH与POV,否则将会发生运行时错误 |
I |
Dialog box对话框中显示 |
Program continues processing after the MESSAGEStatement 程序会继续向下执行 |
S |
Status bar of next screen 消息会显示在下一屏幕的状态栏中 |
Program continues processing after the MESSAGEStatement 程序会继续向下执行 |
选择屏幕中
包括AT SELECTION-SCREEN及所有带ON选项的AT SELECTION-SCREEN,但不包括AT SELECTION-SCREEN OUTPUT,具体有哪些事件请参考这里
另:此节具体的各种情况下的演示,还可以通过 DEMO_MESSAGES程序(SAP自带的各种情况下的Message测试)此节的程序来演示
类型pe |
Display显示 (显示在对话框中还是状态栏中) |
Processing处理 (是终止程序还是继续,以及终止时返回到哪里) |
A |
Dialogbox以对话框显示 |
Program terminates, and control returns to last area menu 并且会终止当应用程序,控制权返回到欢迎屏幕 |
E |
Statusbar 在状态栏中显示 |
Selection screen processing terminates, and the selection screen is redisplayed. The screen fields specified through the additions to the AT SELECTION-SCREEN statement are ready for input. The user mustenter a new value. The system then restarts the selection screen processing using the new values. You cannot use error messages with the ON HELP-REQUEST or ON VALUE-REQUEST additions. Instead, a runtime error occurs. 选择屏幕处理结束,并且控制权返回到选择屏幕重新显示。 AT SELECTION-SCREEN ON中的字段将可以重新输出(如果是发生在AT SELECTION-SCREEN里,则所有屏幕字段都是可以重新输入的),并且用户必须输入新的值,系统然后重新对新输入的值进行处理,如果验证通过(不再弹出错误消息),则是继续后面的屏幕事件处理。 不能将error消息与ON HELP-REQUEST or ON VALUE-REQUEST选项的AT SELECTION-SCREEN一起使用,否则出现运行时错误 |
W |
Statusbar |
Like type E, but the user can confirm the message by pressing ENTER without having to enter new values. The system then resumes selection screen processing directly after the MESSAGE statement. You cannot use warning messages with the ON HELP-REQUEST or ON VALUEREQUEST additions. Instead, a runtime error occurs. 像类型E一样(指出弹出警告消息后,哪些屏幕字段变灰,哪些需要重新输入,这些处理相同)。但用户可以在不必输入新的值情况下按回车键继来忽略警告消息,系统会继续后面的PAI处理。 注:不能将warning消息与ON HELP-REQUEST or ON VALUE-REQUEST选项的AT SELECTION-SCREEN一起使用,否则出现运行时错误 |
I |
Dialogbox 对话框中显示 |
Program continues processing after the MESSAGEStatement 程序会继续向下执行 |
S |
Statusbarof nextscreen 消息会显示在下一屏幕的状态栏中 |
Program continues processing after the MESSAGEStatement 程序会继续向下执行 |
X |
None 不会显示消息 |
Triggers a runtime error with short dump 触发运行时错误并伴随着dump |
在List输出列表事件中
适用于所有列表处理list is being processed。
2 TOP-OF-PAGE DURING LINE-SELECTION
另:此节具体的各种情况下的演示,还可以通过 DEMO_MESSAGES程序(SAP自带的各种情况下的Message测试)此节的程序来演示
类型 |
Display显示(显示在对话框中还是状态栏中) |
Processing处理(是终止程序还是继续,以及终止时返回到哪里) |
A |
Dialogbox以对话框显示
|
Program terminates, and control returns to last area menu 并且会终止当应用程序,控制权返回到欢迎屏幕 |
E |
Statusbar在状态栏中显示
|
Processing block terminates. Previous list levels remaindisplayed. 事件块处理终止,继续保留上一级别的List |
I |
Dialogbox对话框中显示
|
Program continues processing after the MESSAGEStatement 程序会继续向下执行 |
S |
Status bar of next screen 消息会显示在下一屏幕的状态栏中
|
Program continues processing after the MESSAGEstatement 程序会继续向下执行 |
W |
Statusbar在状态栏中显示
|
Like type E. 像类型E一样 |
X |
None 不会显示消息
|
Triggers a runtime error with short dump 触发运行时错误并伴随着dump |
Messages in Function Modules and Methods
Message在Funcion与Method中有下面两种不同的功能:Messsage的普通使用、使用Messsage触发异常
此节具体的各种情况下的演示,还可以通过 DEMO_MESSAGES程序(SAP自带的各种情况下的Message测试)此节的程序来演示
Messsage的普通使用
如果你在Message词句中未使用RAISING选项,则它就是一个普通的Message,是不能被调用者所捕获的,此时Message将会根据上下文来进行显示与处理
Messsage转异常(…RAISING选项)
如果加了选项RAISING时:MESSAGE... RAISING <exc>,此时的Message 的处理方式与是否显示,就要依赖于主调者在调用时,是否加上了exception <exc>选项:
1、如果调用时没有带exception <exc>选项,此时Message语包中的RAISING <exc>选项抛出的异常将会被忽略,Message语句会当作正常消息来处理
2、如果调用时加上了exception <exc>选项对exc 异常进行了捕获,则不会再显示消息(但如果即使加上了exception选项,但没有捕获到exc异常,则此时会忽略RAISING选项)。只要异常被捕获,相关消息内容将会入存入到SY-MSGID,SY-MSGTY, SY-MSGNO, and SY-MSGV1 to SY-MSGV4有关系统变量中。
捕获Message(error_message)
可以在Message语句没有使用RAISING选项的情况下,在主调程序中的Exception参数列表中使用隐式异常error_message选项来捕获Message,但error_message是否能捕获得到Message,与消息类型相关:
1、对于W、I、S类型的消息,将不显示消息(本来是要显示的),也不会去设置 sy-subrc = n_error,但此时还是会将消息的相关信息存储到SY-MSGID, SYMSGTY,SY-MSGNO, and SY-MSGV1 to SY-MSGV4这些系统变量中
2、对于A、E类型消息,也将不显示提示消息,但会抛出ERROR_MESSAGE异常,即这两类型的消息会自动被转换为error_message异常抛出,并终最被CALL FUNCTION 中Exception异常列表中的error_message异常所捕获,并设置sy-subrc = n_error。此时与消息相关的信息分别存储到相应系统字段中:
SY-MSGID 消息类
SY-MSGNO 消息号
SY-MSGTY 消息类型
SY-MSGV1 ... SY-MSGV4 消息参数
此时,对于A类型消息而言,ROLLBACK WORK语句将会隐式执行
3、对于X类型消息将会抛出runtime error,并且程序会dump
DEMO_MESSAGES程序(SAP自带的各种情况下的Message测试)
关于Message不同上下文环境的运行情况,请参数SAP自带的实例程序:DEMO_MESSAGES
下面的程序是从DEMO_MESSAGES拷贝过来,并进行了少量修改,可以对不同情况下,Message的运行情况测试。如果需运行此程序,请先从DEMO_MESSAGES拷贝一份,生成必要的屏幕,再将下面的代码贴入。
REPORT zjzj_demo_messages.
DATA: ok_code TYPE sy-ucomm,"用来接收对话屏幕传递过来的 Function Code
save_ok TYPE sy-ucomm,"ok_code的副本,使用副本的原因请参考这里
BEGIN OF place,"消息执行所在程序类型复选框
report(1) TYPE c,
function(1) TYPE c,
list(1) TYPE c,
selscreen(1) TYPE c,
dynpro(1) TYPE c,
END OF place,
BEGIN OF type,"消息的类型复选框
a(1) TYPE c,
e(1) TYPE c,
i(1) TYPE c,
s(1) TYPE c,
w(1) TYPE c,
x(1) TYPE c,
END OF type,
BEGIN OF event,"屏幕事件类型复选框
pai(1) TYPE c,
pbo(1) TYPE c,
END OF event,
BEGIN OF except,"异常抛出、消息捕获复选框
no(1) TYPE c,
yes(1) TYPE c,
catch(1) TYPE c,
nocatch(1) TYPE c,
END OF except,
message_type(1) TYPE c,
message_place(40) TYPE c,
message_event(20) TYPE c.
DATA:msg TYPE string.
"此选择屏幕供后面对话屏幕的Module来调用
SELECTION-SCREEN BEGIN OF SCREEN 1100.
PARAMETERS: input1(10) TYPE c,
input2(10) TYPE c.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(33) text-001.
PARAMETERS funct AS CHECKBOX.
SELECTION-SCREEN COMMENT 38(64) text-015.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF SCREEN 1100.
START-OF-SELECTION.
"为对话屏幕上相应字段设置默认值
place-report = 'X'.
type-i = 'X'.
"event-pai = 'X'.
except-no = 'X'.
"将CALL SCREEN 100放在死循环里的调用的效果是:由于100是这里的主屏幕(第一个屏幕)
"后续其他的屏幕都是由此屏幕来调用(CALL SELECTION-SCREEN 1100、CALL SCREEN 300)新
"产生的或者是跳转得到的(LEVE TO 200)。如果在Module user_command_0100中是通过 LEVE TO 200
"跳转到200对话屏幕的,则在200屏幕上的标准工具栏中点击了 Back 或者 Exit 按钮后,则
"主屏幕(100)所在的屏幕序列会结束(因为LEVE TO 200就是在主屏幕序列中,所以在200
"屏幕中的 LEAVE TO SCREEN 0 最终会结束掉主屏幕所在的屏幕序列),当屏幕序列结事时,序列中的
"所有屏幕也会随之关闭,并返回到被关闭序列所产生之外,即CALL SCREEN 100调用处,此时会继续执行
"CALL SCREEN 100的后续语句,如果果此时不再调用其他屏幕,则整个程序会结束(最终的界面会停留在
"ABAP编辑器上——在通过ABAP编辑运行此程序的情况下),所以为了后继其他情况的Message 测试
"将 CALL SCREEN 100语句的调用就放在了循环中;另一种情况是,如果在Module user_command_0100中是通过
"CALL SELECTION-SCREEN 1100或CALL SCREEN 300调用产生的新序列屏幕,则在选择屏幕1100或对话
"屏幕300所在的屏幕序列结束时(可点击选择屏幕1100标准工具栏中的Back按钮,或在屏幕逻辑流中使用
"LEAVE TO SCREEN 0语句时会结束屏幕序列),不会返回到 CALL SCREEN 100 语句后面的后续语句继续执行,
"而是停留在以前已经显示出来的主调屏幕100(会调用100屏幕的PBO,重新显示100屏幕),所以此种情况
"下可以省略这个Do...While循环
DO.
CALL SCREEN 100."全屏方式调用对话屏幕100
IF place-report = 'X'.
message_event = 'START-OF-SELECTION'.
message_place = 'in main program'.
PERFORM call_message.
ELSEIF place-function = 'X'.
message_event = 'START-OF-SELECTION'.
message_place = 'in function module from main program'.
PERFORM call_function.
ENDIF.
ENDDO.
************************************************************************
* Dialog Modules *
************************************************************************
MODULE status_0100 OUTPUT.
"在这里控制复制框是否可选(禁止输入)
IF place-report = 'X' OR place-function = 'X' OR place-list = 'X' .
PERFORM modi_screnn USING '' '0' '' '0'.
ENDIF.
IF place-dynpro = 'X' OR place-selscreen = 'X'.
PERFORM modi_screnn USING 'X' '0' '' '1'.
ENDIF.
SET PF-STATUS 'SCREEN_100'.
SET TITLEBAR 'TITL_100'.
ENDMODULE. "status_0100 OUTPUT
MODULE cancel INPUT.
LEAVE PROGRAM.
ENDMODULE. "cancel INPUT
MODULE user_command_0100 INPUT.
save_ok = ok_code.
CLEAR ok_code.
"将100屏幕上用户选中的消息转换成真实的消息类型
PERFORM convert_user_input.
CASE save_ok.
WHEN 'TEST'.
"如果选择的是在 主调程序中 或者是在 Function 执行Message
IF place-report = 'X' OR place-function = 'X'.
LEAVE TO SCREEN 0."结束当前屏幕序列,返回到主调程序的CALL SCREEN后继续执行
"如果选择是在对话屏幕中执行Message,则结束当前屏幕100,调转到200屏幕(不会产生
"新的屏幕序列)
ELSEIF place-dynpro = 'X'.
LEAVE TO SCREEN 200.
"如果选择是在选择屏幕中执行Message,则会产生一个新的屏幕序列,跳转1100选择屏幕
ELSEIF place-selscreen = 'X'.
"下面是原程序采用CALL方式来调用1100选择屏幕的,但这种方式会产生一个新的屏幕
"序列,结束1100选择屏幕所有的新屏幕序列后,原主调屏幕100所在的屏幕序列不会消失
",所以这种方式下,主调程序中的 CALL SCREEN 100 所在的Do...While就没有意义了
"且点击标准工具栏上的 Back 按钮时,该选择屏幕所在的屏幕序列会结束,返回到 100 屏幕
CALL SELECTION-SCREEN 1100.
"在这里不能使用下面方式代替上面的CALL SELECTION-SCREEN 1100,否则在第二次调用此语句时
"会出错,具体问题不清
"LEAVE TO SCREEN 1100.
"如果选择是在输出列表List中执行Message,则跳转到 300屏幕,也不会产生新的屏幕序列
ELSEIF place-list = 'X'."如果要求Messge在输出列表List中调用时
"会产生新的屏幕序列,如果此地方运行50次,则最后因为屏幕序列大于50而堆栈溢出,
"因为每次运行此语句时,都会产生一个新的屏幕序列,且在离开300屏幕所在
"的序列时,并未关掉屏幕序列(status_0300 PBO中设置返回到100屏幕)。但上面的
"CALL SELECTION-SCREEN 1100 不会有这样的问题,因为在按1100所在屏幕的标准工具栏上
"的Back按钮时,会结束1100所在的屏幕序列。所以这里最好修改成 LEAVE TO SCREEN 300
"这样在多次调用此处后不会因为产生了50个序列而溢出
CALL SCREEN 300.
"LEAVE TO SCREEN 300.
ENDIF.
WHEN 'FC_PLC'."FC_PLC为屏幕上的单先按钮的Function code
"不要在这里控制屏幕字段的可输入性(比如这里点 Main Program单选按钮后,
"要使屏幕上的 PBO与PAI两个复选框变灰),即不要在这里对SCREEN内表进行修改
"而是将修改的代码直接移到PBO事件块里。因为在这里即使你修改了SCRENN内表的
"值,但在该PAI执行完后,去执行PBO时,SCREEN内表的值又会回到屏幕设计时设定的
"的初始设置了,所以在这里直接修改SCREEN是无法将屏幕字段置为灰的,除非在这里
"将这些修改设置存储起来,再在PBO根据这些值来修改SCREEN内表,但这样显得麻烦,
"还不如直接在PBO中对SCREEN进行修改
WHEN OTHERS.
"如果是其他情况,则结束整个程序
LEAVE PROGRAM.
ENDCASE.
ENDMODULE. "user_command_0100 INPUT
MODULE status_0200 OUTPUT.
SET PF-STATUS 'SCREEN_200'.
SET TITLEBAR 'TITL_200'.
"如果设置的是在对话屏幕的 PBO 事件块中执行Message
IF event-pbo = 'X'.
message_event = 'PBO'.
message_place = 'on dynpro'.
"在对话屏幕的PBO里并没有通过调用函数方式去执行Message
PERFORM call_message.
ENDIF.
ENDMODULE. "status_0200 OUTPUT
MODULE user_command_0200 INPUT.
save_ok = ok_code.
CLEAR ok_code.
CASE save_ok.
"如果用户点击的是标准工具栏中的 Back 或 Exit 按钮时,则立即结束当前屏幕序列
WHEN 'BACK_100'.
LEAVE TO SCREEN 0.
WHEN 'LAUNCH'.
"IF event-pai = 'X'.
message_event = 'PAI'.
message_place = 'on dynpro'.
PERFORM call_message.
" ENDIF.
WHEN 'FUNC'.
message_event = 'PAI'.
message_place = 'in function module on dynpro'.
PERFORM call_function.
WHEN 'EXIT'.
LEAVE TO SCREEN 100.
ENDCASE.
ENDMODULE. "user_command_0200 INPUT
MODULE status_0300 OUTPUT.
SET PF-STATUS 'LIST'.
SET TITLEBAR 'TITL_300'.
"LEAVE TO LIST-PROCESSING将控制权从对话屏幕转向输出列表处理器LIST PROCESSING,让当前屏幕的PBO与
"PAI中的Write输出语句将结果都输出到该输出列表List屏幕之上
"离开这里(300屏幕)并到达(TO)列表处理,并且(AND)设置 after exiting the list processor时,会
"跳转到对话屏幕100,如果设置为0,则当前屏幕序列会关闭
"该语句不会挂起当前屏幕的PBO处理,执行后会立即继续执行后续语句,这与LEAVE TO SCREEN XXX是不同的
LEAVE TO LIST-PROCESSING AND RETURN TO SCREEN 100.
NEW-PAGE NO-TITLE.
WRITE 'Basic List'.
"让当前屏幕(300屏幕)不弹出来。该语句作用是:如果该语句用在PBO中,当前屏幕不会显示,但会继续后续的PBO
"处理,且前一屏幕还会继续保持显示。
"该语句不能使用在PBO之外的块处理中。该语句的一般是与LEAVE TO LIST-PROCESSING一起使用,当使用
"LEAVE TO LIST-PROCESSING之后,控制权从屏幕转向了输出列表,所有的Write输出结果都会写到输出列表中(否
"则这些Write语句会输入到对话屏幕中),如果此时不想显示屏幕200,则可以使用此语句来过路此屏幕,当然这可
"以使用LEAVE SCREEN.语句来代替此语句,但LEAVE screen需要放在pbo的最后面(因为leave screen后面的
"语句是不会再执行的),但suppress dialog可以放在pbo中的任何位置
"注:如果在被压制的屏幕的PAI事件中弹出了任何类型的消息,则被压制的屏幕还是会显示出来。
SUPPRESS DIALOG.
"LEAVE SCREEN.离开当前屏幕跳转到当前屏幕的下一屏幕,注:如果全要使用此语句代替SUPPRESS DIALOG,则要
"放Module的最后面
ENDMODULE. "status_0300 OUTPUT
************************************************************************
* Selection screen events *
************************************************************************
AT SELECTION-SCREEN OUTPUT."1100选择屏幕的PBO事件
IF event-pbo = 'X'.
message_event = 'PBO'.
message_place = 'on selection screen'.
PERFORM call_message.
ENDIF.
"此为1100选择屏幕的PAI事件,该事件在点击选择屏幕上的 "执行" 按钮后调用。
AT SELECTION-SCREEN.
IF funct = 'X'.
message_event = 'PAI'.
message_place = 'in funktion module on selection screen'.
PERFORM call_function.
ELSEIF event-pai = 'X'.
message_event = 'PAI'.
message_place = 'on selection screen'.
PERFORM call_message.
ENDIF.
************************************************************************
* List events
************************************************************************
AT USER-COMMAND.
CASE sy-ucomm.
WHEN 'DETAIL'.
WRITE: / 'Detail list, level:', sy-lsind.
WHEN 'MESSAGE'.
message_event = 'AT USER-COMMAND'.
message_place = 'on list'.
WRITE: / 'Detail list, level:', sy-lsind.
PERFORM call_message.
WHEN 'FUNCT'.
message_event = 'AT USER-COMMAND'.
message_place = 'in funktion module on list'.
PERFORM call_function.
WRITE: / 'Detail list, level:', sy-lsind.
ENDCASE.
************************************************************************
* Subroutines *
************************************************************************
FORM call_message.
CONCATENATE message_type ', ' message_place ',' message_event INTO msg.
MESSAGE ID '00' TYPE message_type NUMBER '001' WITH msg .
ENDFORM. "call_message
FORM call_function.
IF except-no = 'X'."抛(RAISING)异常,但不处理
"由于函数抛出了异常,但未处理,所以会忽略掉 MESSAGE 的raising 选项,最
"后message以原本的形式展现,不会转存到 SY-MSGID 、SY-MSGNO 、SY-MSGTY、
"SY-MSGV1 ... SY-MSGV4 系统变量中去
CALL FUNCTION 'ZJZJ_FUNCTION_MESSAGE_RAISING'
EXPORTING
message_type = message_type
message_place = message_place
message_event = message_event.
ELSEIF except-yes = 'X'."抛(RAISING)异常,且进行处理
"由于函数抛出了异常,且在主调程序中进行了处理,所以MESSAGE最终不会以原本形式展现,raising 选
"项抛出的的异常信息会转存到 SY-MSGID 、SY-MSGNO 、SY-MSGTY、SY-MSGV1 ... SY-MSGV4 系统变量中去
CALL FUNCTION 'ZJZJ_FUNCTION_MESSAGE_RAISING'
EXPORTING
message_type = message_type
message_place = message_place
message_event = message_event
EXCEPTIONS
mess = 4."捕获到异常
CASE sy-subrc.
WHEN 0.
CONCATENATE sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO msg.
MESSAGE i001(00)
WITH 'No exception raised in function module' msg.
WHEN 4."如果捕获到了mess异常
CONCATENATE sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO msg.
MESSAGE i001(00)
WITH 'Handling exception from function module.' msg .
ENDCASE.
ELSEIF except-catch = 'X'."捕获消息
CALL FUNCTION 'ZJZJ_FUNCTION_MESSAGE'
EXPORTING
message_type = message_type
message_place = message_place
message_event = message_event
EXCEPTIONS
error_message = 4.
CASE sy-subrc.
WHEN 0.
CONCATENATE sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO msg.
MESSAGE i001(00)
WITH 'No exception(type E A) raised in function module.' msg.
WHEN 4.
CONCATENATE sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO msg.
MESSAGE i001(00)
WITH 'Handling exception from function module.' msg.
ENDCASE.
ELSEIF except-nocatch = 'X'."未捕获消息
CALL FUNCTION 'ZJZJ_FUNCTION_MESSAGE'
EXPORTING
message_type = message_type
message_place = message_place
message_event = message_event.
ENDIF.
ENDFORM. "call_function
FORM convert_user_input.
IF type-a = 'X'.
message_type = 'A'.
ELSEIF type-e = 'X'.
message_type = 'E'.
ELSEIF type-i = 'X'.
message_type = 'I'.
ELSEIF type-s = 'X'.
message_type = 'S'.
ELSEIF type-w = 'X'.
message_type = 'W'.
ELSEIF type-x = 'X'.
message_type = 'X'.
ENDIF.
ENDFORM. "convert_user_input
FORM modi_screnn USING pai pai_input pbo pbo_input.
LOOP AT SCREEN.
IF screen-name = 'EVENT-PAI'.
"复选框 EVENT-PAI 是否钩选上
event-pai = pai.
"设置 EVENT-PAI 是否可选(禁止输入)
screen-input = pai_input.
MODIFY SCREEN.
ENDIF.
IF screen-name = 'EVENT-PBO'.
"复选框 EVENT-PBO 是否钩选上
event-pbo = pbo.
"设置 EVENT-PBO 是否可选(禁止输入)
screen-input = pbo_input.
MODIFY SCREEN.
ENDIF.
IF place-report = 'X'
and ( screen-name = 'EXCEPT-NO'
or screen-name = 'EXCEPT-YES'
or screen-name = 'EXCEPT-CATCH'
or screen-name = 'EXCEPT-NOCATCH' ).
except-no = ''.
screen-input = '0'.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
ENDFORM. " MODI_SCRENN
FUNCTION ZJZJ_FUNCTION_MESSAGE_RAISING.
DATA: msg TYPE string.
CONCATENATE MESSAGE_TYPE ',' MESSAGE_PLACE ',' MESSAGE_EVENT INTO msg.
MESSAGE ID '00' TYPE MESSAGE_TYPE NUMBER '001' WITH msg RAISING MESS.
ENDFUNCTION.
FUNCTION ZJZJ_FUNCTION_MESSAGE.
DATA: msg TYPE string.
CONCATENATE message_type ',' message_place ',' message_event INTO msg.
MESSAGE ID '00' TYPE message_type NUMBER '001' WITH msg.
ENDFUNCTION.
在状态栏中显示信息
一般用于多步操作的进度指示,显示当前正在处理的任务信息
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'"
EXPORTING
TEXT = text-022.
“E”消息与回退按扭
START-OF-SELECTION.
DATA: l_vkorg TYPE likp-vkorg .
SELECT SINGLE vkorg FROM likp INTO l_vkorg WHERE vbeln = p_vbeln .
CALL FUNCTION 'ZMM_ILG_LOCK_DN'
EXPORTING
i_vbeln = p_vbeln
i_loctyp = p_loctyp
IMPORTING
e_zflag = flg
e_errmg = msg.
IF p_loctyp = '0' AND flg = 'S'.
MESSAGE 'DN block successful.' TYPE 'S'.
ELSEIF p_loctyp = '1' AND flg = 'S'.
MESSAGE 'DN unblock successful.' TYPE 'S'.
ELSE.
CONCATENATE 'Update failed: ' msg INTO msg.
* MESSAGE msg TYPE 'E'."如果使用此种方式打印消息,则程序会显示成下面截图样子,此时界面没有了,回退按钮也不能使用,所以修改成如下形式即可
MESSAGE msg TYPE 'S' DISPLAY LIKE 'E'.
STOP.”使用程序停止下来,不然的话会执行START-OF-SELECTION事件块后面剩余的程序
ENDIF.
MESSAGE s001(00) DISPLAY LIKE 'E' WITH text-001 l_vkorg.
STOP.
在函数中,不直接弹出消息,而是向上再次抛出:
MESSAGE E201 WITH HOST RAISING NOT_CONNECTED.
在上层可以这样捕获:
CALL FUNCTION 'ZMM_DATA_TO_FTP'
EXPORTING
im_funid = l_funid
im_filename = l_filename
im_rfcdest = 'SAPFTPA'
TABLES
text = t_div
EXCEPTIONS
not_connected = 2
OTHERS = 5.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
确认框函数POPUP_TO_CONFIRM