Private Sub Worksheet_Calculate() [closed] - vba

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I can't post an image so I wanted to explain my question in more detail.
I have 2 files: The vlookup formulas are in the Destination File. The vlookup values are in the Source File. The Destination File will be closed. The Source File will be opened. In the Source File, I may change 15 cell values. If so, I want the 15 cells in the Destination File (closed workbook) to be highlighted yellow as they contain the vlookups when I open it. I hope this explains what we're trying to solve.

UPDATE
Instead of highlighting the cells, do you know how to insert a comment in each cell whenever the cell value changes? I would like to comment to say, "Changed cell from 20 to 30".
Try this code (may be time consuming for big ranges with formulas):
in Code module (standart module):
Public cVals As New Dictionary
Sub populateDict()
Dim rng As Range, c As Range
With ThisWorkbook.Worksheets("Sheet1")
Set rng = Intersect(.UsedRange, .Range("CP:CV"))
If rng Is Nothing Then Exit Sub
For Each c In rng
cVals(c.Address) = c.Text
Next c
.Calculate
End With
End Sub
in ThisWorkbook module:
Private Sub Workbook_Open()
Application.Calculation = xlCalculationManual
Call populateDict
Application.Calculation = xlCalculationAutomatic
End Sub
in Sheet module:
Private Sub Worksheet_Calculate()
Dim rng As Range, c As Range
Dim rngToColor As Range
On Error GoTo ErrorHandler
Application.EnableEvents = False
'get only used part of the sheet
Set rng = Intersect(Me.UsedRange, Me.Range("CP:CV"))
If rng Is Nothing Then GoTo ExitHere ' if there is no formulas in CP:CV - exit from sub
'reset color for all cells
rng.Interior.Color = xlNone
For Each c In rng
'check if previous value of this cell not equal to current value
If cVals(c.Address) <> c.Text Then
'if so (they're not equal), remember this cell
c.ClearComments
c.AddComment Text:="Changed value from '" & cVals(c.Address) & "' to '" & c.Text & "'"
End If
'store current value of cell in dictionary (with key=cell address)
cVals(c.Address) = c.Text
Next c
ExitHere:
Application.EnableEvents = True
Exit Sub
ErrorHandler:
Resume ExitHere
End Sub
Note that I'm uisng Dictionary object. For working with Dictionary object you should add reference to Microsoft Scripting Runtime library. Go to Tools->References and select Microsoft Scripting Runtime library:

It looks like you want to build something similar to a trading platform to highlight cells linked with RTD formulas. If it is true (or even if you make changes manually), you can achieve your goal by using worksheet_change.
The below procedure looks at cells in columns 12 to 15 (the real-time values that change) and it compares the values in the FmlaRng (which I assume is a fixed range) before the calculate occurs and after. It is important you set your sheet as xlCalculateManual otherwise Excel will calculate the new values before you can record the old ones.
Also, I am not sure if you need to keep the Application.EnableEvents, but I left it there.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim endrow As Long, startrow As Long, i As Long, j As Long
Dim PreValue As Variant
Dim FmlaRng As Range
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
If Target.Column >= 12 And Target.Column <= 15 Then 'This is where the cell initally changes (the lookupvalue cells)
On Error GoTo 0
startrow = 1
endrow = 1000
With Workbooks("Workbook2").sheets("Sheet1") 'You need to change these names
Set FmlaRng = .Range(.Cells(startrow, 94), .Cells(endrow, 100)) 'FmlaRng is where the lookups should be
FmlaRng.Cells.Interior.ColorIndex = 0
PreValue = FmlaRng
Calculate 'This is when vlookups update
For i = LBound(PreValue, 1) To UBound(PreValue, 1)
For j = LBound(PreValue, 2) To UBound(PreValue, 2)
If FmlaRng.Cells(i, j) = PreValue(i, j) Then
Else
FmlaRng.Cells(i, j).Interior.ColorIndex = 36
End If
Next j
Next i
End with
End If
Application.EnableEvents = True
End Sub

Related

Runtime error 1004 - The command cannot be used on multiple selections

