ABAP關鍵字SUBMIT的簡單例子和學習小記


網上有關SUBMIT實現程序調用的例子稍顯復雜,而相關的參考和解釋則不是很完善。本文給出一個SUBMIT的小示例程序(代碼見文末),實現了最簡單的程序間調用及返回值,以及SAP官方文檔中相關內容的翻譯、解釋。

 

本文鏈接:http://www.cnblogs.com/hhelibeb/p/5802398.html

轉載請注明

SUBMIT - 參考

語法

SUBMIT {rep|(name)}
  [USING SELECTION-SCREEN dynnr]
  [VIA SELECTION-SCREEN]
  [USING SELECTION-SET variant]
  [USING SELECTION-SETS OF PROGRAM prog]
  [WITH SELECTION-TABLE rspar]
{ [WITH sel1 { {{EQ|NE|CP|NP|GE|LT|LE|GT} dobj [SIGN sign]}
              | {[NOT] BETWEEN dobj1 AND dobj2 [SIGN sign]}
              | {IN rtab} }]
  [WITH sel2 { {{EQ|NE|CP|NP|GE|LT|LE|GT} dobj [SIGN sign]}
              | {[NOT] BETWEEN dobj1 AND dobj2 [SIGN sign]}
              | {IN rtab} }]
   ... }
  [WITH FREE SELECTIONS texpr]
  [LINE-SIZE width]
  [LINE-COUNT page_lines]
  { [EXPORTING LIST TO MEMORY]
  | [TO SAP-SPOOL SPOOL PARAMETERS pri_params
                  [ARCHIVE PARAMETERS arc_params]
                  WITHOUT SPOOL DYNPRO] }
  [[USER user] VIA JOB job NUMBER n]
  [AND RETURN].

效果

  調用一個可執行程序。

附加項

  • {rep|(name)}

    使用rep靜態地指定一個程序,或者使用name動態地指定

  • USING SELECTION-SCREEN dynnr

    指定要訪問的選擇屏幕dynnr,如不使用該條目,系統調用標准選擇屏幕。

  • VIA SELECTION-SCREEN

    顯示被調用的選擇屏幕。如不使用該條目,選擇屏幕過程(selection screen processing)將會在后台發生。

  • USING SELECTION-SET variant

    選擇屏幕使用變式

  • USING SELECTION-SETS OF PROGRAM prog

    指定使用的變式的程序

  • WITH SELECTION-TABLE rspar

    選擇屏幕使用內表rspar中的值,內表的行結構為RSPARAMS或者RSPARAMSL_255,如圖
    

   

  • WITH sel1 ... WITH sel2 ...

    傳入單獨的參數和條件值(selection criteria ) sel1, sel2....給選擇屏幕:

  1.  {EQ|NE|CP|NP|GE|LT|LE|GT} dobj [SIGN sign] - 傳輸一個單值和相關的操作符,以及selection table中SIGN列的設定
  2.   [NOT] BETWEEN dobj1 AND dobj2 [SIGN sign] - 傳輸一個從dobj1到dobj2之間的區間和可選的操作符NOT,以及selection table中SIGN列的設定
  3.   in rtab - 傳輸一個Range Table rtab

tips: Range Table

  Range Table為系統標准內表,結構與Selection Table一致,由SIGN, OPTION, LOW, HIGH和條件值字段組成;
  可以通過 TYPE RANGE OF 語句或 RANGES 關鍵字定義 Range Table。
  Range Table 常用於Open SQL語句中的條件篩選,可以優化取數效率與程序性能。

 例子:

REPORT report1. "program accessed

DATA text TYPE c LENGTH 10.

SELECTION-SCREEN BEGIN OF SCREEN 1100.
  SELECT-OPTIONS: selcrit1 FOR text,
                  selcrit2 FOR text.
SELECTION-SCREEN END OF SCREEN 1100.

...
REPORT report2. "calling program

DATA: text       TYPE c LENGTH 10,
      rspar_tab  TYPE TABLE OF rsparams,
      rspar_line LIKE LINE OF rspar_tab,
      range_tab  LIKE RANGE OF text,
      range_line LIKE LINE OF range_tab.

...

rspar_line-selname = 'SELCRIT1'.
rspar_line-kind    = 'S'.
rspar_line-sign    = 'I'.
rspar_line-option  = 'EQ'.
rspar_line-low     = 'ABAP'.
APPEND rspar_line TO rspar_tab.

range_line-sign   = 'E'.
range_line-option = 'EQ'.
range_line-low    = 'H'.
APPEND range_line TO range_tab.

