Combobox linked cell value change does not fire worksheet change event - vba

As per the question: selecting a new value in an ActiveX combobox linked to a cell by it's .LinkedCell property does not fire the worksheet change event.
I know there are various events for combo boxes like it's own change event but none of them are really suitable for what I need to do (custom data validation on the changed cell).
As a workaround I pass the .LinkedCell to my validation code on the combobox mouse up and key up events (I can't use lost focus... long story, and on change fires on every character change which is too much).
Does anyone know of a cleaner way to pass the value around at the event level once the user has finished using the control?

If you want to trigger the ChangeEvent in a worksheet, without doing anything, here is a way to do it:
In a module:
Option Explicit
Public Sub CheckMe()
Application.Run "tblDB.Worksheet_Change", tblDB.Cells(1, 1)
End Sub
In a workbook, named tblDB:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Debug.Print "triggered"
End Sub
Now, whenever you run the CheckMe, the Worksheet_Change event would be triggered.

Related

Triggering Worksheet Change in Excel VBA

This is more of a general question but I was wondering what exactly triggers a Workbook_SheetChange() on Excel VBA. It claims to change when a value in a cell is changed, but when you try and drag instead of entering a value into a new cell, the macro doesn't trigger. Is there any way to go around that or is there another way to trigger a macro that will detect any change in a workbook?
For me it does seem to trigger the change event when dragging and dropping cells.
I'm using (In the "ThisWorkbook" Module);
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Debug.Print Now
End Sub
Are you definitely using the WORKBOOK event and not the WORKSHEET event?
Edit: Phrasing

Run macro when linked cell changes value (Excel VBA)

I am currently trying to obtain historical information about how the backlog is developing.
My Excel file is based on queries from an Access Database which can give me a view of the current situation.
I would like to automatically run a macro every time the week number changes. I am currently using the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("D3")) Is Nothing Then
Call KPIupdate
End If
End Sub
The macro that should fire is called KPIupdate
My problem is that the Macro only fires if I click the cell. I would like it to just fire when the number changes. The cell "D3" is linked to another cell with the formula =Weeknum(Today();21)
I hope you can help me
According to the MSDN entry for Worksheet_Change:
This event does not occur when cells change during a recalculation. Use the Calculate event to trap a sheet recalculation.
To use Worksheet_Calculate to trap the change in a cell that is set by a formula looking at another cell, you need to set a variable to hold the value of the 'Target' and then check if it has changed after the Calculate event fires.
Here is a simple example:
Option Explicit
Private strCurrentWeek As String
Private Sub Worksheet_Calculate()
If Me.Range("A1").Value <> strCurrentWeek Then
'the linked cell changed
Debug.Print "Sheet1!A1 was changed"
'call another macro
End If
'update the new current week
strCurrentWeek = Me.Range("A1").Value
End Sub
To test this, just set the formula in A1 to be =B1 and then change the value of B1 and check the output in the Immediate window.
You can adapt this code to call KPIupdate where my Debug.Print... statement is.

Append Procedure to Event upon User Action

Say, I have a procedure which changes the random colour of a cell based on selection change. I know that I can code in a procedure for the worksheet SelectionChange event.
I guess Im asking, as in javascript where we can use addEventListeners, can we do something similar in Excel VBA.
What I am wondering is can this be done dynamically? I.e. when a user chooses an option, then I bind a procedure to the event SelectionChange of the worksheet.
Note, I know that I could declare a global boolean & use that to ascertain user action & use it in my SelectionChange event procedure.
Im just curious whether in Excel VBA, we can dynamically append procedures to events?
You can't dynamically assign event handlers. Excel will always call the built-in event handlers (SelectionChange, Calculate, etc) and there's no way to substitute your own. You can create your own Worksheet variable using the WithEvents keyword, however, and choose when to start receiving the events. For example, start with this structure in one of your worksheets:
Dim WithEvents MySheet As Worksheet
Private Sub MySheet_SelectionChange(ByVal Target As Range)
Debug.Print "Receiving events"
End Sub
As long as MySheet isn't bound to an active sheet, you're not going to receive any events. When you're ready to begin, call a custom subroutine to do the assignment:
Public Sub DoIt()
Set MySheet = Sheet1
End Sub

Provide a range selection tool/utility to the user in Excel VBA

