SAP 捕捉 Exception 的几种处理

599 阅读2分钟

ALV 左下角显示错误

在写 ALV 的时候,我们经常需要给报表界面报错,让用户知道操作失败的原因是什么,所以我们大概率是使用如下代码:

IF sy-subrc <> 0.
    MESSAGE 'Critical Error' TYPE 'E'.
ENDIF.

比如时候在用户没有勾选内容时,就给一个“请选择的”错误,我们会这样写:

READ TABLE gt_out INTO gs_out WITH KEY sel = 'X'.  
  IF sy-subrc NE 0.  
    MESSAGE '请选择保存的数据!' TYPE 'S' DISPLAY LIKE 'E'.  
    RETURN.  
  ENDIF.

image.png

弹出错误消息

在一些增强或者系统文件如 INCLUDE 文件中增加一些业务限制时,可能使用 MESSAGE 就不会起作用了,此时就可以通过 POP_UP_CONFIRM 的弹窗框用来显示错误,比如:

IF lv_msg IS NOT INITIAL.  
  
      CALL FUNCTION 'POPUP_TO_CONFIRM'  
        EXPORTING  
          text_question         = lv_msg  
          display_cancel_button = ''  
        IMPORTING  
          answer                = lv_answer  
        EXCEPTIONS  
          text_not_found        = 1  
          OTHERS                = 2.  
      IF sy-subrc <> 0.  
      ENDIF.  
ENDIF.  

SAP 系统消息文本

除了一些我们直观定义的消息之外,在调用 SAP 系统的函数时,可能会产生一些系统默认的 err,此时就可以通过弹出这些错误而不是自己定义的错误文本。

在 SAP 系统中,重要的是消息 ID(消息类别)和消息号码 No 。通过在 T100 表中使用上述组合,您可以找到确切的消息文本。

image.png

这个表中根据不同语言有大量的错误文本,如图:

image.png

比如,在 调用 IBAN 转换为银行账户的 CALL FUNCTION 中,就有这样一段代码:

* Check the IBAN  
  CALL FUNCTION 'CHECK_IBAN'  
    EXPORTING  
      i_iban    = i_iban  
    EXCEPTIONS  
      not_valid = 1  
      OTHERS    = 2.  
  IF sy-subrc <> 0.  
    IF sy-msgty EQ 'I'.  
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno  
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.  
    ELSEIF sy-msgty EQ '-'.  
    ELSE.  
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno  
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4  
              RAISING no_conversion.  
  
    ENDIF.  
  ENDIF.

这段代码用于检查一个国际银行账户号码(IBAN)是否有效。它调用了 SAP 系统中的 CHECK_IBAN 函数,并将 i_iban 参数设置为输入的 IBAN 号码。如果 IBAN 号码无效,则会引发一个异常。如果sy-subrc 不等于 0,则表示发生了异常,并且需要处理异常。如果异常类型为 'I',则会输出一条信息,否则会引发 no_conversion 异常。

但是在接口中,可能我需要的是把这段错误文本给返回给接口,因此,在转换过程中,我需要捕捉这段异常,然后就使用了下面的代码:

CALL FUNCTION 'CONVERT_IBAN_2_BANK_ACCOUNT'  
      EXPORTING  
        i_iban             = lv_iban  
      IMPORTING  
        e_bank_account     = lv_bank_account  
        e_bank_control_key = lv_control_key  
        e_bank_country     = lv_bank_country  
        e_bank_number      = lv_bank_number  
      EXCEPTIONS  
        no_conversion      = 1  
        OTHERS             = 2.  
    IF sy-subrc <> 0.  
      SELECT SINGLE text FROM t100 INTO l_msg_iban WHERE sprsl = sy-langu  
        AND arbgb = sy-msgid AND msgnr = sy-msgno.  
    ENDIF.

在这段代码中,我会将 l_msg_iban 不为空的消息文本返回给外部接口的 msg 字段。通过调用了"CONVERT_IBAN_2_BANK_ACCOUNT" 的函数,并传递了一个名为 "lv_iban" 的输入参数。函数会将输入的 IBAN 转换成对应的银行账户信息,包括银行账号、银行控制键、银行国家和银行号码,并将这些信息保存在输出参数中,

