I have two macros in a worksheet. The first one check whether certain cells are addressed and have certain values then runs another macro. The following code is used for this:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("K10:K1000")) Is Nothing And Target.Value = "Trapezoidal roof 0.6mm and above" Or Target.Value = "LightBox ballasted" Then
Application.ScreenUpdating = False
Call PPAPricePerkWp
End If
End Sub
This works fine on it's own.
The second macro is run when a button is clicked. This macro copies and pastes cells/rows to other parts of the spreadsheet.
When the macro is run I get the error Runtime error 7 - out of memory and it breaks on the above bit of code.
Is there another way I can check whether cells in a certain column are addressed and have certain values and won't lead to the above error?
you might want to disable events before you call your subroutine, so that the Worksheet_Change is not being triggered every time you change a cell
Application.EnableEvents = False
Don't forget to turn it back on when you are finished
Related
How can I automatically execute an Excel macro each time a value in a particular cell changes?
Right now, my working code is:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub
where "H5" is the particular cell being monitored and Macro is the name of the macro.
Is there a better way?
Your code looks pretty good.
Be careful, however, for your call to Range("H5") is a shortcut command to Application.Range("H5"), which is equivalent to Application.ActiveSheet.Range("H5"). This could be fine, if the only changes are user-changes -- which is the most typical -- but it is possible for the worksheet's cell values to change when it is not the active sheet via programmatic changes, e.g. VBA.
With this in mind, I would utilize Target.Worksheet.Range("H5"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub
Or you can use Me.Range("H5"), if the event handler is on the code page for the worksheet in question (it usually is):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub
I spent a lot of time researching this and learning how it all works, after really messing up the event triggers. Since there was so much scattered info I decided to share what I have found to work all in one place, step by step as follows:
1) Open VBA Editor, under VBA Project (YourWorkBookName.xlsm) open Microsoft Excel Object and select the Sheet to which the change event will pertain.
2) The default code view is "General." From the drop-down list at the top middle, select "Worksheet."
3) Private Sub Worksheet_SelectionChange is already there as it should be, leave it alone. Copy/Paste Mike Rosenblum's code from above and change the .Range reference to the cell for which you are watching for a change (B3, in my case). Do not place your Macro yet, however (I removed the word "Macro" after "Then"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub
or from the drop-down list at the top left, select "Change" and in the space between Private Sub and End Sub, paste If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
4) On the line after "Then" turn off events so that when you call your macro, it does not trigger events and try to run this Worksheet_Change again in a never ending cycle that crashes Excel and/or otherwise messes everything up:
Application.EnableEvents = False
5) Call your macro
Call YourMacroName
6) Turn events back on so the next change (and any/all other events) trigger:
Application.EnableEvents = True
7) End the If block and the Sub:
End If
End Sub
The entire code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
Application.EnableEvents = False
Call UpdateAndViewOnly
Application.EnableEvents = True
End If
End Sub
This takes turning events on/off out of the Modules which creates problems and simply lets the change trigger, turns off events, runs your macro and turns events back on.
Handle the Worksheet_Change event or the Workbook_SheetChange event.
The event handlers take an argument "Target As Range", so you can check if the range that's changing includes the cell you're interested in.
I prefer this way, not using a cell but a range
Dim cell_to_test As Range, cells_changed As Range
Set cells_changed = Target(1, 1)
Set cell_to_test = Range( RANGE_OF_CELLS_TO_DETECT )
If Not Intersect(cells_changed, cell_to_test) Is Nothing Then
Macro
End If
I have a cell which is linked to online stock database and updated frequently. I want to trigger a macro whenever the cell value is updated.
I believe this is similar to cell value change by a program or any external data update but above examples somehow do not work for me. I think the problem is because excel internal events are not triggered, but thats my guess.
I did the following,
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheets("Symbols").Range("$C$3")) Is Nothing Then
'Run Macro
End Sub
How can I automatically execute an Excel macro each time a value in a particular cell changes?
Right now, my working code is:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub
where "H5" is the particular cell being monitored and Macro is the name of the macro.
Is there a better way?
Your code looks pretty good.
Be careful, however, for your call to Range("H5") is a shortcut command to Application.Range("H5"), which is equivalent to Application.ActiveSheet.Range("H5"). This could be fine, if the only changes are user-changes -- which is the most typical -- but it is possible for the worksheet's cell values to change when it is not the active sheet via programmatic changes, e.g. VBA.
With this in mind, I would utilize Target.Worksheet.Range("H5"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub
Or you can use Me.Range("H5"), if the event handler is on the code page for the worksheet in question (it usually is):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub
I spent a lot of time researching this and learning how it all works, after really messing up the event triggers. Since there was so much scattered info I decided to share what I have found to work all in one place, step by step as follows:
1) Open VBA Editor, under VBA Project (YourWorkBookName.xlsm) open Microsoft Excel Object and select the Sheet to which the change event will pertain.
2) The default code view is "General." From the drop-down list at the top middle, select "Worksheet."
3) Private Sub Worksheet_SelectionChange is already there as it should be, leave it alone. Copy/Paste Mike Rosenblum's code from above and change the .Range reference to the cell for which you are watching for a change (B3, in my case). Do not place your Macro yet, however (I removed the word "Macro" after "Then"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub
or from the drop-down list at the top left, select "Change" and in the space between Private Sub and End Sub, paste If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
4) On the line after "Then" turn off events so that when you call your macro, it does not trigger events and try to run this Worksheet_Change again in a never ending cycle that crashes Excel and/or otherwise messes everything up:
Application.EnableEvents = False
5) Call your macro
Call YourMacroName
6) Turn events back on so the next change (and any/all other events) trigger:
Application.EnableEvents = True
7) End the If block and the Sub:
End If
End Sub
The entire code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
Application.EnableEvents = False
Call UpdateAndViewOnly
Application.EnableEvents = True
End If
End Sub
This takes turning events on/off out of the Modules which creates problems and simply lets the change trigger, turns off events, runs your macro and turns events back on.
Handle the Worksheet_Change event or the Workbook_SheetChange event.
The event handlers take an argument "Target As Range", so you can check if the range that's changing includes the cell you're interested in.
I prefer this way, not using a cell but a range
Dim cell_to_test As Range, cells_changed As Range
Set cells_changed = Target(1, 1)
Set cell_to_test = Range( RANGE_OF_CELLS_TO_DETECT )
If Not Intersect(cells_changed, cell_to_test) Is Nothing Then
Macro
End If
I have a cell which is linked to online stock database and updated frequently. I want to trigger a macro whenever the cell value is updated.
I believe this is similar to cell value change by a program or any external data update but above examples somehow do not work for me. I think the problem is because excel internal events are not triggered, but thats my guess.
I did the following,
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheets("Symbols").Range("$C$3")) Is Nothing Then
'Run Macro
End Sub
when using the below code my excel freezes with no error (i have to pause code and end to allow excel to be used again. - the weird thing is i can run each of the updates individually and it wll work fine. but when all of them are active it stops working.
any advice?
Private Sub Worksheet_Change(ByVal Target As Range)
With ThisWorkbook
Dim Country As String
Country = .Sheets("Views").Range("C2").Text
Select Case Country
Case Is = "Australia"
.Sheets("Views").Range("C5").Formula = "=Volume!B7+Volume!H7+Volume!N7+Volume!T7+Volume!Z7+Volume!AF7"
.Sheets("Views").Range("C6").Formula = "=Volume!C7+Volume!I7+Volume!O7+Volume!U7+Volume!AA7+Volume!AG7"
.Sheets("Views").Range("C7").Formula = "=Volume!D7+Volume!J7+Volume!P7+Volume!V7+Volume!AB7+Volume!AH7"
.Sheets("Views").Range("C8").Formula = "=Volume!E7+Volume!K7+Volume!Q7+Volume!W7+Volume!AC7+Volume!AF7"
Case Is = "China"
'do china
End Select
End With
End Sub
thanks Variatus, you were 100% correct.
Presuming that the code is in the code sheet of Sheets("Views") the Change event, once triggered, would cause Change events by the changes it creates on the sheet, resulting in an endless loop which would, probably, eventually end in "out of memory". To avoid that, set Application.EnableEvents = False before any changes are made and set the property back to True after all changes have been completed. – yesterday
I also found that adding the following at the start also helped, this way the code only trigered updates when the specific Cell i wanted changed was changed i.e. the Country selection
If Not Application.Intersect(Range("C2"), Range(Target.Address)) Is Nothing Then
'code you want exicuted
End If
Recently I have update the MS office version to Office 365 and I found that one of my excel file doesn't work. It is a simple code to apply concatenate formula to some columns when I paste data into the sheet.
What do I need to do with the code?
Private Sub Worksheet_Change(ByVal Target As Range)
Range("B23:B4023").FormulaR1C1 = "=CONCATENATE(IF(RC[2]=""TTL"","""",RC[2]),IF(RC[3]="""","""",RC[3]),IF(RC[4]="""","""",RC[4]),IF(R7C4=""Class"",RC[6],RC[7]),RC[8],RC[5])"
End Sub
Normally there will be formula apply to column B to join text from column D,E,F,G,H,I&J
However, there is
run-time error '1004': Method 'Range' of object '_Worksheet' failed.
The Worksheet_Change runs on every content change in the current worksheet. But when this code then also changes content in the same worksheet, then this leads to infinity loops because every of those changes also runs the Worksheet_Change again and again.
Setting Application.EnableEvents property to False before the code in Worksheet_Change avoids this problem.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Me.Range("B23:B4023").FormulaR1C1 = "=CONCATENATE(IF(RC[2]=""TTL"","""",RC[2]),IF(RC[3]="""","""",RC[3]),IF(RC[4]="""","""",RC[4]),IF(R7C4=""Class"",RC[6],RC[7]),RC[8],RC[5])"
Application.EnableEvents = True
End Sub
But why on earth is it necessary setting that formulas every time content changes in the worksheet? Why not setting it only once?
You need to remove the .FormulaR1C1
This question was asked and answered back in 2010 but when I follow the directions of the venerable Mr. Buggabill and then run the macro (by editing the target cell) Excel promptly crashes. The code looks like this:
Private Sub Worksheet_Change(ByVal target As Range)
If target.Address = "$A$1" Then
ActiveWorkbook.Worksheets("Sheet2").Range(target.Address).Value = target.Value
End If
End Sub
I created one version of the macro under Sheet1 (which pushes the target value to A1 on Sheet2) and another version of the macro under Sheet2 (which does the reverse). With only one macro in place this works fine but my intent is to be able to enter a value on either sheet and have the new value propagated into both input cells. Excel crashes because it's a circular reference, right? Is there a way around this?
I suspect that it's not a circular reference, but rather a stack overflow ;)
You might consider turning off eventing inside the execution of your macros.
Application.EnableEvents = False
...
Application.EnableEvents = True
This way, the other event handler won't get called when you're poking values onto the other sheet.
Just add in another if inside the first one.
Private Sub Worksheet_Change(ByVal target As Range)
If target.Address = "$A$1" Then
If ActiveWorkbook.Worksheets("Sheet2").Range(target.Address).Value <> target.Value
ActiveWorkbook.Worksheets("Sheet2").Range(target.Address).Value = target.Value
End If
End If
End Sub
That should stop it from trying to execute when the two values already match. It checks to see if they are the same before doing the update.