Issue with TAB event in Excel VBA - excel

When user click TAB key from keyboard, some cells should be updated in the same row(Event should be happen iff there is some data in that cell). As of know I written some sample code to display some message. I written code inside the workbook as below
Private Sub Workbook_SheetselectionChange (ByVal Sh As Object, ByVal Target As Range)
Application.EnableEvents = True
Application.OnKey"{TAB}", "sayHi"
End Sub
Sub sayHi()
Application.EnableEvents = True
MsgBox "Hiiii"
End Sub
Issue :- whenever I am clicking TAB key, getting one warning like "cannot run the macro 'C:...sayHi'. The macro may not be available in this workbook or all macros may be disabled".

Related

In Excel, updating a formula seems to trigger an unrelated private sub on the same worksheet. How can I get this to stop?

I've created a drop down menu through data validation for workbook navigation. The following is a snippet of code I have for the drop down box to change worksheets in the workbook:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then _
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets("Imported Data").Visible = False
End Sub
The code is meant to hide all other worksheets that are accessible by the drop down list besides the one selected. I have about 10 tabs and this code has worked perfectly to achieve the basic goal of navigation. However, some pages have formulas and when you update data in the cells meant for calculations the workbook jumps to a random worksheet in the workbook that is not at all referenced in this sub.
Is there some way to have my worksheets not try to do anything with this sub unless the dropdown menu itself is changed?
Bonus (less important) Question: is there a way to make the drop box default to (blank) unless the menu itself is accessed?
Then _
The space followed by an underscore _ means that the current statement isn't finished yet but continues on the next line. Right now the last 3 lines will run whenever there is a change in the worksheet. Put the entire code in If-Endif.
Also avoid unnecessary use of On Error Resume Next. Use proper error handling.
You need to make the sheet visible before you activate it and not vice versa.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets("Imported Data").Visible = False
End If
Letscontinue:
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
is there a way to make the drop box default to (blank) unless the menu itself is accessed?
If you have created it with Data Valdation then insert a blank value in the list.

Change Worksheet When a Cell Value and a Checkbox Change

I have a Workbook with multiple Sheets. I have a menu page (Worksheet) with multiple user choices (Enter a new order, update an order, etc.) Each choice has a check box beside it and depending on which check box is checked, cells F4:F21 change from 0 to 1 and, cell B1 changes to the name of the Worksheet where I want to go. I have the following VBA in the Main Menu worksheet but when I click a check box, nothing happens. Any ideas why?
CODE
Private Sub Worksheet_Activate()
ClearMenuForm
End Sub
Private Sub Worksheet_Change (ByVal Target As Range)
Dim sh As String
If Not Intersect(Target, Range("F4:F21")) Is Nothing Then
sh = Cells(1, "B").Value
Sheets(sh).Select
End If
End Sub
Clicking a check box does not activate the event Worksheet_Change (see this). That is why nothing happens.
Try changing one of the cells instead to see the effect.
What I think you want to do is assign an action to your Checkbox(es). You can do this in two ways:
Right clicking on the checkbox, and Assign Macro...
You have to create the associated macro, which will likely contain parts of the code that you already wrote, and/or calls to subs you have. You may bring the VBE (Alt+F11), insert a module in your VBA project, and write your Sub, e.g.,
Sub CheckBox1_Click()
MsgBox "Checkbox 1a has changed"
End Sub
Via VBA (e.g., this). With the sample code below, you would execute InitCBs, and that would associate CheckBox1Change with the checkbox (it actually assigns actions for both checkboxes in the figure; action for checkbox 2 is CheckBox2Change). You may also set InitCBs to be executed when opening the file.
Sub CheckBox1Change()
MsgBox "Checkbox 1b has changed"
End Sub
Sub InitCBs()
Dim cb As CheckBox
For Each cb In ActiveSheet.CheckBoxes
With cb
Dim action As String
'action = "CheckboxChange"
action = Replace(cb.Name, " ", "") & "Change"
.OnAction = action
End With
Next cb
End Sub
You've defined sh as a String. Since there is no sheet named "1", for example, your code will generate a "Subscript out of Range" runtime error. Try changing sh to a Long.
Dim sh As Long

How can I automatically convert a field in lowercase to uppercase in Excel?

I have produced some VBA code to resolve this problem :
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Value <> Empty Then
Target.Value = UCase(Target.Value)
End If
End Sub
But when I try to input some data in a field, Excel stops working without a single error message.
Does anyone know where this problem can come from ?
You probably have set Application.EnableEvents = False. Open the Immediate window in the VBA editor and type in application.EnableEvents = True then ENTER to turn them back on.
Also, you need to disable events if you don't want to cause a cycle of changing the sheet and re-triggering the event. The ISEMPTY function is slightly different in VBA and your code could be updated to the following which will also handle changing more than just 1 cell
Option Explicit
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim cell As Variant
Application.EnableEvents = False
For Each cell In Target
If Not IsEmpty(cell.Value) Then
cell.Value = UCase(cell.Value)
End If
Next cell
Application.EnableEvents = True
End Sub
or if you want to restrict this running to 1 cell change only, replace the for each loop with If Target.rows.count = 1 AND Target.columns.count = 1....
You may not have the callback function in the right spot:
From Events And Event Procedures In VBA
For sheet (both worksheet and chart sheet) level events, the event procedure code must be placed in the Sheet module associated with that sheet. Workbook level events must be placed in the ThisWorkbook code module. If an event procedure is not in the proper module, VBA will not be able to find it and the event code will not be executed.

