Remember cell selected before double click - vba

I have an Excel sheet that has a doubleclick event in cell "P1" (runs a macro).
I may have cell "J30" (or any other cell) selected before I doubleclick "P1"
How can I remember, and return to the cell "J30" after the "P1" doubleclick?
Storing the active cell doesn't work because the first click in the doubleclick sequence, selects "P1".
I also tried rightclick on "P1", but it also selects "P1" before running the event.

Well, it's a bit more complicated than the "duplicate thread" because the SelectionChange event is invoked prior to the BeforeDoubleClick event, so the former will update the last selection to the new one before the latter gets hand.
What you need is to go "one step further" in saving the selections, by actually saving both:
The current selection
The previous selection
Something like this should work
' Code module of your worksheet
Option Explicit
Private lastSelection As Range, beforeLastSelection As Range
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
' Your Code for this event, i.e.
If Target.Address = "$P$1" Then
' Some code ...
Cancel = True
If Not beforeLastSelection Is Nothing Then beforeLastSelection.Select
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Set beforeLastSelection = lastSelection
Set lastSelection = Target
End Sub

Using the method here you can do as follows
Public PreviousActiveCell As Range
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
MsgBox ("Previous selection: " & PreviousActiveCell.Value & vbNewLine & _
"Double clicked selection: " & Target.Value)
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Static pPrevious As Range
Set PreviousActiveCell = pPrevious
Set pPrevious = ActiveCell
End Sub

Related

Multiple ActiveX buttons visible/hidden

I have a Worksheet in excel 2013, with 25 activex buttons on it. depending on a cell value for each button, i would like it to be visible or hidden. In my case the value of cell U6 makes my commandbutton1 visible, U7 would make commandButton2 visible.... Only my CommandButton1 works properly. I have tried different combinations of code without succes.
Private Sub CommandButton1_Click()
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
'ActiveX button1
If Range("U6") = 1 Then
Sheets("Feuil1").CommandButton1.Visible = True
Else
Sheets("Feuil1").CommandButton1.Visible = False
End If
End Sub
If Range("U6") = 1 Then
Shouldn't that check if the Target (i.e. the modified cell) is in column U?
Sheets("Feuil1").CommandButton1.Visible = True
That road leads to pastaland, you don't want to go there: extract a method. You'll want to query the OLEObjects collections to get the ActiveX control by name, rather than hard-coding the button names 25+ times.
Private Sub SetControlVisibility(ByVal controlName As String, ByVal isVisible As Boolean)
Dim axControl As OLEObject
On Error Resume Next 'next statement may throw error #9
Set axControl = Me.OLEObjects(controlName)
If axControl Is Nothing Then Exit Sub
On Error GoTo 0 'restore error handling
axControl.Object.Visible = isVisible
End Sub
Now you have a method that can toggle the visibility of any ActiveX control on the sheet, given its name.
So in the Worksheet_Change handler, you now just need to work out the name of the ActiveX control, and whether or not you want it visible:
Private Sub Worksheet_Change(ByVal Target As Range)
'bail out if the modified cell isn't interesting, or if it's more than 1 cell:
If Intersect(Target, Me.Range("U6:U31") Is Nothing Or Target.Count <> 1 Then Exit Sub
Dim buttonName As String
buttonName = "CommandButton" & Target.Row - 5
Dim isVisible As Boolean
isVisible = Target.Value = 1
SetControlVisibility buttonName, isVisible
End Sub
Or something like it. Note: code written in the answer box, untested & for illustrative purposes only. Copy-pasta at your own risk.

How to Detect if a Cell is Changed by an "=IF()" Formula and not by a User

I read a lot of pages saying that, but none of them put the solution if the value change by an "if function" not by hand.
The code I get is that:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Me.Range("A18:A30")) Is Nothing Then Exit Sub
Application.EnableEvents = False 'to prevent endless loop
On Error GoTo Finalize 'to re-enable the events
MsgBox "You changed THE CELL!"
Finalize:
Application.EnableEvents = True
End Sub
It only works if I change the value by hand.
Thank you in advance.
Another solution; instead of triggering your function every time when your worksheet recalculates, add a function in a module:
Function DetectChange() As Integer
MsgBox "You changed THE CELL!"
DetectChange = 0
End Function
Assuming the outcome of your formula is numeric:(otherwise outcome of function must be a empty string and the "+" must be "&")
Add to your IF-formula at the end ...+Detectchange()
Now there will be a msgbox only when your formula is recalculated
Edit by Darren Bartrup-Cook:
I found this code gave worked when the formula recalculated. It didn't fire if I changed a cell that doesn't affect the cell it's entered to and it didn't fire using Calculate Now or Calculate Sheet.
It did occasionally fire for all formula that I used the function in, but that seemed to be when I was debugging - maybe further investigation needed.
Public Function DetectChange()
MsgBox "You changed cell " & Application.Caller.Address
End Function
e.g.:
=IF(A1=1,A2,A3) & DetectChange() entered in cell A4 displays the message "You changed cell $A$4" if cells A1, A2 or A3 is changed.
Write this in Sheet1 and run the TestMe sub:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Me.Range("A1:A30")) Is Nothing Then Exit Sub
Application.EnableEvents = False
On Error GoTo Finalize
MsgBox "You changed THE CELL!"
Finalize:
Application.EnableEvents = True
End Sub
Sub TestMe()
Range("A1") = 34
End Sub
It has worked quite ok on my PC.
If the cell is changed by a built-in Excel function, then the comment of #Vincent G states the correct answer:
Worksheet_Change event occurs when cells on the worksheet are changed by the user or by an external link. and This event does not occur when cells change during a recalculation. Use the Calculate event to trap a sheet recalculation.
If you want to track the calclulation event based on some changes at Range(A18:A30) this is a working solution:
Add a new Worksheet to your Workbook (Sheet2);
In the current Worksheet write the Calculate event:
Private Sub Worksheet_Calculate()
Dim cell As Range
For Each cell In Sheet2.Range("A18:A30")
If cell <> Sheet1.Range(cell.Address) Then
cell = Sheet1.Range(cell.Address)
End If
Next cell
End Sub
In the Sheet2 write an event, catching the changes.
As simple as #Vincent G says.
Private Sub Worksheet_Calculate()
Call YourFunction
End Sub

