handle the event of finished editing of the cell value (vba) - vba

Hi in my EXCEL workbook I am using vba. How can I handle the event of loss of focus of the cell or finished editing its value.

You can use the Worksheet_Change event. For example in the code below we are checking if any changes have been made in cell A1
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1")) Is Nothing Then
MsgBox "Hello World"
End If
End Sub
Please note even if you press F2 and press Enter the above event will fire. If you need to run the code only if there is an actual change in the cell then you will have to take help of a Public variable which will store the previous value of the cell.
The Worksheet_Change event goes in the sheet code area. Please see screenshot.

See this Link: http://www.wiseowl.co.uk/blog/s194/event-handling-vba.htm
There are five different short, helpful articles on events, how to use them, and which events are available to you. This article was helpful to me also.

Related

Check if Data was entered by the User or by a macro [VBA]

In my VBA-Project I have different Buttons (Ribbon Bar with Custom UI Editor) that start Subs, which enter data into the Cells. I want to prevent the users from entering data on their own to the cells as this might destroy the routines. Is there a way to validate whether the data has been entered manually or automatically? I thought about a control sheet where I would put a variable to 1 if I am in a function and check for this variable in the worksheet_change sub. Anyhow I think this might be a risky way as a Sub can always crash and then the value is still at 1 and no values can be entered anymore.
I suggest you simply lock the sheet from user input with the Protect function.
You have to use the UserInterfaceOnly property of this function to achieve what you're trying to do.
Sheets(“sheetname”).Protect Password:="Secret", UserInterFaceOnly:=True
This will protect your sheet from user input and let VBA change values in the sheet.
EDIT - Disable alerts
You asked in the comments if it's possible to disable alerts when the user select these cells. The following code should do the trick.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Cancel = True
End Sub

How to detect if ctrl + enter in an Excel spreadsheet with VBA

My understanding is: Macro canNOT be activated while a cell is active for editing.
I notice by hitting ctrl + enter, the cell is de-activate for editing but remain selected. I would like then to run some macro refer to this cell.
Therefore, using VBA, how to detect if ctrl+ enter is pressed?
Easiest way should be using the Change event of the worksheet.
This would not (only) detect a ctrl + enter but any change of a cell.
Private Sub Worksheet_Change(ByVal Target As Range)
End Sub
This sub has to be added to the worksheets code (not into a module)!
Another approach would be using the OnKey Method
Application.OnKey "^{RETURN}", "InsertProc"
See here for a decent explanation: Application.OnKey Method (Excel)

Excel VBA - Calling TextBox Exit Event on Userform manually?

I'm building a userform where it has two text boxes to enter dates. Once the date is entered, I'm validating them when the Exit event fires. If the validation turns up that the user data isn't what is needed, the user is notified, the text box is cleared, and the focus is returned back to the textbox.
The issue comes if the user uses the mouse to select outside of the box, rather than Tab. If Tab is used, it fires perfectly and as expected, and the field is cleared and the focus is returned. If the mouse is used, it doesn't fire. According to this article, this is expected behavior (It's for Access, but I didn't see the similar relevant MSDN article for Excel.)
So instead I tried the AfterUpdate event. However, SetFocus doesn't work within an AfterUpdate event, I'm assuming because of the chain of events as outlined in the response to this question. Thus, I don't have a way to return the focus back to the textbox after it has fired. That thread had a suggestion as an alternate answer to SetFocus to another control and come back as a workaround, but that doesn't work for me, so I assume that may be an Access-specific workaround.
My last option I've considered is having the AfterUpdate event just call the Exit event, however the Exit event has a required argument (ByVal Cancel As MSForms.ReturnBoolean), which is how you cancel out of the exit and return the user to the textbox. As such, there isn't a value that you can pass to it that doesn't throw an error that I can find (the closest I found was passing Nothing but it failed out when trying to set it to True later to cancel the exit.)
Is there a way to achieve what I'm looking for here, or should I just stick to the AfterUpdate and ignore the SetFocus I'm trying to achieve?
I know that this was answered a few months back but giving an alternative solution. For any one who finds this question.
For validation of Excel Textbox data use the BeforeUpdate Event, it fires before the AfterUpdate Event and has the ability to prevent losing Focus on the control.
Rework the sample code to your requirements
Remember Cancel = True stops the control update to the control and it remains in focus.
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
Cancel = doValidation(Textbox1.Text) 'Validation Route
End Sub
Private Function doValidation(strText) as Boolean
'Do Validation
if Valid then
doValidation = False
Else
msgBox "Not Valid"
doValidation = True
End if
End Sub
In my opinion this is the easiest way to validate an input on an Excel Userform Textbox
I can't right now find the correct MSDN article at this time, all Google wants to return is Access Results.
Exit event works on all the mouse clicks which fire up Enter for another Control on the Form. But When you click, directly on the form instead of any other control, nothing happens.
Here, use the ActiveControl property to determine about the last control you were in, before exiting and moving to user form.
Sample Code, rework it according to your requirement.
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Call doValidation(Me.TextBox1.Text) '/ Validation Routine when user leaves TextBox
End Sub
Private Sub UserForm_Click()
'/ If user clicked on the user form instead of ay other control
If Me.ActiveControl.Name = Me.TextBox1.Name Then
Call doValidation(Me.TextBox1.Text) '/ Validation Routine when user leaves TextBox
End If
End Sub
Private Sub doValidation(strText)
MsgBox strText
End Sub
Advise: For Date inputs, use DateTimePicker instead of TextBox, will save you from alot of trouble in future.
In VBA you can call any defined sub or function with the word Call Subname:
e.g. Call Textbox1_exit(params)
However from the somewhat confusing description I believe your problem is that you limit yourself to just a few event functions. I would suggest exploring all event functions and see which one is a good fit for your event fire.
Here is a list of events and their sequences in Access VBA:
https://msdn.microsoft.com/en-us/library/office/jj249049.aspx
and the order of form events:
https://support.office.com/en-us/article/Order-of-events-for-database-objects-e76fbbfe-6180-4a52-8787-ce86553682f9
I think for your application from the description you gave the lost_focus or got_focus for certain components might be useful.
Furthermore, you can manually set the focus to almost any component it is a built in method: compName.SetFocus()

Order of Events for the SheetFollowHyperlink Event

