SAP Gui Scripting循环异常:IW31工单创建脚本仅执行首行
问题排查与修正方案
核心问题分析
你的脚本仅执行首行就终止,主要由以下几个原因导致:
1. 行数计算逻辑缺陷
Rowmax = Rng.End(xlDown).Row - Rng.Row 依赖xlDown定位最后一行,若A列数据中间存在空行,会错误截断有效行数,导致循环提前结束。此外Rowmax未声明变量,可能引发隐式类型错误。
2. 未处理SAP弹窗异常
部分行数据处理时可能不会弹出确认窗口(wnd[1]),直接执行Session.findById("wnd[1]/tbar[0]/btn[0]").press会触发"找不到元素"错误,中断循环。
3. 缺乏错误捕获机制
任何单步操作失败(如SAP元素加载延迟、数据格式错误)都会直接终止脚本,无法继续后续行处理。
修正后的代码
Public SapGuiAuto, WScript, MsgCol Public ObjGui As GuiApplication Public ObjCon As GuiConnection Public Session As GuiSession Sub WOCreate() 'Connection to SAP Application.DisplayAlerts = False Application.ScreenUpdating = False Set SapGuiAuto = GetObject("SAPGUI") Set ObjGui = SapGuiAuto.GetScriptingEngine Set ObjCon = ObjGui.Children(0) Set Session = ObjCon.Children(0) ObjGui.AllowSystemMessages = False ObjGui.HistoryEnabled = False Session.findById("wnd[0]").maximize Dim Rng As Range Dim ActRng As Range Dim i As Long Dim Rowmax As Long ' 声明变量 ' 正确计算有效行数:从A2开始到最后一行非空单元格 Set ActRng = Sheets("Load").Range("A1") Rowmax = Sheets("Load").Cells(Sheets("Load").Rows.Count, "A").End(xlUp).Row - 1 ' A2到最后一行的行数 On Error Resume Next ' 启用错误捕获 For i = 1 To Rowmax 'Loop Starts Err.Clear ' 清除上一次错误 ' 打开IW31事务 Session.findById("wnd[0]/tbar[0]/okcd").Text = "/NIW31" Session.findById("wnd[0]").sendVKey 0 If Err.Number <> 0 Then ActRng.Offset(i, 8).Value = "打开IW31失败: " & Err.Description GoTo NextRow ' 跳过当前行 End If ' 填写工单类型 Session.findById("wnd[0]/usr/ctxtAUFPAR-PM_AUFART").Text = ActRng.Offset(i, 0).Value If Err.Number <> 0 Then ActRng.Offset(i, 8).Value = "填写工单类型失败: " & Err.Description GoTo NextRow End If ' 填写功能位置 Session.findById("wnd[0]/usr/subOBJECT:SAPLCOIH:7120/ctxtCAUFVD-TPLNR").Text = ActRng.Offset(i, 1).Value If Err.Number <> 0 Then ActRng.Offset(i, 8).Value = "填写功能位置失败: " & Err.Description GoTo NextRow End If ' 填写参考工单 Session.findById("wnd[0]/usr/ctxtRC62C-REFNR").Text = ActRng.Offset(i, 2).Value If Err.Number <> 0 Then ActRng.Offset(i, 8).Value = "填写参考工单失败: " & Err.Description GoTo NextRow End If ' 勾选复制选项 Session.findById("wnd[0]/usr/chkRC62C-FOLLOW_UP_ORDER").Selected = True Session.findById("wnd[0]/usr/chkRC62C-COPY_OPR").Selected = True Session.findById("wnd[0]/usr/chkRC62C-COPY_MAT").Selected = True Session.findById("wnd[0]/usr/chkRC62C-FOLLOW_UP_ORDER").SetFocus Session.findById("wnd[0]").sendVKey 0 Session.findById("wnd[0]").sendVKey 0 ' 设置优先级 Session.findById("wnd[0]/usr/cmbCAUFVD-PRIOK").Key = "3" Session.findById("wnd[0]").sendVKey 0 Session.findById("wnd[0]").sendVKey 0 ' 填写描述文本 Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/subSUB_KOPF:SAPLCOIH:1102/subSUB_TEXT:SAPLCOIH:1103/cntlLTEXT/shell").Text = ActRng.Offset(i, 3) & vbCr & vbCr Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/subSUB_KOPF:SAPLCOIH:1102/subSUB_TEXT:SAPLCOIH:1103/cntlLTEXT/shell").SetSelectionIndexes 28, 28 ' 填写附加字段 Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/tabsTS_1100/tabpIHKZ/ssubSUB_AUFTRAG:SAPLCOIH:1120/subHEADER:SAPLCOIH:0154/ctxtCAUFVD-INGPR").Text = ActRng.Offset(i, 4).Value Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/tabsTS_1100/tabpIHKZ/ssubSUB_AUFTRAG:SAPLCOIH:1120/subHEADER:SAPLCOIH:0154/ctxtCAUFVD-VAPLZ").Text = ActRng.Offset(i, 5).Value Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/tabsTS_1100/tabpIHKZ/ssubSUB_AUFTRAG:SAPLCOIH:1120/subHEADER:SAPLCOIH:0154/ctxtCAUFVD-ILART").Text = ActRng.Offset(i, 6).Value Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/tabsTS_1100/tabpIHKZ/ssubSUB_AUFTRAG:SAPLCOIH:1120/subTERM:SAPLCOIH:7300/ctxtCAUFVD-REVNR").Text = ActRng.Offset(i, 7).Value Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/tabsTS_1100/tabpIHKZ/ssubSUB_AUFTRAG:SAPLCOIH:1120/subTERM:SAPLCOIH:7300/ctxtCAUFVD-REVNR").SetFocus Session.findById("wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1100/tabsTS_1100/tabpIHKZ/ssubSUB_AUFTRAG:SAPLCOIH:1120/subTERM:SAPLCOIH:7300/ctxtCAUFVD-REVNR").CaretPosition = 7 ' 保存工单 Session.findById("wnd[0]/tbar[0]/btn[11]").press If Err.Number <> 0 Then ActRng.Offset(i, 8).Value = "保存工单失败: " & Err.Description GoTo NextRow End If ' 处理确认弹窗(仅当窗口存在时) Err.Clear Session.findById("wnd[1]/tbar[0]/btn[0]").press If Err.Number <> 0 Then ' 无弹窗则忽略错误 End If ' 记录状态消息 ActRng.Offset(i, 8).Value = Session.findById("wnd[0]/sbar").Text NextRow: Next i On Error GoTo 0 ' 关闭错误捕获 MsgBox "Process Completed" Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub
关键优化点
- 可靠的行数计算:改用
Cells(Rows.Count, "A").End(xlUp)定位最后一行,不受中间空行影响。 - 错误捕获与跳过机制:使用
On Error Resume Next和Err.Clear捕获操作错误,记录错误信息并跳过当前行,确保循环继续执行。 - 弹窗存在性判断:执行弹窗确认前先清除错误,若弹窗不存在则忽略错误,避免中断循环。
- 变量声明:补全
Rowmax变量声明,避免隐式类型错误。
内容的提问来源于stack exchange,提问作者Burak83
相关产品推荐
相关产品推荐