Trigger change event of a worksheet with activated edited cell in a shape/button click event

I have a worksheet with a clickable shape and a class listening to the change events of that sheet:
Sheet1:
Public Sub Shape_click()
Debug.Print "click"
End Sub
Class1:
Private WithEvents sh As Worksheet
Private Sub Class_Initialize()
Set sh = Sheet1
End Sub
Private Sub sh_Change(ByVal Target As Range)
Debug.Print "change: " & Target.Address
End Sub
When I edit a cell in Sheet1 and click directly on the shape the output is
click
change: $B$1
I would like to trigger the change event in the shape macro so that the change event would occur before printing "click". DoEvents, Sleep from kernel32 and activation of some other cell from the Shape_click were not working for me.
I have found two "hacks", the first one quite limited, but the second one does the job:
Selection.Cut:
Public Sub Shape_click()
Selection.Cut Selection
Debug.Print "click"
End Sub
It makes the Change event to fire 3 times (2x before "click", 1x after that), every time with the right (changed) value.
Of course you need to check the Selection (if it is set, if it's of Range type etc.)
The solution is quite limited as you can't use it with merged cells in the selection (will ask if you want to unmerge them).
Selection.Value = Selection.Value
Public Sub Shape_click()
Selection.Value = Selection.Value
Debug.Print "click"
End Sub
Works even with merged cells. There is also need to check Selection if it really contains a range.

Excel Userform with Textbox, how to toggle through values in range of textbox

Purpose: Click on a cell in a range (Range: Column K:K on excel worksheet). Once you click on a specific cell in column K, userform pops up with cell value using following code:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error Resume Next
If Target.Cells.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("K:K")) Is Nothing Then
Credit_Information.TextBox1.Value = Target.Value
Credit_Information.Show
End If
End Sub
My question, is depending on where I click on column K, I want to use two buttons on my userform (Previous and Next) to move up and down column K and see the values of the cell dynamically change on my userform. Is this possible? Please let me know if any clarification is needed.
Just add the two command buttons to your userform.
Name one of the buttons cmdNext and give it a caption of "Next".
Name the other button cmdPrev and give it a caption of "Previous".
Then, in the userform code module, place these routines:
Private Sub cmdNext_Click()
ActiveCell(2).Select
End Sub
Private Sub cmdPrev_Click()
If ActiveCell.Row > 1 Then ActiveCell(0).Select
End Sub
That's it.
Note: if you want you can add code to ensure that the ActiveCell is in column K before allowing the new selections:
If ActiveCell.Column = 11 Then ...
Perfect, Thanks!
I also found out that using Offset worked for me too in this manner. I'm not sure however if I'm breaking any conventions by doing this.
Private Sub CommandButton1_Click()
ActiveCell.Offset(-1).Activate
End Sub
Private Sub CommandButton2_Click()
ActiveCell.Offset(1).Activate
End Sub
It is possible, but I would create another procedure for that. What you could do is declare a public variable in your userform & set it equal to the range Target. Then you could call another procedure from the userform on each button click and redefine the selected range after each click.
So, at the top of your userform do this:
Public selected_cell as Range
Then for the up button:
Private Sub ButtonUp.Click()
If selected_cell.Row < 2 Then Exit Sub
selected_cell.Rows(0).Select
Set selected_cell = selected_cell.Rows(0)
me.TextBox1.Value = selected_cell
End Sub
And the down button would be:
Private Sub ButtonDown.Click()
selected_cell.Rows(2).Select
Set selected_cell = selected_cell.Rows(2)
me.TextBox1.Value = selected_cell
End Sub
Now let's make your code like this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error Resume Next
If Target.Cells.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("K:K")) Is Nothing Then
With Credit_Information
Set .selected_cell = target
.TextBox1.Value = Target.Value
.Show
End With
End If
End Sub