I have a workbook that lists people's names and overall performance for the past few weeks. I was asked to make it so that when their names are clicked, the details for that person would show. The solution I came up with at the time was to point all of the hyperlinks to a sheet that reminded them to turn on their macros.
In the WorkSheet_Activate event, I redirected them to another sheet that populated with the details for the person they had selected. This works fine. If the user doesn't have their macros turned on, they get a friendly reminder, but if they do, they immediately get redirected. There's just one problem. Because the hyperlink takes them somewhere else first, it causes the infamous "screen flicker".
On researching, I found the FollowHyperlink Events (I think the workbook level event would be most suitable for my purposes, though). However, before I get started rebuilding it, I wanted to make sure that this would solve the "screen flicker".
On MSDN, it states that the Event occurs when the user clicks the hyperlink. I can't seem to find anywhere that directly states whether this Event is triggered before or after the user is directed to the other sheet, though. If it gets triggered right after, that wouldn't really help me, but if it gets triggered before, I could put an Application.ScreenUpdates = False in the event, and it would solve my problem.
TL;DR (Get to the point already):
Does the Workbook_SheetFollowHyperlink Event happen before or after the user is directed to where ever the hyperlink is pointed?
To answer your question, the event is triggered after the hyperlink is followed. You can demonstrate this using the code below:
Private Sub Workbook_SheetFollowHyperlink(ByVal Sh As Object, ByVal Target As Hyperlink)
Debug.Print "Workbook level: " & ActiveSheet.Name
End Sub
When the event is triggered, the ActiveSheet is the sheet directed to by the hyperlink.
I'm not sure of a way to solve your problem directly, even the Click() event won't be raised when you click a hyperlink. However, the Worksheet level hyperlink event handler will be called before the Workbook level handler and this may speed the process up enough to not see the flicker.
You can prove this if you leave the Workbook level event as is and add the following code to the Worksheet containing the hyperlinks:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Debug.Print "Worksheet level: " & ActiveSheet.Name
Sleep 1000
Debug.Print "Leaving worksheet level event"
End Sub
After a few experiments (see below) I concluded that:
Allow the user to use the hyperlink columns when macros are disabled.
When macros are enabled, hide the current hyperlink column and show another column that gives the user a different "hyperlink" that takes them directly to where you want them to go.
The 2nd hyperlink can easily be "simulated" such that it picks up the other columns hyperlink. (See below)
I hope his helps
Interesting, here's a few things I tried
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' This does not fire if the user clicks directly on the hyperlink text
' it only fires if when click on the cell space that is not text
With ActiveCell
If Hyperlinks.Count Then
MsgBox "hi" & .Hyperlinks(1).Range
.Hyperlinks(1).Follow
End If
End With
End Sub
However you could make the text in the cells look like a hyperlink but actually just be blue underlined text. You could then use the Worksheet_SelectionChange to go to a related cell.
The question then become how to store the related cell.
You want to store it so that if row and column are inserted on the destination sheet, the reference will adjust. (eg NOT in comments, or the description of named ranges etc..)
Depending on how much data you have there's a variety of ways you could choose from.
I think I would favour this:
Having a hidden column next to the cell on display that has a hyperlink. The cell on display has a formula that is set to pick up the value from the hidden column (I quite like the sound of this as you have the hyperlink column already - so just modify the above code to get the hyperlink from the column next to the clicked cell using offset perhaps)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' This does not fire if the user clicks directly on the hyperlink text
With ActiveCell.offset(0,1)
If Hyperlinks.Count Then
.Hyperlinks(1).Follow
End If
End With
End Sub
You could mess around with named ranges, but it will be a pain.
I've just realised that what I tried won't help much as you need the hyperlink to work when macros have not been enabled!
So to get the above to work you could change the columns displayed when the user enables macros. ie the hyperlink column is shown when macros are disabled (and the column to the left of it is not).
When macros are enabled hide the hyperlink column and show the one to the left of it that will cause the SelectionChange event to run.
(You need to beware how other hyperlinks are used as any cell with a hyperlink next to it will respond to the event. You may need to use intersection to check the cell clicked is in a namedrange that contains "all the cells that need to respond to a user clicking them in the manner".
All the above sounds a bit mad, but it would appear the event model does not facilitate stopping the screen flickering.
I hope there is a better way of doing what you want, but for what it's worth, the above might help.
Harvey

Can i launch userform from a button in a Sheet

Pop up charts in VBA Excel
I was very curious with the answer in the above link.
My question is, Can I pop up a graph with click of button(The button is on Sheet1) and when i go bach to
Sheet thr graph is gone
Pertinent to your question as it is worded in the Title (i.e. 'Can i launch userform from a button in a Sheet'), you can implement this functionality in two simple steps:
1). From Excel 'Developer' tab select Insert -> Button. By default, it will create a new Button1 and corresponding Click event handle will be added to the Module1
Sub Button1_Click()
End Sub
2). Provided that you have a User Form named UserForm1, add a single statement in that event handle that will open the UserForm1 on Button click:
Sub Button1_Click()
UserForm1.Show
End Sub
In case you are trying to implement additional functionality, please include your code snippet highlighting the problematic part.
Hope this will help. Best regards,
Let's do it by point and basing on the answer you have posted.
Can I pop up a graph with click of button(The button is on Sheet1)?
Yes, you can. You need to:
Put a Button on Sheet1 and associate to it a macro, let's say popUpChart;
Create and show the chart:
Sub popUpChart()
Dim ch As UserForm1
Set ch = New UserForm1
'ch.CommandButton1_Click()
'a) Uncomment the line above if you want to invoke the button press before to show the chart
'b) If you decide to uncomment, remember to change the sub from "Private" to "Public"
ch.Show
End Sub
when i go bach to Sheet thr graph is gone
I don't understand well what you mean here. Do you mean "I want the graph to be gone when I go back to the sheet" or "I would like the chart to stay here but actually it's gone?
a) In the first case, it's enough to remove the image from the Image control of the form;
b) In the second case, it's enough to remove the Set statement from the button's macro.