The code below copies data from a specific column and transfers it to another one. For example, if in column A I have data from row 1 to 10 and press the button, then the values from row 1 to 10 will be transferred to i.e. column D. Afterwards, If I change the values in row 5, 7 and 9 in column A and press the button, only the values from row 5, 7 and 9 will be transferred to column D. The reason why the code is like that is because the worksheet has many rows filled with values and I want to be transferred (copy) only the values that have been modified. Otherwise, it will take quite some time.
The code works, but sometimes I get the error The commnand cannot be used on multiple selections. I tried to have a look on the internet to fix it but I couldn't come up with any solutions. Any help will be appreciated!
Note: A user from this community helped me to write the code below a time ago, but I cannot find the link anymore for that.
This code is pasted in the worksheet that I am using:
Option Explicit
Private Sub Worksheet_Change(ByVal target As Range)
Dim creation As Worksheet
Set creation = ActiveSheet
Dim copydata As Range
Set copydata = Application.Intersect(target, creation.Range("A2:A5000", "A" & creation.Rows.Count))
If (Not copydata Is Nothing) Then
If (CopyDataRange Is Nothing) Then
Set CopyDataRange = copydata
Else
Set CopyDataRange = Application.Union(CopyDataRange, copydata)
End If
End If
End Sub
And this code is pasted in a module:
Option Explicit
Public CopyDataRange As Range
Public Sub CommandButton1_Click()
Application.ScreenUpdating = False
If (Not CopyDataRange Is Nothing) Then
CopyDataRange.Copy
CopyDataRange.Offset(0, 3).PasteSpecial Paste:=xlPasteValues ' this where I get the error
Set CopyDataRange = Nothing
End If
Application.ScreenUpdating = True
End Sub
PasteSpecial doesn't work on multiple ranges. You can loop over all parts of the range using the Areas property:
if Not CopyDataRange Is Nothing then
Dim r As Range
For Each r In CopyDataRange.Areas
r.Copy
r.Offset(0, 3).PasteSpecial Paste:=xlPasteValues
Next
set CopyDataRange = nothing
end if
This will work even if you don't have a multiple range, in that case it contains only one Area (Areas.Count = 1)

Timestamp on one sheet from updated cell on another VBA excel

I have a workbook with upto 31 sheets,(named (01),(02) etc, Each with the same format as per the screenshot below
I wish to use the following code which I have found(with help from this forum :) ) to place a timestamp in a mirror file (WorkBook2) that will work out the difference from when column B and Column C in workbook 1 is changed.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("B:B, C:C"), Target) Is Nothing Then 'add Columns that will be changed to BA:BA and BB:BB
'add error control
On Error GoTo safe_exit
'don't do anything until you know something has to be done
Dim r As Range
Application.EnableEvents = False
For Each r In Intersect(Range("B:B, C:C"), Target) 'i know this would only work on the same sheet
r.Offset(0, 1).Value = Now() 'Need to get this section to populate workbook2
Next r
End If
safe_exit:
Application.EnableEvents = True
End Sub
I know people have asked similar questions and im sorry if this is a duplicate but I really am lost on trying to get this to work.
Edit - Workbook two sheets are named in the same way with just a "t" after ie (01t), (02t) etc
Try this. The code needs to go in the ThisWorkbook module of workbook 1 and you need to add the name of workbook 2.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim r As Range
On Error GoTo safe_exit
Application.EnableEvents = False
For Each r In Target
Select Case r.Column
Case 2, 3, 5, 6, 8, 9, 11, 12 'b c e f h i k l
Workbooks("name of workbook2").Sheets(Sh.Name & "t").Range(r.Address).Value = Now()
End Select
Next r
safe_exit:
Application.EnableEvents = True
End Sub

Prevent sub from running

