Managing Excel Worksheet_Change Feature - excel

I have created a spreadsheet which uses the Worksheet_Change feature and the code associated with that works very well. I can stop it firing unnecessarily when inside the module by using Application.EnableEvents = False.
However, while I've created a form to enter data directly into the next available row (again, that works fine in terms of entry) it doesn't cause the formulae in the sheet to calculate (even though auto calculation is on and re-enabled within the module). If I manually place my cursor in the row, hit F2 and simply press enter, everything then fires up.
I have tried to enter data directly into the cells, but of course the Worksheet_Change feature then kicks in again and the cursor isn't simply moving to the next adjacent cell ....
I've tried to check firs for any direct entry with the code below and if it looks like the user isn't entering directly into the cell, the Worksheet_Change is disabled:
Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo eventhandler
Sheets(1).Range("a1").Select
LastCell2 = Sheets(1).Cells(Rows.Count, "A").End(xlUp).Row
Dim intersection As Range
Set intersection = Intersect(Target, Range("A3:F" & LastCell2))
If intersection.Row = LastCell + 1 Then
Exit Sub
End If
Application.EnableEvents = False
The code above is simply checking to see if data is being entered into the next empty cell and if that's the case I want it to just exit there but it isn't working.
So I actually have 2 problems :
the first is why this formula isn't triggering after entry via a vba form - I've used INDIRECT since there are other macros that delete rows by moving the remaining cells up and that was causing the count in the $A$3:$A$500 to reduce to $A$499 and then 498 etc - the addition is done depending on the system date and the transaction date so I get a current value and a future value using a standard sum statement:
=AD1-(SUMIF(INDIRECT("$A$3:$A$500"),"<="&TODAY(),INDIRECT("$E$3:$E$500")))+(SUMIF(INDIRECT("$A$3:$A$500"),"<="&TODAY(),INDIRECT("$F$3:$F$500")))
The second is why I can't enter data directly into the spreadsheet and trap the fact that I don't want it to do anything and simply allow the user to hit enter and move to the next adjacent cell to the one they just entered data into.
Is this a lost cause and am I trying to do too much here? I'm relatively new to coding and teaching myself so apologies if the standard and style isn't to everyone's taste.
Thanks in advance for any replies.

Related

Filling a range of cells with the same value using drop-down list

We all know that Excel has some counter-intuitive behaviours and it is, I believe, one of them:
When you select a range of few cells, starting your selection with the cell with data validation list and choose value from drop-down list: only one cell changes (the one containing drop-down list) instead of all selected.
Sometimes a few magic keyboard shortcuts such as CTRL+d, or combination of CTRL+' and CTRL+ENTER can fix this behaviour, but from my experience clients doesn't like to learn some new hacks, they just want to work everything in as simple way as possible.
I found even similar questions on SO e.g. here:
Adding same drop-down value to multiple cells simultaneously
I know that this is very simple code, but following few lines of code make my life easier, and I am sure this will help somebody too. Code in Worksheet module of course:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
' MACRO FILLS THE WHOLE SELECTED RANGE
' WITH THE SAME VALUE USING DROP-DOWN LIST
' IN JUST ONE ACTIVE CELL
' change to false if all selected cells should be filled with value
Const FILL_VISIBLE_CELLS_ONLY As Boolean = True
' detecting if dropdown list was used
'
' I am using very clever solution by JvdV from SO
' ~~~~> stackoverflow.com/questions/56942551/
'
' If after edit we're in the same cell - drop-down list was used
' I know that may be also drag&drop or copy-paste
' but it seems no matters here.
' Warning! Should be add one more check if someone used
' 'accept OK character' next to formula bar, not implemented here.
'
If ActiveCell.Address <> Target.Address Then Exit Sub
' preventing error which sometimes occurs
If IsEmpty(ActiveCell.Value) Then Exit Sub
' fill a range or visible range with activeCell value
If FILL_VISIBLE_CELLS_ONLY Then
Selection.Cells.SpecialCells(xlCellTypeVisible) _
.Value = ActiveCell.Value
Else
Selection.Value = ActiveCell.Value
End If
End Sub
When you select a Range of more than one Cell, is is important to distinguish between the Active Cell (the single highlighted cell) and the Selection (the entire selected range, including the Active Cell).
Then:
Any Content (such as Values or Formulas) that you enter into the Formula bar is input into the Active Cell only, not the entire Selection.
Any Formatting changes you make are applied to the entire Selection, not just the Active Cell.
An exception is when entering an Array formula which applies to the Selection.
Since in this case you are making a change to content not formatting, it is applied to only the Active Cell.
When considering the above, it is not counterintuitive but entirely consistent with the design and operation of the software.
However, from a UX experience this may seem counterintuitive simply because it defies your expectation. This is kind of like a "customer is always right" type situation, which can be very frustrating for programmers, but is essential that it be understood. You can read more about the concept in a series of well-written articles on the topic at https://www.joelonsoftware.com/2000/04/10/controlling-your-environment-makes-you-happy/ (disclosure: the author of these articles happens to be integral to the development history of both Excel and SO, but it is linked here on merit). It was written more than 20 years ago and is still every bit as relevant today.

