[SAP ABAP開發技術總結]消息處理Messages


 

14.         Messages

14.1.     00消息ID中的通用消息

00消息ID中的001消息本身未設置任何消息串,這條消息可以傳遞8個參數,在用於拼接消息時很有用

image135

MESSAGE e001(00) WITH 'No local currecny maintained for company:' p_bukrs.

14.2.     消息常量

直接顯示消息常量,不引用消息ID與消息號

MESSAGE 'aaaa' TYPE 'S'.

14.3.     靜態指定

MESSAGE <t><nnn>(<id>) [with<f1>... <f4>][raising <exc>].

MESSAGE s002(00).

14.4.     動態指定

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.

14.5.     消息拼接MESSAGE …INTO

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.

14.6.     修改消息顯示性為…DISPLAY LIKE…

此種方式不會影響到消息本身的處理性為,只是改變了消息的顯示圖標類型,如下面只是改變了S類型消息在狀態欄中以錯誤圖標來顯示(本來是綠色狀態圖標):

MESSAGE  msg  TYPE 'S' DISPLAY LIKE 'E'.

:消息以異常形式拋出">14.7.     RAISING <exc>:消息以異常形式拋出

 MESSAGE ID 'SABAPDEMOS' TYPE MESSAGE_TYPE NUMBER '777'
         
WITH
MESSAGE_TYPE MESSAGE_PLACE MESSAGE_EVENT
 
RAISING MESS.

當使用該選項后,並且如果在調用的地方(CALL FUNCTION或者是 CALL METHOD的地方)使用了EXCEPTION選項來捕獲RAISING拋出的異常,不再以MESSAGE的原有形式來顯示消息而是被主調捕獲后進一步處理或者是程序DumpAEWIS類型都能被捕獲到,但X類型的Message不會走到被主調者捕獲這一步,因為在被調程序中就宕掉了);反過來,當主調者未使用EXCEPTION選項(或者使用了但未捕獲到所拋出的異常),則RAISING選項會被忽略MESSAGE語句會按照無RAISING選項時那樣運行(彈框還是在狀態欄中顯示、以及程序是否終止等性為、還是轉換為error_message拋出)

如果加了選項RAISING時:MESSAGE... RAISING <exc>此時的Message 的處理方式與是否顯示,就要依賴於主調者在調用時,是否加上了exception <exc>選項:

1、如果調用時沒有帶exception <exc>選項,此時Message語包中的RAISING <exc>選項拋出的異常將會被忽略,Message語句會當作正常消息來處理

2、  如果調用時加上了exception <exc>選項對exc 異常進行了捕獲,則不會再顯示消息(但如果即使加上了exception選項,但沒有捕獲到exc異常,則此時會忽略RAISING選項),並設置sy-subrc。只要異常被捕獲,相關消息內容將會入存入到SY-MSGID,SY-MSGTY, SY-MSGNO, and SY-MSGV1 to SY-MSGV4有關系統變量中

