【问题标题】:SAP and Excel: On Error GoTo Within On Error GoTo?SAP 和 Excel:On Error GoTo Within On Error GoTo?
【发布时间】:2019-07-25 19:58:18
【问题描述】:

我试图在我的 SAP GUI 和我的 Excel 电子表格之间来回切换。我有一个要在 SAP 中查看的表列表,从 SAP 中提取数据,粘贴到 Excel 中,然后转到下一个表。如果该表在 SAP 中不存在,我希望它转到下一个表(该表可能当前不存在,但将来可能存在,我希望这是动态的我不想对表进行硬编码名称)。

我已经有一个 On Error GoTo 序列正在工作,但是说我们要引用的下一个表也不存在;必须处理该错误。

Sub SAPEverything()

Application.ScreenUpdating = False
Application.DisplayAlerts = False

ans = MsgBox("Are you currently logged into SAP?", vbYesNoCancel)

If ans = vbNo Then
    MsgBox ("Please log into SAP, then come back to this macro.")
    Exit Sub
ElseIf ans = vbCancel Then
    Exit Sub
ElseIf ans = vbYes Then
    frmSAP.Show
    frmSAP.Hide

    LastRow = Sheets("Sheet2").Cells(Rows.Count, 19).End(xlUp).Row
    CurrRow = 2

    For i = 2 To LastRow
        Set SapGuiAuto = GetObject("SAPGUI")  'Get the SAP GUI Scripting object
        Set SAPApp = SapGuiAuto.GetScriptingEngine 'Get the currently running SAP GUI
        Set SAPCon = SAPApp.Children(0) 'Get the first system that is currently connected
        Set session = SAPCon.Children(0) 'Get the first session (window) on that connection
        'Start the transaction to view a table
        session.StartTransaction "Transaction"

        session.findById("wnd[0]").maximize
        session.findById("wnd[0]/tbar[1]/btn[16]").press
        session.findById("wnd[0]/tbar[1]/btn[8]").press
        On Error GoTo HandlingIt
        session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").SelectAll
        session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").contextMenu
        session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectContextMenuItemByText "Copy Text"

        Workbooks("WorkbookName").Activate
        Sheets("Sheet2").Select
        Cells(CurrRow, 2).Select
        ActiveSheet.Paste
        NewLastRow = Sheets("Sheet2").Cells(Rows.Count, 2).End(xlUp).Row
        For k = CurrRow To NewLastRow
            Sheets("Sheet2").Cells(k, 1).Value = Sheets("Sheet2").Cells(i, 19).Value
        Next k
        CurrRow = NewLastRow + 1

    Next i
HandlingIt:
    currErr = i
    For i = currErr + 1 To LastRow
        Set SapGuiAuto = GetObject("SAPGUI")  'Get the SAP GUI Scripting object
        Set SAPApp = SapGuiAuto.GetScriptingEngine 'Get the currently running SAP GUI
        Set SAPCon = SAPApp.Children(0) 'Get the first system that is currently connected
        Set session = SAPCon.Children(0) 'Get the first session (window) on that connection
        'Start the transaction to view a table
        session.StartTransaction "Transaction"

        session.findById("wnd[0]").maximize
        session.findById("wnd[0]/tbar[1]/btn[16]").press

        session.findById("wnd[0]/tbar[1]/btn[8]").press
        On Error GoTo HandlingIt
        session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").SelectAll
        session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").contextMenu
        session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectContextMenuItemByText "Copy Text"

        Workbooks("WorkbookName").Activate
        Sheets("Sheet2").Select
        Cells(CurrRow, 2).Select
        ActiveSheet.Paste
        NewLastRow = Sheets("Sheet2").Cells(Rows.Count, 2).End(xlUp).Row
        For k = CurrRow To NewLastRow
            Sheets("Sheet2").Cells(k, 1).Value = Sheets("Sheet2").Cells(i, 19).Value
        Next k
        CurrRow = NewLastRow + 1

    Next i
End If

一旦我已经在 On Error GoTo 部分中,是否有任何可能的方法来引用代码的另一个 On Error GoTo 部分?或者甚至回到当前 On Error GoTo 部分的开头?

【问题讨论】:

  • 我有点困惑;如果您在一行中遇到错误,您是否只是想跳过该行的其余代码?
  • @JoshEller 是的,这就是我想要做的。我想去新行(下一个表名)
  • 您应该事先检查该表是否存在。顺便说一句,你没有提到事务我们在谈论什么样的表,一个“普通”的 gui 表控件还是一个 alv 网格?
  • @Storax 在代码中还是在运行宏之前?如果是前者,我该怎么做?我是连接 SAP 和 Excel 的新手。我相信这是一个 alv 网格。
  • 写一个以sapsession为变量的函数

标签: excel vba


【解决方案1】:

将错误处理代码与“快乐路径”完全分开。您希望错误处理子例程中的代码仅在出现运行时错误时执行,最重要的是您希望处理该错误 - 为此使用 Resume [label] 指令。

Public Sub DoSomething()
    'do stuff...
    On Error GoTo CleanFail
    For i = a To b
       'do more stuff...
Skip:
    Next
    Exit Sub ' end of happy path

CleanFail: ' begin error handling code
    Debug.Print Err.Description; ". Skipping iteration #" & i
    Resume Skip ' clears error state and jumps to Skip label
End Sub

如果您发现自己需要多个错误处理子例程,则说明您的过程做的事情太多。将其分解为更小的程序,这些程序做的事情更少,因此失败的原因也更少。

【讨论】:

    【解决方案2】:

    没有理由重复代码。如果您只想在遇到错误时跳过循环的其余部分,您完全可以这样做。

    附带说明,当您完成错误处理后,您应该始终重置OnError 行为(通过运行OnError GoTo 0)。您不希望代码中的错误进一步神秘地将您送回循环。调试简直就是噩梦。

        For i = 2 To LastRow
            Set SapGuiAuto = GetObject("SAPGUI")  'Get the SAP GUI Scripting object
            Set SAPApp = SapGuiAuto.GetScriptingEngine 'Get the currently running SAP GUI
            Set SAPCon = SAPApp.Children(0) 'Get the first system that is currently connected
            Set session = SAPCon.Children(0) 'Get the first session (window) on that connection
            'Start the transaction to view a table
            session.StartTransaction "Transaction"
    
            session.findById("wnd[0]").maximize
            session.findById("wnd[0]/tbar[1]/btn[16]").press
            session.findById("wnd[0]/tbar[1]/btn[8]").press
            On Error GoTo NextLoopIteration
            session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").SelectAll
            session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").contextMenu
            session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectContextMenuItemByText "Copy Text"
    
            Workbooks("WorkbookName").Activate
            Sheets("Sheet2").Select
            Cells(CurrRow, 2).Select
            ActiveSheet.Paste
            NewLastRow = Sheets("Sheet2").Cells(Rows.Count, 2).End(xlUp).Row
            For k = CurrRow To NewLastRow
                Sheets("Sheet2").Cells(k, 1).Value = Sheets("Sheet2").Cells(i, 19).Value
            Next k
            CurrRow = NewLastRow + 1
    
    NextLoopIteration:
            On Error GoTo 0
        Next i
    

    【讨论】:

    • 感谢您的回答。但是,我把它放在 vba 中并运行它,它只是一直卡在第一行(第一个表名)。它找不到“下一个 i”语句,因为它在错误处理程序中。有关如何解决此问题的任何建议?
    • @abbsichel 在第一次迭代后,错误处理被重置,因为“错误处理程序”与“快乐路径”交织在一起,所以 On Error GoTo 0 每次迭代都会运行,这会否定任何 On Error GoTo NextLoopIteration将在此循环之前的语句。解决方案是将错误处理代码与过程逻辑分开,并确保错误处理子例程中的代码仅在 VBA 处于错误状态时才被执行。或者只是牛仔它并将On Error GoTo NextLoopIteration/skipit 粘贴在循环体内,就像另一个答案一样。
    【解决方案3】:

    如果出现错误,您可以直接跳到下一个循环迭代,并在继续下一个迭代之前重置错误处理程序。见代码中的 cmets。

    Sub SAPEverything()
    
        Application.ScreenUpdating = False
        Application.DisplayAlerts = False
    
        ans = MsgBox("Are you currently logged into SAP?", vbYesNoCancel)
    
        If ans = vbNo Then
            MsgBox ("Please log into SAP, then come back to this macro.")
            Exit Sub
        ElseIf ans = vbCancel Then
            Exit Sub
        ElseIf ans = vbYes Then
            frmSAP.Show
            frmSAP.Hide
    
            LastRow = Sheets("Sheet2").Cells(Rows.Count, 19).End(xlUp).Row
            CurrRow = 2
    
            For i = 2 To LastRow
                Set SapGuiAuto = GetObject("SAPGUI")  'Get the SAP GUI Scripting object
                Set SAPApp = SapGuiAuto.GetScriptingEngine 'Get the currently running SAP GUI
                Set SAPCon = SAPApp.Children(0) 'Get the first system that is currently connected
                Set session = SAPCon.Children(0) 'Get the first session (window) on that connection
                'Start the transaction to view a table
                session.StartTransaction "Transaction"
    
                session.findById("wnd[0]").maximize
                session.findById("wnd[0]/tbar[1]/btn[16]").press
                session.findById("wnd[0]/tbar[1]/btn[8]").press
    
                ' Enable error handler, in case of any error, execution will go to SkipIt.
                On Error GoTo SkipIt
    
                session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").SelectAll
                session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").contextMenu
                session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectContextMenuItemByText "Copy Text"
    
                Workbooks("WorkbookName").Activate
                Sheets("Sheet2").Select
                Cells(CurrRow, 2).Select
                ActiveSheet.Paste
                NewLastRow = Sheets("Sheet2").Cells(Rows.Count, 2).End(xlUp).Row
                For k = CurrRow To NewLastRow
                    Sheets("Sheet2").Cells(k, 1).Value = Sheets("Sheet2").Cells(i, 19).Value
                Next k
    
                CurrRow = NewLastRow + 1
    
    SkipIt:
                On Error GoTo 0 ' Reset error handler.
    
            Next i
    
        End If
    End Sub
    

    【讨论】:

      【解决方案4】:

      没有测试过,就这样做吧

      Function sapObjectExist (session as object) as boolean
         On error goto EH
         session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").SelectAll
         exit function
      EH:
         sapObjectExist  = false
      End Function
      

      进一步阅读

      SAP Documentation

      Stefan's Homepage: Scritping Tracker

      【讨论】:

        猜你喜欢
        • 2012-12-18
        • 1970-01-01
        • 2015-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多