range_line-sign   = 'E'.
range_line-option = 'EQ'.
range_line-low    = 'K'.
APPEND range_line TO range_tab.

SUBMIT report1 USING SELECTION-SCREEN '1100'
               WITH SELECTION-TABLE rspar_tab
               WITH selcrit2 BETWEEN 'H' AND 'K'
               WITH selcrit2 IN range_tab
               AND RETURN.

結果:在report1被report2訪問之后,被訪問程序中的條件值selcrit1selcrit2selection table中包含了以下記錄:

  SIGN OPTION LOW HIGH
selcrit1 I EQ ABAP  
selcrit2 I BT H K
selcrit2 E EQ H  
selcrit2 E EQ K  

 

  • WITH FREE SELECTIONS texpr

    通過一個內表texpr向選擇屏幕提供基於邏輯數據庫的動態選擇,內表texpr的類型是RSDS類型組中的RSDS_TEXPR

  • LINE-SIZE width

    使用width設置程序訪問的Basic List的行寬

tips: Basic List

  Basic List: 參考List Screen的相關內容。
  在START-OF-SELECTION事件處理塊中,用WRITE語句向列表緩沖區(List Buffer)輸出要顯示的內容。
  當該事件結束的時候,所有在列表緩沖區中的內容將被顯示到一個基本列表屏幕(Basic List)上。

 

  • LINE-COUNT page_lines

    使用設置程序訪問的Basic List的頁包含的行數

  • EXPORTING LIST TO MEMORY

    將程序訪問的Basic List以行類型為ABAPLIST的內表形式保存到ABAP Memory

  • TO SAP-SPOOL

    為程序訪問的basic list創建一個spool request,並帶有以下參數:

  1.  SPOOL PARAMETERS pri_params - 打印參數,保存在類型為PRI_PARAMS的結構pri_params中
  2.  ARCHIVE PARAMETERS arc_params - 歸檔參數,保存在類型為ARC_PARAMS的結構arc_params中
  3.  WITHOUT SPOOL DYNPRO - 阻止打印對話框
  • [USER user] VIA JOB job NUMBER n

  有待后續補充  效果:

  此附加項將被訪問的程序安排為后台任務運行,后台請求作業號為n。后台請求作業號n由函數組BTCH中的函數JOB_OPEN提供。整個程序不是直接運行的,而是根據后台請求指定的參數在后台過程中運行。你可以使用可選的附加項USER去指定一個類型為sy-uname的用戶ID user,這個ID用於運行后台任務。附加項VIA JOB只能和AND RETURN一起使用

   當submit語句執行時,VIA JOB也獨立地在內部模式中加載被訪問的程序,在被訪問的程序中,系統會執行在START-OF-SELECTION事件之前指定的所有步驟。這意味着事件LOAD-OF-PROGRAM和INITIALIZATION會被觸發,selection screen processing會執行。如果指定了附加項VIA SELECTION-SCREEN使得選擇屏幕不在后台處理,調用程序的用戶可以編輯選項並且使用函數PLACE IN JOB安排被訪問的程序在后台請求中運行。如果用戶取消了selection screen processin,程序不會被安排后台作業中。在這兩種情況下,被執行程序的執行都是完全在selection screen processin之后執行的,並因為AND RETURN附加項的存在,系統會返回調用程序。

  當程序被安排為后台任務時,用戶或附加項指定的、用來填充選擇屏幕的選擇條件存儲在一個內部變式中。當程序在后台請求中執行時,選擇條件被完全地處理,但是選擇屏幕是在后台運行的。系統觸發所有的事件,包括selection screen processing的。內部存儲的變式在INITIALIZATION和AT SELECTION SCREEN OUTPUT事件之間傳遞給選擇屏幕。

  如果被訪問的程序創建了一個基本列表屏幕,你應該通過使用指定TO SAP-SPOOL的方式,來創建一個帶有顯式打印參數的spool request。否則VIA JOB附加項會隱式地創建一個spool request,這個spool request繼承自它的來自於標准值的打印參數,有的標准值是用戶默認的,不一定符合相應的需要。

系統字段

sy-subrc 含義
0 后台任務計划成功
4 用戶在選擇屏幕中斷了計划
8 計划過程中的錯誤, 發生在JOB_SUBMIT的內部調用中.
12 內部號分配過程中的錯誤

注:

  你可以通過選擇菜單 系統(System)——服務(Services)——作業(Jobs)創建和監視后台作業。這里內部地使用了語言元素。除了JOB_OPEN以外,ABAP程序中中也可以使用函數JOB_CLOSE和JOB_SUBMIT。函數JOB_CLOSE可以關閉后台請求的創建。JOB_SUBMIT通過后台請求安排一個ABAP程序成為后台任務,像SUBMIT語句那樣。而JOB_SUBMIT為后台處理(background processing)提供更多的控制選項,但是必須從已經存在的變式來獲得選擇屏幕的值。SUBMIT語句可以創建這個變式,並且在內部訪問JOB_SUBMIT。

例子:

   使用后台請求name中的作業號number來把一個程序安排為后台任務。在設定后,后台任務由函數JOB_CLOSE完成,並且立即發布,同時提供給用戶的相關權限。

DATA: number           TYPE tbtcjob-jobcount,
      name             TYPE tbtcjob-jobname VALUE 'JOB_TEST',
      print_parameters TYPE pri_params.

...

CALL FUNCTION 'JOB_OPEN'
  EXPORTING
    jobname              = name
  IMPORTING
    jobcount             = number
  EXCEPTIONS
    cant_create_job  = 1
    invalid_job_data = 2
    jobname_missing      = 3
    OTHERS           = 4.
IF sy-subrc = 0.
  SUBMIT submitable TO SAP-SPOOL
                    SPOOL PARAMETERS print_parameters
                    WITHOUT SPOOL DYNPRO
                    VIA JOB name NUMBER number
                    AND RETURN.
  IF sy-subrc = 0.
    CALL FUNCTION 'JOB_CLOSE'
      EXPORTING
        jobcount             = number
        jobname              = name
        strtimmed            = 'X'
      EXCEPTIONS
        cant_start_immediate = 1
        invalid_startdate    = 2
        jobname_missing      = 3
        job_close_failed     = 4
        job_nosteps          = 5
        job_notex            = 6
        lock_failed          = 7
        OTHERS           = 8.
    IF sy-subrc <> 0.
      ...
    ENDIF.
  ENDIF.
ENDIF.

 

  • AND RETURN

     AND RETURN通過運行時環境決定了在程序被調用后的訪問對象:

  1. 沒有AND RETURN關鍵字的時候,伴隨着SAP LUW的退出,被訪問程序的內部會話在訪問隊列的相同位置替代了訪問程序的內部會話。一旦程序訪問結束,系統返回到調用程序開始的位置。SUBMIT上系統字段SY-CALLD復制調用程序的值。
  2. AND RETURN關鍵字在一個新的內部會話中運行程序。調用程序和當前的SAP LUW會保持存在。被調用程序運行它自己的SAP LUW。一旦程序訪問結束,程序將繼續執行SUBMIT語句之后的內容。

tips: SAP LUW, SY-CALLD

SAP LUW:SAP logical unit of work(LUW)是一個邏輯單位,我們把需要完成的工作分成一個個獨立的單元(LUW),每個單元包含若干操作,這些操作要么完全執行,要么完全不執行 (all-or-nothing principle)。相應地,數據庫層面存在更小的單元Database LUW。
SY-CALLD: 在一個調用序列中的第一個程序里為空字符串,否則為值“X”。在調用using CALL TRANSACTION,CALL DIALOG或  者SUBMIT ... AND RETURN后變為“X”。如果程序以LEAVE TO TRANSACTION或者從一個屏幕事務開始的話,則為空。使用SUBMIT(沒有AND RETURN)時設定為調用它的程序的值。



    注:

  1.  如果在一個submit里依然有注冊在當前的SAP LUW中的程序,且沒有 AND RETURN,SAP LUW的退出沒有伴隨着調用或者回滾程序。已注冊的更新函數(update function modules)會保留在數據庫中,但是無法再運行。為了防止這種情形,你可以在程序調用前顯式地執行語句COMMIT WORK或者ROLLBACK WORK。
  2.  帶有AND RETURN的SUBMIT語句開啟了一個新的SAP LUW,但是注意並不會自動開啟一個新的database LUW。這意味着在這個SAP LUW中使用語句 CALL FUNCTION IN UPDATE TASK或者CALL FUNCTION IN BACKGROUND TASK in the tables VB... or ARFCSSTATE and ARFCSDATA會回滾全部登記項。在某些情況下,被調用程序的ROLLBACK WORK語句也會影響到暫停的SAP LUW。為了防止這點,必須在程序被調用前顯式地運行database commit。這個問題不會在本地模式更新中發生。

tips: 本地模式

更新數據庫的幾種模式:異步模式、同步模式、本地模式。

異常

  • ·原因:未找到指定程序

  運行時錯誤:LOAD_PROGRAM_NOT_FOUND

  • 原因:嘗試使用SIGN傳輸一個無效的選擇值

  運行時錯誤:SUBMIT_WRONG_SIGN

  • 原因:指定程序不是一個report

  運行時錯誤:SUBMIT_WRONG_TYPE


