SAP和Excel:在错误转到内在错误转到内?
我试图在SAP GUI和Excel电子表格之间来回切换。我有一个表列表,我想在SAP中查看,从SAP中提取数据,粘贴到Excel,然后转到下一个表。如果该表在SAP中不存在,我希望它转到下一个表(该表当前可能不存在,但将来可能存在,我希望它是动态的,我不想硬编码表名) 我已经有一个错误序列开始工作,但是说我们要引用的下一个表也不存在;这个错误必须得到处理SAP和Excel:在错误转到内在错误转到内?,excel,vba,Excel,Vba,我试图在SAP GUI和Excel电子表格之间来回切换。我有一个表列表,我想在SAP中查看,从SAP中提取数据,粘贴到Excel,然后转到下一个表。如果该表在SAP中不存在,我希望它转到下一个表(该表当前可能不存在,但将来可能存在,我希望它是动态的,我不想硬编码表名) 我已经有一个错误序列开始工作,但是说我们要引用的下一个表也不存在;这个错误必须得到处理 Sub SAPEverything() Application.ScreenUpdating = False Application.Dis
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部分的开头?没有理由重复代码。如果您只是想在遇到错误时跳过循环的其余部分,那么您完全可以这样做 另一方面,当您完成错误处理时,应始终重置
OnError
行为(通过运行OnError GoTo 0
)。您不希望代码中的bug进一步神秘地将您发送回循环。调试是噩梦中的事情
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
未经测试,就这样做了
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
供进一步阅读
如果出现错误,您可以直接跳到下一个循环迭代,并在继续下一个迭代之前重置错误处理程序。请参阅代码中的注释
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
将错误处理代码与“快乐路径”完全分开。您希望错误处理子例程中的代码仅在出现运行时错误时执行,最重要的是您希望处理该错误-为此使用
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
如果您发现自己需要不止一个错误处理子例程,那么您的过程做的事情太多了。把它分解成更小的过程,做更少的事情,因此失败的原因更少。我有点困惑;如果你在一行中遇到错误,你只是想跳过该行的其余代码吗?@JoshEller是的,这就是我要做的。我想转到新行(下一个表名),您应该事先检查表是否存在。顺便说一句,正如您没有提到的,我们谈论的是什么类型的表,“普通”gui表控件还是alv网格?@Storax在代码中,还是在运行宏之前?如果是前者,我会怎么做?我不熟悉连接SAP和Excel。我相信这是一个alv网格。用sapsession作为变量编写一个函数谢谢你的回答。然而,我把它放在vba中并运行它,它只是一直停留在第一行(第一个表名)。它找不到“next i”语句,因为它位于错误处理程序中。关于如何解决这个问题有什么建议吗?@abbsichel在第一次迭代之后,错误处理会被重置,因为“错误处理程序”与“快乐路径”交织在一起,所以每次迭代都会运行
on error GoTo 0
,这会否定此循环之前的任何on error GoTo NextLoopIteration
语句。解决方案是将错误处理代码与过程逻辑分离,并确保错误处理子例程中的代码仅在VBA处于错误状态时执行。或者就像另一个答案一样,在循环体中牛仔它并坚持错误转到下一个循环迭代/skipit
。