VB.net how to wait for user to select an Excel cell - excel

I have created a VSTO project in Visual Studio with a Ribbon and a Form. There is a button on this form which I want when a user clicks on it, it waits for user to select a single cell from the workbook which this add-in is used in it.
I am currently at designing stage and have not much code written. Any key ideas to achieving this? Should I use Application.SendKeys method? Any other/better ideas?
Thanks
My Ribbon Code so far:
Imports Microsoft.Office.Tools.Ribbon
Public Class Ribbon1
Private Sub Ribbon1_Load(ByVal sender As System.Object, ByVal e
As RibbonUIEventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As Object, e As
RibbonControlEventArgs) Handles Button1.Click
Dim f As New Form1
f.Show()
End Sub
End Class
My Form Code so far:
Public Class Form1
'Variables for my "Custom Vlookup Function"
Dim RHeader As Excel.Range 'Reference Header
Dim SRange As Excel.Range 'Seleceted Range
Dim ColNo As Integer 'Column number ahead
Dim xlApp As Excel.Application = Globals.ThisAddIn.Application
Dim xlWB As Excel.Workbook =
Globals.ThisAddIn.Application.ActiveWorkbook
Private Sub Button2_Click(sender As Object, e As EventArgs)
Handles Button2.Click
End Sub
End Class

Wait for the Worksheet.SelectionChange event which is fired when the selection changes on a worksheet.

Related

How to make counting the cells with button in Excel, VBA?

I'm making the simple app using the VBA code and forms in Excel. So, I need to have a simple Private Sub CommandButton1_Click() method which will call for calculation methods and write down the results in Label. How can I do this? (yes, I'm new to VBA)
Private Sub CommandButton1_Click()
MsgBox "My text here"
End Sub
Private Sub UserForm_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
CommandButton1_Click
End Sub
But instead of the calling the window with my text there I need to make calculations of cells.
Will it be correct if I'll write code like shown down there and somehow add the calculations of cells?
Sub Button1_Click()
Sheet1.testing
End Sub
Sub testing()
Dim ell As Object
Dim post As String
Dim Count As Double
Dim cm As String
End Sub
In vba editor, double-click on the command-button in the UserForm to enter the code:
If you put the sub-procedure in the module (e.g doSomething sub-procedure), you have to add the module name:
Call Module1.doSomething
Option Explicit
Private Sub CommandButton1_Click()
Call doSomething
End Sub
'--------------------------------------
Sub doSomething()
MsgBox "My text here"
End Sub
#FunThomas helped me (you can see it in comments to this question). And here is the solution on my question:
Private Sub CommandButton1_Click()
testing
End Sub
Sub testing()
Dim value1
calc = value1 + 10
Label1 = value1 + 10
Dim ell As Object
Dim post As String
Dim Count As Double
Dim cm As String
Dim sText As String
sText = Sheet1.Range("A1").Value
Label2 = sText
End Sub

VBA Excel: Get the clicked cell´s adress on another workbook

I have an excel file A with a macro and I have to retrive a cell´s adress in another excel file B by the user´s click on it.
The macro looks like this.
In the Class:
Public WithEvents appevent As Application
Private Sub appevent_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
ClickedCell = ActiveCell.Address
End Sub
In the Module
Sub ClickedCellSub()
Dim WbA As Variant, WbB As Variant
WbA = ThisWorkbook.Name
WbB = "B.xlsx"
MsgBox "Please double click on the Assembly SS 00 you want to compare"
Set myobject.appevent = Application
Workbooks(WbB).Sheets(1).Activate
Set myobject.appevent = Nothing
MsgBox ClickedCell
Workbooks(WbA).Activate
End Sub
The problem is, the macro doesn´t wait for the event DoubleClick on the other excel sheet and goes to the end.
How can I stop the macro until the event happens?
Many thanks in advance!
I would use event sinking, but not sure how you have approached it, but this is how i'd use.
In a class use the following :
Private WithEvents wb As Excel.Workbook
Private rng As Excel.Range
Public Event evtCellClicked(rngClicked As Excel.Range)
Public Event evtCellDoubleClicked(rngDoubleCliecked As Excel.Range)
Public Sub init(wbInput As Excel.Workbook)
Set wb = wbInput
End Sub
Public Property Get CellClicked() As Excel.Range
CellClicked = rng
End Property
Private Sub wb_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
Set rng = Target
RaiseEvent evtCellClicked(Target)
End Sub
Private Sub wb_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Set rng = Target
RaiseEvent evtCellClicked(Target)
End Sub
I changed the code. In the module:
enter Option Explicit
Private mobjApplication As clsApplication
Global ClickedCell As String
Sub Vergleichen()
Dim StruktBer As Variant
StruktBer = Application.GetOpenFilename(, , "Strukturbericht öffnen") '####Name der Datei aus der Strukturberich
Set mobjApplication = New clsApplication
Workbooks.Open StruktBer
MsgBox "Bitte die Sachnummer der Strukturstufe '00' anklicken die man vergleichen möchte"
End Sub
Sub GOFURTHER
In the Class:
Option Explicit
Private WithEvents mobjApplication As Application
Private Sub Class_Initialize()
Set mobjApplication = Application
End Sub
Private Sub mobjApplication_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
ClickedCell = Target.Address
Set mobjApplication = Nothing
Call GOFURTHER
End Sub
The macro stops until the user clicks on the other excel table. Is there any way not to exit the first sub and to remain in the first one?
Why not simply using an InputBox ?
https://learn.microsoft.com/en-us/office/vba/api/excel.application.inputbox
In your prompt you ask the user to select a range in the appropriate document, and that's it.