tips: 程序類型

  1 REPORT(報表)
  M PROGRAM(屏幕程序)
  F FUNCTION-POOL(函數組)
  K CLASS-POOL(類組)
  J CLASS-POOL(接口組)
  T TYPE-POOL(類型池)

 

  • 原因:嘗試向報表參數傳輸一個以上的值

  運行時錯誤:SUBMIT_IMPORT_ONLY_PARAMETER

  • 原因:嘗試使用WITH sel IN itab傳輸的表的結構與selection不符合

  運行時錯誤:SUBMIT_IN_ITAB_ILL_STRUCTURE

  • 原因:嘗試傳輸一個不能被轉換為選擇屏幕目標字段的參數

  運行時錯誤: SUBMIT_PARAM_NOT_CONVERTIBLE

  • 原因:被調用程序存在語法錯誤

  運行時錯誤: SYNTAX_ERROR

程序示例

  示例包含3個程序,調用程序CALLING,被調用程序 ACCESSED1和ACCESSED2。

  其中,ACCESSED1和ACCESSED2均為獨立可運行的REPORT程序,帶有標准選擇屏幕,可以將選擇屏幕輸入的數值計算后輸出到屏幕。

  在CALLING程序中,我們可以在選擇屏幕輸入一個值,運行后,分別調用ACCESSED1和ACCESSED2進行數值處理,並顯示在CALLING的結果屏幕中,這是調用過程的簡單示意圖:

  

CALLING程序代碼如下:

REPORT ztestcalling.

CONSTANTS: g_memory1(30) VALUE 'JACKYTESTA'."定義MEMORY ID
CONSTANTS: g_memory2(30) VALUE 'JACKYTESTB'.

DATA:      val_return_from_accessed1 TYPE i,
           val_return_from_accessed2 TYPE i.

DATA: selectable LIKE TABLE OF rsparams.  "選擇參數內表
DATA: selectline LIKE LINE OF selectable.


SELECTION-SCREEN BEGIN OF BLOCK blk.
PARAMETERS: p_value TYPE i.
SELECTION-SCREEN END OF BLOCK blk.


INITIALIZATION.

START-OF-SELECTION.

  selectline-selname = 'P_VALUE'.   "選擇屏幕字段名
  selectline-kind = 'P'.       "選擇類型為單選,如果是多選則為S
  selectline-low = p_value.      "選擇字段的值
  APPEND selectline TO selectable.

  SUBMIT ztestACCESSED1 WITH SELECTION-TABLE selectable  AND RETURN.
  IMPORT val TO val_return_from_accessed1 FROM MEMORY ID g_memory1.   "取出ABAP內存中的數據
  FREE MEMORY ID g_memory1.               "釋放MEMORY ID

  SUBMIT ztestACCESSED2 WITH SELECTION-TABLE selectable  AND RETURN.
  IMPORT val TO val_return_from_accessed2 FROM MEMORY ID g_memory2.
  FREE MEMORY ID g_memory2.

  SKIP.

  WRITE:  '程序ACCESSED1的運行結果是', p_value, '+ 1 =',  val_return_from_accessed1 .
  WRITE: /'程序ACCESSED2的運行結果是', p_value, '* 3 =',  val_return_from_accessed2 .

 

接下來是被調用的ACCESSED1和ACCESSED2,程序內容基本一致,不同之處在於使用了不同的memory id傳輸數據。

REPORT ztestACCESSED1.

DATA val TYPE i.
CONSTANTS: g_memory1(30) VALUE 'JACKYTESTA'.


SELECTION-SCREEN BEGIN OF BLOCK blk1.
PARAMETERS: p_value TYPE i.
SELECTION-SCREEN END OF BLOCK blk1.


INITIALIZATION.

START-OF-SELECTION.

  val = p_value + 1.

  IF sy-calld = 'X'.
    EXPORT val FROM val TO MEMORY ID g_memory1.
  ELSE.
    WRITE val.
  ENDIF.

 

REPORT ztestACCESSED2.

DATA val TYPE i.
CONSTANTS: g_memory2(30) VALUE 'JACKYTESTB'.


SELECTION-SCREEN BEGIN OF BLOCK blk1.
PARAMETERS: p_value TYPE i.
SELECTION-SCREEN END OF BLOCK blk1.


INITIALIZATION.

