excel - 创建循环以从 SAP 下载附件文档
问题描述
我每天都会获得文档列表(接近 500 个唯一文档编号),我需要从 SAP 下载每个文档的附件。我记录了 SAP 脚本,但我无法遍历所有 5 个文档。需要帮忙。
我需要输入文件编号、公司代码和会计年度。(所有将是动态的“)我如何创建一个变量和循环来从我的 Excel 表中为这三个标准选择值?
Public Sub SAPlogin()
Set WshShell = CreateObject("WScript.Shell")
Set proc = WshShell.Exec("C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe")
Dim temp
temp = Timer
Do While Timer - temp < 5
Loop
Set SapGui = GetObject("SAPGUI")
Set Appl = SapGui.GetScriptingEngine
Set Connection = Appl.Openconnection("ERP", True)
Set session = Connection.Children(0)
session.findById("wnd[0]/usr/txtRSYST-BNAME").Text = "XXXX"
session.findById("wnd[0]/usr/pwdRSYST-BCODE").Text = "XXXX"
session.findById("wnd[0]/usr/txtRSYST-LANGU").Text = "EN"
session.findById("wnd[0]").sendVKey 0
If Not IsObject(Application) Then
Set SapGuiAuto = GetObject("SAPGUI")
Set Appl = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(Connection) Then
Set Connection = Application.Children(0)
End If
If Not IsObject(session) Then
Set session = Connection.Children(0)
End If
If IsObject(WScript) Then
WScript.ConnectObject session, "on"
WScript.ConnectObject Application, "on"
End If
session.findById("wnd[0]").maximize
session.findById("wnd[0]/tbar[0]/okcd").Text = "fb03"
session.findById("wnd[0]").sendVKey 0
session.findById("wnd[0]/usr/txtRF05L-BELNR").Text = "1"
session.findById("wnd[0]/usr/ctxtRF05L-BUKRS").Text = "20"
session.findById("wnd[0]/usr/txtRF05L-GJAHR").Text = "2019"
session.findById("wnd[0]/usr/txtRF05L-GJAHR").SetFocus
session.findById("wnd[0]/usr/txtRF05L-GJAHR").caretPosition = 4
session.findById("wnd[0]").sendVKey 0
session.findById("wnd[0]/titl/shellcont/shell").pressContextButton "%GOS_TOOLBOX"
session.findById("wnd[0]/titl/shellcont/shell").selectContextMenuItem "%GOS_VIEW_ATTA"
session.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").currentCellColumn = "BITM_DESCR"
session.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").selectedRows = "0"
session.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").pressToolbarButton "%ATTA_EXPORT"
session.findById("wnd[1]/tbar[0]/btn[0]").press
session.findById("wnd[0]").sendVKey 12
session.findById("wnd[0]/usr/txtRF05L-BELNR").Text = "2"
session.findById("wnd[0]").sendVKey 0
session.findById("wnd[0]/titl/shellcont/shell").pressContextButton "%GOS_TOOLBOX"
session.findById("wnd[0]/titl/shellcont/shell").selectContextMenuItem "%GOS_VIEW_ATTA"
session.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").currentCellColumn = "BITM_DESCR"
session.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").selectedRows = "0"
session.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").pressToolbarButton "%ATTA_EXPORT"
session.findById("wnd[1]/tbar[0]/btn[0]").press
session.findById("wnd[0]").sendVKey 12
End Sub
解决方案
首先简化您拥有的脚本,将其分解为更小的组件。例如,创建一个用于登录的函数,特别是如果您要开始创建几个不同的函数。
Public Function StartSAPSession() as Variant
' Enter your script here for logging in and starting a new session
'....
' Return the session
Set StartSAPSession = Connection.Children(0)
End Function
我会全局声明会话对象,这样每次运行宏时都不需要登录并打开新会话。请注意,使用小写的会话将简化从 SAP GUI 脚本记录器复制和粘贴的过程。
Public session as Variant
然后实际上“做”你所追求的......
假设您有 Table1 和需要查询的 3 个字段;文件编号、公司代码和会计年度。我们将循环浏览此表中的每一行。我们还将假设每个文档的数量可能会发生变化。我们检查是否存在会话(如果不存在),填充查询字段,通过上下文菜单查看附件并下载它们。注意:我目前无权访问 SAP 实例,因此没有机会对此进行测试。它改编自我之前编译的工具。它需要逐步完成并进行一些测试。我通常还进行大量测试以了解可能收到的错误,然后找到有效处理它们的方法。无论如何,给你...
Public Function ExtractDocuments()
Dim Arr() as Variant
Dim DocNum as String
Dim Company as String
Dim FY as String
Dim AttCnt as Integer
Dim i as Long
Dim j as Long
' When session is Nothing then we need to create a new session
' else assume we can re-use the session
If session Is Nothing Then
Set session = StartSAPSession
End If
' Load the table as an Array, this will be faster
Arr = Range("Table1").ListObject.DataBodyRange
' Cycle through each row of the table (Arr)
For i = 1 to Ubound(Arr, 1)
' Start by loading the row you will enter
DocNum = Arr(i, 1)
Company = Arr(i, 2)
FY = Arr(i, 3)
With session
.findById("wnd[0]").maximize
.StartTransaction "FB03" ' Load the transaction you are after
.findById("wnd[0]/usr/txtRF05L-BELNR").Text = DocNum
.findById("wnd[0]/usr/ctxtRF05L-BUKRS").Text = Company
.findById("wnd[0]/usr/txtRF05L-GJAHR").Text = FY
.findById("wnd[0]").sendVKey 0 ' Execute transaction
' The query runs and you select context menu and attachments
.findById("wnd[0]/titl/shellcont/shell").pressContextButton "%GOS_TOOLBOX"
.findById("wnd[0]/titl/shellcont/shell").selectContextMenuItem "%GOS_VIEW_ATTA"
' How many attachments are there? If 1 or more then save each.
AttCnt = .findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").RowCount
If AttCnt > 0 Then
For j = 0 to AttCnt -1
.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").selectedRows = j
.findById("wnd[1]/usr/cntlCONTAINER_0100/shellcont/shell").pressToolbarButton "%ATTA_EXPORT"
Next j
.findById("wnd[1]/tbar[0]/btn[0]").press ' Exit the Attachments window
End If
End With
Next i
End Function
还有更多的机会将其进一步分解为更多的 Subs 和 Functions,以使其更具可读性和可重用性。
祝你好运!
推荐阅读
- node.js - 如何在node.js中为jade中的每个循环制作
- ckan - 停止/启动ckan docker容器后“未找到数据集”
- ssas - SSAS表格模型:具有相同维度表的两个关系
- redirect - AWS Cognito 电子邮件确认未重定向到我的网站
- git - GIT 将分支代码与最新的修补程序代码合并
- sql - 如何使用 sql select 语句中的列将公式写为列
- python - 熊猫数据框函数返回日期最近的行并且其中一列包含输入值,抛出错误
- angular - Angular 7如何从多个输入上传文件
- spring - 如何使用 @MockBean 和 MockMvc 将一些带有 HTTP POST 的数据附加到模拟存储库
- reactjs - 当父状态更改时,React 子组件不会重新渲染