如何从EXCEL VBA将参数传递到SAP BAPI

时间:2019-07-19 23:23:12

标签: excel vba parameters sap bapi

关于BAPI的参数有很多描述,但是它们是无法理解的。 我将解决方案发布在这里,因为我自己在实现EXCEL VBA的参数化BAPI调用时遇到了很多困难。

我的任务是查询SAP。应该可以(在Excel中通过表单)选择
-日期范围
-不同的状态(例如10、20、60)
-不同的部门代码(例如10、20、60)
-是否显示Z800项目

要访问BAPI,您必须达到以下条件:

  1. 建立与您的SAP实例的连接(网络上有很多此部分的示例,因此我将不作赘述,例如https://turbofuture.com/computers/Silent-Connection-with-SAPLOGON-with-RFCSDK-Example-RFC-Excel-VBA)。在示例代码中,您将类似于
    If Not (connection Is Nothing) Then
                debug.print "connection is successful"
  1. 实例化BAPI(网上有很多关于此部分的示例,因此我也将跳过它,例如https://turbofuture.com/computers/Silent-Connection-with-SAPLOGON-with-RFCSDK-Example-RFC-Excel-VBA) 在示例代码中,您将类似于
    Set functions = sapFunctions(connection)
    Set obSapBapi = functions.Add(BapiName)

如果您看到BAPI对象在调试模式下包含BAPI名称,则此分配成功完成: Successful BAPI assignment 如果分配不成功,则BAPI对象包含“ Nothing”。

  1. 使用参数调用BAPI 在任何地方都可以阅读“导入” /“导出”……等等。但是我只想知道,如何将用户选择传递给SAP? 最常见的用例是,用户在excel工作表中选择数据,然后启动程序,该程序根据用户的选择从SAP提取数据,这也是我的事情。

BAPI可以具有2种不同的参数类型(每个参数都引用SAP视图中的一个显式字段): 1.仅传递1个值:这是.exporting(例如,姓=“ Smith”) 2.传递了多个参数:这是通过表格进行的(例如,姓氏=“ Smith”或“ Myer”或“ Pitt”,订购日期> 4/1/2019和<4/15/2019) Input / Output of a BAPI

输入和输出表具有相同的类型。您的SAP部门可以命名您的数据表。 要获取BAPI的所有表(及其字段),您可以运行以下代码(指输入表和输出表):

        If obSapBapi.Call <> False Then
            'Function Call is Successfull
            Dim oTables As Object 
            Set oTables = obSapBapi.Tables     'Tables collection
            Call GetColumnDetails(oTables)
            Set oTables = Nothing

            Debug.Print "Function Call is Successfull"
        End If

子代码:

    Private Sub GetColumnDetails(ByVal obTables As Object)
    on error resume next
    Dim iLoop As Integer, iColIndx As Integer, iColValuePos As Integer
    Dim iTblCnt As Integer, iColCnt As Integer
    dim iRowCnt As Integer,  iRowIndx As Integer
    Dim oTable As Object, oColumn As Object, iValuePosn As Integer

    iTblCnt = obTables.Count
    iValuePosn = 1
    For iLoop = 1 To iTblCnt
        Set oTable = obTables.Item(iLoop)
        iColCnt = oTable.ColumnCount
        iRowCnt = oTable.RowCount
        iColValuePos = 1
        Sheet3.Cells(iValuePosn, 1) =  oTable.Name
        iValuePosn = iValuePosn + 1
        For Each oColumn In oTable.Columns
            Sheet3.Cells(iValuePosn, iColValuePos) = oColumn.Name
            iColValuePos = iColValuePos + 1
        Next oColumn
       Set oTable = Nothing
    Next
    End Sub

导入/输入表 导入表通常看起来像: SAP import/input table

将单行组装为与OR连接的SQL-WHERE语句。输入表的说明:

Field Zeile(zh-CN)
您必须提供行号(i ++,从1开始)!!!

栏位签名
(仅)可能的值:
I:包含范围在内
E:专属定义范围

字段OPTION的可能值(=运算符):  -EQ等于(=低)
 -NE不等于(<>低)
 -BT在低和高之间,包括两者(低<= x <=高)
 -NB在低和高之外(x <低和x>高)
 -CP包含图案
 -NP不包含图案
 -LT低于(  -LE下限等于(<=下限)
 -GT大于(>低)
 -GE大于等于(> =低)

字段LOW的可能值
取决于引用字段的数据类型。范例:

  • [C(2)] =>字符串
  • [D(8)]是一个日期,您应该将其作为字符串传输,格式为“ yyyyMMdd”
  • [N(2)] =>整数

字段“高”的可能值

  • 为空,但OPTION为BT或NB

数据类型

    SAP BAPI Data Type /  Description   /   Passed from VBA as  
    C (<len>) /           Character    /    string  
    D(8)      /           Date         /    Format$(mydate,”yyyyMMdd”)  
    F(<len>)  /           float        /    Double  
    I(<len>)  /           Integer      /    Integer  
    N(<len>)  /           Numeric      /    Integer / long  
    B         /           Boolean      /    String (length 1)  

示例: 我在上面描述了我的任务。应该可以选择

  • 日期范围(在SAP中,==>名为IT_WORKD_RANGE的表,日期类型为LOW和HIGH)
  • 不同状态(在SAP中==>名为IT_STATUS_RANGE,CHAR 2类型的LOW和HIGH的表)
  • 不同部门(在SAP中,==>名为IT_ZZIDL_RANGE,类型为NUMC 2的LOW和HIGH的表)
  • 是否显示Z800项目(或不显示)(在SAP中,= IF> BOOLEAN名为IF_AWART,导出参数为“ X”或空白,其中空白为默认值,表示FALSE)

解决方案

单击工作表中的按钮后,将显示一个表单。输入上面所有可能的值,然后将其写入工作表“ Connection”,B9:B13

     B9: 20190401  
     B10: 20190701  
     B11: 10;20;40  
     B12: X  
     B13: 05;08;11

和代码:

    Function ReadCatsData()
    On Error GoTo ReadCatsDataError

    Dim MyWB As Workbook
    Dim MyWS As Worksheet


    Dim connection As Object
    Dim SAP_System As String
    Dim WinUser As String
    Dim functions  As Object
    Dim ErrText As String
    Dim ErrTitel As String
    Dim BapiName As String

    Dim DatumVon As String
    Dim DatumBis As String
    Dim Status As String
    Dim Z8 As String
    Dim ILC As String
    Dim Result() As String

    Dim a As Integer
    Dim i As Integer

    Dim obSapBapi As Object

    'Basiswerte setzen:

    ErrTitel = "Monitoring times"
    WinUser = UCase(Environ$("Username"))
    SAP_System = ActiveWorkbook.Sheets("Connection").Cells(2, 1) 
    BapiName = "Z_BAPI_CATS_MON_GET"

    Set MyWB = ActiveWorkbook
    Set MyWS = MyWB.Worksheets("SapDaten")

    Debug.Print SAP_System, WinUser, BapiName

    Set connection = sapConnectionLogon(SAP_System, WinUser)  ' "SGI"
    If Not (connection Is Nothing) Then

        Set functions = sapFunctions(connection)
        Set obSapBapi = functions.Add(BapiName)
        If Not (obSapBapi Is Nothing) Then
                DatumVon = Sheets("Connection").Cells(9, 2).Value    
                           'DatumVon = "20190401"
                DatumBis = Sheets("Connection").Cells(10, 2).Value   
                           'DatumBis = "20190418"
                Status = Sheets("Connection").Cells(11, 2).Value      
                           'Status = "10;20;30"
                Z8 = Sheets("Connection").Cells(12, 2).Value
                ILC = Sheets("Connection").Cells(13, 2).Value   
                           'ILC = "05;08"


                Debug.Print DatumVon, DatumBis, Status, Z8, ILC

                'Declare the Table Parameters  => Uebergabewerte
                    ' Date table (1)    
                    Dim vbIT_WORKD_RANGE As Object    
                    Set vbIT_WORKD_RANGE = obSapBapi.Tables("IT_WORKD_RANGE")
                    vbIT_WORKD_RANGE.Rows.Add
                    vbIT_WORKD_RANGE(1, "SIGN") = "I"
                    vbIT_WORKD_RANGE(1, "OPTION") = "BT"
                    vbIT_WORKD_RANGE(1, "LOW") = DatumVon
                    vbIT_WORKD_RANGE(1, "HIGH") = DatumBis

                    ' Status (2)
                    If Status <> "" Then              
                        Dim vbIT_STATUS_RANGE As Object
                    Set vbIT_STATUS_RANGE = obSapBapi.Tables("IT_STATUS_RANGE")

                        Result = Split(Status, ";")
                        For i = LBound(Result()) To UBound(Result())
                            vbIT_STATUS_RANGE.Rows.Add
                            vbIT_STATUS_RANGE(vbIT_STATUS_RANGE.Rows.Count, _
                                         "SIGN") = "I"
                            vbIT_STATUS_RANGE(vbIT_STATUS_RANGE.Rows.Count, _
                                         "OPTION") = "EQ"
                            vbIT_STATUS_RANGE(vbIT_STATUS_RANGE.Rows.Count, _
                                         "LOW") = Result(i)
                            Debug.Print i, Result(i)
                        Next i
                    End If

                    Erase Result

                     ' Industry_line  (3)
                    If ILC <> "" Then                
                        Dim vbIT_ZZIDL_RANGE As Object
                    Set vbIT_ZZIDL_RANGE = obSapBapi.Tables("IT_ZZIDL_RANGE")

                        Result = Split(ILC, ";")
                        For i = LBound(Result()) To UBound(Result())
                            vbIT_ZZIDL_RANGE.Rows.Add
                            vbIT_ZZIDL_RANGE(vbIT_ZZIDL_RANGE.Rows.Count, _
                                   "SIGN") = "I"
                            vbIT_ZZIDL_RANGE(vbIT_ZZIDL_RANGE.Rows.Count, _
                                    "OPTION") = "EQ"
                            vbIT_ZZIDL_RANGE(vbIT_ZZIDL_RANGE.Rows.Count, _
                                    "LOW") = Val(Result(i))
                            Debug.Print i, Result(i)

                        Next i
                    End If
            'Declare the Export Parameter 
                    ' show Z800 projects (4) 
                    obSapBapi.exports("IF_AWART") = Z8          

            'Call the function. get error in Bapi via obSapBapi.Exception

            If obSapBapi.Call = False Then
                ErrText = "Established connection with SAP system " & _
                          SAP_System  & vbCrLf
                ErrText = ErrText & "BAPI " & BapiName & " exists. " & vbCrLf
                ErrText = ErrText & "BAPI could not be called. " & vbCrLf
                ErrText = ErrText & "SAP delivers the following message: " & _
                          obSapBapi.Exception & vbCrLf 
                ErrText = ErrText & "Data cannot be fetched from SAP." & vbCrLf
                a = MsgBox(ErrText, vbOKOnly + vbCritical, ErrTitel)

            Else
               'Function Call is Successfull
                Dim obSAPTblData As Object

                Set obSAPTblData = obSapBapi.Tables("ET_Data")

                Dim SheetRowPos As Integer
                Dim iRowCnt As Integer
                Dim iRowIndx As Integer
                Dim iColCnt As Integer
                Dim iColIndx As Integer

                iColCnt = obSAPTblData.ColumnCount
                iRowCnt = obSAPTblData.RowCount

                SheetRowPos = 1                            'init

                For iRowIndx = 1 To iRowCnt
                    SheetRowPos = SheetRowPos + 1          'start at row 2 
                    For iColIndx = 1 To iColCnt
                        MyWS.Cells(SheetRowPos, _
                           iColIndx) = obSAPTblData.Value(iRowIndx, iColIndx)

                    Next
                Next

               'Debug.Print "Col.: " & iColCnt & ", Rows: " & iRowCnt
            End If

            Set vbIT_WORKD_RANGE = Nothing
            Set vbIT_STATUS_RANGE = Nothing
            Set vbIT_ZZIDL_RANGE = Nothing

            functions.Remove (BapiName)
            Set obSapBapi = Nothing
         Else
            ErrText = "Established connection with SAP system " & _
                      SAP_System  & vbCrLf
            ErrText = ErrText & "BAPI " & BapiName & _
                      " was not found (could not instantiate object)." & vbCrLf
            ErrText = ErrText & "Data cannot be fetched from SAP." & vbCrLf
            a = MsgBox(ErrText, vbOKOnly + vbCritical, ErrTitel)
        End If


        connection.LogOff
        Set connection = Nothing
        Set functions = Nothing
    Else
        ErrText = "Could not establish connection with SAP system." & vbCrLf
        ErrText = ErrText & "User: " & WinUser
        ErrText = ErrText & ", SAP System: " & SAP_System & vbCrLf
        ErrText = ErrText & "Data cannot be fetched from SAP." & vbCrLf
        a = MsgBox(ErrText, vbOKOnly + vbCritical, ErrTitel)
    End If


    ReadCatsDataExit:
        Set MyWS = Nothing
        Set MyWB = Nothing
        Exit Function
    ReadCatsDataError:
        Resume ReadCatsDataExit

    End Function

3 个答案:

答案 0 :(得分:0)

您提到的外部文档中未解释的是,在7.70之前的SAP GUI版本中(当前为beta,尚未公开),SAP GUI脚本OCX库为32位。许多人使用MS Office 64位,因此您必须按照there所述更改一些SAP GUI条目的Windows注册表。

如果调用涉及称为 BAPI 的特殊RFC功能模块,要创建,更新或删除数据,则需要分别根据成功或失败来调用BAPI_TRANSACTION_COMMITRESULT参数E的消息中指示的失败(如果存在类型为AXobjRfcFunc.Call = False的消息)。请注意,internetMessageId表示系统错误。

答案 1 :(得分:0)

您能否也为 BAPI“导入结构化参数”发布类似的代码。您发布的以下代码适用于 BAPI 表

Set vbIT_WORKD_RANGE = obSapBapi.Tables("IT_WORKD_RANGE")
vbIT_WORKD_RANGE.Rows.Add
vbIT_WORKD_RANGE(1, "SIGN") = "I"
vbIT_WORKD_RANGE(1, "OPTION") = "BT"
vbIT_WORKD_RANGE(1, "LOW") = DatumVon
vbIT_WORKD_RANGE(1, "HIGH") = DatumBis

我在将值传递给 BAPI GRAC_API_RISK_ANALYSIS 中导入参数结构的相同 4 个字段 (SIGN/OPTION/HIGH/LOW) 时遇到问题,参数名称 - IT_SYS_RANGE

答案 2 :(得分:0)

以下是问题作者给出的解决方案(她最初发布在她的问题中)。


解决方案

单击工作表中的按钮后,将显示一个表单。输入上述所有可能的值,然后写入工作表“连接”,B9:B13

     B9: 20190401  
     B10: 20190701  
     B11: 10;20;40  
     B12: X  
     B13: 05;08;11

和代码:

    Function ReadCatsData()
    On Error GoTo ReadCatsDataError

    Dim MyWB As Workbook
    Dim MyWS As Worksheet


    Dim connection As Object
    Dim SAP_System As String
    Dim WinUser As String
    Dim functions  As Object
    Dim ErrText As String
    Dim ErrTitel As String
    Dim BapiName As String

    Dim DatumVon As String
    Dim DatumBis As String
    Dim Status As String
    Dim Z8 As String
    Dim ILC As String
    Dim Result() As String

    Dim a As Integer
    Dim i As Integer

    Dim obSapBapi As Object

    'Basiswerte setzen:

    ErrTitel = "Monitoring times"
    WinUser = UCase(Environ$("Username"))
    SAP_System = ActiveWorkbook.Sheets("Connection").Cells(2, 1) 
    BapiName = "Z_BAPI_CATS_MON_GET"

    Set MyWB = ActiveWorkbook
    Set MyWS = MyWB.Worksheets("SapDaten")

    Debug.Print SAP_System, WinUser, BapiName

    Set connection = sapConnectionLogon(SAP_System, WinUser)  ' "SGI"
    If Not (connection Is Nothing) Then

        Set functions = sapFunctions(connection)
        Set obSapBapi = functions.Add(BapiName)
        If Not (obSapBapi Is Nothing) Then
                DatumVon = Sheets("Connection").Cells(9, 2).Value    
                           'DatumVon = "20190401"
                DatumBis = Sheets("Connection").Cells(10, 2).Value   
                           'DatumBis = "20190418"
                Status = Sheets("Connection").Cells(11, 2).Value      
                           'Status = "10;20;30"
                Z8 = Sheets("Connection").Cells(12, 2).Value
                ILC = Sheets("Connection").Cells(13, 2).Value   
                           'ILC = "05;08"
                
                    
                Debug.Print DatumVon, DatumBis, Status, Z8, ILC
                    
                'Declare the Table Parameters  => Uebergabewerte
                    ' Date table (1)    
                    Dim vbIT_WORKD_RANGE As Object    
                    Set vbIT_WORKD_RANGE = obSapBapi.Tables("IT_WORKD_RANGE")
                    vbIT_WORKD_RANGE.Rows.Add
                    vbIT_WORKD_RANGE(1, "SIGN") = "I"
                    vbIT_WORKD_RANGE(1, "OPTION") = "BT"
                    vbIT_WORKD_RANGE(1, "LOW") = DatumVon
                    vbIT_WORKD_RANGE(1, "HIGH") = DatumBis
                    
                    ' Status (2)
                    If Status <> "" Then              
                        Dim vbIT_STATUS_RANGE As Object
                    Set vbIT_STATUS_RANGE = obSapBapi.Tables("IT_STATUS_RANGE")
                   
                        Result = Split(Status, ";")
                        For i = LBound(Result()) To UBound(Result())
                            vbIT_STATUS_RANGE.Rows.Add
                            vbIT_STATUS_RANGE(vbIT_STATUS_RANGE.Rows.Count, _
                                         "SIGN") = "I"
                            vbIT_STATUS_RANGE(vbIT_STATUS_RANGE.Rows.Count, _
                                         "OPTION") = "EQ"
                            vbIT_STATUS_RANGE(vbIT_STATUS_RANGE.Rows.Count, _
                                         "LOW") = Result(i)
                            Debug.Print i, Result(i)
                        Next i
                    End If
                    
                    Erase Result
                    
                     ' Industry_line  (3)
                    If ILC <> "" Then                
                        Dim vbIT_ZZIDL_RANGE As Object
                    Set vbIT_ZZIDL_RANGE = obSapBapi.Tables("IT_ZZIDL_RANGE")
                   
                        Result = Split(ILC, ";")
                        For i = LBound(Result()) To UBound(Result())
                            vbIT_ZZIDL_RANGE.Rows.Add
                            vbIT_ZZIDL_RANGE(vbIT_ZZIDL_RANGE.Rows.Count, _
                                   "SIGN") = "I"
                            vbIT_ZZIDL_RANGE(vbIT_ZZIDL_RANGE.Rows.Count, _
                                    "OPTION") = "EQ"
                            vbIT_ZZIDL_RANGE(vbIT_ZZIDL_RANGE.Rows.Count, _
                                    "LOW") = Val(Result(i))
                            Debug.Print i, Result(i)

                        Next i
                    End If
            'Declare the Export Parameter 
                    ' show Z800 projects (4) 
                    obSapBapi.exports("IF_AWART") = Z8          
                    
            'Call the function. get error in Bapi via obSapBapi.Exception
            
            If obSapBapi.Call = False Then
                ErrText = "Established connection with SAP system " & _
                          SAP_System  & vbCrLf
                ErrText = ErrText & "BAPI " & BapiName & " exists. " & vbCrLf
                ErrText = ErrText & "BAPI could not be called. " & vbCrLf
                ErrText = ErrText & "SAP delivers the following message: " & _
                          obSapBapi.Exception & vbCrLf 
                ErrText = ErrText & "Data cannot be fetched from SAP." & vbCrLf
                a = MsgBox(ErrText, vbOKOnly + vbCritical, ErrTitel)

            Else
               'Function Call is Successfull
                Dim obSAPTblData As Object
            
                Set obSAPTblData = obSapBapi.Tables("ET_Data")
                            
                Dim SheetRowPos As Integer
                Dim iRowCnt As Integer
                Dim iRowIndx As Integer
                Dim iColCnt As Integer
                Dim iColIndx As Integer
                
                iColCnt = obSAPTblData.ColumnCount
                iRowCnt = obSAPTblData.RowCount
                
                SheetRowPos = 1                            'init
              
                For iRowIndx = 1 To iRowCnt
                    SheetRowPos = SheetRowPos + 1          'start at row 2 
                    For iColIndx = 1 To iColCnt
                        MyWS.Cells(SheetRowPos, _
                           iColIndx) = obSAPTblData.Value(iRowIndx, iColIndx)
            
                    Next
                Next
              
               'Debug.Print "Col.: " & iColCnt & ", Rows: " & iRowCnt
            End If
            
            Set vbIT_WORKD_RANGE = Nothing
            Set vbIT_STATUS_RANGE = Nothing
            Set vbIT_ZZIDL_RANGE = Nothing
            
            functions.Remove (BapiName)
            Set obSapBapi = Nothing
         Else
            ErrText = "Established connection with SAP system " & _
                      SAP_System  & vbCrLf
            ErrText = ErrText & "BAPI " & BapiName & _
                      " was not found (could not instantiate object)." & vbCrLf
            ErrText = ErrText & "Data cannot be fetched from SAP." & vbCrLf
            a = MsgBox(ErrText, vbOKOnly + vbCritical, ErrTitel)
        End If
        
        
        connection.LogOff
        Set connection = Nothing
        Set functions = Nothing
    Else
        ErrText = "Could not establish connection with SAP system." & vbCrLf
        ErrText = ErrText & "User: " & WinUser
        ErrText = ErrText & ", SAP System: " & SAP_System & vbCrLf
        ErrText = ErrText & "Data cannot be fetched from SAP." & vbCrLf
        a = MsgBox(ErrText, vbOKOnly + vbCritical, ErrTitel)
    End If


    ReadCatsDataExit:
        Set MyWS = Nothing
        Set MyWB = Nothing
        Exit Function
    ReadCatsDataError:
        Resume ReadCatsDataExit

    End Function