我正在尝试在一些具有一些宏的Excel工作表上自动化数据填充。现在excel受到保护,我无法获得密钥。现在我能够运行宏,但是当我尝试传递参数时,我得到的参数不匹配。
如果我只是运行带有名称的宏,我会得到一个inputbox
,它需要一个额外的参数作为输入,并自动为列生成一些值。到目前为止,我必须手动将此值输入inputbox
。有什么方法可以自动化该过程,即捕获vb.net脚本中的宏抛出的输入框并从那里输入值?即,我想运行宏,并在弹出窗口要求我输入一些值后,使用vb.net代码输入该弹出窗口的值。
这是我现在所拥有的
Public Class Form1
Dim excelApp As New Excel.Application
Dim excelWorkbook As Excel.Workbook
Dim excelWorkSheet As Excel.Worksheet
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
excelWorkbook = excelApp.Workbooks.Open("D:/excelSheets/plan_management_data_templates_network.xls")
excelApp.Visible = True
excelWorkSheet = excelWorkbook.Sheets("Networks")
With excelWorkSheet
.Range("B7").Value = "AR"
End With
excelApp.Run("createNetworks")
// now here I would like to enter the value into the createNetworks Popup box
excelApp.Quit()
releaseObject(excelApp)
releaseObject(excelWorkbook)
End Sub
宏定义
createNetworks()
//does so basic comparisons on existing populated fields
//if true prompts an inputbox and waits for user input.
这使我的vb.net脚本停止移动到下一行。
答案 0 :(得分:12)
和你我一样,我们都有名字,类似的窗口有handles(hWnd)
,Class
等等。一旦你知道hWnd
是什么,就更容易与那个窗口进行交互。
这是InputBox的截图
<强>逻辑强>:
使用FindWindow
找到InputBox的句柄,输入框的标题为Create Network IDs
找到后,使用FindWindowEx
找到编辑框的句柄后,只需使用SendMessage
即可写入。
在下面的示例中,我们将It is possible to Interact with InputBox from VB.Net
写入Excel输入框。
<强>代码强>:
创建表单并向其添加按钮。
粘贴此代码
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Form1
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, _
ByVal lParam As String) As Integer
Const WM_SETTEXT = &HC
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Ret As Integer, ChildRet As Integer
'~~> String we want to write to Input Box
Dim sMsg As String = "It is possible to Interact with InputBox from VB.Net"
'~~> Get the handle of the "Input Box" Window
Ret = FindWindow(vbNullString, "Create Network IDs")
If Ret <> 0 Then
'MessageBox.Show("Input Box Window Found")
'~~> Get the handle of the Text Area "Window"
ChildRet = FindWindowEx(Ret, 0, "EDTBX", vbNullString)
'~~> Check if we found it or not
If ChildRet <> 0 Then
'MessageBox.Show("Text Area Window Found")
SendMess(sMsg, ChildRet)
End If
End If
End Sub
Sub SendMess(ByVal Message As String, ByVal hwnd As Long)
Call SendMessage(hwnd, WM_SETTEXT, False, Message)
End Sub
End Class
<强>截图强>
当你运行代码时,这就是你得到的
编辑(基于进一步请求自动化聊天中的确定/取消)
自动输入输入框的正常/取消按钮
好的,这是一个有趣的事实。
您可以在Excel中以两种方式调用InputBox
函数
Sub Sample1()
Dim Ret
Ret = Application.InputBox("Called Via Application.InputBox", "Sample Title")
End Sub
和
Sub Sample2()
Dim Ret
Ret = InputBox("Called Via InputBox", "Sample Title")
End Sub
在您的情况下,第一种方式被使用,不幸的是,OK
和CANCEL
按钮没有句柄,所以不幸的是,您必须使用SendKeys (Ouch!!!)
与之交互。如果您通过第二种方法生成Inbutbox,那么我们可以轻松自动化OK
和CANCEL
按钮:)
其他信息:
在Visual Studio 2010 Ultimate(64位)/ Excel 2010(32位)
上测试 受您的问题的启发,我实际上写了一篇关于如何与InputBox上的OK
按钮互动的博客Article。
答案 1 :(得分:4)
目前,我使用的方法是在脚本调用宏之前运行一个线程。线程检查是否已调用输入框。如果是,它从该位置获取值并使用sendkeys,提交该框。
这是一个基本的解决方案,但我希望能更优雅地解决这个问题。
我的解决方案代码:
Public Class Form1
Dim excelApp As New Excel.Application
Dim excelWorkbook As Excel.Workbook
Dim excelWorkSheet As Excel.Worksheet
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
excelWorkbook = excelApp.Workbooks.Open("D:/excelSheets/some_excel.xls")
excelApp.Visible = True
excelWorkSheet = excelWorkbook.Sheets("SheetName")
With excelWorkSheet
.Range("B7").Value = "Value"
End With
Dim trd = New Thread(Sub() Me.SendInputs("ValueForInputBox"))
trd.IsBackground = True
trd.Start()
excelApp.Run("macroName")
trd.Join()
releaseObject(trd)
excelApp.Quit()
releaseObject(excelApp)
releaseObject(excelWorkbook)
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
Private Sub SendInputs(ByVal noOfIds As String)
Thread.Sleep(100)
SendKeys.SendWait(noOfIds)
SendKeys.SendWait("{ENTER}")
SendKeys.SendWait("{ENTER}")
End Sub