Unable to perform simple Excel.Application event handling

I am new to Events Handling on a VSTO.
I did som extensive reserch online, including digging the Microsoft documentation and trying to apply a practical but old example from the support center.
The problem with this example is that it does not work on the Excel.Application instance which calls ThisAddin. So I tried one of my own:
I have an Excel 2010 application wide VSTO, created through VS 2017.
I added a new file MyEvents.vb, which contains the following:
.
Imports Microsoft.Office.Interop.Excel
Module MyEvents
WithEvents ThisApp As Excel.Application '= Globals.ThisAddIn.Application
Private Sub ThisApp_SheetBeforeDoubleClick(Sh As Object, Target As Range, ByRef Cancel As Boolean) Handles ThisApp.SheetBeforeDoubleClick
Dim FromSheet As Excel.Worksheet = Sh
System.Diagnostics.Debug.Print("Event triggered: ThisApp_SheetBeforeDoubleClick in {0} or {1}", FromSheet, Target.Worksheet.Name)
End Sub
Private Sub ThisApp_WorkbookActivate(Wb As Workbook) Handles ThisApp.WorkbookActivate
System.Diagnostics.Debug.Print("Event triggered: ThisApp_WorkbookActivate")
End Sub
End Module
When I compile, open a new workbook and try double clicking or activating another workbook: nothing happens. I must be missing something obvious.. I feel I lack some fundamentals on events handling via VSTO, and I would be glad to be proposed some extra reading on the matter.
For example:
Do I need WithEvents ThisApp As Excel.Application =
Globals.ThisAddIn.Application or just WithEvents ThisApp As
Excel.Application? i.e. can I bind the event to a given object (Application, Worksheet, etc) or do I need to check the caller in my Sub once the event has been triggered, and why?
Is it possible to handle VSTO events from a class, or does it have to be a Module? Can it be in a Module in a Namespace? Does/can it be linked to a Shared WithEvents ThisApp?
What happens if it is not a Shared Class? Will it run my handling Sub as many time as I currently have instances of that Class?
As one can see, I am a little lost here.. I wanted to run all these tests by myself but I am not event able to do something which should be pretty basic.. !
For whoever might be interested:
MyEvents.vb
Imports Microsoft.Office.Interop.Excel
Module MyEvents
WithEvents ThisApp As Excel.Application
'Start listening to Events thrown by ExcelApp
Sub StartEvents(ExcelApp as Excel.Application)
ThisApp = ExcelApp
End Sub
Private Sub ThisApp_SheetBeforeDoubleClick(Sh As Object, Target As Range, ByRef Cancel As Boolean) Handles ThisApp.SheetBeforeDoubleClick
Dim FromSheet As Excel.Worksheet = Sh
System.Diagnostics.Debug.Print("Event triggered: ThisApp_SheetBeforeDoubleClick in {0} or {1}", FromSheet, Target.Worksheet.Name)
End Sub
Private Sub ThisApp_WorkbookActivate(Wb As Workbook) Handles ThisApp.WorkbookActivate
System.Diagnostics.Debug.Print("Event triggered: ThisApp_WorkbookActivate")
End Sub
End Module
ThisAddIn.vb
Public Class ThisAddIn
Private Sub ThisAddIn_Startup() Handles Me.Startup
MyEvents.StartEvents(Globals.ThisAddIn.Application)
End Sub
End Class

How to call macro after Refresh or Refresh All button pressed?

