FUNCTION y_prg_maint.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(INPUT) TYPE  TRDIR-NAME
*"----------------------------------------------------------------------

  TYPESBEGIN OF itype,
           line(100),
         END OF itype.
  DATA itab TYPE itype OCCURS WITH HEADER LINE.
  DATA l_cnt TYPE i.

  IF input+0(1<> 'Z' AND
     input+0(1<> 'Y'.
    MESSAGE i000(MMRP01WITH '스탠다드 프로그램은 손댈수 없습니다.'.

    EXIT.
  ENDIF.

  DATAl_name LIKE trdir-name.

  CLEAR l_name.
  SELECT SINGLE name INTO l_name
    FROM trdir
   WHERE name input.
  IF sy-subrc <> 0.
    MESSAGE s000(MMRP01WITH '존재하지 않는 프로그램 입니다.'.

    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

ZEXECUTE-source edit.txt

ZSDR9999-source edit screen 까지.txt


ABAP_Util.zip



'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 사용하기

SAP Program/ABAP 2018. 4. 20. 17:23

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:

zUseDotNet.jpg

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:

  1. TestMethod is only a sub (function with result void), without any parameters.
  2. TestMethod2 is also a sub, with a string parameter.
  3. TestMethod3 is a function, with a string, an integer parameter and a string result.
  4. TestMethod4 is a function, with a float parameter and result.
  5. TestMethod5 is a function, with no parameters and an integer result.
  6. TestMethod6 is a sub, with a structure parameter.
  7. 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

설정

트랙백

댓글