11

I am trying to automate data population on some excel sheets that have some macros. Now the excel is protected and I cannot get the secret key. Now I am able to run the macros but when I try to pass arguments I get arguments mismatch.

If I just run the macro with the name, I get an inputbox which takes an extra argument as input and auto generates some of the values for the columns. I have to manually enter this value into the inputbox as of now. Is there any way that I could automate that process, i.e capture the inputbox thrown by the macro in the vb.net script and enter the values from there? i.e., I would like to run the macro and after I get the popup asking me to enter some value, use the vb.net code to enter the value to that popup.

Here is what I have till now

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

Macro definition

createNetworks()
//does so basic comparisons on existing populated fields
//if true prompts an inputbox and waits for user input.

This stall my vb.net script too from moving to the next line.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Shouvik
  • 11,350
  • 16
  • 58
  • 89
  • `Popup` you mean `inputbox`? show that part of code you call that inputbox/popup... or you just asking how to pass argument from `Button4_Click` to `CreateNetworks` with `.Run` method?? Sorry, but I'm not sure... – Kazimierz Jawor Apr 10 '13 at 10:15
  • Okay, so I am trying to pass a value into an inputbox. It's not an argument. – Shouvik Apr 10 '13 at 10:42
  • something like this in Excel-VBA: `A = Inputbox("This is prompt", "This is caption", "Here is default value in inputbox")`? – Kazimierz Jawor Apr 10 '13 at 13:19
  • I don't have access to the macro code, but I am guessing that's the syntax. when I call the macro from vb.net can I pass done argument that can be treated as input for the inputbox? – Shouvik Apr 10 '13 at 13:48
  • Yes, that's the syntax which could do this sample input `type your file name here` as presented on [this randomly found](http://www.wiseowl.co.uk/blog/s174/i2.jpg) example in the internet. – Kazimierz Jawor Apr 10 '13 at 13:55
  • I am sorry, I don't think my question is being clear. I will update it once I have access to a machine. I am not trying to create an input box. – Shouvik Apr 10 '13 at 14:09
  • 2
    when you run the macro, does the inputbox get focus automatically? If it does you might be able to use sendkeys. to both populate and submit the input box. – NickSlash Apr 11 '13 at 00:53
  • maybe you can make a video of running it? and if you have rights to the excel then you can try cracking the password there are paid versions of password crackers if you own the excel. not if you hacked it. that be bad. – tgkprog Apr 16 '13 at 03:43
  • I craked the excel ;). That why I posted the question on how to pass data to the excel inputbox from excel. I implemented a soln... – Shouvik Apr 16 '13 at 05:58
  • I implemented a soln but that is restricted to the inputbox getting focus and then operating some sendkeys... But I was hoping for a more robust data parsing methodology. – Shouvik Apr 16 '13 at 07:55
  • 1
    If the input ox is the same title every time you could do a seach on the window and sendmessage to it? http://stackoverflow.com/a/13150233/1685810 and http://www.vbforums.com/showthread.php?637783-RESOLVED-Sendkeys-and-Findwindow – glh Apr 16 '13 at 10:48
  • @glh I don't think it has the same message. Hence I try identifying active window here but even that I am not doing now, I just execute the code when I think focus should be on the input box. – Shouvik Apr 16 '13 at 11:36
  • or you can programmatically add a temp/dummy module to the file youre opening - write the code in the module that overwrites the constructors of the other macros - add parameters - run YOUR overwritten macro from your vbscript. OR open another temp spreadsheet and copy / paste all modules then you have the code and you can edit the macro to take parameters instead of using an inputbox –  Apr 18 '13 at 08:24
  • @mehow Yeah, that soln doesn't work for me. You see the excel files are a prescribed file which is given to us and we are supposed to use. The macros which use the inputbox are using the inputs to initialize the sheets to a particular specification. If I don't execute the macros on this sheet, the file never actually created the dropdowns and other fields which are generated based on the input box and hence validations on this sheet fail. We want the sheet to be initialized too and not just contain data dumps.. – Shouvik Apr 18 '13 at 11:42
  • o yea i get it now. i think vbscripits sendkeys its only way to do it then. this is why (maybe in future) we should be able to write scripts in the path as parameters –  Apr 18 '13 at 12:08
  • I think it is possible using APIs. – Siddharth Rout Apr 19 '13 at 19:05
  • @SiddharthRout Can you please elaborate with some links? I actually did refer your site for a lot of excel automation I did. Could not find any reference to how inputbox can be handled.. – Shouvik Apr 19 '13 at 19:09
  • Can you show me a screenshot of the inputbox? – Siddharth Rout Apr 19 '13 at 19:10
  • `Could not find any reference to how inputbox can be handled..` Did you see [this](http://www.siddharthrout.com/2011/10/23/vbavb-netvb6click-opensavecancel-button-on-ie-download-window/) Revolves around the same principle. I would love to give it a try if you can show me a screenshot of how your inputbox looks... – Siddharth Rout Apr 19 '13 at 19:12
  • Well, I am sorry. I don't have one. But here is a link to the excel [file](http://www.serff.com/documents/plan_management_data_templates_network.xls). – Shouvik Apr 19 '13 at 19:13
  • Which button should i be cliking? – Siddharth Rout Apr 19 '13 at 19:14
  • createNetworks macro. It needs to be done after you set the state – Shouvik Apr 19 '13 at 19:15
  • Ok.. Let me play with this file ;) – Siddharth Rout Apr 19 '13 at 19:16
  • Sure, knock yourself out! :) – Shouvik Apr 19 '13 at 19:17
  • Also if you want to leave a msg for me use "@" I tend to wander aimlessly on SO and might not keep an eye on this comment history:P – Siddharth Rout Apr 19 '13 at 19:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28527/discussion-between-shouvik-and-siddharth-rout) – Shouvik Apr 19 '13 at 19:18
  • Any answer needs to address the concept of a 'modal' dialog: the InputBox grabs the focus **and the flow of logic** - your code has handed control to the modal object, and won't run any commands until the modal object hands back control. There's a very similar question on the VBA board, and [The answer involves a rather intimidating use of delayed callbacks from the API timer](http://stackoverflow.com/questions/18771801/get-hwnd-of-excel-inputbox-method/30353590#30353590) . – Nigel Heffernan Jun 18 '15 at 09:42

2 Answers2

13

Like you and me, we both have names, similarly windows have handles(hWnd), Class etc. Once you know what that hWnd is, it is easier to interact with that window.

This is the screenshot of the InputBox

enter image description here

Logic:

  1. Find the Handle of the InputBox using FindWindow and the caption of the Input Box which is Create Network IDs

  2. Once that is found, find the handle of the Edit Box in that window using FindWindowEx

  3. Once the handle of the Edit Box is found, simply use SendMessage to write to it.

In the below example we would be writing It is possible to Interact with InputBox from VB.Net to the Excel Inputbox.

Code:

Create a Form and add a button to it.

enter image description here

Paste this code

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

When you run the code this is what you get

enter image description here


EDIT (Based on further request of automating the OK/Cancel in Chat)

AUTOMATING THE OK/CANCEL BUTTONS OF INPUTBOX

Ok here is an interesting fact.

You can call the InputBox function two ways in Excel

Sub Sample1()
    Dim Ret
    Ret = Application.InputBox("Called Via Application.InputBox", "Sample Title")
End Sub

and

Sub Sample2()
    Dim Ret
    Ret = InputBox("Called Via InputBox", "Sample Title")
End Sub

enter image description here

In your case the first way is used and unfortunately, The OK and CANCEL buttons do not have a handle so unfortunately, you will have to use SendKeys (Ouch!!!) to interact with it. Had you Inbutbox been generated via the second method then we could have automated the OK and CANCEL buttons easily :)

