글
Source 변경 function
FUNCTION y_prg_maint.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(INPUT) TYPE TRDIR-NAME
*"----------------------------------------------------------------------
TYPES: BEGIN OF itype,
line(100),
END OF itype.
DATA itab TYPE itype OCCURS 0 WITH HEADER LINE.
DATA : l_cnt TYPE i.
IF input+0(1) <> 'Z' AND
input+0(1) <> 'Y'.
MESSAGE i000(MMRP01) WITH '스탠다드 프로그램은 손댈수 없습니다.'.
EXIT.
ENDIF.
DATA: l_name LIKE trdir-name.
CLEAR l_name.
SELECT SINGLE name INTO l_name
FROM trdir
WHERE name = input.
IF sy-subrc <> 0.
MESSAGE s000(MMRP01) WITH '존재하지 않는 프로그램 입니다.'.
EXIT.
ENDIF.
READ REPORT input INTO itab.
CLEAR : l_cnt.
DESCRIBE TABLE itab LINES l_cnt.
IF l_cnt EQ 0.
EXIT.
ENDIF.
EDITOR-CALL FOR itab.
INSERT REPORT input FROM itab.
COMMIT WORK AND WAIT.
ENDFUNCTION.
Z_KSJ_PRG_MAINT-source edit.txt
ZSDR9999-source edit screen 까지.txt
'SAP Program > ABAP' 카테고리의 다른 글
DLL 사용하기 (0) | 2018.04.20 |
---|---|
병렬처리 예제 (0) | 2018.04.18 |
권한 check & is supplied (0) | 2018.04.05 |
sorted table 선언 (0) | 2018.03.23 |
amount를 currency에 맞게 conversion input/output (0) | 2018.03.21 |
글
DLL 사용하기
Five years ago I presented here a way how to call DLL functions in ABAP via the DynamicWrapperX library, which is furthermore available here. It is a COM library which maps the DLL functions to COM calls, which are easy usable inside an ABAP program.
Nearly two years ago I presented here a way, how to call DLL functions via SAPIENs COM library ActiveXPosh.dll. With this library I use PowerShells possibilities to compile .NET languages dynamically at runtime.
Two days ago I presented here an enhancement for an easy using of .NET languages inside ABAP, based on the same method.
Here now an enhancement which combines the knowledge, to show how easy it is to use DLL function calls in ABAP.
At first a small architecture map about the using components and their interfaces:
From the ABAP program, which contains a PowerShell script, we call the ActiveX PowerShell library, via the COM interface. The PowerShell script contains the .NET language code, which is compiled at runtime. And the .NET language code stores the interface to the dynamic link library (DLL). On this way it is possible to call a specific function of the DLL from the ABAP code and to work with its results.
Here now the code. The first code is the include ZCODEINCLUDE which contains the interface to the DLL:
'-Begin-----------------------------------------------------------------
'-Imports-------------------------------------------------------------
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic
'-Namespaces----------------------------------------------------------
Namespace Methods
Public Structure TestStruct
Public x As Integer
Public y As Integer
End Structure
Public Class Test
Public Declare Sub TestMethod Lib "Test.dll" _
Alias "TestMethod" ()
Private Declare Sub pTestMethod2 Lib "Test.dll" _
Alias "TestMethod2" (strParam1 As IntPtr)
Public Shared Sub TestMethod2(strParam1 As String)
Dim ptrParam1 As IntPtr = Marshal.StringToHGlobalAuto(strParam1)
pTestMethod2(ptrParam1)
End Sub
Private Declare Function pTestMethod3 Lib "Test.dll" _
Alias "TestMethod3" (strParam1 As IntPtr, intParam2 As Integer) As IntPtr
Public Shared Function TestMethod3(strParam1 As String, intParam2 As Integer) As String
Dim ptrParam1 As IntPtr = Marshal.StringToHGlobalAuto(strParam1)
Dim retParam As IntPtr = pTestMethod3(ptrParam1, intParam2)
Return Marshal.PtrToStringAuto(retParam)
End Function
Public Declare Function TestMethod4 Lib "Test.dll" _
Alias "TestMethod4" (fltParam1 As Double) As Double
Public Declare Function TestMethod5 Lib "Test.dll" _
Alias "TestMethod5" () As Integer
Private Declare Sub pTestMethod6 Lib "Test.dll" _
Alias "TestMethod6" (StructTest As IntPtr)
Public Shared Sub TestMethod6(StructTestAs TestStruct)
Dim ptrStructTest As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(StructTest))
Marshal.StructureToPtr(StructTest, ptrStructTest, True)
pTestMethod6(ptrStructTest)
End Sub
Private Declare Function pTestMethod7 Lib "Test.dll" _
Alias "TestMethod7" (X As Integer, Y As Integer) As IntPtr
Public Shared Function TestMethod7(X As Integer, Y As Integer) As TestStruct
Dim ptrStructTest As IntPtr = pTestMethod7(X, Y)
Return Marshal.PtrToStructure(ptrStructTest, New TestStruct().GetType)
End Function
End Class
End Namespace
'-End-------------------------------------------------------------------
As you can see there are seven external test methods declarations with different interfaces and different parameter types. A few of them are declared as private, but they owns a public wrapper function. These wrapper functions convert the parameter types, e.g. from string to pointer. So it is easier to call the functions.
Now the PowerShell code from the include ZPSINCLUDE, to load the .NET language class:
#-Begin-----------------------------------------------------------------
If (-Not ("Methods.Test" -as [type])) {
Add-Type -TypeDefinition $MethodDefinitions -Language VisualBasic > $Null
}
#-End-------------------------------------------------------------------
Last but not least the ABAP code:
"-Begin-----------------------------------------------------------------
Program zUseDotNet.
"-TypePools---------------------------------------------------------
Type-Pools OLE2.
"-Constants--------------------------------------------------------
Constants OUTPUT_CONSOLE Type i Value 0.
Constants OUTPUT_WINDOW Type i Value 1.
Constants OUTPUT_BUFFER Type i Value 2.
Constants CrLf(2) Type c Value cl_abap_char_utilities=>cr_lf.
"-Classes-----------------------------------------------------------
Class lcl_PoSh Definition.
Public Section.
Class-Methods Init
Importing i_OutputMode Type i
Returning Value(r_oPS) Type OLE2_OBJECT.
Class-Methods Flush.
Class-Methods ReadInclAsString
Importing i_InclName Type SOBJ_NAME
Returning Value(r_strIncl) Type String.
EndClass.
Class lcl_PoSh Implementation.
Method Init.
"-Variables---------------------------------------------------
Data lv_Result Type i.
Create Object r_oPS 'SAPIEN.ActiveXPoSHV3'.
If sy-subrc = 0 And r_oPS-Handle > 0 And r_oPS-Type = 'OLE2'.
Call Method Of r_oPS 'Init' = lv_Result Exporting #1 = 0.
If lv_Result = 0.
Call Method Of r_oPS 'IsPowerShellInstalled' = lv_Result.
If lv_Result <> 0.
Set Property Of r_oPS 'OutputMode' = i_OutputMode.
Set Property Of r_oPS 'OutputWidth' = 128.
EndIf.
Else.
Free Object r_oPS.
EndIf.
Else.
Free Object r_oPS.
EndIf.
EndMethod.
Method Flush.
Call Method CL_GUI_CFW=>Flush.
EndMethod.
Method ReadInclAsstring.
"-Variables---------------------------------------------------
Data lt_TADIR Type TADIR.
Data lt_Incl Type Table Of String.
Data lv_InclLine Type String.
Data lv_retIncl Type String.
"-Main--------------------------------------------------------
Select Single * From TADIR Into lt_TADIR
Where OBJ_NAME = i_InclName.
If sy-subrc = 0.
Read Report i_InclName Into lt_Incl.
If sy-subrc = 0.
Loop At lt_Incl Into lv_InclLine.
lv_retIncl = lv_retIncl && lv_InclLine &&
cl_abap_char_utilities=>cr_lf.
lv_InclLine = ''.
EndLoop.
EndIf.
EndIf.
r_strIncl = lv_retIncl.
EndMethod.
EndClass.
"-Variables---------------------------------------------------------
Data lo_PS Type OLE2_OBJECT.
Data lv_Result Type String.
Data lt_Result Type Table Of String.
Data lv_Code Type String.
Data lv_PSCode Type String.
Data lv_PSCodeExec Type String.
Data lv_strBuf Type String.
Data lv_Path Type String.
"-Main--------------------------------------------------------------
Start-Of-Selection.
lo_PS = lcl_PoSh=>Init( OUTPUT_BUFFER ).
If lo_PS-Handle > 0.
"-Add path to the libray to environment path--------------------
lv_PSCodeExec = '$EnvPath = $env:PATH;' &&
'$env:PATH += ";C:\Dummy";$EnvPath'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
Call Method Of lo_PS 'OutputString' = lv_Result.
Call Method Of lo_PS 'ClearOutput'.
lcl_PoSh=>Flush( ).
lv_Path = lv_Result.
"-Read the dotNET language code from include--------------------
lv_Code = '$MethodDefinitions = @"' && CrLf &&
lcl_PoSh=>ReadInclAsString( 'ZCODEINCLUDE' ) &&
'"@;' && CrLf.
"-Read PowerShell code from include-----------------------------
lv_PSCode = lv_Code && lcl_PoSh=>ReadInclAsString( 'ZPSINCLUDE' ).
"-Call the different functions of the library-------------------
lv_PSCodeExec = lv_PSCode && '[Methods.Test]::TestMethod()'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
lv_PSCodeExec = lv_PSCode &&
'[Methods.Test]::TestMethod2("Hallo Welt")'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
lv_PSCodeExec = lv_PSCode &&
'$strRc = [Methods.Test]::TestMethod3("Hallo Welt", 4711)'.
lv_PSCodeExec = lv_PSCodeExec && CrLf && 'Write-Host $strRc'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
lv_PSCodeExec = lv_PSCode &&
'$fltRc = [Methods.Test]::TestMethod4(3.14159267)'.
lv_PSCodeExec = lv_PSCodeExec && CrLf && 'Write-Host $fltRc'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
lv_PSCodeExec = lv_PSCode &&
'$intRc = [Methods.Test]::TestMethod5()'.
lv_PSCodeExec = lv_PSCodeExec && CrLf && 'Write-Host $intRc'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
lv_PSCodeExec = lv_PSCode &&
'$TestStruct = New-Object Methods.TestStruct'.
lv_PSCodeExec = lv_PSCodeExec && CrLf && '$TestStruct.x = 4'.
lv_PSCodeExec = lv_PSCodeExec && CrLf && '$TestStruct.y = 2'.
lv_PSCodeExec = lv_PSCodeExec && CrLf &&
'[Methods.Test]::TestMethod6($TestStruct)'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
lv_PSCodeExec = lv_PSCode &&
'$rcStruct = [Methods.Test]::TestMethod7(1606, 1964)'.
lv_PSCodeExec = lv_PSCodeExec && CrLf &&
'Write-Host $rcStruct.x " : " $rcStruct.y'.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
lcl_PoSh=>Flush( ).
"-Catch output buffer into a variable and clear output buffer---
Call Method Of lo_PS 'OutputString' = lv_Result.
Call Method Of lo_PS 'ClearOutput'.
lcl_PoSh=>Flush( ).
"-Write the content of the output buffer------------------------
Split lv_Result At CrLf Into Table lt_Result.
Loop At lt_Result Into lv_strBuf.
Write: / lv_strBuf.
EndLoop.
"-Set environment path back-------------------------------------
lv_PSCodeExec = '$env:PATH = ' && lv_Path.
Call Method Of lo_PS 'Execute' Exporting #1 = lv_PSCodeExec.
Free Object lo_PS.
EndIf.
"-End-------------------------------------------------------------------
In comparison with my example here, I added the method flush to the local class.
If you look at the section “Add path to the library to environment path” you will see the method how to call a PowerShell command, to get the result back and to work with it.
The calls of the DLL functions are also easily:
- TestMethod is only a sub (function with result void), without any parameters.
- TestMethod2 is also a sub, with a string parameter.
- TestMethod3 is a function, with a string, an integer parameter and a string result.
- TestMethod4 is a function, with a float parameter and result.
- TestMethod5 is a function, with no parameters and an integer result.
- TestMethod6 is a sub, with a structure parameter.
- TestMethod7 is a function, with a structure result.
As you can see my example uses many different types of parameters and results. All what you can do with a .NET language, you can do inside ABAP.
Here now the code of the dynamic link library (DLL), to show the receiver of the calls. You can use any program language you want to build a DLL, my example library was programmed in FreeBasiclanguage.
'-Begin-----------------------------------------------------------------
'-Includes------------------------------------------------------------
#Include Once "windows.bi"
'-Structures----------------------------------------------------------
Type TestStruct
x As Integer
y As Integer
End Type
'-Variables-----------------------------------------------------------
Dim Shared struct As TestStruct
Extern "Windows-MS"
'-Sub TestMethod------------------------------------------------------
Sub TestMethod Alias "TestMethod" () Export
MessageBox(NULL, "Dies ist ein Test", "Test", MB_OK)
End Sub
'-Sub TestMethod2-----------------------------------------------------
Sub TestMethod2 Alias "TestMethod2" _
(ByVal strParam1 As WString Ptr) Export
MessageBox(NULL, Str(*strParam1), "Test2", MB_OK)
End Sub
'-Function TestMethod3------------------------------------------------
Function TestMethod3 Alias "TestMethod3" _
(ByVal strParam1 As WString Ptr, ByVal intParam2 As Integer) _
As WString Ptr Export
MessageBox(NULL, Str(*strParam1) & " " & Str(intParam2), _
"Test3", MB_OK)
TestMethod3 = @WStr("Hallo zusammen")
End Function
'-Function TestMethod4------------------------------------------------
Function TestMethod4 Alias "TestMethod4" _
(ByVal fltParam1 As Double) As Double Export
Dim rcValue As Double
rcValue = fltParam1 * 2
MessageBox(NULL, Str(fltParam1) & " * 2 = " & Str(rcValue), _
"Test4", MB_OK)
TestMethod4 = rcValue
End Function
'-Function TestMethod5------------------------------------------------
Function TestMethod5 Alias "TestMethod5" () As Integer Export
TestMethod5 = 16061964
End Function
'-Sub TestMethod6-----------------------------------------------------
Sub TestMethod6(ByVal structParam1 As TestStruct Ptr) Export
MessageBox(NULL, Str(structParam1->x) & " " & _
Str(structParam1->y), "Test6", MB_OK)
End Sub
'-Function TestMethod7------------------------------------------------
Function TestMethod7(ByVal x As Integer, ByVal y As Integer) _
As TestStruct Ptr Export
struct.x = x
struct.y = y
TestMethod7 = @struct
End Function
End Extern
'-End-------------------------------------------------------------------
Enjoy it.
Cheers
Stefan
'SAP Program > ABAP' 카테고리의 다른 글
Source 변경 function (0) | 2018.04.30 |
---|---|
병렬처리 예제 (0) | 2018.04.18 |
권한 check & is supplied (0) | 2018.04.05 |
sorted table 선언 (0) | 2018.03.23 |
amount를 currency에 맞게 conversion input/output (0) | 2018.03.21 |
글
병렬처리 예제
#######################################################################
DO.
CALL FUNCTION 'ZCKM8N_ML_DATA_PROCESS'
STARTING NEW TASK taskname
DESTINATION IN GROUP p_rfcgr "GROUP
PERFORMING get_data_routine ON END OF TASK
EXPORTING
i_bdatj = g_bdatj
i_poper = g_poper
TABLES
it_item = pt_item
EXCEPTIONS
communication_failure = 1 MESSAGE msg
system_failure = 2 MESSAGE msg
resource_failure = 3.
CASE sy-subrc.
WHEN 0.
taskname = taskname + 1.
snd_jobs = snd_jobs + 1.
jobs = jobs + 1.
EXIT. "Job processing finished
WHEN OTHERS.
WRITE:/ msg.
IF excp_flag = space.
excp_flag = 'X'.
WAIT UNTIL rcv_jobs >= snd_jobs UP TO '0.1' SECONDS.
ELSE.
WAIT UNTIL rcv_jobs >= snd_jobs UP TO '0.1' SECONDS.
IF sy-subrc = 0.
CLEAR excp_flag.
ENDIF.
ENDIF.
ENDCASE.
ENDDO.
FORM get_data_routine USING p_taskname.
DATA : l_count LIKE sy-tabix.
*&
RECEIVE RESULTS FROM FUNCTION 'ZCKM8N_ML_DATA_PROCESS'
IMPORTING
e_count = l_count
EXCEPTIONS
communication_failure = 1
system_failure = 2 .
IF sy-subrc = 0.
g_total = g_total + l_count.
ENDIF.
*&
rcv_jobs = rcv_jobs + 1. "Receiving data
jobs = jobs - 1.
ENDFORM. " get_data_routinE
#######################################################################
lv_nr_of_tasks = pa_ntask.
DESCRIBE TABLE gt_zcov_001 LINES sy-tfill.
lv_rsnum_entries = sy-tfill / lv_nr_of_tasks.
LOOP AT gt_zcov_001.
ADD 1 TO lv_counter.
APPEND gt_zcov_001 TO lt_zcov_001.
IF lv_counter = lv_rsnum_entries.
ADD 1 TO lv_task.
lv_task_id = lv_task.
CALL FUNCTION 'Z_CO_COLLECT_ML_P'
STARTING NEW TASK lv_task_id
DESTINATION IN GROUP pa_group
PERFORMING ret_data_collect_ml ON END OF TASK
EXPORTING
i_bdatj = pa_spmon+0(4)
i_poper = gv_pa_poper
i_bukrs = pa_bukrs
i_curtp = gv_check
i_untper = gv_untper
TABLES
i_itab = lt_zcov_001
e_collect_ml = lt_ml_temp1
e_mlast = lt_ml_temp2.
CLEAR lv_counter.
REFRESH lt_zcov_001.
ENDIF.
ENDLOOP.
FORM ret_data_collect_ml USING taskname.
DATA lt_zcov_001 LIKE zcov_001 OCCURS 0 WITH HEADER LINE.
DATA lt_ml_temp1 LIKE zcos_collect_ml OCCURS 0 WITH HEADER LINE.
DATA lt_ml_temp2 LIKE zcos_collect_ml OCCURS 0 WITH HEADER LINE.
RECEIVE RESULTS FROM FUNCTION 'Z_CO_COLLECT_ML_P'
TABLES
i_itab = lt_zcov_001
e_collect_ml = lt_ml_temp1
e_mlast = lt_ml_temp2.
LOOP AT lt_ml_temp1 .
MOVE-CORRESPONDING lt_ml_temp1 TO gt_collect_ml.
COLLECT gt_collect_ml. CLEAR gt_collect_ml.
ENDLOOP.
LOOP AT lt_ml_temp2 .
MOVE-CORRESPONDING lt_ml_temp2 TO gt_mlast.
COLLECT gt_mlast. CLEAR gt_mlast.
ENDLOOP.
ADD 1 TO gv_answers_received.
REFRESH: lt_zcov_001, lt_ml_temp1, lt_ml_temp2.
ENDFORM. " RET_DATA_COLLECT_ML
#######################################################################
FORM call_rfc_function TABLES lt_keko STRUCTURE gt_keko
USING value(p_times) LIKE sy-index.
DATA : msg_text(80) TYPE c,
l_index LIKE sy-tabix,
lv_serial LIKE sy-tabix.
lv_serial = gv_counts * gv_process_count. "현재 돌아갈 개수
DO.
READ TABLE it_task WITH KEY status = 'I'.
IF sy-subrc = 0.
l_index = sy-tabix.
CALL FUNCTION 'ZCO_C041_GETEXPLOSION'
STARTING NEW TASK it_task-name
DESTINATION IN GROUP DEFAULT
PERFORMING get_keko_data ON END OF TASK
EXPORTING
referenceobject = c_ref_object
costingtype = p_cost_type
costingversion = p_tvers
valuationvariant = p_variant
enteredmanually = '' "KKZMA
cost_component_view = c_cost_view
* EXPLOSION_DEPTH = DEPTH
lot_size = p_lot
TABLES
im_keko = lt_keko
EXCEPTIONS
communication_failure = 1
system_failure = 2
RESOURCE_FAILURE = 3.
.
CASE sy-subrc.
WHEN 0.
* Administration of asynchronous tasks
snd_jobs = snd_jobs + 1.
it_task-status = 'W'.
MODIFY it_task INDEX l_index.
EXIT.
WHEN 1 OR 2.
* Handling of communication and system failure
...
EXIT.
WHEN 3. "No resources available at present
* Receive reply to asynchronous RFC calls
IF excp_flag = space.
excp_flag = 'X'.
* First attempt for RESOURCE_FAILURE handling
WAIT UNTIL rcv_jobs >= snd_jobs UP TO '0.01' SECONDS.
ELSE.
* Second attempt for RESOURCE_FAILURE handling
WAIT UNTIL rcv_jobs >= snd_jobs UP TO '0.1' SECONDS.
ENDIF.
IF sy-subrc = 0.
CLEAR excp_flag. "Reset flag
ELSE. "No replies
"Endless loop handling
...
ENDIF.
ENDCASE.
ELSE.
WAIT UP TO 1 SECONDS.
ENDIF.
ENDDO.
ENDFORM. "CALL_RFC_FUNCTION
*&--------------------------------------------------------------------*
*& Form GET_KEKO_DATA
*&--------------------------------------------------------------------*
* Remote Call Function 결과값 처리
*---------------------------------------------------------------------*
FORM get_keko_data USING taskname.
DATA : lt_return LIKE zcos_041_return OCCURS 0 WITH HEADER LINE,
lt_explosion_list LIKE zcos_041_explosionlist
OCCURS 0 WITH HEADER LINE.
RECEIVE RESULTS FROM FUNCTION 'ZCO_C041_GETEXPLOSION'
TABLES
ex_return = lt_return
ex_explosion_list = lt_explosion_list
EXCEPTIONS
OTHERS = 0.
rcv_jobs = rcv_jobs + 1. "Receiving data
APPEND LINES OF lt_explosion_list TO gt_rfc_explosion_list.
APPEND LINES OF lt_return TO gt_rfc_return.
READ TABLE it_task WITH KEY name = taskname.
it_task-status = 'I'.
MODIFY it_task INDEX sy-tabix.
ENDFORM. "GET_KEKO_DATA
#######################################################################
FORM parallel_processing USING p_count TYPE i
p_insert.
DO.
WAIT UNTIL g_running_arfc_wps < g_jobnum.
CALL FUNCTION 'ZQSA_GET_ZCE1_BACKUP'
STARTING NEW TASK g_taskname
DESTINATION IN GROUP p_rfcgrp
PERFORMING return_get_zce1 ON END OF TASK
EXPORTING
i_insert = p_insert
i_tabname = g_tabname
i_perio = gt_perio-perio
i_versi = p_versi
is_qsadic = gs_qsadic
TABLES
it_uniqu = gt_key_t.
CASE sy-subrc.
WHEN 0.
g_taskname = g_taskname + 1.
g_sendjobs = g_sendjobs + 1.
g_running_arfc_wps = g_running_arfc_wps + 1.
EXIT.
ENDCASE.
ENDDO.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form RETURN_GET_ZCE1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
* -->P_IT_UNIQU text
* -->P_= text
* -->P_GT_KEY_T text
*&---------------------------------------------------------------------*
FORM return_get_zce1 USING p_taskname.
DATA: l_processed_count TYPE zqsa_srcnt,
l_tab01 TYPE tabname VALUE 'SY-SUBRC = '.
RECEIVE RESULTS FROM FUNCTION 'ZQSA_GET_ZCE1_BACKUP'
IMPORTING
e_process_count = l_processed_count
EXCEPTIONS
communication_failure = 1 MESSAGE g_message
system_failure = 2 MESSAGE g_message.
g_running_arfc_wps = g_running_arfc_wps - 1.
g_recvjobs = g_recvjobs + 1. " Receiving data
g_processed_count = g_processed_count + l_processed_count.
IF sy-subrc <> 0.
MESSAGE a003 WITH l_tab01 sy-subrc g_message.
ENDIF.
ENDFORM.
#######################################################################
FORM CREATE_PROD_VERSION_PARA .
DATA: LT_MATNR LIKE GT_OUTTAB OCCURS 0 WITH HEADER LINE,
LT_DATA LIKE GT_OUTTAB OCCURS 0 WITH HEADER LINE.
DATA: LT_SEND LIKE TABLE OF ZPPS_0030 WITH HEADER LINE.
DATA: L_CNT_OK TYPE I,
L_CNT_ERROR TYPE I.
DATA: LV_TIME LIKE SY-UZEIT.
LOOP AT GT_OUTTAB WHERE MARK EQ C_X.
MOVE-CORRESPONDING GT_OUTTAB TO LT_DATA.
APPEND LT_DATA. CLEAR LT_DATA.
ENDLOOP.
CHECK LT_DATA[] IS NOT INITIAL.
CLEAR: GV_SEND, GV_RECEIVE, GV_TOTAL_SEND.
CLEAR: GT_SNTASK[], GV_COUNT, GT_ADDTAB[], GT_ADDTAB.
GET TIME FIELD LV_TIME.
DO PA_CNT TIMES.
GV_COUNT = GV_COUNT + 1.
GT_SNTASK-STATUS = 'I'.
CONCATENATE 'Prod_Vers_' LV_TIME GV_COUNT INTO GT_SNTASK-NAME.
APPEND GT_SNTASK.
ENDDO.
LT_MATNR[] = LT_DATA[].
SORT LT_MATNR BY WERKS MATNR.
DELETE ADJACENT DUPLICATES FROM LT_MATNR COMPARING WERKS MATNR.
SORT LT_DATA BY WERKS MATNR.
LOOP AT LT_MATNR.
CLEAR LT_SEND[].
FREE LT_SEND.
READ TABLE LT_DATA WITH KEY WERKS = LT_MATNR-WERKS
MATNR = LT_MATNR-MATNR
BINARY SEARCH.
IF SY-SUBRC = 0.
LOOP AT LT_DATA FROM SY-TABIX.
IF LT_DATA-WERKS <> LT_MATNR-WERKS OR
LT_DATA-MATNR <> LT_MATNR-MATNR.
EXIT.
ENDIF.
CLEAR LT_SEND.
MOVE-CORRESPONDING LT_DATA TO LT_SEND.
APPEND LT_SEND.
ENDLOOP.
ENDIF.
CHECK LT_SEND[] IS NOT INITIAL.
DO.
READ TABLE GT_SNTASK WITH KEY STATUS = 'I'.
IF SY-SUBRC = 0.
GT_SNTASK-STATUS = 'U'.
MODIFY GT_SNTASK INDEX SY-TABIX.
DO.
CALL FUNCTION 'Z_PP_PARA_VERSION'
STARTING NEW TASK GT_SNTASK-NAME
DESTINATION IN GROUP PA_CLASS
PERFORMING RECEIVE_FUNCTION ON END OF TASK
TABLES
T_DATA = LT_SEND
EXCEPTIONS
SYSTEM_FAILURE = 1
COMMUNICATION_FAILURE = 2
RESOURCE_FAILURE = 3
OTHERS = 4.
IF SY-SUBRC <> 0.
WAIT UP TO 1 SECONDS.
WAIT UNTIL GV_TOTAL_SEND <= GV_RECEIVE.
ELSE.
GV_SEND = GV_SEND + 1.
GV_TOTAL_SEND = GV_TOTAL_SEND + 1.
EXIT.
ENDIF.
ENDDO.
EXIT.
ELSE.
WAIT UP TO 1 SECONDS.
WAIT UNTIL GV_TOTAL_SEND <= GV_RECEIVE.
ENDIF.
ENDDO.
* IF GV_SEND = PA_CNT.
** WAIT UNTIL GV_SEND = PA_CNT.
* WAIT UNTIL GV_TOTAL_SEND <= GV_RECEIVE.
* CLEAR GV_SEND.
* ENDIF.
ENDLOOP.
WAIT UNTIL GV_TOTAL_SEND <= GV_RECEIVE.
* WAIT UNTIL GV_SEND <= GV_RECEIVE.
SORT GT_ADDTAB BY WERKS MATNR PLNNR PLNAL STLAL STEUS.
LOOP AT GT_OUTTAB WHERE MARK EQ C_X.
READ TABLE GT_ADDTAB WITH KEY WERKS = GT_OUTTAB-WERKS
MATNR = GT_OUTTAB-MATNR
PLNNR = GT_OUTTAB-PLNNR
PLNAL = GT_OUTTAB-PLNAL
STLAL = GT_OUTTAB-STLAL
BINARY SEARCH.
IF SY-SUBRC = 0.
GT_OUTTAB-ICON = GT_ADDTAB-ICON.
GT_OUTTAB-VERID = GT_ADDTAB-VERID.
GT_OUTTAB-MDV02 = GT_ADDTAB-MDV02.
GT_OUTTAB-LINE = GT_ADDTAB-LINE.
GT_OUTTAB-WC_ICON = GT_ADDTAB-WC_ICON.
GT_OUTTAB-ERRTYP = GT_ADDTAB-ERRTYP.
GT_OUTTAB-ERRMSG = GT_ADDTAB-ERRMSG.
MODIFY GT_OUTTAB.
IF GT_OUTTAB-ERRTYP IS INITIAL.
L_CNT_OK = L_CNT_OK + 1.
ELSE.
L_CNT_ERROR = L_CNT_ERROR + 1.
ENDIF.
ENDIF.
ENDLOOP.
MESSAGE S071 WITH L_CNT_OK L_CNT_ERROR.
GV_GET_TOT = L_CNT_OK + L_CNT_ERROR.
GV_OK = L_CNT_OK .
GV_ERROR = L_CNT_ERROR.
ENDFORM.
**&---------------------------------------------------------------------*
**& Form RECEIVE_FUNCTION
**&---------------------------------------------------------------------*
FORM RECEIVE_FUNCTION USING PV_TASKNAME.
DATA: LT_SEND LIKE TABLE OF ZPPS_0030 WITH HEADER LINE.
RECEIVE RESULTS FROM FUNCTION 'Z_PP_PARA_VERSION'
TABLES
T_DATA = LT_SEND
EXCEPTIONS
SYSTEM_FAILURE = 1
COMMUNICATION_FAILURE = 2
RESOURCE_FAILURE = 3
OTHERS = 4.
GV_RECEIVE = GV_RECEIVE + 1.
APPEND LINES OF LT_SEND TO GT_ADDTAB.
READ TABLE GT_SNTASK WITH KEY NAME = PV_TASKNAME.
IF SY-SUBRC = 0.
GT_SNTASK-STATUS = 'I'.
MODIFY GT_SNTASK INDEX SY-TABIX.
ENDIF.
ENDFORM.
#######################################################################
WAIT UNTIL RESULT_JOB_COUNT >= SEND_JOB_COUNT. 사용은 어떠신지.
던져놓은 작업들이 끝날때까지 기다렸다가 다음 병렬처리를 수행하도록 합니다.
도움이 되셨으면 좋겠네요.
Ex) EXE_JOB_COUNT 는 한번에 실행시킬 작업수입니다.
CLEAR : SEND_JOB_COUNT, RESULT_JOB_COUNT.
DO EXE_JOB_COUNT TIMES.
CALL FUNCTION ~
STARTING NEW TASK ~
DESTINATION IN GROUP DEFAULT
CALLING form_result ON END OF TASK
.....
CASE SY-SUBRC.
WHEN 0. ADD 1 TO SEND JOB_COUNT.
WHEN 1.
...
WHEN OTHERS.
ENDDO.
WAIT UNTIL RESULT_JOB_COUNT >= SEND_JOB_COUNT.
~~~~~Next process.
FORM form_result.
ADD 1 TO RESULT_JOB_COUNT.
RECEIVING RESULTS FROM FUNCTION 'function_name'
....
ENDFORM.
#######################################################################
DO.
IF LT_BWKEY[] IS INITIAL.
EXIT.
ENDIF.
_INIT LT_CBWKEY.
IF LV_RETRY IS INITIAL.
APPEND LINES OF LT_BWKEY[]
FROM LV_SLINE TO LV_ELINE TO LT_CBWKEY.
_INIT : LT_WERKS.
LOOP AT LT_CBWKEY.
_RANGES : LT_WERKS ZGCOZ_I ZGCOZ_EQ LT_CBWKEY-BWKEY SPACE.
ENDLOOP.
DELETE LT_BWKEY FROM LV_SLINE TO LV_ELINE.
GV_INDEX = GV_INDEX + 1.
ENDIF.
CLEAR LV_RETRY.
CONCATENATE 'TASK' GV_INDEX INTO GV_TASK.
CALL FUNCTION 'Z_CO_GET_ENDING_STOCK'
STARTING NEW TASK GV_TASK DESTINATION IN GROUP P_RFCGRP
PERFORMING RETURN_GET_ENDING_STOCK ON END OF TASK
EXPORTING
IV_PFLAG = LV_PFLAG
IV_KOKRS = P_KOKRS
IV_BUKRS = P_BUKRS
IV_SPMON = P_SPMON
IT_BWKEY = LT_WERKS[]
IT_BKLAS = LT_BKLAS[]
IT_MATNR = LT_MATNR[]
TABLES
T_STOCK = LT_STOCK
EXCEPTIONS
SYSTEM_FAILURE = 1 MESSAGE GV_MSG_TEXT
COMMUNICATION_FAILURE = 2 MESSAGE GV_MSG_TEXT
RESOURCE_FAILURE = 3
INVALID_PERIOD = 4
NOT_FOUND = 5.
CASE SY-SUBRC.
WHEN 0.
GV_SNJOBS = GV_SNJOBS + 1.
GV_TOJOBS = GV_TOJOBS + 1.
WHEN 1 OR 2.
* Handling of communication and system failure
GV_ERROR = ZGCOZ_X.
* Some Logging about this status...
CONCATENATE 'Main Call Function Error: ' GV_MSG_TEXT
INTO GV_MSG_TEXT.
MESSAGE S000(ZMC_CO02) WITH GV_MSG_TEXT DISPLAY LIKE ZGCOZ_E.
LEAVE LIST-PROCESSING.
WHEN 3. "No resources available at present
* IF gv_snjobs >= 1.
WAIT UNTIL GV_RCJOBS >= GV_SNJOBS
UP TO 5 SECONDS.
* ENDIF.
LV_RETRY = ZGCOZ_X.
CONTINUE.
WHEN 4.
*-- INVALID PERIOD
MESSAGE S000(ZMC_CO02) WITH TEXT-TM2 DISPLAY LIKE ZGCOZ_E.
GV_ERROR = ZGCOZ_X.
EXIT.
WHEN 5.
MESSAGE S166(ZMC_CO02) DISPLAY LIKE ZGCOZ_E.
GV_ERROR = ZGCOZ_X.
EXIT.
ENDCASE.
IF GV_TOJOBS >= P_WPNUM.
WAIT UNTIL GV_TOJOBS < P_WPNUM.
ENDIF.
ENDDO.
IF GV_ERROR IS INITIAL.
WAIT UNTIL GV_RCJOBS >= GV_SNJOBS.
ENDIF.
#######################################################################
'SAP Program > ABAP' 카테고리의 다른 글
Source 변경 function (0) | 2018.04.30 |
---|---|
DLL 사용하기 (0) | 2018.04.20 |
권한 check & is supplied (0) | 2018.04.05 |
sorted table 선언 (0) | 2018.03.23 |
amount를 currency에 맞게 conversion input/output (0) | 2018.03.21 |