In sheet1 (which I've Called "MainSheet") I have a sub in my VBA script that check the values of some cells whenever a cell is changed in this sheet. (one of the main actions that will occur when a cell is changed is modifying it's color, green for Cell's with a value, red for empty cells)
But now I've got some other sub's that also change cells (in the main sheet) but in this case I don't need (and don't want) VBA to check the cells and adapt the color to their values after every cell change. (annoying when editing a large amount of cells).
(I've already tried to put this sub in the "ThisWorkbook"part of VBA instead of the Sheet1(MainSheet) part, but unfortunately this made no difference at all).
Question one: is it possible to prevent this?
I also have a correlated problem with another sub that worth mentioning in the same question I think: In this sub a new sheet is created, named and filled with text from a .txt document. Then the sheet will be saved as new workbook, and the sheet will be deleted. (The name of the sheet equals the name it will get when it's saved, and varies ever new occurrence.)
When I'm copying the .txt lines into this sheet one by one, the first sub I mentioned (the one editing cell color) is called. one of the first things happening in this sub is calling my MainSheet. When thin sub is finished the line copying sub will continue but will start pasting the lines in my Main Sheet. I tried to enter lines in this sub that select the sheet with variable name, but it keeps jumping to the MainSheet.
Question two: How do I prevent jumping to the MainSheet?
(Both questions probably could have the same solution.)
The sub that modifies the cell colours:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim j As Integer
'Collor all cells green containing values, collor empty cells red.
''Starts automaticly after every cell change within this sheet
'Huidige Cell onthouden
If Not Intersect(Target, Range("A9:A29")) Is Nothing Then
On Error GoTo bm_Safe_Exit3
Application.EnableEvents = False
If Intersect(Target, Range("A9:A29")).Cells.Count > 1 Then
Application.Undo
MsgBox "Please edit one cell at a time!"
Else
Dim newVal3 As Variant
newVal3 = Target.Value
Range("A9:A29").ClearContents
Target.Value = newVal3
End If
End If
bm_Safe_Exit3:
Application.EnableEvents = True
Set myActiveCell = ActiveCell
Set myActiveWorksheet = ActiveSheet
Set myActiveWorkbook = ActiveWorkbook
Sheets("MainSheet").Select
Range("C5").Select
j = 0
Do While j < 6
If ActiveCell.Offset(0, j).Value = "" Then
ActiveCell.Offset(-1, j).Interior.Color = RGB(255, 0, 0)
Else: ActiveCell.Offset(-1, j).Interior.Color = RGB(0, 255, 0)
End If
j = j + 1
Loop
'Terug naar de voormalig active cell
myActiveWorkbook.Activate
myActiveWorksheet.Activate
myActiveCell.Activate
End Sub
Using .Select and .Activate is inefficient at the best of times; in a Worksheet_Change event macro it can really foul the waters.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
If Not Intersect(Target, Range("A9:A29")) Is Nothing Then
If Intersect(Target, Range("A9:A29")).Cells.Count > 1 Then
Application.Undo
MsgBox "Please edit one cell at a time!"
'intentionally throw an error; no more code run; sent to bm_Safe_Exit
Err.Raise 0
Else
Dim newVal3 As Variant
newVal3 = Intersect(Target, Range("A9:A29")).Cells(1).Value
Range("A9:A29").ClearContents
Intersect(Target, Range("A9:A29")).Cells(1) = newVal3
End If
End If
Dim j As Integer
With Worksheets("MainSheet").Range("C5")
For j = 0 To 6
If Not CBool(Len(.Offset(0, j).Value)) Then
.Offset(-1, j).Interior.Color = RGB(255, 0, 0)
Else
.Offset(-1, j).Interior.Color = RGB(0, 255, 0)
End If
Next j
End With
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
It isn't clear exactly what worksheet this is running under; I hope it isn't the MainSheet as I've used direct referencing to the cells on that worksheet.
See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals.

Inserting Comment and Color into a cell that satisfies If...Then Statement

So I am basically trying to insert a comment and color the cell that basically meets the criteria that I set in my code. I searched all over but cant seem to find a viable solution.
Here is the code that I have so far and I mentioned in the code below where I would like the color and comment to be. The way I have this macro set up is that it gets "Called" from the Worksheet. I used the Selection_Change function. So I have a range where in one column someone enters data and then whatever data is entered the following macro runs and checks to see if it is within limits.
If it is not within the limits that are set in the excel sheet ("M7" and "M19"), I would like a color to highlight that certain cell and a set comment in that cell. How would I go about this? I really appreciate the help. Thank you!
Also I found a code online and my problem is that when i use the
ActiveCell.AddComment ("Text")
I keep getting an error, and also after I enter my data point and I press enter, the comment goes into the next cell.
Here is the macro that gets called:
Option Explicit
Public Sub OutofControlRestofData()
Dim lRow As Long
Dim lstRow As Long
Dim data As Variant
Dim ul As Variant
Dim ll As Variant
Dim wb As Workbook
Dim ws As Worksheet
With Application
.ScreenUpdating = True
.EnableEvents = True
.DisplayAlerts = True
End With
Set ws = Sheets(2)
ws.Select
lstRow = WorksheetFunction.Max(1, ws.Cells(Rows.Count, "R").End(xlUp).Row)
For lRow = 1 To lstRow
data = Cells(lRow, "E").Value
ul = Range("M7")
ll = Range("M19")
If data > ul Or data < ll Then
If IsNumeric(data) = True And data Like "" = False Then
MsgBox ("There was an Out of Control Point at " & Cells(lRow, "C").Value)
'THIS IS WHERE I THINK THE COMMENTING AND COLOR CODE WOULD BE
End If
End If
Next lRow
End Sub
Also here is the code that Calls the Macro:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("E39:E138")) Is Nothing Then
Run ("OutofControlRestofData")
End If
End Sub
A few things to note.
You should practice using tab to "nest" your If statements. Makes
it clearer to see.
You can go ahead and combine the two Subs. Just make sure you put the code in the Sheet's code page (not in a workbook module).
You don't need a loop if you already have a "Target" as that is the cell (Range) you want to check anyways.
You have defined your Change sub to only work if the data entry is between E39 and E138. Will this always be the case? Consider using the entire column E if you want more flexibility to grow your sheet and data.
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Set ws = Sheets(2)
If Not Intersect(Target, ws.Range("E39:E138")) Is Nothing Then
Dim lRow As Long
Dim lstRow As Long
Dim data As Variant
Dim ul As Variant
Dim ll As Variant
Dim wb As Workbook
Dim ws As Worksheet
With Application
.ScreenUpdating = True
.EnableEvents = True
.DisplayAlerts = True
End With
data = Target.Value
ul = Range("M7").Value
ll = Range("M19").Value
If data > ul Or data < ll Then
If IsNumeric(data) = True And data Like "" = False Then
MsgBox ("There was an Out of Control Point at " & Target.Address)
Target.Interior.Color = RGB(255, 0, 0)
Target.AddComment ("This is an Out of Control Point")
End If
End If
End If
End Sub
Just to be on the safe side, I'd recommend changing your code here to include value:
data = Range("E" & lRow).Value
ul = Range("M7").Value
ll = Range("M19").Value
Then in the spot where you want to do the color/comment stuff:
Range("E" & lRow).Interior.Color = RGB(255, 0, 0)
Range("E" & lRow).AddComment("This is an Out of Control Point")

VBA (Excel): Jump to (or remain) cell in column

I would like to start off with stating that I have virtually no coding experience. I found a VBA snippet online for highlighting an entire selected range (just to as a visual guide):
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
Application.ScreenUpdating = False
' Clear the color of all the cells
Cells.Interior.ColorIndex = 0
With Target
' Highlight the entire column that contain the active cell
.EntireRow.Interior.ColorIndex = 8
End With
Application.ScreenUpdating = True
End Sub
I would like to also have the cursor jump-to column "J". For instance, after performing a search for cells containing the words "strawberry topping" after pressing 'OK' the cell containing that text becomes active and, due to the VBA code, the entire row is highlighted.
The first cell I need to work on is in column "J". Can I also have column J selected along with the row being highlighted?
Thank you so much for your time and would appreciate any help you may have to offer.
My Three cents
If you are using xl2007+ then do not use Target.Cells.Count. Use Target.Cells.CountLarge else you will get an Overflow error if a user tries to select all cells by pressing CTRL + A as Target.Cells.Count can't hold a Long value.
If you want to select the row and the column, you might want to switch off events else you might end up in endless loop.
Since you are working with events, use error handling.
Is this what you are trying?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim Rw As Long, Col As Long
Dim ColName As String
On Error GoTo Whoa
If Target.Cells.CountLarge > 1 Then Exit Sub
Application.ScreenUpdating = False
Application.EnableEvents = False
' Clear the color of all the cells
'Cells.Interior.ColorIndex = 0
With Target
Rw = .Row
Col = .Column
ColName = Split(Cells(, Col).Address, "$")(1)
' Highlight the entire column that contain the active cell
'.EntireRow.Interior.ColorIndex = 8
Range(ColName & ":" & ColName & "," & Rw & ":" & Rw).Select
End With
LetsContinue:
Application.ScreenUpdating = True
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
End Sub