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.
Related
I'm looking to try and run a macro when data is added to a cell. All I've been able to find advice on so far is how to run a macro when data is changed in a cell, which won't work. if data is removed from a cell then i don't want the macro to run. I'm fairly new to VBA so any advice would be appreciated.
I have tried using an intersect function as well as other, but I can only make my code run macros when the cells change as oppose to when data is added.
this is my current code
Sub Worksheet_Change(ByVal Target As Range)
'detect data in cell
If Not Intersect(Target, Range("J13:J27")) Is Nothing Then
Call Copy_Cell
End If
End Sub
There is no other event that you can use, the Change-event is the right place to go. All you need to do is to check if the modified cell(s) contain something or not.
Now when the change-event is triggered, more than one cell can be modified (eg by Cu&Paste), so you will likely need to check all modified cells individually.
As you don't show the code of Copy_Cell, I can only assume that this routine is copying something - likely using ActiveCell. You should change that routine and let it receive the cell to be copied as parameter.
Also, you need to be aware that if Copy_Cell is writing something in the same worksheet, the Change-Trigger is called recursively. To avoid that, use Application.EnableEvents = False.
Your code could look like this:
Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Change_exit ' Ensure that Events are enabled even if an error occurs
Application.EnableEvents = False
Dim cell As Range
For Each cell In Target
If Not Intersect(cell, Range("J13:J27")) Is Nothing And Not IsEmpty(cell) Then
copy_Cell cell
End If
Next cell
Change_exit:
Application.EnableEvents = True
End Sub
I'd like to modify values on specific cells depending on a specific group if it's expanded or collapsed.
I found a way, but it's a manual way (image1 image2) (the macro needs to be launched on each run).
Is there a way to use a function (i.e. worksheet_change), so that will be on real time ?
P.S. Sorry for my bad English and be kind, I'm kinda new on VBA (first code).
Thank you.
Private Sub groups()
If Worksheets("Feuil1").Columns("F").ShowDetail = True Then
Range("K2:K7").Value = "YES"
Else
Range("K2:K7").Value = "NO"
End If
End Sub
Thank you Luuklag for your solution, but as I said in my comment, in your code I have to update manually the placeholder cell which is not what I'm looking for.
But, I found something where my cells get updated by expanding or collapsing my group. And for this, as you said, I need a placeholder cell that gets updated on each calculation.
I use the formula =NOW on cell A1, because it's always useful to know the time and date.
Here is the (combined) code, for those who are looking a solution :
Private Sub Worksheet_Calculate()
Application.EnableEvents = False
'Where F is the column having the group button
If Columns("F").ShowDetail = True Then
'This is where you choose the cells that are dependent to the group and attribute something
Range("G10:G19").Value = "YES"
Else
'Same here. It could be other cells too
Range("G10:G19").Value = "NO"
End If
Application.EnableEvents = True
End Sub
There is a simple solution to this. Every time you expand or collapse a group you trigger the worksheet_calculate event. This can be used to your advantage.
All you need is a placeholder cell, which you populate with a volatile function (a function that changes its value on each calculation). You can use =randbetween(1,10) or =NOW() for example.
You then have your worksheet change event to look for your placeholder cell, AA1 in this example.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("AA1")) Is Nothing Then
Call groups
End If
End Sub
I am having a list of names in a Range A2:A77, in the worksheet name called Manual. whenever i choose a name, that is when a cell gets selected from the range, that active cell value should get reflected in the cell C1. Also, the macro should not work incase if i selected else where, other than the given worksheet or range.
I have googled alot but nothing seem to be matching my criteria, so i'm here, hoping for a better solution. You may ask me to achieve this by using data validation, but for that i will have to do multiple clicks and scrolling work to be done everytime. so to avoid that i'm looking for vba code to minimize the work and time.
Thank You.
I am only just learning VBA at the moment so this could be some very horible code but here goes.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells As Range
Set cells = ActiveSheet.Range("A1:A27")
If Not (Intersect(Target, cells) Is Nothing) Then
ActiveSheet.Range("C1").Value = Target.Value
End If
End Sub
Worksheet_SelectionChange is called if the selected cell in the sheet changes then using the test from InRange that I found here: VBA test if cell is in a range test if the cell is within the defined range then set the values.
Edited as sugested by #Vitaliy Prushak in comments.
I apologise for how trivial this must be for VBA developers, but I have done some digging and cannot fathom why the following code, when assigned to a cell and executed, results in #VALUE!
Function foo()
Range("A1:B3").Value = 10
End Function
The excel sheet:
I initially tried
ActiveSheet.Range("A1").Value = "abc"
but that didn't work either. What very simple thing am I doing wrong here?
Also, why, when I try to re-execute the function (using F2 and then Enter), does excel resubmit other functions that are in the same worksheet? This is truly maddening. I have hit F2 and Enter, so why would Excel think that I want to resubmit all other functions, and how can this be prevented?
Thanks very much.
Edit: You tried to use UDF for changing some fields and consistent about the use of some kind of event modification instead of firing your code from a button in your comments with #Mathieu Guindon. Since UDF fire the code only when some cells are recalculated, it is assumed that your requirement is to fire the code when some cells in the sheet get changed either manually or through some formula. The solutions offered below run the code when value of cell F1 change. You may please modify it according to your need.
Old Post: It is not a clean way but may be a called dirty workaround idea. Supposing you want to any change in cell F1 value to execute the code, may try
Public F1Val As Variant
Private Sub Worksheet_Activate()
F1Val = Range("F1").Value
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If F1Val <> Range("F1").Value Then
Range("A1:B3").Value = 10
F1Val = Range("F1").Value
End If
End Sub
Caution:Certainly it will backfire if cell F1 is linked with formula with the cells getting changed.
Alternately if only manual change of cell F1 is suffice for code to execute then may simply try
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F1")) Is Nothing Then
Range("A1:B3").Value = 10
End If
End Sub
I'm trying to imlpement a code that displays a message when a certain condition is met. In this case, it should happen when Sheet2's A1's value is equal or bigger than 1000. This value, on the other hand, is defined by a formula located in Sheet1. I tried implementing a solution based on this thread: How can I run a VBA code each time a cell get is value changed by a formula?
So I got this:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim updatedCell As Range
Set updatedCell = Range("A1")
If Not Application.Intersect(updatedCell, Range("A:A")) Is Nothing Then
If updatedCell.Value >= 1000 Then
MsgBox "Something requires attention"
End If
End If
End Sub
When I change the value of A1 through something from Sheet2, it works, but if for example I define it as =Sheet1!A7, and change Sheet1's A7, nothing happens.
How could I make it work?
Well, the linked thread deals with the problem that you want to find out the cell that is recalculated by the current change. (Anyway, the Dependents method only works for formula on the active sheet so this would not work across sheets).
In your case, you already know that you only want to monitor one specific (formula) cell.
So, I'd simply go with this:
Put this code in sheet 1 if you know that Sheet2!A1 only depends on values on sheet1.
Just catch all changes and look at your cell each time:
Private Sub Worksheet_Change(ByVal Target As Range)
If Worksheets("Table2").Range("A1").Value >= 1000 Then
MsgBox "Something requires attention"
End If
End Sub
Make sure that you use Worksheets(...).Range - a blank Range can be the source of sleepless nights of error-hunting, it refers to the worksheet where the code is located if the code is in a worksheet module and to the active sheet if it is in another code module.