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

설정

트랙백

댓글




FUNCTION z_cm_auth_check.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(P_BUKRS) TYPE  BUKRS OPTIONAL
*"     VALUE(P_WERKS) TYPE  WERKS_D OPTIONAL
*"     VALUE(P_KOKRS) TYPE  KOKRS OPTIONAL
*"     VALUE(P_MODULE) TYPE  CHAR5 OPTIONAL
*"  EXPORTING
*"     VALUE(E_CODE) TYPE  CHAR1
*"     VALUE(E_MSG) TYPE  CHAR100
*"  TABLES
*"      S_BUKRS STRUCTURE  BUKRS_RAN OPTIONAL
*"      S_WERKS STRUCTURE  RANGE_WERKS OPTIONAL
*"      S_KOKRS STRUCTURE  TYPE_KOKRS_RANGE OPTIONAL
*"----------------------------------------------------------------------

  DATA BEGIN OF lt_bukrs OCCURS 0,
           bukrs TYPE t001-bukrs,
         END OF lt_bukrs.

  DATA BEGIN OF lt_werks OCCURS 0,
           werks TYPE t001w-werks,
         END OF lt_werks.

  DATA BEGIN OF lt_kokrs OCCURS 0,
           kokrs TYPE tka01-kokrs,
         END OF lt_kokrs.

  DATAp_chk_bukrs TYPE  char1,
        p_chk_werks TYPE  char1,
        p_chk_kokrs TYPE  char1.

  DATAlv_plant_obj TYPE xuobject.

  e_code 'S'.

  "batch mode에서는 권한 check 하지 않음.
  CHECK sy-batch IS INITIAL.

  IF p_bukrs IS NOT INITIAL.
    p_chk_bukrs 'X'.

    s_bukrs-sign    'I'.
    s_bukrs-option  'EQ'.
    s_bukrs-low     p_bukrs.
    APPEND s_bukrs.
  ENDIF.

  IF p_werks IS NOT INITIAL.
    p_chk_werks 'X'.

    s_werks-sign    'I'.
    s_werks-option  'EQ'.
    s_werks-low     p_werks.
    APPEND s_werks.
  ENDIF.

  IF p_kokrs IS NOT INITIAL.
    p_chk_kokrs 'X'.

    s_kokrs-sign    'I'.
    s_kokrs-option  'EQ'.
    s_kokrs-low     p_kokrs.
    APPEND s_kokrs.
  ENDIF.

  IF s_bukrs IS SUPPLIED OR
     s_bukrs[] IS NOT INITIAL.
    p_chk_bukrs 'X'.

    SELECT  bukrs
      INTO  TABLE lt_bukrs
      FROM  t001
     WHERE  bukrs IN s_bukrs.
    IF sy-subrc <> 0.
      e_code 'E'.
      "Company code is not available.
      MESSAGE s004(zmc_commINTO e_msg.
      EXIT.
    ENDIF.
  ENDIF.

  IF s_werks IS SUPPLIED OR
     s_werks[] IS NOT INITIAL.
    p_chk_werks 'X'.

    SELECT  werks
      INTO  TABLE lt_werks
      FROM  t001w
     WHERE  werks IN s_werks.
    IF sy-subrc <> 0.
      e_code 'E'.
      "Plant code is not available.
      MESSAGE s005(zmc_commINTO e_msg.
      EXIT.
    ENDIF.
  ENDIF.

  IF s_kokrs IS SUPPLIED OR
     s_kokrs[] IS NOT INITIAL.
    p_chk_kokrs 'X'.

    SELECT  kokrs
      INTO  TABLE lt_kokrs
      FROM  tka01
     WHERE  kokrs IN s_kokrs.
    IF sy-subrc <> 0.
      e_code 'E'.
      "Controlling Area code is not available.
      MESSAGE s006(zmc_commINTO e_msg.
      EXIT.
    ENDIF.
  ENDIF.

  IF lt_werks[] IS NOT INITIAL.
    SELECT tk~bukrs
 APPENDING TABLE lt_bukrs
      FROM t001w AS tw
     INNER JOIN t001k AS tk
        ON tk~bwkey tw~bwkey
       FOR ALL ENTRIES IN lt_werks
     WHERE tw~werks lt_werks-werks.
  ENDIF.

  CASE p_module.
    WHEN 'PP'.
      CLEAR lv_plant_obj.
*      lv_plant_obj = 'Z_PP_WRK'.
    WHEN OTHERS.
      CLEAR lv_plant_obj.
  ENDCASE.

  "Plnat code check 시에는 Bukrs 권한도 check 한다.
  IF p_chk_werks 'X'.
    p_chk_bukrs 'X'.
  ENDIF.

  IF p_chk_bukrs IS NOT INITIAL AND
     lt_bukrs[] IS INITIAL.
    e_code 'E'.
    "회사코드 값이 없습니다.
    e_msg TEXT-t01.
    EXIT.
  ENDIF.

  IF p_chk_werks IS NOT INITIAL AND
     lt_werks[] IS INITIAL.
    e_code 'E'.
    "플랜트 값이 없습니다.
    e_msg TEXT-t02.
    EXIT.
  ENDIF.

  IF p_chk_kokrs IS NOT INITIAL AND
     lt_kokrs[] IS INITIAL.
    e_code 'E'.
    "관리회계 영역 값이 없습니다.
    e_msg TEXT-t03.
    EXIT.
  ENDIF.

  IF lt_werks[] IS NOT INITIAL AND
     lv_plant_obj IS NOT INITIAL.

    LOOP AT lt_werks.
      "권한 Object 결정되면 수정 필요
      AUTHORITY-CHECK OBJECT lv_plant_obj
                      ID 'WERKS' FIELD lt_werks-werks.

      IF sy-subrc <> 0.
        e_code 'E'.
        "플랜트 & 에 대한 사용권한이 없습니다.
        MESSAGE s002(zmc_commWITH lt_werks INTO e_msg.
        EXIT.
      ENDIF.
    ENDLOOP.
  ENDIF.

  IF lt_bukrs[] IS NOT INITIAL.
    LOOP AT lt_bukrs.
      AUTHORITY-CHECK OBJECT 'Z_COM_BUK'
                      ID 'BUKRS' FIELD lt_bukrs-bukrs.

      IF sy-subrc <> 0.
        e_code 'E'.
        "회사코드 & 에 대한 사용권한이 없습니다.
        MESSAGE s001(zmc_commWITH lt_bukrs INTO e_msg.
        EXIT.
      ENDIF.
    ENDLOOP.
  ENDIF.

  IF lt_kokrs[] IS NOT INITIAL.
    LOOP AT lt_kokrs.
      "권한 Object 결정되면 수정 필요
*      AUTHORITY-CHECK OBJECT 'Z_COM_BUK'
*                      ID 'KOKRS' FIELD lt_kokrs-kokrs.
*
*      IF sy-subrc <> 0.
*        e_code = 'E'.
*        "관리회계 영역 & 에 대한 사용권한이 없습니다.
*        MESSAGE s003(zmc_comm) WITH lt_kokrs INTO e_msg.
*
*        EXIT.
*      ENDIF.
    ENDLOOP.
  ENDIF.


ENDFUNCTION.

'SAP Program > ABAP' 카테고리의 다른 글

DLL 사용하기  (0) 2018.04.20
병렬처리 예제  (0) 2018.04.18
sorted table 선언  (0) 2018.03.23
amount를 currency에 맞게 conversion input/output  (0) 2018.03.21
Number range 관련 재미있는 coding  (0) 2018.02.20

설정

트랙백

댓글

Sorted Internal Table

Sorted table is another kind of index table which has unique / non unique key. It also can be accessed via index or key. For sorted table the key must be specified. The declaration is as follows:

DATA: it_mat TYPE SORTED TABLE OF ty_mat WITH UNIQUE KEY matnr,
it_mat TYPE SORTED TABLE OF ty_mat WITH NON-UNIQUE KEY matnr.

Unique key means the MATNR (material no) will must be unique. If same material number is inserted then a run time error will happen. However we can declare the sorted table with non unique key also. In this case same material number can be entered but it will be sorted after entering the number. Here the sorted table behaves similar to sorted standard table. We use INSERT statement to enter any records to the sorted table.

INSERT wa_mat INTO TABLE it_mat.

Here is an example of sorted table by using unique key concept.
REPORT  zabap_gui.

* Declaring the local structure of internal table
TYPES:
      BEGIN OF ty_tab,
        item     TYPE char10,
        quantity TYPE i,
        price    TYPE i,
      END OF ty_tab.

* Declaring the Sorted internal table with non unique key
DATA:
      itab TYPE SORTED TABLE OF ty_tab WITH UNIQUE KEY item,
      wtab TYPE ty_tab.

* Entering records to each field
wtab-item = 'Rice'. wtab-quantity = 2. wtab-price = 80.

* Now one single row has been fulfilled with data
* Next inserting one single row data into the table
INSERT wtab INTO TABLE itab.

wtab-item = 'Suger'. wtab-quantity = 1. wtab-price = 90.
INSERT wtab INTO TABLE itab.

wtab-item = 'Tea'. wtab-quantity = 1. wtab-price = 100.
INSERT wtab INTO TABLE itab.

wtab-item = 'Rice'. wtab-quantity = 3. wtab-price = 150.
INSERT wtab INTO TABLE itab.

wtab-item = 'Horlicks'. wtab-quantity = 1. wtab-price = 200.
INSERT wtab INTO TABLE itab.

wtab-item = 'Suger'. wtab-quantity = 2. wtab-price = 70.
INSERT wtab INTO TABLE itab.

WRITE:  /3 'Item',
        13 'Quantity (KG)',
        28 'Price (Rs)'.
WRITE / '=========================================='.
SKIP" Skipping one single line

LOOP AT itab INTO wtab.

  WRITE:  /3 wtab-item,
          12 wtab-quantity,
          25 wtab-price.
ENDLOOP.

SKIP.
WRITE '=========================================='.


















Since the key is unique the similar entries are ignored by the system.

Here is an example of sorted table by using non unique key concept.

REPORT  zabap_gui.

* Declaring the local structure of internal table
TYPES:
      BEGIN OF ty_tab,
        item     TYPE char10,
        quantity TYPE i,
        price    TYPE i,
      END OF ty_tab.

* Declaring the Standard internal table with non unique key
DATA:
      itab TYPE SORTED TABLE OF ty_tab WITH NON-UNIQUE KEY item,
      wtab TYPE ty_tab.

* Entering records to each field
wtab-item = 'Rice'. wtab-quantity = 2. wtab-price = 80.

* Now one single row has been fulfilled with data
* Next inserting one single row data into the table
INSERT wtab INTO TABLE itab.

wtab-item = 'Suger'. wtab-quantity = 1. wtab-price = 90.
INSERT wtab INTO TABLE itab.

wtab-item = 'Tea'. wtab-quantity = 1. wtab-price = 100.
INSERT wtab INTO TABLE itab.

wtab-item = 'Rice'. wtab-quantity = 3. wtab-price = 150.
INSERT wtab INTO TABLE itab.

wtab-item = 'Horlicks'. wtab-quantity = 1. wtab-price = 200.
INSERT wtab INTO TABLE itab.

wtab-item = 'Suger'. wtab-quantity = 2. wtab-price = 70.
INSERT wtab INTO TABLE itab.

WRITE:  /3 'Item',
        13 'Quantity(KG)',
        28 'Price(Rs)'.
WRITE / '=========================================='.
SKIP" Skipping one single line

LOOP AT itab INTO wtab.

  WRITE:  /3 wtab-item,
          12 wtab-quantity,
          25 wtab-price.
ENDLOOP.

SKIP.
WRITE '=========================================='.



'SAP Program > ABAP' 카테고리의 다른 글

병렬처리 예제  (0) 2018.04.18
권한 check & is supplied  (0) 2018.04.05
amount를 currency에 맞게 conversion input/output  (0) 2018.03.21
Number range 관련 재미있는 coding  (0) 2018.02.20
Dialog 화면에서 debugging  (0) 2018.02.06

설정

트랙백

댓글

CURRENCY_AMOUNT_DISPLAY_TO_SAP 이 펑션을 태우면


USD인경우  1을     반환하고


KRW인경우  0.01을 반환합니다.


 


CURRENCY_AMOUNT_SAP_TO_IDOC 이 펑션을 태우면


USD는 1.00D을 반환하고


KRW는 100을 반환합니다.



예를 들어 excel로 금액을 입력받아 DB에 저장해야 하는 경우에


Excel 작성자는 currency에 상관없이 1000원이면 1000으로 excel에 입력하지만


DB에 입력될때는 currency를 감안하여 저장해야 하기 때문에


CURRENCY_AMOUNT_DISPLAY_TO_SAP  이 펑션을 사용해서 금액을 currency에 맞게 변환한 후


DB에 저장하면 됩니다.


excel에 1000으로 입력되어 있고, 저장될 currency가 KRW일 경우 실제 DB에는 10으로 저장이 됩니다.

'SAP Program > ABAP' 카테고리의 다른 글

권한 check & is supplied  (0) 2018.04.05
sorted table 선언  (0) 2018.03.23
Number range 관련 재미있는 coding  (0) 2018.02.20
Dialog 화면에서 debugging  (0) 2018.02.06
LEAVE LIST-PROCESSING  (0) 2018.02.02

설정

트랙백

댓글

FORM number_range_create .
  DATA lv_nr_range_nr     LIKE inri-nrrangenr,
         lv_nr_object       LIKE inri-object,
         lv_returncode      LIKE inri-returncode,
         lv_h_ret_code(1)   TYPE c,
         lv_error_occured,
         lv_warning_occured.
  DATA BEGIN OF lt_error_tab OCCURS 5.
      INCLUDE STRUCTURE inriv.
  DATA END OF lt_error_tab.
  DATA BEGIN OF lt_errors_tab OCCURS 5.
      INCLUDE STRUCTURE inoer.
  DATA END OF lt_errors_tab.
  DATA BEGIN OF ls_err.
      INCLUDE STRUCTURE inrer.
  DATA END OF ls_err.
  DATA BEGIN OF lt_interval_tab OCCURS 5.
      INCLUDE STRUCTURE inriv.
  DATA END OF lt_interval_tab.
  DATA BEGIN OF lt_obj_attr_tab OCCURS 5.
      INCLUDE STRUCTURE tnro.
  DATA END OF lt_obj_attr_tab.
  DATA BEGIN OF lt_obj_text_tab OCCURS 5.
      INCLUDE STRUCTURE tnrot.
  DATA END OF lt_obj_text_tab.
  DATA lv_number_numc(12TYPE n" LIKE INRIV-NRLEVEL.

  lv_nr_range_nr '01'.
  lv_nr_object 'ZQM_005'.

  CALL FUNCTION 'NUMBER_GET_NEXT'
    EXPORTING
      nr_range_nr             lv_nr_range_nr
      object                  lv_nr_object
    IMPORTING
      number                  lv_number_numc
      returncode              lv_returncode
    EXCEPTIONS
      interval_not_found      1
      number_range_not_intern 2
      object_not_found        3
      quantity_is_0           4.

* Check if number found...
  CASE sy-subrc.
    WHEN 0.                            "Number found...
    WHEN 1.                            "Interval not found...
*     Create new Interval... first get the old counter from SOOC
*     Pass the obj_type to the key
*     Fill the interval structure for insert
      CLEAR lt_interval_tabREFRESH lt_interval_tab.
      lt_interval_tab-fromnumber '1'.
      lt_interval_tab-tonumber '999999999999'.
      MOVElv_nr_range_nr    TO lt_interval_tab-nrrangenr,
            lv_number_numc         TO lt_interval_tab-nrlevel,
            'I'            TO lt_interval_tab-procind.
      APPEND lt_interval_tab.
*     Insert the new interval
      CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE'
        EXPORTING
          object           lv_nr_object
        IMPORTING
          error            ls_err
          error_occured    lv_error_occured
          warning_occured  lv_warning_occured
        TABLES
          error_iv         lt_error_tab
          interval         lt_interval_tab
        EXCEPTIONS
          object_not_found 1.
*     Write the Numberrangedata to the Database.
      CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE'
        EXPORTING
          object                 lv_nr_object
        EXCEPTIONS
          no_changes_made        1
          object_not_initialized 2.
      IF sy-subrc NE 0.
        EXIT.
      ENDIF.
      CALL FUNCTION 'NUMBER_GET_NEXT'
        EXPORTING
          nr_range_nr             lv_nr_range_nr
          object                  lv_nr_object
        IMPORTING
          number                  lv_number_numc
          returncode              lv_returncode
        EXCEPTIONS
          interval_not_found      1
          number_range_not_intern 2
          object_not_found        3
          quantity_is_0           4.

    WHEN 3.                            "Interval not found
*     Create new object... first get the old counter from SOOC
*     Create the object...
      CLEAR lt_obj_attr_tabREFRESH lt_obj_attr_tab.
      MOVElv_nr_object TO lt_obj_attr_tab-object,
            ''        TO lt_obj_attr_tab-yearind,
            'NUMC12'  TO lt_obj_attr_tab-domlen,
            10        TO lt_obj_attr_tab-percentage,
            'X'       TO lt_obj_attr_tab-buffer,
            10        TO lt_obj_attr_tab-noivbuffer.
      APPEND lt_obj_attr_tab.
      CLEAR lt_obj_text_tabREFRESH lt_obj_text_tab.
      MOVEsy-langu TO lt_obj_text_tab-langu,
            lv_nr_object TO lt_obj_text_tab-object,
            TEXT-m01 TO lt_obj_text_tab-txtshort"Issue Number
            TEXT-m01 TO lt_obj_text_tab-txt.      "Issue Number
      APPEND lt_obj_text_tab.
*     Insert the object...
      CALL FUNCTION 'NUMBER_RANGE_OBJECT_UPDATE'
        EXPORTING
          indicator                 'I'  "Insert
          object_attributes         lt_obj_attr_tab
          object_text               lt_obj_text_tab
        IMPORTING
          returncode                lv_h_ret_code
        TABLES
          errors                    lt_errors_tab
        EXCEPTIONS
          object_already_exists     1
          object_attributes_missing 2
          object_not_found          3
          object_text_missing       4
          wrong_indicator           5.
      IF sy-subrc NE 0.
        EXIT.
      ENDIF.
*     Save the changes..
      CALL FUNCTION 'NUMBER_RANGE_OBJECT_CLOSE'
        EXPORTING
          object                 lv_nr_object
        EXCEPTIONS
          object_not_initialized 1.
      IF sy-subrc NE 0.
        EXIT.
      ENDIF.
*     Check if an interval already exists
*     Shouldn't occur but we've had already problems with it
      CALL FUNCTION 'NUMBER_GET_NEXT'
        EXPORTING
          nr_range_nr             lv_nr_range_nr
          object                  lv_nr_object
        IMPORTING
          number                  lv_number_numc
          returncode              lv_returncode
        EXCEPTIONS
          interval_not_found      1
          number_range_not_intern 2
          object_not_found        3
          quantity_is_0           4.
      CASE sy-subrc.
        WHEN 0.
        WHEN 1.
*         Fill the interval structure for insert
          CLEAR lt_interval_tabREFRESH lt_interval_tab.
          lt_interval_tab-fromnumber '1'.
          lt_interval_tab-tonumber '999999999999'.
          MOVElv_nr_range_nr    TO lt_interval_tab-nrrangenr,
                lv_number_numc         TO lt_interval_tab-nrlevel,
                'I'            TO lt_interval_tab-procind.
          APPEND lt_interval_tab.
*         Insert the new interval
          CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE'
            EXPORTING
              object           lv_nr_object
            IMPORTING
              error            ls_err
              error_occured    lv_error_occured
              warning_occured  lv_warning_occured
            TABLES
              error_iv         lt_error_tab
              interval         lt_interval_tab
            EXCEPTIONS
              object_not_found 1.
*         Write the Numberrangedata to the Database.
          CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE'
            EXPORTING
              object                 lv_nr_object
            EXCEPTIONS
              no_changes_made        1
              object_not_initialized 2.
          IF sy-subrc GE 2.                                 "BS310395
            EXIT.
          ENDIF.
          CALL FUNCTION 'NUMBER_GET_NEXT'
            EXPORTING
              nr_range_nr             lv_nr_range_nr
              object                  lv_nr_object
            IMPORTING
              number                  lv_number_numc
              returncode              lv_returncode
            EXCEPTIONS
              interval_not_found      1
              number_range_not_intern 2
              object_not_found        3
              quantity_is_0           4.

        WHEN OTHERS.
          EXIT.
      ENDCASE.
    WHEN OTHERS.

  ENDCASE.
  gs_header-ziss_id lv_number_numc.
ENDFORM.

'SAP Program > ABAP' 카테고리의 다른 글

sorted table 선언  (0) 2018.03.23
amount를 currency에 맞게 conversion input/output  (0) 2018.03.21
Dialog 화면에서 debugging  (0) 2018.02.06
LEAVE LIST-PROCESSING  (0) 2018.02.02
LEAVE TO LIST-PROCESSING  (0) 2018.02.02

설정

트랙백

댓글

[FUNCTION]

Command=/H

Title=Debugger

Type=SystemCommand


위 내용을 가지고 있는 text file을 만들어서

dialog 화면으로 drag 하면 됨

'SAP Program > ABAP' 카테고리의 다른 글

amount를 currency에 맞게 conversion input/output  (0) 2018.03.21
Number range 관련 재미있는 coding  (0) 2018.02.20
LEAVE LIST-PROCESSING  (0) 2018.02.02
LEAVE TO LIST-PROCESSING  (0) 2018.02.02
abap source hide & decompress  (0) 2018.01.26

설정

트랙백

댓글

Use of LEAVE LIST-PROCESSING.

LEAVE LIST-PROCESSING: This statement immediately exits the list processor. This statement can be used in various purposes. Let's take one case where it can be sued.


Suppose a user provides any value in the selection-screen parameter and once press F8 , then in the START-OF-SELECTION event let's we validate the value and raise an error message if it is not a valid one. Then the user perspective the selection-screen should appear again where he can specify the correct value but this is not the case. As soon as the error message is raised then the selection screen disappears. In such a situation Leave List-Processing can be used.

Step1. Crate the below report and have an error message.















Step2. Execute and provide the correct value.










Step3. We receive the o/p.











Step4. Provide a different value.













Step5. Well the raised error disappears the selection-screen. Go back.

















Step6. Well home screen is reached.


















Step7. In the validation change the message type and put the statement 'Leave list-processing'.















Step8. run and provide a value.














Step9. The O/P appears.












Step10. Provide a different value.












Step11. We receive the message but still the selection-screen appears enabling the user to provide a correct value.


'SAP Program > ABAP' 카테고리의 다른 글

Number range 관련 재미있는 coding  (0) 2018.02.20
Dialog 화면에서 debugging  (0) 2018.02.06
LEAVE TO LIST-PROCESSING  (0) 2018.02.02
abap source hide & decompress  (0) 2018.01.26
SAP Standard menu exit - MENUSYST  (0) 2018.01.11

설정

트랙백

댓글

Thursday, 11 September 2014

Use of LEAVE TO LIST-PROCESSING .


 LEAVE TO LIST-PROCESSING :  This statement is used when we are processing a screen and want to print our output in a list. In order to navigate from a screen to list LEAVE TO LIST-PROCESSING statement is used with some conditions. The below post describes some of those:

------------------------------------------------------------------------------------------------------------------------
Step1.  Create a report program and create a screen 9999 to take the input & result screen is 9998.






















Step2. Flow logic of 9999 screen.














Step3. The flow logic of screen 9998.
















Step4. Screen design of 9999 that takes input of the field SCARR-CARRID.


















Step5. The pf status of screen 9999.

















Step6. Execute the report & provide an input value AA and Hit the Enter key to trigger the PAI of screen 9999 which calls the screen 9998 and the PBO of the screen 9998 triggers.















Step7.  This is the screen 9998. Click on the Back button.






















Step8. Here the list appears and hit the back button.














Step9. The plain screen of the list still appears. Now click on the back button.













Step10. Again the list with values appears. Hit again the back button.














Step11. Again the Plain list appears.














Conclusion: If in a PBO of the screen we mention : Leave to list-processing, then we unconditionally leave the calling screen ( here the calling screen is - 9999) and the called screen appears( here the called screen is 9998). As we unconditionally left the calling screen, after reaching the called screen (here from 9998 we move to the list ) we can not go back . That why after a several back we can not reach the calling screen.

-------------------------------------------------------------------------------------------------------------------------


Step12. Let's make some change to the statement  LEAVE TO LIST-PROCESSING and add some extra to it :  LEAVE TO LIST-PROCESSING AND RETURN TO SCREEN 0. Execute the report.
This is a conditional call from the calling screen 9999 and after reaching the called screen 9998 it can reach the calling screen by the keyword :  RETURN TO SCREEN 0. This keyword  RETURN TO SCREEN 0 makes the control reach from the list to the calling screen.
























Step13. Provide the I/P and hot enter key.
















Step14. The below screen 9998 appears. Click on Back button.













Step15. Hence the list appears. now again click on the back button.















Step16. Oh great it calls the I/P screen.

















 
Conclusion: Hence the Leave to screen 0 calls the calling screen from the list so the user can provide again a different value in the I/P screen and see the details of the records in the list output. But here also facing some issue.After providing the I/P in the first screen when we hit enter a blank screen of 9998 appears and if we then select the back button then the list appears. So this is not the ideal O/P the user want to accept. So we have to skip this blank screen 9998 and direct proceed to the list O/P.
________________________________________________________________________________


Step17. Then put one extra statement SUPPRESS DIALOG & Execute the report.
























Step18. Provide the i/P and hit enter key from keyboard.
















Step19. So the first  blank screen of 9998 is suppressed ad directly the list appears. click the back button.

















Step20. Again the I/P screen appears bcoz we have mentioned a conditional call Leave to Screen 0.
Again change the I/P and hit Enter key.

















Step21. Again the List appears with fresh set of records.
















 


'SAP Program > ABAP' 카테고리의 다른 글

Dialog 화면에서 debugging  (0) 2018.02.06
LEAVE LIST-PROCESSING  (0) 2018.02.02
abap source hide & decompress  (0) 2018.01.26
SAP Standard menu exit - MENUSYST  (0) 2018.01.11
PO Ack read demo report  (0) 2018.01.03

설정

트랙백

댓글