11

我正在尝试在一些具有一些宏的 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 脚本无法移动到下一行。

4

2 回答 2

13

像你和我一样,我们都有名字,类似地窗口有handles(hWnd)Class等等。一旦你知道那hWnd是什么,与那个窗口交互就更容易了。

这是输入框的截图

在此处输入图像描述

逻辑

  1. 使用输入框的句柄FindWindow和输入框的标题找到输入框的句柄Create Network IDs

  2. 一旦找到,在该窗口中找到编辑框的句柄,使用FindWindowEx

  3. 找到编辑框的句柄后,只需使用SendMessage写入即可。

在下面的示例中,我们将写入It is possible to Interact with InputBox from VB.NetExcel 输入框。

代码

创建一个表单并向其添加一个按钮。

在此处输入图像描述

粘贴此代码

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

截屏

当你运行代码时,这就是你得到的

在此处输入图像描述


编辑(基于在聊天中自动确定/取消的进一步请求)

自动化输入框的确定/取消按钮

好的,这是一个有趣的事实。

InputBox您可以在 Excel 中以两种方式调用该函数

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

在此处输入图像描述

在您的情况下,使用第一种方式,不幸的是,OKCANCEL按钮没有手柄,所以不幸的是,您将不得不使用SendKeys (Ouch!!!)它来与之交互。如果您的收件箱是通过第二种方法生成的,那么我们可以轻松地自动化OKCANCEL按钮 :)

在此处输入图像描述

附加信息

在 Visual Studio 2010 Ultimate(64 位)/Excel 2010(32 位)上测试

受您的问题启发,我实际上写了一篇关于如何与InputBox 上的按钮进行交互的博客文章。OK

于 2013-04-19T19:49:04.057 回答
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
于 2013-04-13T05:07:38.437 回答