下面程序中,第一次調用時中會彈出消息框(因為沒有使用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.

14.8.     CALL FUNCTION…EXCEPTIONS

CALL FUNCTION func [EXCEPTIONS 
                       [
exc1= n1 exc2
= n2]
                       [
others
= n_others] ]
                       [
ERROR_MESSAGE = n_error].

exc1exc2...OTHERS異常只能捕獲到MESSAGE...RAISING選項或RAISE語句拋出的異常,而error_message是無法捕獲MESSAGE...RAISINGRAISE拋出的異常的

MESSAGE中的RAISING <exc1...exci>拋出異常時,如果在Call FunctionException列表中有exc1...exciothers異常,則異常會優先被exc1...exciothers捕獲到;否則RAISING選項將直接被忽略掉,MESSAGE會被error_message所捕獲(在使用error_message捕獲的前提下)

image136

CALL FUNCTION 'ZJZJ_FUNC1'
 
EXCEPTIONS
    error_message
= 5
   
"e捕獲,如果注釋掉下面E類型異常捕獲列表,則會被error_message捕獲
    e            
= 4
    d            
= 6.

14.8.1.           error_message = n_error捕獲消息

可以Message語句沒有使用RAISING選項的情況下(使用exc1...exciothers但未捕獲),在主調程序中的CALL FUNCTION ...Exception參數列表中使用隱式異常error_message選項來捕獲Message,但error_message是否能捕獲到Message(實為是否設置sy-subrc = n_error),與消息類型有關:

1、對於WIS類型的消息,將不顯示消息(本來是要顯示的),也不會去設置 sy-subrc = n_error此時還是會將消息的相關信息存儲到SY-MSGID, SYMSGTY,SY-MSGNO, and SY-MSGV1 to SY-MSGV4這些系統變量中

2、對於AE類型消息,也將不顯示提示消息,但會拋出ERROR_MESSAGE異常,即這兩類型的消息會自動被轉換error_message異常拋出,並終最被CALL FUNCTION Exception異常列表中的error_message異常所捕獲,並設置sy-subrc = n_error。此時還會將消息的相關信息存儲到SY-MSGID, SYMSGTY,SY-MSGNO, and SY-MSGV1 to SY-MSGV4這些系統變量中

此時,對於A類型消息而言,ROLLBACK WORK語句將會隱式執行

3、對於X類型消息將會拋出runtime error,並且程序會dump

14.9.     各種消息的顯示及處理

消息類型

非屏幕PAI事件

PBO

AT SELECTION-SCREEN OUTPUTINITIALIZATIONSTART-OF-SELECTION

GET

END-OF-SELECTION

TOP-OF-PAGE

END-OF-PAGE

對話/選擇屏幕

PAI

AT SELECTION-SCREEN [ON]

List列表事件

AT LINE-SELECTION

AT USER-COMMAND

AT PF<nn>

TOP-OF-PAGE DURING LINE-SELECTION

顯示

顯示在對話框中還是狀態欄中

處理

是終止程序還是繼續

顯示

處理

顯示

處理

X

不顯示信息

觸發運行時錯誤並伴隨着dump

不顯示信息

觸發運行時錯誤並伴隨着dump

不顯示信息

觸發運行時錯誤並伴隨着dump

A

Dialogbox以對話框形式顯示

程序終止

Dialogbox以對話框形式顯示

程序終止

Dialogbox以對話框形式顯示

程序終止

E

PBO:與A相同,否則顯示在狀態欄

程序終止

狀態欄中顯示

PAI處理結束,並且控制權返回到當前對話/選擇屏幕繼續輸入

狀態欄中顯示

事件塊處理終止,返回上一級別的List

W

PBO:與S相同,否則顯示在狀態欄

程序終止

狀態欄中顯示

PAI處理結束,並且控制權返回到當前對話/選擇屏幕可繼續輸入可按回車鍵繼來忽略警告繼續運行后面程序而不必輸入

狀態欄中顯示

事件塊處理終止,返回上一級別的List

I

PBO:與S相同,否則對話框的形式顯示

程序會繼續向下執行

Dialog box對話框中顯示

程序會繼續向下執行

Dialog box對話框中顯示

程序會繼續向下執行

S

消息會顯示在下一屏幕的狀態欄中,如果沒有下一屏幕,則顯示在當前屏幕的狀態欄中

程序會繼續向下執行

消息會顯示在下一屏幕的狀態欄中,如果沒有下一屏幕,則顯示在當前屏幕的狀態欄中

程序會繼續向下執行

消息會顯示在下一屏幕的狀態欄中,如果沒有下一屏幕,則顯示在當前屏幕的狀態欄中

程序會繼續向下執行

14.10.             異常處理

14.10.1.      RAISE [EXCEPTION]…觸發異常

兩種方式觸發異常:

l  RAISE <except>.  只在函數中使用

l  MESSAGE...RAISING <except>.

一旦主調程序捕獲了異常,以上兩種觸發異常的方式都會返回到主調程序,並且不會返回值Function Module參數輸出)。MESSAGE ..... RAISING語句也不會再顯示消息,而是將相關的信息填充到SY-MSGID, SY-MSGTY,SY-MSGNO, and SY-MSGV1 to SY-MSGV4這些系統變量中(即使是I,S,W三種消息類型也會設置這些系統變量

14.10.1.1.觸發類異常

RAISE [RESUMABLE] EXCEPTION { { TYPE cx_class [EXPORTING p1 = a1 p2 = a2 ...]} | oref }.

cx_class為異常ClassEXPORTING為構造此異常類的構造參數,oref可以是已存在的異常Class引用。

RAISE EXCEPTION語句一般用來拋出基於Class的異常類class-based exceptions,而RAISE一般是直接用來拋出 non-class-based exceptions(在函數中使用)

  DATA result TYPE p DECIMALS 2.
 
DATA oref TYPE REF TO cx_root.
 
DATA text TYPE string.
 
DATA i TYPE i.
 
TRY .
     
i = 1 / 0.
 
CATCH cx_root INTO oref.
     
text = oref->get_text( ).
     
WRITE: '---' , text.
      
RAISE EXCEPTION oref.
 
ENDTRY.

 

DATA: exc  TYPE REF TO cx_sy_dynamic_osql_semantics,
     
text TYPE string.
TRY.
  
RAISE EXCEPTION TYPE cx_sy_dynamic_osql_semantics
       
EXPORTING textid = cx_sy_dynamic_osql_semantics=>unknown_table_name token  = 'Test'.

 
CATCH cx_sy_dynamic_osql_semantics INTO exc.
    text
 = exc->get_text( ).
   
MESSAGE text TYPE 'I'.
ENDTRY.

image137

image138

image139

14.10.1.2.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

14.10.2.      捕獲異常

14.10.2.1.類異常捕獲TRY…CATCH 

DATA myref TYPE REF TO cx_sy_arithmetic_error.
DATA err_text TYPE
string.
DATA result TYPE i
.
TRY
.
    result =
1 / 0
.
CATCH cx_sy_arithmetic_error INTO
myref.
    err_text = myref->get_text( ).

ENDTRY.

14.10.2.2.老式方式捕獲runtime errors(運行時異常)

CATCH SYSTEM-EXCEPTIONS [exc1 = n1 exc2 = n2 ...][OTHERS = n_others].
  …
ENDCATCH.

 

DATA: result TYPE i.
CATCH SYSTEM-EXCEPTIONS arithmetic_errors = 5
.
    result =
1 / 0
.  
ENDCATCH
.
IF sy-subrc = 5
.
 
WRITE / 'Division by zero!'
.
ENDIF
.

14.10.3.      向上拋出異常

如果Form中出現了運行時錯誤,但Form簽名又沒有使用RAISING向上拋,則程序會直接掛掉,所以最好是向上拋

FORM subform RAISING cx_static_check cx_dynamic_check.
...

ENDFORM.

Funcion函數不會主動向外拋出運行時錯誤,所以要先在Function手動CATCH,再手動向外拋如果出現運行時錯誤不拋出,則Function與會直接宕掉

image140

14.10.4.      類異常

l   CX_STATIC_CHECK

l   CX_DYNAMIC_CHECK

l   CX_NO_CHECK

image141

CX_NO_CHECK類似於Java中的ErrorCX_DYNAMIC_CHECK類似於Java中的RuntimeExceptionCX_STATIC_CHECK類似於Java檢測性異常Exception     [dai?n?mik] 

image142

自己定義的異常一般繼承CX_STATIC_CHECKCX_DYNAMIC_CHECK,但CX_NO_CHECK也可以創建,不像Java

 

CX_STATIC_CHECK是一個抽象類。在程序中使用RAISE EXCEPTION 手動拋出這類異常時,方法或過程接口上一定要顯示的通過RAISING 來向上層拋出異常、或者直接在方法或過程中進行處理也可以,否則靜態編譯時就會出現警告

CX_NO_CHECK類型的異常一般表示系統資源不足引起的,不能在方法或過程接口后面拋出CX_NO_CHECK類型的異常,它會被隱含的拋出與傳遞。系統中已有預定義這類異常。

如果程序邏輯能夠排除可能性的潛在性錯,相應的異常就可能不用處理或繼續拋出,此類情況下可以使用CX_DYNAMIC_CHECK類型的異常,這與Java中的運行時異常相似,一旦發生也該類異常,表示問題出現在程序的本身設計上,程序設計不嚴謹(如沒有判斷空指針問題)。ABAP大多數的系統預定義的異類都是屬於該類型異常,這就意味着不需要處理或拋出ABAP語句可能出現的每一種異常,但一旦發生了該類異常,則表示程序的出現了問題,程序執行的結果將不會在正確。

自定義的全局異常類名以ZCX_  作為前綴

如果是通過Class Builder創建的全局異常類時,由於構造器是默認創建好的(異常相關參數已經固定下來了),不能傳遞自定義參數,所以異常文本ID只能通過TEXTID傳遞(參考觸發類異常),但局部異常類沒有這個限制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM