I am encountering an error in MS Excel when the following VB code is executed and the "Tracking Changes" feature is turned on:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 1 Then
If IsEmpty(Target) Then
Target.Offset(0, 1).Value = Empty
Else
Target.Offset(0, 5).Value = Now()
End If
End If
End Sub
It seems that I can enter data into the first 2 rows just fine but once I start populating data in the 3rd row and onwards, I get a error stating "run-time error '1004' application-defined or object-defined error".
I get the error from row 2 onwards with this code and track changes turned on. The code however seems to do what it is supposed to do regardless of the error, so I would advise an On Error Resume Next to work around.
This doesn't address any underlying problem with the change tracking and your changes may not be being tracked.
Change Tracking forces the workbook to become Shared, which disables many features (e.g. you can't access VBA with Change Tracking enabled).
I'm not entirely sure why this error is being thrown, but a workaround to avoid seeing this message would be to Resume Next when an error occurs:
On Error Resume Next
Simply add this line of code about your first If block (If Target.Column = 1 Then). Please note that ideally you should want to discern the source of this issue and that this solution is a workaround, which might not be good practice.
Related
Good afternoon.
I’m new at VBA. From my research on the internet, I’ve been able to add some lines that display a message box when an NG is entered into a cell within the range. However, when I try to delete the inputs from several cells, I get a Run-time error ‘13’: Type mismatch message. Any ideas what I’m doing wrong and how to fix it? I’ve added the code that I put in VBA below:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range("I3:JY30")) Is Nothing Then Exit Sub
If Target.Value <> "NG" Then Exit Sub
MsgBox "ATTENTION: If bell cup is No Good, please replace with new cup and notify supervisor/leader for review. Also, document bell cup serial number and concern on worksheet titled Scrap Bell Tracking "
End Sub
Also, when I click Debug, the If Target.Value <> "NG" Then is highlighted.
Thank you in advance for your help.
Target is a Range, and hence it may consist of more than one cell. In that case, the Value property is invalid.
A simple solution would be to ignore changes with more than one cell: For that, we need to add the following before the access to the Value property:
If Target.Count <> 1 Then Exit Sub
But that would not show a message if e. g. the user pastes five cells, and one or more of them contain the text. The perfect solution would be looping through the range and check each cell separately. And then you would have to think if you want to show the message more than one time if the text is found in more than one cell. So, I will leave that as an exercise to the reader...
I am an Excel-VBA newcomer and I am trying to write a short piece of code which is triggered by somebody changing the value of cells in a worksheet. It should set the value of the changed cell to zero if it's less than zero. The code looks like this:
Private Sub Worksheet_Change(ByVal Target As Range)
'Debug.Print Target.Address
If Target.Column = 6 Then
For Each Cell In Target.SpecialCells(xlCellTypeConstants, 3)
If Cell.Value < 0 Then
Cell.Value = 0
End If
Next
End If
End Sub
Now what happens is that when I change the value of any cell in column 6, every cell in the sheet containing numbers less than zero is also changed to zero.
I was thinking that the "Target" Object that is created for the Worksheet_Change event handler would only contain the cell/cells changed, and thus my code would only change the value of cells that were modified and triggered the event in the first place.
I tried to help myself by using Debug.Print to output the address of the object. It printed out the address of every cell in the sheet with a value less than zero, so I assume the handler ran several times.
I actually found a workaround for the problem itself but my questions are these: how did I fail in using the Worksheet_Change event and what can I do in the future to not have such problems?
EDIT 1: Updated code with bug fix suggested in comments
EDIT 2: Updated code with error handling to deal with Array Formulae
In answer to your question
[1] how did I fail in using the Worksheet_Change event and [2] what can I do in the future to not have such problems?
Technically you didn't
Nothing for this type of problem, although the following rule helps in general
You are correct in your understanding of the Targetobject. Your code failed because SpecialCells doesn't like a single cell to operate on. Give it one and it expands it to the entire sheet! Give it anything else and it works just fine.
The reason your Debug.Print displays all the cells is that every time your code changes a cell, another change event is triggered. Luckily for you the second one finds a zero so it doesn't trigger another one. The following general rule should help avoid a lot of problems, just not this particular one:
Always surround any code in an event handler that changes any part of the workbook with Application.EnableEvents.
To fix you code so it works, simply remove the SpecialCells method call. Since you are using Cell.Value instead of the highly recommended Cell.Value2 (see here), VBA implicit type converts numbers formatted as text to actual numbers for you. Thus the code works both on numeric and text values.
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
'Debug.Print Target.Address;
Application.EnableEvents = False
For Each Cell In Target '.SpecialCells(xlCellTypeConstants, 3)
If Cell.Column = 6 And Cell.Value < 0 Then
On Error GoTo Error:
Cell.Value = 0
On Error GoTo 0
End If
Next
GoTo ExitSub:
Error:
If Err.Number = 1004 Then ' 1004 -> "You cannot change part of an array."
'Application.Undo ' Uncomment to disallow array entering a negative value formula into/across column 6
MsgBox "A cell could not be zeroed as" & vbCr & "it is part of an array formula.", vbExclamation, "Microsoft Office Excel"
On Error GoTo 0
Else
On Error GoTo 0
Resume
End If
ExitSub:
Application.EnableEvents = True
End Sub
Notes:
- Update 1: Code now correctly deals with multi-cell changes.
- Update 2: Code now traps error 1004 to deal with entering Array Formulae. It can either allow the array formula to be entered resulting in negative values in column 6, or stop the entry altogether.
This works (Updated)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Range
For Each c In Target
If c.Column = 6 Then If IsNumeric(c) Then If c < 0 Then c = 0
Next c
End Sub
And please, learn and use OPTION EXPLICIT !
I came here looking for a way to stop my worksheet from "flashing" as it ran code to format columns and rows, due to users changing data anywhere in the sheet, including Filters and Sorting.
Aside, from the official answer to the OP's problem, If you're trying to control the Worksheet_Change() event from firing at all (it will still fire but you can bypass it), in circumstances where you want users to change data for example, but not areas around the data, such as fields or labels as part of your VBA system, I use the Target.Row element to determine my limits. Combined with Target.Column, and you can hone-in on specific cells that are free for the user to control.
i.e.
Dim myTopLimit AS Integer
myTopLimit = 6
etc..etc
if Target.Row < myTopLimit and Target.Row > myBottomLimit and Target.Column < myLeftLimit and Target.Column > myRightLimit then
.... code to allow WorkSheet_Change() to do somthing
else
.... code to force WorkSheet_Change() to drop through or no code
End If
I've written the following code to reset any validation and/or autofiltering before my workbook closes:
Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next
Worksheets("Query").Cells.SpecialCells(xlCellTypeAllValidation).Clear
On Error Resume Next
Worksheets("Table").Cells.SpecialCells(xlCellTypeAllValidation).Clear
On Error Resume Next
Worksheets("Table").ShowAllData
On Error Resume Next
Worksheets("Query").Activate
ThisWorkbook.Save
End Sub
However, 'Worksheets("Table").ShowAllData' only seems to work in the immediate window. When I close the program after filtering the table on sheet "Table" and open it up again, I get
We found a problem with some content in "Book1.xlsm". Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes.
This didn't happen at first and it seems to have no cause. Why does the filter reset work in the immediate window, but not in my subroutine? How can I fix it?
never use On Error Resume Next or you will never learn anything
you need to check to see if Autofilter is on first because it's a toggle...
If ActiveSheet.FilterMode Then
ActiveSheet.ShowAllData
End If
or
If ActiveSheet.FilterMode Then
ActiveSheet.AutoFilterMode = False
End If
No need to have so many OERN On Error Resume Next. Just one will do.
I tried this
Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next
Worksheets("Query").Cells.SpecialCells(xlCellTypeAllValidation).Clear
Worksheets("Table").Cells.SpecialCells(xlCellTypeAllValidation).Clear
On Error GoTo 0
If Worksheets("Table").FilterMode Then Worksheets("Table").ShowAllData
Worksheets("Query").Activate
ThisWorkbook.Save
DoEvents
End Sub
and I did not get any errors. Try it.
We found a problem with some content in "Book1.xlsm". Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes.
If you still get an error then it is not because of this piece of code. You need to see the report as to what was repaired. I have a feeling one of your DataValidation list is causing this problem. Like I said, check the repair report. If the report says that the Datavalidation was repaired then you need to check that.
BACKGROUND:
I am trying to identify how many unique time periods I have from a list of dates that have. Elsewhere, I have seen a method which utilizes collections and error trapping (right term? I mean "On Error Resume Next" in any case) to build the collection with unique values. I have even used this structure successfully in other code that I have written, but in my current circumstance, I am getting an "Error 457: This key is already associated with an element of this collection." Thinking I was using the collection incorrectly, I opened up some older code I wrote 6 months ago (on a different computer for a different company) which uses the same structure and was known to WORK. This older code broke on the same identical error, which it previously did not do. Here is the sample of my work-in-progress code:
Dim rng as range
Dim TimePeriod as Collection
Set TimePeriod = New Collection
For Each rng In Range("I2:I6")
On Error Resume Next
TimePeriod.Add rng.Value, CStr(rng.Value) 'This is where the code breaks
On Error GoTo 0
Next rng
QUESTION:
I'm wondering if there is a setting or a reference library that I am somehow missing that is causing both pieces of code to break, or how to determine that, since both codes are functionally identical, and the previously tested satisfactory code breaks like my work-in-progress. I expected the "On Error Resume Next" to force the loop to pass over the error. Any suggestions?
--Update--
Sample data in range("I2:I6") as follows:
1/21/15
1/21/15
1/21/15
1/23/15
1/27/15
Your code works properly on my Excel 2007, although I would rewrite it to enclose the entire loop within the on error resume next for efficiency.
I suspect you are seeing the errors now because of a mis-set macro option error break.
Check Tools/Options that you have not selected to Break on All Errors
Try getting rid of the On Error Goto 0 line. Take a look at this:
Difference between 'on error goto 0' and 'on error goto -1' -- VBA
It comes from Visual Basic 6, but works pretty much the same in VBA, it appears. Should work if you keep the On Error Resume Next line but eliminate the On Error Goto 0 line.
I have this simple VBA code with which I want to change the background of the selected cells. Somehow the command Selection. that I learned before doesn't work. Could you help me with this code? I know the answer is probably stupid, but I can't seem to figure it out.
Sub set_background_color()
'Add background color to selected cells
Selection.Interior.Color = RGB(255, 0, 0)
End Sub
Thanks
EDIT: Sorry for the vague question, it's my first question on stack overflow so I didn't think of the importance of the type of error. It gives me the error "Compile error: Expected function or variable".
It is attached to a button, but even if I run it as a macro without button it gives me the same error.
EDIT 2: I'm running Excel 2011 on a Mac, until now it never gave me any compatibility issues in VBA. However this does not seem to work.
The problem is not within your code, it is within your cells.
Check the locked status of the cells and the protection status of the worksheet.
If your worksheet is not protected then try this
Sub set_background_color()
Dim r As Range
On Error Resume Next
Set r = Selection
On Error GoTo 0
If Not r Is Nothing Then
r.Interior.ColorIndex = 3
Else
MsgBox "Invalid Selection"
End If
End Sub