enter image description here

Additional Info:

Tested on Visual Studio 2010 Ultimate (64 bit) / Excel 2010 (32 bit)

Inspired by your question, I actually wrote a blog Article on how to interact with the OK button on InputBox.

Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
  • Wow, this is awesome stuff. Let me check this out tomorrow.. In the mean while, I don't see how this doesn't answer my question so accepting answer! – Shouvik Apr 21 '13 at 07:43
  • @SiddharthRout Okay, so it works very well! I will open up a bounty again to pass on some more credits. I could not seem to award the bounty. :( – Shouvik Apr 25 '13 at 03:16
  • Thanks for the kind gesture shouvik. But I didn't answer the question just for the bounty. It was an interesting and challenging question. Why? your question even inspired me to write a blog post :) BTW, I am not sure if you can raise a bounty on a solved question like this. Let me check meta. :) – Siddharth Rout Apr 25 '13 at 08:13
  • 2
    +1 as I suspected! http://stackoverflow.com/questions/15922300/passing-value-to-excel-inputbox-from-vb-net#comment22875837_15922300 – glh Apr 25 '13 at 09:54
  • @SiddharthRout You are welcome for the challenge, And as far as the points on the bounty go! It's something that was due to you and thanks for taking on the challenge! :) – Shouvik Apr 27 '13 at 05:23
  • 1
    @glh I actually did not figure out what you meant. But post Siddharth's answer, it became a lot clearer. So, thank you for taking a dig. – Shouvik Apr 27 '13 at 05:25
4

Currently, I employ a method where I run a thread before the macro is called by the script. The thread checks if the inputbox has been called. If it is, it picks up the value from the location and using sendkeys, submits the box.

This is a rudimentary solution but I was hoping for a more elegant solution to this problem.

My solution Code:

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
Shouvik
  • 11,350
  • 16
  • 58
  • 89
  • Do you mind sharing your method to detect the input box and sending the value? – ajakblackgoat Apr 14 '13 at 04:11
  • I spent an hour troubleshooting this and came to the same conclusion. The goal of SE sites is to become a resource of knowledge, of answers, for years to come. If you post your current solution someone maybe able to better it. – Jeremy Thompson Apr 15 '13 at 05:17
  • @MandeepSingh this is a working solution to the problem, but siddhart's is an elegant solution. If you employ his method I am certain it will work much better than this one in instances this code will not help you effectively like if you have an alternate active window, but it's a little more time consuming. – Shouvik Apr 27 '13 at 05:21
  • @Shouvik in my excel file I have the Application.InputBox, the solution of siddhart is not working on Application.InputBox, so I have to use this solution – Mandeep Singh Apr 27 '13 at 08:07
  • That should really not matter. You can check using UI spy and get a handle on this window. Anyway, if this solution works for you, glad that I could help. – Shouvik Apr 27 '13 at 12:22