Excel VBA连接SAP GUI:如何筛选并下载PDF格式文档
SAP CV04N文档下载VBA宏优化:筛选PDF文件避免格式错误
问题背景
通过Excel VBA宏连接SAP GUI,使用事务码CV04N下载文档时,文档列表偶尔会混有TIFF文件。当前代码默认选择第一个条目下载,导致TIFF文件以PDF格式保存时触发错误。需要实现:读取树形控件条目内容,筛选出PDF文件后再执行下载(确保列表中最多一个PDF)。
现有代码
For j = 0 To k - 1 On Error Resume Next FileName = XYZ SaveName = DlFolder & FileName Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").currentCellRow = j Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").doubleClickCurrentCell Set Tree = Session.findById("wnd[0]/usr/tabsTAB_MAIN/tabpTSMAIN/ssubSCR_MAIN:SAPLCV110:0102/cntlCTL_FILES1/shellcont/shell/shellcont[1]/shell") Tree.selectNode " 1" Tree.nodeContextMenu " 1" Tree.selectContextMenuItem "CF_EXP_COPY" 'It has selected the "copy to" in context menu, now just saves it to Folder saved in "Savename" Session.findById("wnd[1]/usr/ctxtDRAW-FILEP").Text = SaveName Session.findById("wnd[1]/tbar[0]/btn[0]").press 'goes to next doc: Session.findById("wnd[0]/tbar[0]/btn[3]").press Next
解决方案
核心思路
- 遍历树形控件的所有节点,获取每个节点的文件名
- 检查文件名后缀是否为
.pdf(不区分大小写) - 找到目标PDF节点后执行下载操作,跳过非PDF节点
实现代码
方法1:使用SAP Tree控件原生方法(优先推荐)
SAP Tree控件提供getItemText方法,可直接获取指定节点指定列的文本,无需模拟复制粘贴:
For j = 0 To k - 1 On Error Resume Next FileName = XYZ SaveName = DlFolder & FileName Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").currentCellRow = j Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").doubleClickCurrentCell Set Tree = Session.findById("wnd[0]/usr/tabsTAB_MAIN/tabpTSMAIN/ssubSCR_MAIN:SAPLCV110:0102/cntlCTL_FILES1/shellcont/shell/shellcont[1]/shell") Dim nodeIdx As Integer Dim nodeStr As String Dim fileNameText As String Dim pdfFound As Boolean pdfFound = False nodeIdx = 1 Do While Not pdfFound ' 生成SAP节点索引字符串(原代码用10个空格+数字,需匹配实际格式) nodeStr = Space(10) & CStr(nodeIdx) ' 获取节点第1列的文本(假设文件名在第1列,索引从0开始,可根据实际调整) fileNameText = Tree.getItemText(nodeStr, 0) ' 检查是否为PDF文件(不区分大小写) If LCase(RTrim(fileNameText)) Like "*.pdf" Then ' 选中PDF节点并执行下载 Tree.selectNode nodeStr Tree.nodeContextMenu nodeStr Tree.selectContextMenuItem "CF_EXP_COPY" ' 保存文件 Session.findById("wnd[1]/usr/ctxtDRAW-FILEP").Text = SaveName Session.findById("wnd[1]/tbar[0]/btn[0]").press pdfFound = True Else nodeIdx = nodeIdx + 1 ' 防止无限循环,超过节点总数则退出 If nodeIdx > Tree.NodeCount Then MsgBox "当前文档未找到PDF文件", vbExclamation pdfFound = True End If End If Loop ' 关闭当前文档窗口,进入下一个 Session.findById("wnd[0]/tbar[0]/btn[3]").press Next j
方法2:模拟Ctrl+C复制粘贴(原生方法无效时使用)
如果getItemText方法无法获取内容,可通过模拟复制粘贴到Excel临时单元格来提取文本:
' 辅助函数:获取树形节点文本 Function GetTreeNodeText(Tree As Object, nodeStr As String) As String Dim tempWs As Worksheet ' 使用现有工作表或创建临时表,这里假设用名为"Temp"的工作表 On Error Resume Next Set tempWs = ThisWorkbook.Sheets("Temp") If Err.Number <> 0 Then Set tempWs = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)) tempWs.Name = "Temp" End If On Error GoTo 0 ' 选中节点并复制 Tree.selectNode nodeStr Tree.SetFocus SendKeys "^c", True Application.Wait Now + TimeValue("00:00:01") ' 等待复制完成 ' 粘贴到临时单元格并返回文本 tempWs.Range("A1").PasteSpecial xlPasteValues GetTreeNodeText = tempWs.Range("A1").Value tempWs.Range("A1").ClearContents End Function ' 主循环修改部分 For j = 0 To k - 1 On Error Resume Next FileName = XYZ SaveName = DlFolder & FileName Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").currentCellRow = j Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").doubleClickCurrentCell Set Tree = Session.findById("wnd[0]/usr/tabsTAB_MAIN/tabpTSMAIN/ssubSCR_MAIN:SAPLCV110:0102/cntlCTL_FILES1/shellcont/shell/shellcont[1]/shell") Dim nodeIdx As Integer Dim nodeStr As String Dim fileNameText As String Dim pdfFound As Boolean pdfFound = False nodeIdx = 1 Do While Not pdfFound nodeStr = Space(10) & CStr(nodeIdx) fileNameText = GetTreeNodeText(Tree, nodeStr) If LCase(RTrim(fileNameText)) Like "*.pdf" Then Tree.selectNode nodeStr Tree.nodeContextMenu nodeStr Tree.selectContextMenuItem "CF_EXP_COPY" Session.findById("wnd[1]/usr/ctxtDRAW-FILEP").Text = SaveName Session.findById("wnd[1]/tbar[0]/btn[0]").press pdfFound = True Else nodeIdx = nodeIdx + 1 If nodeIdx > Tree.NodeCount Then MsgBox "当前文档未找到PDF文件", vbExclamation pdfFound = True End If End If Loop Session.findById("wnd[0]/tbar[0]/btn[3]").press Next j
注意事项
- 节点索引的空格数量需与SAP实际显示一致,可通过SAP GUI Scripting Tracker工具查看节点的完整索引字符串
- 使用
getItemText时,列索引需根据树形控件的实际列位置调整(通常从0开始计数) SendKeys方法可能受系统环境影响导致不稳定,优先使用原生方法- 可根据需求添加错误处理逻辑,比如跳过无PDF的文档
内容的提问来源于stack exchange,提问作者Piperjoe
相关产品推荐
相关产品推荐

