SAP GUI VBScript实现AGR_1251分批处理及数据修改以规避内存错误
我之前帮同事解决过类似的SAP批量查询问题,针对你遇到的TSV_TNEW_PAGE_ALLOC_FAILED错误,用VBScript实现分批处理是完全可行的,下面给你一套具体的方案和代码示例:
解决方案概述
你需要的是一套结合SAP GUI Scripting和文本处理的VBScript脚本,核心逻辑是:读取角色列表→处理特定结尾的角色(加*)→分批(每750个)→自动填充到SE16的多选对话框→执行查询并导出结果。
步骤1:启用SAP GUI Scripting
首先得确保你的SAP客户端允许脚本访问:
- 打开SAP GUI,点击左上角的「选项」(Options)→「脚本设置」(Scripting Settings)
- 勾选「启用脚本」(Enable Scripting),同时取消勾选「脚本执行时显示警告」和「脚本执行时显示状态栏信息」
- 点击确定后重启SAP客户端
步骤2:VBScript实现代码
下面是完整的脚本示例,假设你已经把所有需要查询的角色保存到了C:\sap_roles.txt(每行一个角色):
Option Explicit ' 配置参数 Const BATCH_SIZE = 750 ' 每批处理的角色数量 Const ROLE_FILE_PATH = "C:\sap_roles.txt" ' 角色列表文件路径 Const TARGET_SUFFIX = "_END" ' 需要加*的角色结尾(替换成你的实际结尾) Const EXPORT_FOLDER = "C:\sap_query_results\" ' 查询结果导出目录 ' 创建文件系统对象 Dim fso, sapGuiAuto, application, connection, session Set fso = CreateObject("Scripting.FileSystemObject") ' 创建导出目录(如果不存在) If Not fso.FolderExists(EXPORT_FOLDER) Then fso.CreateFolder(EXPORT_FOLDER) End If ' 连接到SAP会话 Set sapGuiAuto = GetObject("SAPGUI") Set application = sapGuiAuto.GetScriptingEngine Set connection = application.Children(0) ' 假设第一个SAP连接 Set session = connection.Children(0) ' 假设第一个会话 ' 读取角色列表 Dim roleList, processedRoles, role, batchCount, currentBatch Set roleList = fso.OpenTextFile(ROLE_FILE_PATH, 1) processedRoles = Array() batchCount = 1 Do While Not roleList.AtEndOfStream role = Trim(roleList.ReadLine) ' 处理特定结尾的角色,添加* If Right(role, Len(TARGET_SUFFIX)) = TARGET_SUFFIX Then role = role & "*" End If ' 添加到当前批次 ReDim Preserve processedRoles(UBound(processedRoles) + 1) processedRoles(UBound(processedRoles)) = role ' 当批次达到指定大小,或者到文件末尾时处理批次 If (UBound(processedRoles) + 1) Mod BATCH_SIZE = 0 Or roleList.AtEndOfStream Then currentBatch = Join(processedRoles, vbCrLf) ' 用换行分隔,SAP多选框支持换行粘贴 ProcessBatch session, currentBatch, batchCount, EXPORT_FOLDER ' 重置批次数组 processedRoles = Array() batchCount = batchCount + 1 End If Loop roleList.Close Set roleList = Nothing Set fso = Nothing MsgBox "所有批次处理完成!", vbInformation, "完成" ' 处理单个批次的函数 Sub ProcessBatch(session, batchRoles, batchNum, exportPath) ' 打开SE16事务码 session.StartTransaction "SE16" ' 等待界面加载,可根据实际情况调整延迟 WScript.Sleep 1000 ' 输入表名AGR_1251 session.findById("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").Text = "AGR_1251" session.findById("wnd[0]/tbar[1]/btn[7]").Press ' 执行(F8) WScript.Sleep 1000 ' 点击角色字段的多选按钮(假设角色字段是AGR_NAME,根据实际界面调整) session.findById("wnd[0]/usr/txtAGR_1251-AGR_NAME").SetFocus session.findById("wnd[0]/tbar[1]/btn[24]").Press ' 多选按钮(F4旁边的那个) WScript.Sleep 1000 ' 切换到多选输入框,粘贴批次角色 session.findById("wnd[1]/usr/txtENAME-LOW").SetFocus ' 先清空输入框 session.findById("wnd[1]/usr/txtENAME-LOW").Text = "" ' 直接设置文本(比SendKeys更可靠) session.findById("wnd[1]/usr/txtENAME-LOW").Text = batchRoles WScript.Sleep 500 ' 点击确认按钮 session.findById("wnd[1]/tbar[0]/btn[0]").Press WScript.Sleep 1000 ' 执行查询(F8) session.findById("wnd[0]/tbar[1]/btn[7]").Press WScript.Sleep 3000 ' 等待查询结果加载,根据数据量调整 ' 导出查询结果到本地文件(Excel格式) session.findById("wnd[0]/tbar[1]/btn[45]").Press ' 导出按钮 WScript.Sleep 1000 session.findById("wnd[1]/usr/subSUBSCREEN_STEPLOOP:SAPLSPO5:0150/sub:SAPLSPO5:0150/radSPOPLI-SELFLAG[1,0]").Select ' 选择Excel格式 session.findById("wnd[1]/tbar[0]/btn[0]").Press WScript.Sleep 1000 ' 设置导出文件名 session.findById("wnd[1]/usr/ctxtDY_PATH").Text = exportPath session.findById("wnd[1]/usr/ctxtDY_FILENAME").Text = "AGR_1251_batch_" & batchNum & ".xlsx" session.findById("wnd[1]/tbar[0]/btn[0]").Press WScript.Sleep 2000 ' 返回SE16初始界面,准备下一批 session.findById("wnd[0]/tbar[0]/btn[3]").Press ' 后退(F3) session.findById("wnd[0]/tbar[0]/btn[3]").Press End Sub
关键注意事项
- 界面元素ID调整:脚本里的元素ID(比如
wnd[0]/usr/ctxtDATABROWSE-TABLENAME)可能因为SAP版本或界面布局不同而变化。你可以用SAP GUI的「脚本录制」功能获取准确ID:按Alt+F12→「脚本录制和回放」→开始录制,手动操作一遍后导出脚本,复制里面的元素ID替换到代码中。 - 延迟时间调整:
WScript.Sleep的时间需要根据你的SAP响应速度调整,避免因界面未加载完成导致操作失败。 - 角色列表格式:确保角色列表文件是每行一个角色,没有多余空格。
- 权限问题:确保你的SAP账号有SE16查询AGR_1251的权限,以及导出文件到本地的权限。
替代方案:用ABAP程序(如果有开发权限)
如果VBScript的脚本操作不稳定,你也可以写一个简单的ABAP程序,直接分批读取AGR_1251表并导出结果,这种方式更可靠。但如果没有ABAP开发权限,VBScript方案是最适合的。
内容的提问来源于stack exchange,提问作者Harvey
相关产品推荐
相关产品推荐

