I run into this issue a fair amount and am curious if someone can tell me why or how I can write this a little cleaner.
Below is my code and it does work.
If Target.Row = rTime.Offset(0, 1).Row Then
If Target.Column = rTime.Offset(0, 1).Column Then
cboStatus.Activate
End If
End If
How come I can’t just write it like this?
If Target = rTime.Offset(0, 1) Then
cboStatus.Activate
End If
If target is already a range then why do I need to specify the individual row and individual column? That second code will not work and I have tried many variations of it. I even tried something like If Target.Range = range(“C4”) Then or If Target.Range = cells(4, 3) Then, but neither of those worked either. I tried many variations of similar stuff. Although, I don’t want to use a specific range like A4, since I wanted to use the rTime like what is in the example, but I was just trying to figure this out.
Nothing seems to work, other than specifying the individual row and column each time. Can someone please explain this to me? Also, is there a better way to write this than what I did in the first example, which does work?
Thanks for anything that relieves my confusion.
The default property of a range object is .Value so when you say If Target = rTime.Offset(0, 1), it will always compare the values in that range rather than the address of those ranges.
One way is already shown by L42. Here is another way using Intersect
If Not Intersect(Target, rtime.Offset(0, 1)) Is Nothing Then cboStatus.Activate
EDIT
When you say Target.Column and Target.Row, you will always get the first column and the first row of the cell in that range, even if Target has multiple cells. To avoid this use the below to ensure that you have the desired Target. Your code will give you unexpected results even if there is a single cell in Target. For example, say the value of cell B1 is equal to any other cell which at the moment is target. So if Cell B1 = "Sid" and Cell F1 = "Sid" and you select cell F1 then you will get the "Hello World" message box.
For xl2003, you can use an additional check
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rtime As Range
Set rtime = Range("A1")
If Target.Cells.Count > 1 Then
MsgBox "you have chosen more than one cell"
Exit Sub
End If
If Not Intersect(Target, rtime.Offset(0, 1)) Is Nothing Then
MsgBox "Hello World"
End If
End Sub
For xl2007+, replace Target.Cells.Count with Target.Cells.CountLarge
For L42
Your method is correct but then you also will have to put the above check to get the correct results.
try this:
Edit1: To cover Chis' concern
If Target.Address = rtime.Offset(0,1).Address(,,,True) then cboStatus.Activate
you cannot compare objects, just the properties? I'm not certain though.
Related
I want to hide columns with value 0 in range G4:FC4
The cell can take values 0 (in that case the columns should be hidden) or 1 (in that case they should be visible). The value 0 or 1 is formula based and depends on the drop down input value in cell D2.
When I change the value in D2 manually the macro works fine, but when I use the drop down box it doesn't. Please find below my code. Any advice?
Many thanks
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Range
Dim c As Range
For Each c In Sheets("P_MM6").Range("G4:FC4").Cells
c.EntireColumn.Hidden = True
If c.Value = 1 Then
c.EntireColumn.Hidden = False
End If
Next c
End Sub
Changing manually vs drop-down should not matter, except if perhaps somewhere else in your code events are being disabled and not turned back on, or maybe calculations are set to manual and thus do not create a change in the formula value, so, even though the code fires, the column values don't change.
That said, the code below will help you because it will not try to hide/unhide on every cell change, but only when D2 changes.
Private Sub Worksheet_Change(ByVal Target As Range)
If target.address = "$D$2" Then
Dim c As Range
For Each c In Sheets("P_MM6").Range("G4:FC4").Cells
c.EntireColumn.Hidden = c.Value = 0
Next c
End If
End Sub
Also make sure that calculations are set to automatic and they are not being turned off somewhere in your code and also that events are not being disabled and not turned back on somewhere else in the code.
If all that doesn't help, put a break point on the Worksheet_Change line of code and change the cell via drop-down and see what happens.
I don't want to use direct cell references in this bit of VBA code, because these three cells of this "form" will shift around. Can't figure a correct way to get Named Ranges on Interset Target Range approach to work.
Googling, I've not had success (oviously), thus ny first post. Tried changing things up, even random wrapping in quotes, with without square brackets, adding .Name. Ugh. It's Friday.
To color the story,
E18 is StartDate
E19 is Term(mo)
E20 is EndDate
FYI, Cell change triggers code to run nicely. The same named ranges work well in the rest-of-the-code.
Expecting
Something like Range("E18:E18, E19:E19, E20:E20") be turned into named ranges instead (which by design are single cell named assignments) in my non-working code snippet below.
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range([Term_End_Date], [Term_Duration__mo], [Term_Start_Date])) Is Nothing Then Exit Sub
'was If Intersect(Target, Range("E18:E20")) Is Nothing Then Exit Sub
'<snip> rest works well
Thanks!
Try this
Dim rng As Range
Set rng = Union(Range("Term_End_Date"), Range("Term_Duration__mo"), _
Range("Term_Start_Date"))
If Not Intersect(Target, rng) Is Nothing Then
'~~> Do What you want
End If
I'm currently using Target.Address to identify when a cell is double clicked and run a piece of code to take the user to a relevant sheet showing the information contained in that cell.
So for example, if a cell says that 3 systems haven't done some sort of action, if a user clicks on that cell they get taken to what those 3 systems are.
Currently, I'm doing this like so:
If Target.Address = "$B$20" Then
Win2KTrackerIncompleteFilter (strEngUnits(9))
ElseIf Target.Address = "$C$20" Then
Win2KTrackerIncompleteFilter (strEngUnits(0))
ElseIf Target.Address = "$D$20" Then
Win2KTrackerIncompleteFilter (strEngUnits(1))
etc
I've put the majority of the code in one small function, so this seems to be doing the job okay. However, if I were to insert a new row above row 20 (from the above example), all of these references would be pointing to the wrong place. I thought I could handle this by removing the absolute references (the $ sign) but that just breaks the mechanism.
Can anybody advise how I could either a) rewrite the code to make it more efficient and b) protect the code so new rows can be inserted and the code will remember which rows/columns it was pointing to and update itself accordingly.
Select a cell on a spreadsheet and give it a name
For example B3 is now named myCell
and edit your script a little to use the named ranges like this
Dim namedRange As Name
If Target.Address = Me.Range("myCell").Address Then
Win2KTrackerIncompleteFilter (strEngUnits(9))
ElseIf ...
...
End If
So now even if you insert new rows the name will update its .RefersTo property automatically and you will not have to touch the script.
I usually do this using named ranges, along with the Not Intersect(...) Is Nothing technique, which is a bit more robust than simply looking at the Address property.
First, name your cells e.g. as shown here:
If you insert more rows/columns, the names will follow the cells as they get pushed around, so you won't have to change the code each time.
Then, to test for which cells is being clicked, you can use Not Intersect(...) Is Nothing:
If Not Intersect(Target, Range("System1Report")) Is Nothing Then
Win2KTrackerIncompleteFilter strEngUnits(9)
ElseIf Not Intersect(Target, Range("System2Report")) Is Nothing Then
Win2KTrackerIncompleteFilter strEngUnits(0)
ElseIf Not Intersect(Target, Range("System3Report")) Is Nothing Then
Win2KTrackerIncompleteFilter strEngUnits(1)
End If
Why do this instead of just checking if Target.Address = Range("System1Report").Address? In some circumstances (in my case, most of the time), you may want to have named ranges that include many cells. In that case, that named range's address won't match a single cell's address. Hence checking whether they intersect is more robust.
I'm currently trying to write a macro based on sheet change, where the letters in a table column are automatically converted to upper case. So, for example, if I entered "abcde-12345-678" into a cell, it would automatically correct to "ABCDE-12345-678". After doing some digging, I found some code that has worked for some people, but I'm having trouble tweaking it to suit my needs.
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range("E:E")) Is Nothing Then Exit Sub
Application.EnableEvents = False
Target = UCase(Target)
Application.EnableEvents = True
End Sub
There are two things that I would like to address. The first being, that this code isn't currently working for me. I have it in the correct location according to the author (located in the Sheet1 object). Are there any ideas as to why this isn't working?
The second is that I would like to modify the code to refer to a table column rather than a range. For example, I've tried changing the second line of the above code to the following (the name of my table is ReviewTracker, and the column I'm interested in is Product Number):
If Intersect(Target, Range(ReviewTracker[[#Headers],[Product Number]])) Is Nothing Then Exit Sub
This returned a compile error "Expected: list separator or )". So there is obviously something wrong with it, but hopefully it might help illustrate what it is I'm trying to accomplish.
Thanks in advance for any help on the issue.
-Sean
First. You can have events disabled due to lots of reason. Let's make it sure that events are on which you can do as follows:
go to VBA Editor >> open Immediate Window >> write there: Application.EnableEvents = true >> press Enter
Second. To check if intersection match appropriate column within you ListObject table you need something like this:
If Intersect(Target, Range("ReviewTracker[Product Number]")) is Nothing Then
assuming that ReviewTracker is table name and Product Number is table column. You don't need #Headersas it will refer only to header row.
What UCase does is converting all the characters in a given string into upper case and thus you can apply it to any Range.Value. Worksheet_Change is called every time the value of a cell has changed and thus is a good place to put your code. But the way you are using to refer the table is wrong. The code your posted adapted to your requirements:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Sheet1.ListObjects("Table1").ListColumns(1).Range) Is Nothing Then Exit Sub
Target.Value = UCase(Target.Value)
End Sub
It converts into upper caps any string input in the first column of Table1 in Sheet1. It has to be placed in the Sheet1 object file (in the VBA Project explorer: Sheet1 (Sheet1) inside the Microsoft Excel Object folder). Adapting it to your actual conditions is straightforward.
After all, I already have the dropdownlists, the dependencies etc. and it works well, ALSO I have a vba code that, when the user change one value from the dropdownlist parent, the dependence clear their contents. BUT
That only works with that cell...
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("C2")) Is Nothing Then
Range("D2").ClearContents
End If
End Sub
Obviusly because I'm tellin vba that only C2 & D2, but What I want it's that somebody would help to figure it out how to make it the entire column, not just that specific cell, like (column - 1 ) or something... because if I copy paste those dropdownlists only works in the first one cause that is specified...
Anybody? Any ideas? please.
Here there are some pics
In the pictures above, the dropdownlists work only in that specific cell, I tried what Hol told me with the function Cells(row index,columnIndex) but I need a for or something like that isn't it ? This is the first thing I'm doing in vba so I dont have a clue and I'm looking for examples and then trying, it takes too long hahaha,
I've already tried instead of "C2" , Column(3) and in D2 Column(4) but I have an error in the conditional If Not Intersect(Target, Range(Column(3))) Is Nothing Then
As far as I understand you want your macro to works in pairs: any change in C column (as of 2nd row bottom direction) will clear cell in D column in the same row. If so the following code does the trick.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Target.Column = 3 Then
Target.Offset(0, 1).ClearContents
End If
End Sub