2013-04-10 46 views
11

我想在一些有一些宏的Excel表上自動化數據填充。現在,excel已被保護,我無法獲得密鑰。現在我能夠運行宏,但是當我嘗試傳遞參數時,我得到的參數不匹配。將值傳遞給excel輸入框從VB.NET

如果我只是用名稱運行宏,我會得到一個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

'Popup'你的意思是'inputbox'?顯示那部分代碼你調用inputbox/popup ...或者你只是問怎麼用'.Run'方法將參數從'Button4_Click'傳遞給'CreateNetworks'?對不起,但我不確定... – 2013-04-10 10:15:29

+0

好吧,所以我正在嘗試將一個值傳遞給輸入框。這不是一個爭論。 – Shouvik 2013-04-10 10:42:11

+0

在Excel-VBA中是這樣的:'A = Inputbox(「這是提示」,「這是標題」,「這是輸入框的默認值」)? – 2013-04-10 13:19:21

回答

12

你和我一樣,我們都有名字,類似於窗口有handles(hWnd)Class等。一旦你知道hWnd是什麼,更容易與窗口交互。

這是對的InputBox

截圖enter image description here

邏輯

  1. 使用FindWindow和輸入框的標題是Create Network IDs

    找到的InputBox的Handle
  2. 一旦發現,找到該窗口中的編輯框的句柄使用FindWindowEx

  3. 一旦找到編輯框的句柄,只需使用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 

截圖

當您運行的代碼,這是你得到的

enter image description here


EDIT(在聊天基於自動確定的進一步請求/取消)

自動化OK /輸入框的取消按鈕

確定這裏是一個有趣的事實。

可以調用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

在你的情況下,使用第一種方式和遺憾的是,OKCANCEL按鈕沒有句柄,所以不幸的是,你將不得不使用SendKeys (Ouch!!!)進行交互h it。假如你Inbutbox已通過第二種方法生成的,然後我們可以很容易地自動化的OKCANCEL按鈕:)

enter image description here

附加信息

測試上的Visual Studio 2010旗艦版(64位)/Excel 2010(32位)

受你問題的啓發,我實際上寫了一個博客Article關於如何與OK進行交互,但是噸在InputBox上。

+1

+ 1真棒!我從你的博客收到了一個提醒。做得好! – 2013-04-20 12:01:59

+0

lol @ PradeepKumar:謝謝:) – 2013-04-20 12:03:52

+0

哇,這是很棒的東西。讓我明天檢查一下吧。同時,我不明白這怎麼回答我的問題,所以接受答案! – Shouvik 2013-04-21 07:43:13

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 
+0

你介意分享你的方法來檢測輸入框併發送值嗎? – ajakblackgoat 2013-04-14 04:11:14

+0

我花了一個小時解決這個問題,並得出了相同的結論。 SE網站的目標是成爲未來幾年知識和答案的資源。如果你發佈你現有的解決方案,有人可能會更好。 – 2013-04-15 05:17:06

+0

我會在一段時間內添加到我的答案代碼片段中。 – Shouvik 2013-04-15 05:27:39