How to get an excel cell to show the time it was selected

I am trying to create a table that tracks downtime for a production machine. the operator will be using a table with the columns down time start and down time stop. each time something happens that they have to leave the station I want them just to have to click the empty cell under downtime stat title and the time will appear/ log itself in the cell then the same for downtime stop.
I under stand how =now() works but then it shows the time when the file is opened, i want it to display only when the cell is selected.
Any help is much appreciated! I have never had to do anything like this in excel before.
You'll need some VBA for this. In your VBE (alt+f11) go to your worksheet and use something like the following:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'Check to see if the click/selected cell is in columns A or B
If Not Intersect(Target, Range("A:B")) Is Nothing Then
'Make sure just one cell is selected:
If Target.Cells.Count = 1 Then
'Update the value
Target.Value = Now()
End If
End If
End Sub
Here we are using the Worksheet_SelectionChange() event. This event will fire any time a selection change is detected on the worksheet in which this code is placed. When the change is detected it will test to see if the selection was in columns A or B. It will also test to insure that only one cell was clicked (otherwise highlighting those columns would cause every row in the column to update with the time, which would be bad). If that all passes, then it just sets the selected cell's (target) value to the current time.

Excel Worksheet_Change not working when macro changes cell

I'm trying to finish up a project of mine and I right now have a Form Control that when pressed adds to the value of a number and another button will subtract that value.
Another value has the two different buttons for the same thing, but the value is also dependent on the first value and other things than just the buttons modify that value. I tried implementing this code for validation
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("F19")) Is Nothing Then
If Range("E19") = 2 And Range("F19") < 12 Then
Range("E20") = 1
End If
End If
End Sub
but Excel apparently doesn't recognize that cell F19 has changed when the change is caused by the button, only when it is caused by user input. So, what this is saying is, if F19 updates and 19 is 2 and F19 is less than 12 (the prerequisite for E12 being 2 is F19 being 12 or greater) then set E20 to 1 (E20 is a modifier for E19 which also has other modifiers going into it). This method works on other values that aren't button controlled, but how can I get excel to realize when the Form Control button changes the value (or at least monitor when the form control is pressed.)
Edit: The macro actually doesn't work if the cell changes by formula either. I don't think I can use Worksheet_Calculate to monitor the change in a specific cell.
Why are you doing this with code anyway? You could have Cell E20 have a formula like: =IF(AND(E19=2,F19<12),1,"") which would make the cell blank unless the condition is met.
If you really want to do it with code, you should take this into account: The Worksheet_Change event "Occurs when cells on the worksheet are changed by the user or by an external link."
I would recommend instead of having
If Range("E19") = 2 And Range("F19") < 12 Then
Range("E20") = 1
End If
In your Worksheet_Change event that you add it as a separate sub, that you call from Worksheet_Change. You would also call the sub from the code for your button, after you've performed whatever action your button does. That way, you're guaranteed the check gets run and do not try to rely on events.
Daniel is partialy right, Worksheet_Change "Occurs when cells on the worksheet are changed by the user or by an external link." But this includes changes caused by VBA, and Excludes changes by a formula.
Your problem may be caused (or at least exacerbated) by the only partial qualification of your ranges:
Range("E19") will refer to 'E19' on the active sheet, which may or may not be be the sheets Target is on. You got it right with Target.Worksheet.Range("F19")
Try (note the .'s)
With Target.Worksheet
If Not Intersect(Target, .Range("F19")) Is Nothing Then
If .Range("E19") = 2 And .Range("F19") < 12 Then
.Range("E20") = 1
End If
End If
End With
BTW. I'm with Daniel in that your whole solution seems a little off, but we may not be getting the whole picture...

Highlighting a cell on click and forwarding to a new cell

So, it's a new week, and I've got new ideas for improving things. Part of what I do is send out reports to individual offices and departments all over the place; these offices in turn are supposed to go through the information and note inconsistencies. As with everything in life, this turns out to be more trouble than anything else. In an effort to make it a little bit more painless (I hope) I want to try somethinga little different for them. What I would like to do is set up something within the worksheet that the individuals receive that does two things:
First, I would like to set up the worksheet so that when the user
clicks on a cell the cell is highlighted;
Second, after the cell highlights then the activebox would
automatically transfer to a "comments" box at the end of the row
where the user would enter their comments as to why the cell in
question was highlighted; and
Third, assuming that someone will make a mistake and highlight
something by mistake I would like to add the additional function
that if a user selects a cell that is highlighted then it would
clear the highlight from the cell.
Possible? Suggestions? Thanks!
JMax is correct in identifying the flaw in that you cannot edit a cell if it changes color and selects a comments cell every time you click on it. The best way around this problem is to change the color only on double-click. I would also define the selected row/column and see if they fall within a table's range (instead of using Application.Intersect) but that's just personal preference
Something like...
Private Sub Worksheet_Beforedoubleclick(ByVal target As Range, cancel As Boolean)
Application.EnableEvents = False
Dim TargRow as Variant
Dim TargCol as Variant
TargRow = target.Row
TargCol = target.Column
'Define Header, FirstCol, CommentCol, LastCol as required to define your table/range where you wish these changes to be made. CommentCol is the cell in which comments should be made
If TargRow > Header And TargCol > FirstCol and TargCol < LastCol Then
If Cells(TargRow,TargCol).Interior.ColorIndex <> -4142 Then 'change color as required to match background
Cells(TargRow,TargCol).Interior.ColorIndex = 3 'change color as required; this makes them red
Cells(TargRow,CommentCol).Select
Else
Cells(TargRow,TargCol).Interior.ColorIndex = -4142 'match color from start of IF statement
End If
End If
Application.EnableEvents = True
End Sub
Note that we disable events so no other code can be triggered by us selecting a different cell. This is an absolute necessity when implementing the Worksheet_SelectionChange event, less so with the BeforeDoubleClick event
It's very important to consider how you trigger macros and how they give the user flexibility. This Excel help video provides a reasonable introduction
What you can (and probably have to) use is the Worksheet_SelectionChange event procedure:
See MSDN for how it works.
You also should have a look at Chip Pearson's page about events.
When the user changes the selection, you should check wheter you are in the right cells (using Intersect) and if so, change the Target background color and change the ActiveCell to the one where you should put comments.
Btw, you can check if the cell is aldreay highlighted before moving to another cell.
The main drawback of this method is that it will move the Excel Selection every time the user clicks on a corresponding cell. A solution would be to tell the user to use the Scroll Lock key and to navigate with arrows. See this link on how it works.

live execution of formula

can we execute a formula without moving cursor from the cell? After giving data in to Input cell either we press enter or we move from that cell and then any formula related to that gets executed. Is there any way that while entering input itself we can see the result in output in excel?Please help me in finding this option.
I don't believe it's possible for code to execute while the "editor" of a cell has focus and control. For example, try doing something else in Excel while you are editing a formula. I believe that the cell has to finish saving its value or formula before code can execute.
You can have a formula "listen" for when a cell is updated, but this is a little bit complicated. It could then force you back into the original cell once it is updated. Here's how you can write some code to "listen" for when a value of a cell changes. In the following example:
I record the value of Cell I1 to strValue.
Then I run a loop that stays running as long as the value of cell I1 has not changed.
The DoEvents command releases control back to the processor, which is what allows you to work in Excel while this is running.
Once the value of cell I1 changes, the While statement will be false and the loop will exit.
After the loop exits, a message box pops up that tells you the value changed and then the original cell is selected again.
'
Sub testChange()
Dim strValue As String
strValue = Range("I1").Value
Do While strValue = Range("I1").Value
DoEvents
Loop
MsgBox "The value changed!"
Range("I1").Activate
End Sub
Perhaps if you simply wanted to return control back to the original cell every time the value changed, you could use the line above without the message box and return to the loop once your method executes. Keep in mind that you might have to figure out another way to exit your code if you do that.
Why do you want to have it execute from within the cell? What is the end purpose of your task?
Press F9 to do a re-calc without moving from the input cell. This works in Excel 2007. I'm not sure about earlier versions.

Resources