Application.EnableEvents = False not working

I don't seem to understand the strange behaviour of Excel 2007, and after a dozen solutions, I came to you asking for help.
I have office 2007.
Here is my class module code :
Public WithEvents App As Application
Private Sub App_SheetChange(ByVal Sh As Object, ByVal Target As Range)
MsgBox "event din app"
End Sub
Here is my InitializeAppObject module :
Dim X As New EventClassModule
Sub InitializeApp()
Set X.App = Application
MsgBox "am facut setarea"
End Sub
Here is my Sheet one code :
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Me.Range("a1:c10")) Is Nothing _
Then
Application.EnableEvents = False
MsgBox "suntem in range"
Application.EnableEvents = True
Else
MsgBox "nu suntem in range"
End If
End Sub
Before changing any values on the grid, I execute the InitializeApp() procedure.
From my understanding, the sheet event should be triggered first, then the workbook one, and then the application one. However this is not the case. It first fires up the workbook one, the the application one, and finally the sheet one.
Is Excel malfunctioning or I got it wrong ?
How can I execute just the sheet event? cause obviously the Application.EnableEvents = false is not doing any good from stopping the event from being triggered upstream.
Thank you so much in advance for all your help!
kind regards,
radu
I think the problem may be that you're using the SelectionChange event in the sheet module. You're correct about the order of events. Here's how it goes - you're events have a *
Worksheet_Change
Workbook_SheetChange*
Application_SheetChange*
then assuming the selection moves after you enter something
Worksheet_SelectionChange*
Workbook_SheetSelectionChange
Application_SheetSelectionChange
Nothing in your code is triggering events, so putting message boxes in between EnableEvents doesn't achieve the desired result. All of the events are already queued up by the time the first event code runs. If instead, you had
Private Sub App_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Application.EnableEvents = False
Sh.Range("a1").Value = 1
Application.EnableEvents = True
End Sub
Then the code that changed the value of A1 would not trigger any events. If you only want to run the Worksheet_Change event, you should delete the other event code. OK, it's probably there for a good reason. But whatever the logic is for when you run which event code needs to be in the procedure. For instance, if you only want to run the Worksheet_Change event on a particular worksheet name "Master", you would set it up like this
Private Sub App_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Sh.Name <> "Master" Then
MsgBox "event din app"
End If
End Sub
And the Worksheet_Change event code would be in master sheet's class module, so it would only respond to events on that page.

Excel VBA: Save As triggers Change event in ComboBox

I have an Excel workbook containing some ComboBox controls placed directly on the sheets. These are standard combo boxes from the Forms toolbar.
When the user uses "Save As" to save the workbook with a different name, this triggers the Change event on all the combo boxes, including ones on sheets that aren't active. This seems unreasonable as the selection hasn't actually changed. This causes various undesirable behaviour because of the code in the event handlers. The event isn't triggered on a simple "Save".
Google suggests this is a known problem in Excel. There are rumours that it's caused by using a named range as the ListFillRange for the combo box, which I have done, although it's not a volatile name. I'm looking for a way to prevent this happening with minimal changes to the code and the spreadsheet. Does anyone have a proven solution?
I did the following in a new workbook with only one sheet, Sheet1, and it seemed to work to diable events before save and then reenable them after. It should bypass the problem you see by mimicing an AfterSave event. This is my event code on Sheet1 (could be OLEObject code, too)
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox Target.Address & ": " & Target.Value
End Sub
This is my ThisWorkbook code
Option Explicit
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
' To see the change code work before disabling
' Should show a message box
Sheet1.Range("A1") = "Before After Events Off"
Application.EnableEvents = False
Application.OnTime Now, "ThisWorkbook.Workbook_AfterSave"
' This time it will not show a message box
' You will never see this one . . .
Sheet1.Range("A1") = "After After Events Off"
End Sub
Private Sub Workbook_AfterSave()
Application.EnableEvents = True
End Sub
The .OnTime method throws the AfterSave "event" onto the execution queue. It works!
You could set a flag in the Workbook's BeforeSave event and then check that flag before processing a change event in each of the combo boxes. There does not seem to be an AfterSave event, so you would need to clear the flag after checking it within the combo box change events. The flag would need to be more than a simple boolean since it could not be turned off until all combo box change events were processed. Here's some sample code:
Public ComboBoxChangeCounter As Integer
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Const NumOfComboBoxChangeEvents As Integer = 5
ComboBoxChangeCounter = NumOfComboBoxChangeEvents
End Sub
Function JustSaved() As Boolean
If ComboBoxChangeCounter > 0 Then
ComboBoxChangeCounter = ComboBoxChangeCounter - 1
JustSaved = True
End If
End Function
Private Sub Combo1_Change()
If JustSaved Then Exit Sub
'Your existing code '
' ... '
' ... '
' ... '
End Sub
I set the number of combo box change events as a constant, but there may be some way for you to determine that number programmatically. This workaround does require adding code to every combo box change event, but it should be easy as all you need to do is copy and paste the line If JustSaved Then Exit Sub at the beginning of each event.
This workaround assumes that the Workbook BeforeSave event will get called prior to the combo box change events. I don't know for a fact if that's the case.

Resources