START-OF-SELECTION.

  val = p_value * 3.

  IF sy-calld <> 'X'.
    WRITE val.
  ELSE.
    EXPORT val FROM val TO MEMORY ID g_memory2.
  ENDIF.

 

  運行CALLING程序,輸入數字2:

 

  

   點擊運行,直接顯示兩個程序的計算結果:

  

說明和注意

  在實際應用當中,我們很可能需要判斷一個程序是獨立運行的,還是處於被調用狀態,以決定接下來的處理邏輯(展示結果/傳輸結果),這時需要使用系統字段SY-CALLD:

字段名 類型 長度 應用目標 說明
SY-CALLD CHAR 1 ABAP程序 ABAP程序調用模式 

  SY-CALLD通過一個標識符顯示程序是否被調用。以上面的程序為例,如果ACCESSED1和ACCESSED2是獨立運行的,則SY-CALLD應為空;而在被程序CALLING調用時,SY-CALLD的值為“X”。

 

  需要注意的一點是,如果在SE38中運行ACCESSED1和ACCESSED2,SY-CALLD的值為'X'。這使得我們無法看到本應由WRITE語句輸出的計算結果。如果是復雜一些的程序,這種現象可能會給調試帶來麻煩。查詢系統字段的解釋:

 

  英文:Contains a blank character in the first program in a call sequence, otherwise contains the value "X". Is set to "X" after calls using CALL TRANSACTION, CALL DIALOG, or SUBMIT ... AND RETURN. Empty if the program was started using LEAVE TO TRANSACTION or a transaction from the screen. A call using SUBMIT (without AND RETURN) assumes the value of the calling program.

  中文:在一個調用序列中的第一個程序里為空字符串,否則為值“X”。在調用using CALL TRANSACTIONCALL DIALOG或者SUBMIT ... AND RETURN后變為“X”。如果程序以LEAVE TO TRANSACTION或者從一個屏幕事務開始的話,則為空。使用SUBMIT(沒有AND RETURN)時設定為調用它的程序的值。

 

  由此,我們有如下解決該問題的辦法:

  1. 分配事務代碼,在SAP主屏幕使用事務代碼運行程序,則SY-CALLD為空。
  2. 在1的基礎上,也可以單獨創建一個可執行程序,在這個新程序中,使用LEAVE TO TRANSACTION調用ACCESSED1或者ACCESSED2。

2017.07.26更新:通常,后台運行的程序的系統變量sy-batch的值應該為'X',但在特定情況下也可能不是這樣,比如調用F.13作為后台程序運行的時候。這時可以嘗試觀察sy-ucomm的值(jobs),來確定程序是否處於后台狀態。

SALV - 在submit后獲取數據

對於獲取某些既有ALV報表數據的需求,可以使用submit來滿足,並且不需要修改既有報表程序的代碼。

如果你不想在調用后輸出報表,但是又想獲取數據,可以在調用前使用以下代碼:

cl_salv_bs_runtime_info=>set(
    display  = SPACE
    metadata = SPACE
    data     = ‘X’ 
).
 

調用后,通過以下代碼獲取數據,

DATA lo_data TYPE REF TO data.
TRY.
    " get data from the SALV model
    cl_salv_bs_runtime_info=>get_data_ref(
          IMPORTING
            r_data = lo_data
    ).
  CATCH cx_salv_bs_sc_runtime_info.
    Message 'Unable to get data from SALV' type 'I'.
ENDTRY.

例子

這里使用一個對SALV_DEMO_TABLE_SIMPLE的調用來作為例子,

DATA: lt_outtab TYPE STANDARD TABLE OF alv_t_t2.
FIELD-SYMBOLS: <lt_outtab> like lt_outtab.
DATA lo_data TYPE REF TO data.
 
" Let know the model
 cl_salv_bs_runtime_info=>set(
    display  = abap_false
    metadata = abap_false
    data     = abap_true
).
 
 
SUBMIT salv_demo_table_simple
  AND RETURN.
 
TRY.
    " get data from SALV model
    cl_salv_bs_runtime_info=>get_data_ref(
          IMPORTING
            r_data = lo_data
    ).
    ASSIGN lo_data->* to <lt_outtab>.
    BREAK-POINT.    
 
  CATCH cx_salv_bs_sc_runtime_info.
ENDTRY.

請注意,這是一種比直接使用Export/Import更好的辦法,因為不需要管理Memory ID,也不再需要對被調用的報表進行侵入式的修改。

 

相關閱讀:ABAP程序間傳遞數據的幾種方法

       ABAP程序互調用:SUBMIT、CALL TRANSACTION、LEAVE TO TRANSACTION

       SALV教程18-讀取其他SALV的顯示結果

原創內容,轉載請注明本文鏈接。


免責聲明!

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



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