如何使用VBA自动选择C#应用程序表单中的指定值实现流程自动化?
实现VBA自动操作C# WinForm控件的方案
前置准备
先安装窗口检测工具(比如系统自带的Spy++),提前获取以下信息:
- C#应用主窗口的标题文本
- Institution Name 对应控件(大概率是下拉框ComboBox/列表框ListBox)的类名
- Put Files、Get Files按钮的控件类名或按钮文本
第一步:声明所需Windows API
注意根据你的Office版本选择对应声明,64位Office需要加PtrSafe关键字:
' 32位Office用以下声明 Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) ' 64位Office用以下声明 'Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr 'Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As LongPtr, ByVal hWndChildAfter As LongPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As LongPtr 'Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr 'Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) ' 常量定义(下拉框场景用) Const CB_FINDSTRINGEXACT = &H158 Const CB_SETCURSEL = &H14E Const BM_CLICK = &HF5 ' 如果是列表框控件,就用下面两个常量替换上面CB开头的两个 ' Const LB_FINDSTRINGEXACT = &H1A2 ' Const LB_SETCURSEL = &H186
第二步:完整操作代码
在你原有启动应用的代码基础上新增操作逻辑:
Sub 自动操作WinForm() Dim fileName As Variant Dim filePath As String Dim fso As Object Dim appHwnd As LongPtr ' 32位Office请改为Long类型 Dim comboHwnd As LongPtr ' 32位Office请改为Long类型 Dim btnPutHwnd As LongPtr ' 32位Office请改为Long类型 Dim btnGetHwnd As LongPtr ' 32位Office请改为Long类型 Dim targetInstitution As String Dim itemIndex As Long ' 填入你要固定选中的机构名 targetInstitution = "你要固定选中的Institution Name值" ' 填入你C#应用主窗口的标题,通过Spy++抓取 Const APP_WINDOW_TITLE = "你的C#应用窗口标题" ' 填入你抓取到的下拉框类名 Const COMBO_CLASS_NAME = "WindowsForms10.COMBOBOX.app.0.xxxxxxx" ' 替换为实际抓取到的类名 ' 原有启动应用逻辑 Set fso = CreateObject("shell.application") filePath = "C:\Dropbox (###)\###\###\###\" fileName = Dir(filePath & "### UI*") ' 原代码的MyPath为笔误,已修正为filePath If fileName <> "" Then fso.Open (filePath & fileName) End If ' 等待3秒确保窗口完全加载,可根据实际运行情况调整时长 Sleep 3000 ' 获取主窗口句柄 appHwnd = FindWindow(vbNullString, APP_WINDOW_TITLE) If appHwnd = 0 Then MsgBox "未找到应用窗口" Exit Sub End If ' 获取下拉框控件句柄 comboHwnd = FindWindowEx(appHwnd, 0, COMBO_CLASS_NAME, vbNullString) ' 如果界面有多个同类型控件,可多次调用FindWindowEx,第二个参数传入上一个找到的句柄遍历定位 If comboHwnd = 0 Then MsgBox "未找到Institution Name下拉框" Exit Sub End If ' 查找目标项的索引 itemIndex = SendMessage(comboHwnd, CB_FINDSTRINGEXACT, -1, ByVal targetInstitution) If itemIndex = -1 Then MsgBox "未找到指定机构名" Exit Sub End If ' 选中目标项 Call SendMessage(comboHwnd, CB_SETCURSEL, itemIndex, 0) ' 点击Put Files按钮,按钮文本和你界面显示一致即可 btnPutHwnd = FindWindowEx(appHwnd, 0, vbNullString, "Put Files") If btnPutHwnd <> 0 Then Call SendMessage(btnPutHwnd, BM_CLICK, 0, 0) End If ' 等待Put操作完成,可根据实际运行情况调整时长 Sleep 5000 ' 点击Get Files按钮 btnGetHwnd = FindWindowEx(appHwnd, 0, vbNullString, "Get Files") If btnGetHwnd <> 0 Then Call SendMessage(btnGetHwnd, BM_CLICK, 0, 0) End If End Sub
注意事项
- 如果你的C#应用是用WPF开发的,上述基于Win32 API的方案不适用,需要换用UI Automation类库实现
- 若应用更新后控件类名发生变化,需要重新抓取类名更新代码
- 操作前确保没有其他同标题的窗口打开,避免FindWindow匹配到错误窗口
内容的提问来源于stack exchange,提问作者bgado
相关产品推荐
相关产品推荐