Ultimately, I would like to run a macro after anyone refreshes the workbook, specifically using the Refresh button under the Data tab in Excel.
For the time being, I would be satisfied just getting the BeforeRefresh or AfterRefresh QueryTable events to fire upon pressing the Refresh button.
In addition to the documentation on the Microsoft Dev Center website, the relevant posts I have read include:
Excel VBA - QueryTable AfterRefresh function not being called after Refresh completes
VBA For Excel AfterRefresh Event
There are other posts but I lack the reputation to post them.
Here is what I have:
Under Class Modules (qtclass)
Option Explicit
Private WithEvents qt As Excel.QueryTable
Private Sub qt_AfterRefresh(ByVal Success As Boolean)
MsgBox "qt_AfterRefresh called sucessfully."
If Success = True Then
Call Module2.SlicePivTbl
MsgBox "If called succesfully."
End If
End Sub
Private Sub qt_BeforeRefresh(Cancel As Boolean)
MsgBox "qt_BeforeRefresh called."
End Sub
Under the ThisWorkbook module
Private Sub Workbook_Open()
Dim qtevent As qtclass
Dim qt As QueryTable
Set qt = ThisWorkbook.Worksheets("Data-Fund").ListObjects(1).QueryTable
Set qtevent = New qtclass
End Sub
I have tried variations of the second code block under specific worksheets as well, but have yet to find anything that works. Do I need to somehow dim the QueryTable in question in the Worksheet module?
You haven't actually connected the querytable to the class instance.
Revised qtclass
Option Explicit
Private WithEvents qt As Excel.QueryTable
Public Property Set HookedTable(q As Excel.QueryTable)
Set qt = q
End Property
Private Sub qt_AfterRefresh(ByVal Success As Boolean)
MsgBox "qt_AfterRefresh called sucessfully."
If Success = True Then
Call Module2.SlicePivTbl
MsgBox "If called succesfully."
End If
End Sub
Private Sub qt_BeforeRefresh(Cancel As Boolean)
MsgBox "qt_BeforeRefresh called."
End Sub
New ThisWorkbook code:
Dim qtevent As qtclass
Private Sub Workbook_Open()
Set qtevent = New qtclass
Set qtevent.HookedTable = ThisWorkbook.Worksheets("Data-Fund").ListObjects(1).QueryTable
End Sub
Note that this is quite closely coupled. It would be more re-usable if you were to raise events in the class and declare your qtevent variable WithEvents.
Source: https://www.excelandaccess.com/create-beforeafter-query-update-events/
Class:
Note: Class Name = clsQuery
Option Explicit
Public WithEvents MyQuery As QueryTable
Private Sub MyQuery_AfterRefresh(ByVal Success As Boolean)
If Success Then
Debug.Print "After ReFresh"
End If
End Sub
Private Sub MyQuery_BeforeRefresh(Cancel As Boolean)
Debug.Print "Before ReFresh"
End Sub
Module:
Option Explicit
Dim colQueries As New Collection
Sub InitializeQueries()
Dim clsQ As clsQuery
Dim WS As Worksheet
Dim QT As QueryTable
For Each WS In ThisWorkbook.Worksheets
For Each QT In WS.QueryTables
Set clsQ = New clsQuery
Set clsQ.MyQuery = QT
colQueries.Add clsQ
Next QT
Next WS
End Sub
ThisWorkbook.Event:
Private Sub Workbook_Open()
Call InitializeQueries
End Sub

I have a range in an excel document which I need to extract into a listbox in Visual basic

I have a range in an excel document which I need to extract into a listbox. I can do this through .txt file, but really would prefer to source the information from excel. How?
I am using Visual Studio 2010 and so far my code is:
Public class1 Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim objXLApp As Excel.Application
Dim intLoopCounter As Integer
objXLApp = New Excel.Application
With objXLApp
.Workbooks.Open("C:\report.xls")
.Workbooks(1).Worksheets(1).Select()
For intLoopCounter = 1 To CInt(.ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row)
List1.AddItem.Range("A" & intLoopCounter)
Next intLoopCounter
.Workbooks(1).Close(False)
.Quit()
End With
objXLApp = Nothing
End Sub
When I build this program I get two errors;
statement is not valid in namespace
end of statement expected (I did put end class but it adds more couple of errors")
I don't really do VB, but I think you should break the binding out of the loop with something like:
var data = .ActiveSheet.Range("A1:A"&.ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row).Value2
List1.DataSource = data
List1.DataBind()
You could try (assuming you want the whole Range object to be bound to the list and not just the displayed value.
For intLoopCounter = 1 To CInt(.ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row)
List1.AddItem .ActiveSheet.Range("A" & intLoopCounter)
Next intLoopCounter
Edit:
Also you should use Set objXLApp = New Excel.Application. You're missing the set keyword.
This is also not how you declare classes in VBA. You make a new class like you make a new module. The class is named in the properties pane.
Also this is not how events are handled in VBA. If you want to handle the button click event of Button1 then the event handler must look like
Private Sub Button1_Click()
End Sub
It must have the same name as the object and the name of the event being handled. It also must be on the code page for the user form and has no parameters. VBA is really lacking in this regard.
Hope this helps!

Resources