What event happens when I select a sheet?

What I am trying to accomplish is fairly simple. When a user selects a sheet, I would like a message box to appear. Meaning: I'm currently viewing Sheet1, I click on the Sheet2 tab and a message pops up before I can do anything. I can't seem to find the event that fires when moving to a different sheet.
Events I've tried: Workbook_SheetActivate and Worksheet_Activate
Private Sub Workbook_SheetActivate(ByVal sh As Object)
MsgBox ("Example Message")
End Sub
Or
Private Sub Worksheet_Activate()
MsgBox ("Example Message")
End Sub
I've done some googling and most things are about when cell values change or the cell selection changes.
This should work:
Private Sub Worksheet_Activate()
MsgBox "you never visit...you never call....you never write"
End Sub
However:
code must be in the worksheet code area
macros must be enabled
events must be enabled
You could use the following in the "ThisWorkbook" module to fire a message whenever you change sheets within the workbook.
Sub Workbook_SheetActivate(ByVal Sh As Object)
MsgBox Sh.Name & " activated!"
End Sub
This will solve the problem without having to add Private Sub Worksheet_Activate() to every worksheet's code module.
Here is a link to all the worksheet events available in Excel:
http://dmcritchie.mvps.org/excel/event.htm
Private Sub Worksheet_Activate()
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) -- (additional examples)
Cancel = True 'turn off Edit mode when using “Edit directly in a cell”
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Cancel = True 'turn off Edit mode when using “Edit directly in a cell”
Private Sub Worksheet_Calculate()
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False 'should be part of Change macro
Application.EnableEvents = True 'should be part of Change macro
Private Sub Worksheet_Deactivate()
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Doesn't Worksheet_Activate work for you?
You need to have the event in the worksheet that is being activated - that is, if you put it is sheet 2, it will fire only when that sheet is opened.
This worked in sheet 2 of my workbook.
Sub worksheet_activate()
MsgBox "activated!"
End Sub