I am trying to develop a user form in Excel 2007 VBA and want to provide a user with a range selection icon, something like this:
However, I have not been able to find any built-in form design tool or any online tool which provides this or at least gives me an idea. If anyone has any idea about this, I will greatly appreciate their help.
This control is called RefEdit control.
To use it, you have to first add it to the toolbox window by right-clicking in the toolbox window and selecting Additional Controls.... Then you select RefEdit.Ctrl and close the dialog.
Now you can select it in the toolbox and place it on your form.
Another alternative to using the RefEdit.Ctrl is to hook into some undocumented features of the TextBox control and use the Application.InputBox function.
There are two properties of the TextBox control that do not appear in the Properties dialog, that allow you to add a button on the right. They are DropButtonStyle and ShowDropButtonWhen. When the button is clicked it will fire the DropButtonClick event for the control where you can show the input box.
Start by placing a TextBox control on the form. Then add the following to the UserForm_Initialize procedure:
Private Sub UserForm_Initialize()
txtRefersTo.DropButtonStyle = frmDropButtonStyleReduce
txtRefersTo.ShowDropButtonWhen = frmShowDropButtonWhenAlways
End Sub
Then add an event handler to the DropButtonClick event as follows to capture the range using the Application.InputBox dialog:
Private Sub txtRefersTo_DropButtonClick()
Me.Hide
txtRefersTo.Text = Application.InputBox("Select the range", "Range Picker", txtRefersTo.Text, Type:=8)
Me.Show vbModal
End Sub
The main advantage to this approach is that it allows you to place a control within a frame or on a separate tab without experiencing the issues associated with the RefEdit.Ctrl. The disadvantage is that it requires a separate dialog to interact with Excel.
Although this question is already almost a decade old, it still came up as my first Google search result so I'm going to post an answer as another approach to consider. The InputBox with type set to cell reference might be sufficient for many people's needs. The InputBox type does the drudge work of validating the user's response. See this article for how to use the InputBox types: https://www.thespreadsheetguru.com/blog/vba-to-select-range-with-inputbox
I liked #krey answer which was basically a very simplified version of the link shared in #stifin answer --> https://www.thespreadsheetguru.com/blog/vba-to-select-range-with-inputbox
But both used "odd" names for the buttons and I think guides should use default names/values for easy understand and manipulation by end user. Additionally, I added a CommandButton to "run" the userform and a "select" statement for initial testing. I also wanted to provide an initial value as I try to pre-populate my userforms, but allow end user to override if needed.
Here is the final code snipppets utilizing a UserForm w/ one TextBox named TextBox1 (default) and one CommandButton named CommandButton1 (also default).
Option Explicit
Public rng As Range
Public Sub UserForm_Initialize()
Me.TextBox1.DropButtonStyle = fmDropButtonStyleReduce
Me.TextBox1.ShowDropButtonWhen = fmShowDropButtonWhenAlways
Set rng = Range("A1:B4")
TextBox1.Value = rng.Address(False, False)
End Sub
Public Sub CommandButton1_Click()
rng.Select
Unload Me
End Sub
Public Sub TextBox1_DropButtonClick()
Me.Hide
Set rng = Application.InputBox("Select the range", "Range Picker", TextBox1.Text, Type:=8)
TextBox1.Value = rng.Address(False, False)
Me.Show
End Sub

VBA function to alert when value is changed within a time frame

I have an excel cell where its value is updated every minute.
What I need is an alert message box; while that cell value moves to a particular time.
Suppose a cell has value 10:
if it reaches 7 in one minute then I need a message box to alert that.
if it is not reaching 7 in one minute then I don't need any alert.
Please help write me a macro for this.
Inside VBA editor for ThisWorkBook, you could write the following code
Dim WithEvents SheetToWatch As Worksheet
Private Sub SheetToWatch_Change(ByVal Target As Range)
If Target.Address = "$A$2" Then
If Target.Value = 7 Then
MsgBox "changed to 7"
End If
End If
End Sub
Private Sub Workbook_Open()
Set SheetToWatch = Sheets("Sheet1")
End Sub
Basically the code sets the reference of Sheet1 to the variable SheetToWatch when the workbook opens. Declaring the variable using WithEvents lets one capture the events.
I am using Change event of the worksheet and checking if the cell that was changed is A2. If so, I am checking or comparing the value with 7 (it can be dynamic and depends on how you want to handle it).
See if this helps.
Cannot be done with a function, any way that I can think of.
If you control the mechanism that is updating the cell, then you could it call a VBA subroutine that you wrote, instead, have to send the alert and then update the cell from that routine.
If you do not control the updating mechanism, then the only thing that I can think of that might work is of the Cell, Range or Worksheet classes have a ChangedDate event that you could catch from VBA and do your alerting from there.