Подтвердить что ты не робот

Передача значения для excel inputbox из VB.NET

Я пытаюсь автоматизировать совокупность данных на некоторых листах excel, которые имеют некоторые макросы. Теперь excel защищен, и я не могу получить секретный ключ. Теперь я могу запускать макросы, но когда я пытаюсь передать аргументы, я получаю несоответствие аргументов.

Если я просто запускаю макрос с именем, я получаю inputbox, который принимает дополнительный аргумент в качестве входных данных и автоматически генерирует некоторые значения для столбцов. Мне нужно вручную ввести это значение в inputbox. Есть ли способ, которым я мог бы автоматизировать этот процесс, например, захватить входной пакет, созданный макросом в vb.net script, и ввести значения оттуда? то есть я хотел бы запустить макрос, и после того, как я получу всплывающее окно с просьбой ввести какое-то значение, используйте код 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 script, чтобы перейти к следующей строке.

4b9b3361

Ответ 1

Как и вы и я, у нас есть имена, аналогично, окна имеют handles(hWnd), Class и т.д. Как только вы знаете, что это за hWnd, с ним легче взаимодействовать.

Это скриншот InputBox

enter image description here

Логика

  • Найдите ручку InputBox с помощью FindWindow и заголовок окна ввода, который Create Network IDs

  • После того, как это найдено, найдите дескриптор окна редактирования в этом окне, используя FindWindowEx

  • Как только дескриптор окна редактирования найден, просто используйте SendMessage для его записи.

В приведенном ниже примере мы будем писать It is possible to Interact with InputBox from VB.Net в поле ввода Excel.

Код

Создайте форму и добавьте к ней кнопку.

enter image description here

Вставьте этот код

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

ScreenShot

Когда вы запускаете код, это то, что вы получаете

enter image description here


РЕДАКТИРОВАТЬ (на основе дальнейшего запроса автоматизации OK/Отмена в чате)

АВТОМАТИЧЕСКИЕ КНОПКИ OK/CANCEL INPUTBOX

Хорошо, интересный факт.

Вы можете вызвать функцию 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

enter image description here

В вашем случае используется первый способ и, к сожалению, кнопки OK и CANCEL не имеют дескриптора, к сожалению, вам придется использовать SendKeys (Ouch!!!) для взаимодействия с ним. Если бы вы создали Inbutbox по второму методу, мы могли бы легко автоматизировать кнопки OK и CANCEL:)

enter image description here

Дополнительная информация:

Протестировано в Visual Studio 2010 Ultimate (64 бит)/Excel 2010 (32 бит)

Вдохновленный вашим вопросом, я на самом деле написал блог Статья о том, как взаимодействовать с кнопкой OK на InputBox.

Ответ 2

В настоящее время я использую метод, в котором я запускаю поток до того, как макрос вызывается script. Поток проверяет, вызван ли входной пакет. Если это так, он берет значение из местоположения и использует 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