如果转换过程中遇到错误,会抛出异常,其中 "no_conversion" 代表无法进行转换,其他异常则用 "OTHERS" 表示。如果调用函数后返回值不为 0,则会从 T100 表中读取与消息 ID 和消息号匹配的文本,并将其保存在变量 "l_msg_iban" 中。

封装 error_message 函数

在 JOSN 返回时,我们能直接将 Error Message 进行封装为函数,比如:

FORM get_error_message   USING  l_message  
                         CHANGING l_error  .  
  
    TYPES:BEGIN OF ty_data ,  
            name           TYPE string,  
            debug          TYPE string,  
            message        TYPE string,  
            arguments      TYPE string,  
            exception_type TYPE string,  
          END OF ty_data .  
  
  
  
    TYPES:BEGIN OF ty_error ,  
            code    TYPE i,  
            message TYPE string,  
            data    TYPE ty_data,  
  
          END OF ty_error .  
  
  
  
    TYPES:BEGIN OF ty_result,  
            id      TYPE i,  
            jsonrpc TYPE string,  
            error   TYPE ty_error,  
  
          END OF ty_result .  
  
    DATA:ls_result  TYPE ty_result .  
  
  
    DATA : lv_unicode TYPE char04,  
           lv_chinese TYPE string,  
           lv_str1    TYPE string,  
           lv_str2    TYPE string,  
           l_n        TYPE int4,  
           l_i        TYPE int4.  
  
    WHILE 1 = 1 .  
  
      l_n = strlen( l_message ) .  
      SEARCH l_message FOR '\U' .  
      IF sy-subrc EQ 0 .  
        l_i = sy-fdpos + 2 .  
        lv_unicode =  l_message+l_i(4) .  
  
        lv_str1 = l_message+0(sy-fdpos) .  
  
        l_i = sy-fdpos + 6 .  
        l_n = l_n - l_i .  
        lv_str2 = l_message+l_i(l_n) .  
  
  
        TRANSLATE lv_unicode TO UPPER CASE.  
        lv_chinese = cl_abap_conv_in_ce=>uccp( lv_unicode ) .  
  
        CONCATENATE lv_str1 lv_chinese lv_str2 INTO l_message .  
      ELSE .  
        EXIT .  
  
      ENDIF .  
  
  
  
    ENDWHILE .  
  
  
    CALL METHOD /ui2/cl_json=>deserialize  
      EXPORTING  
        json        = l_message  
        pretty_name = 'X'  
      CHANGING  
        data        = ls_result.  
  
  
    l_error =  ls_result-error-data-message .  
  
  ENDFORM .

系统标准的错误函数

*----------------------------------------------------------------------*
***INCLUDE L1013F01 .
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Form  set_return_message
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM set_return_message USING VALUE(p_msgty)
                              VALUE(p_msgid)
                              VALUE(p_msgno)
                              VALUE(p_msgv1)
                              VALUE(p_msgv2)
                              VALUE(p_msgv3)
                              VALUE(p_msgv4)
                     CHANGING p_return LIKE bapiret2.

  DATA: BEGIN OF message,
          msgty LIKE bapiret2-type,
          msgid LIKE bapiret2-id,
          msgno LIKE bapiret2-number,
          msgv1 LIKE bapiret2-message_v1,
          msgv2 LIKE bapiret2-message_v2,
          msgv3 LIKE bapiret2-message_v3,
          msgv4 LIKE bapiret2-message_v4,
        END OF message.

  message-msgty = p_msgty.
  message-msgid = p_msgid.
  message-msgno = p_msgno.
  message-msgv1 = p_msgv1.
  message-msgv2 = p_msgv2.
  message-msgv3 = p_msgv3.
  message-msgv4 = p_msgv4.

  CALL FUNCTION 'BALW_BAPIRETURN_GET2'
    EXPORTING
      type   = message-msgty
      cl     = message-msgid
      number = message-msgno
      par1   = message-msgv1
      par2   = message-msgv2
      par3   = message-msgv3
      par4   = message-msgv4
    IMPORTING
      return = p_return
    EXCEPTIONS
      OTHERS = 1.

ENDFORM.                    " set_return_message