Conditional Formatting in VBA - excel

I am tying to manage duplicates on an Excel sheet by having the duplicate cells turn red. I put this in a use to sheet protection to keep from editing the conditional formatting for these columns. However, when I move the cell information (by clicking and dragging) the conditional formatting moves from that cell as well. At the end of the day, I do not have duplicate coverage for every cell that I want. Is there some way I can prevent this from happening when I move the cell, or what macro can I put in to take care of this?
I want to do something like this using VBA:
Sub Duplicate()
Dim rngData As Range
Dim cell As Range
Set rngData = Range("P3:P19, P56:P58, P39:P42, P21:P25, P27:P37, P39:P42, P39:P42, P44:P54, M25:M76, B69:B77, B66:E67, B51:B64, H44:H47, D44:D47, H42, H33:H40, D33:D42, H31, D28:D31, H28:H29, D5:D8" & Cells(Rows.Count, "B").End(xlUp).Row)
For Each cell In rngData
cell.Offset(0, 0).Font.Color = vbBlack ' DEFAULT COLOR
' LOCATE DUPLICATE VALUE(S) IN THE SPECIFIED RANGE OF DATA.
If Application.Evaluate("COUNTIF(" & rngData.Address & "," & cell.Address & ")") > 1 Then
cell.Offset(0, 0).Font.Color = vbRed ' CHANGE FONT COLOR TO RED.
End If
Next cell
Set rngData = Nothing
Application.ScreenUpdating = True
End Sub
But I get a "Type Mismatch" error at:
If Application.Evaluate("COUNTIF(" & rngData.Address & "," & cell.Address & ")") > 1 Then
How can I get around this?

As per comment you would need to loop twice:
Sub Duplicate()
Dim rngData As Range
Dim cell As Range
Dim cell2 As Range
Set rngData = Range("P3:P19, P56:P58, P39:P42, P21:P25, P27:P37, P39:P42, P39:P42, P44:P54, M25:M76, B69:B77, B66:E67, B51:B64, H44:H47, D44:D47, H42, H33:H40, D33:D42, H31, D28:D31, H28:H29, D5:D8" & Cells(Rows.Count, "B").End(xlUp).Row)
rngData.Font.Color = vbBlack
For Each cell In rngData
If cell.Font.Color = vbBlack Then
For Each cell2 In rngData
If cell = cell2 And cell.Address <> cell2.Address Then
cell.Font.Color = vbRed
cell2.Font.Color = vbRed
End If
Next
End If
Next
Set rngData = Nothing
Application.ScreenUpdating = True
End Sub

Related

excel vba: fill another column with color if this column is not null

how to write code in vba if I want the another column to fill with yellow color when one column is not null?
For example:
if A1,A3,A8,A100 is not null:
fill background of B1,B3,B8,B100 into yellow color
If a loop is used would be great because my actual case have 7000 cells to fill instead of 4
Option Explicit
Sub ColorColA()
Dim ws As Worksheet
Dim lastrow As Long, cell As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
lastrow = ws.Range("B" & Rows.Count).End(xlUp).Row
For Each cell In ws.Range("A1:A" & lastrow)
If IsEmpty(cell) Then
cell.Offset(0, 1).Interior.Color = RGB(255, 255, 0) 'yellow
Else
cell.Offset(0, 1).Interior.Pattern = xlNone ' remove color
End If
Next
MsgBox lastrow & " rows scanned", vbInformation
End Sub

Highlighting column headings if any of the cells in that column contains red colour

I am new to the macro world, I am trying to write the VBA to highlight the column heading in Red (7th Row is column heading in my sheet) if any of the cells in that column contains red colour if not then the column heading should be highlighted as green. I tried the below code but it is highlighting all the column heading as green.
Dim headers As Range, body As Range
Set headers = ActiveSheet.UsedRange.Rows(7).Columns
Set body = ActiveSheet.UsedRange.Offset(1).Columns
For Each body In Range(Range("A11:BD11"), Range("a" & Rows.Count).End(xlUp))
If body.Interior.Color = vbRed Then
headers.Interior.Color = IIf(found, vbRed, vbGreen)
End If
Next
try this:
Dim body As Range, ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1") 'Change Sheet1 for the name of the sheet
With ws
For Each body In .Range(.Range("A11"), .Range("BD" & .Cells(.Rows.Count, 1).End(xlUp).Row)
If body.Interior.Color = vbRed And _
Not .Cells(1, body.Column).Interior.Color = IIf(found, vbRed, vbGreen) Then 'To avoid doing it each time a cell on the same colour meets the criteria
.Cells(1, body.Column).Interior.Color = IIf(found, vbRed, vbGreen)
End If
Next
End With
You were taking ranges wrong, and when looping a range you don't set the variable before. It will be set on the For loop
You could use:
Option Explicit
Sub test()
Dim cell As Range, rng As Range
With ThisWorkbook.Worksheets("Sheet1")
'Set the range to loop
Set rng = .Range("A11:A" & .Cells(.Rows.Count, "A").End(xlUp).Row)
'Loop range
For Each cell In rng
If cell.Interior.Color = vbRed Then
'If cell interior is red then color Header(Row 7)
.Cells(7, cell.Column).Interior.Color = vbGreen
'Exit the loop after the first match
Exit For
Else
'If there is no match leave no fill
.Cells(7, cell.Column).Interior.ColorIndex = 0
End If
Next cell
End With
End Sub

Set two different ranges and execute code

I'd appreciate any help as I have no experience in vba.
What I'm trying to do
is that at the sheet "data" when the selected cell belongs to the rng1 then
the value for example 020318 at the cell changes to take the format 02/03/18.
At the same time in column ED at each cell there is a sum formula.
When this sum is under zero then a msgbox should pop up
for example
Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
Dim rng1 As Range
Dim rng2 As Range
Dim cell As Range
Set rng1 = ThisWorkbook.Sheets("DATA").Range("I3:I1000,O3:O1000,P3:P1000,AE3:AE1000,AF3:AF1000,AH3:AH1000,AI3:AI1000")
Set rng2 = ThisWorkbook.Sheets("DATA").Range("ED3:ED1000")
If Not Intersect(ActiveCell, Range("I3:I1000,O3:O1000,P3:P1000,AE3:AE1000,AF3:AF1000,AH3:AH1000,AI3:AI1000")) Is Nothing Then
For Each cell In rng1
If cell <> "" Then
If Len(cell) = 6 Then
cell.Value = Format(cell.Value, "00/00/00")
End If
End If
Next cell
For Each cell In rng2
If IsNumeric(cell) = True Then
If cell.Value < 0 Then MsgBox "Τhe salary " & Cells(cell.Row, 2).Value & " before ....is " & Cells(cell.Row, 3).Value & " try more", vbCritical, "XXXXX"
End If
Next cell
End Sub
thanks in advance

Find duplicate macro not working

The following code works on worksheets labeled Walk INs
Sub Find_Duplicatel()
Dim wrkSht As Worksheet 'The worksheet that you're lookin for duplicates in.
Dim rng As Range 'The range containing the duplicates.
Dim Col As Long 'The last column containing data +1
Set wrkSht = ThisWorkbook.Worksheets("Walk INs")
With wrkSht
'Reference to whole data range.
Set rng = .Range("A5:L2003")
'If the sheet is blank an error will be thrown when trying to find the last column.
'This code looks for the last column - you could just set Col to equal the last column number + 1.
On Error Resume Next
Col = 12
Err.Clear
On Error GoTo 0
If Col = 0 Then Col = 0
'Place a COUNTIF formula in the last column.
rng.Offset(, Col).Columns(1).FormulaR1C1 = "=COUNTIF(" & rng.Columns(1).Address(ReferenceStyle:=xlR1C1) & ",RC" & rng.Column & ") & "" duplicates."""
With rng
'Add conditional formatting to first column in range: If the COUNTIF formula is showing >1 then highlight cell.
With .Columns(1)
'This formula is =VALUE(LEFT($M5,FIND(" ",$M5)-1))>1.
'It returns only the number from the duplicate count and checks it is higher than 1.
.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=VALUE(LEFT(" & rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ",FIND("" ""," & _
rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ")-1))>1"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
.FormatConditions(.FormatConditions.Count).Interior.Color = RGB(0, 100, 255)
End With
'Apply filter to your range.
.AutoFilter
.AutoFilter Field:=12, Criteria1:="Yes"
End With
End With
End Sub`
However when I changed Walk INs to VOC_ASST It hangs up on .AutoFilter I am not certain why. Could you inform me what happened & how to fix it. Other than the sheet titles every thing is identical.
You can add some code it to check if there is an AutoFilter already.
If .AutoFilterMode = False Then
.AutoFilter
.AutoFilter Field:=12, Criteria1:="Yes"
End If
I found the following code on the ENCODEDNA website & after modifying it for my worksheet, it works exactly as I expected.
Sub FIND_DUPLICATE()
`Option Explicit
Dim myDataRng As Range
Dim cell As Range
' WE WILL SET THE RANGE (FIRST COLUMN).
Set myDataRng = Range("A1:A" & Cells(Rows.Count, "B").End(xlUp).Row)
For Each cell In myDataRng
cell.Offset(0, 0).Font.Color = vbBlack ' DEFAULT COLOR.
' LOCATE DUPLICATE VALUE(S) IN THE SPECIFIED RANGE OF DATA.
If Application.Evaluate("COUNTIF(" & myDataRng.Address & "," &
cell.Address & ")") > 1 Then
cell.Offset(0, 0).Font.Color = vbRed ' CHANGE FORE COLOR TO
RED.
End If
Next cell
Set myDataRng = Nothing
ErrHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub`
Thank you to the people that have assisted me.

Get start range and end range of a vertically merged cell with Excel using VBA

I need to find out the first cell and the last cell of a vertically merged cell..
Let's say I merge Cells B2 down to B50.
How can I get in VBA the start cell(=B2) and the end cell(=B50)?
Sub MergedAreaStartAndEnd()
Dim rng As Range
Dim rngStart As Range
Dim rngEnd As Range
Set rng = Range("B2")
If rng.MergeCells Then
Set rng = rng.MergeArea
Set rngStart = rng.Cells(1, 1)
Set rngEnd = rng.Cells(rng.Rows.Count, rng.Columns.Count)
MsgBox "First Cell " & rngStart.Address & vbNewLine & "Last Cell " & rngEnd.Address
Else
MsgBox "Not merged area"
End If
End Sub
Below macro goes through all sheets in a workbook and finds merged cells, unmerge them and put original value to all merged cells.
This is frequently needed for DB applications, so I wanted to share with you.
Sub BirlesenHucreleriAyirDegerleriGeriYaz()
Dim Hucre As Range
Dim Aralik
Dim icerik
Dim mySheet As Worksheet
For Each mySheet In Worksheets
mySheet.Activate
MsgBox mySheet.Name & “ yapılacak…”
For Each Hucre In mySheet.UsedRange
If Hucre.MergeCells Then
Hucre.Orientation = xlHorizontal
Aralik = Hucre.MergeArea.Address
icerik = Hucre
Hucre.MergeCells = False
Range(Aralik) = icerik
End If
Next
MsgBox mySheet.Name & " Bitti!!"
Next mySheet
End Sub
Suppose you merged B2 down to B50.
Then, start cell address will be:
MsgBox Range("B2").MergeArea.Cells(1, 1).Address
End cell address will be:
With Range("B2").MergeArea
MsgBox .Cells(.Rows.Count, .Columns.Count).Address
End With
You can put address of any cell of merged area in place of B2 in above code.
Well, assuming you know the address of one of the cells in the merged range, you could just select the offset from that range and get the row/column:
Sub GetMergedRows()
Range("A7").Select 'this assumes you know at least one cell in a merged range.
ActiveCell.Offset(-1, 0).Select
iStartRow = ActiveCell.Row + 1
Range("A7").Select
ActiveCell.Offset(1, 0).Select
iEndRow = ActiveCell.Row - 1
MsgBox iStartRow & ":" & iEndRow
End Sub
The code above will throw errors if the offset row cannot be selected (i.e. if the merged rows are A1 through whatever) so you will want to add error handling that tells the code if it can't offset up, the top rows must be 1 and if it can't go down, the bottom row must be 65,536. This code is also just one dimensional so you might want to add the x-axis as well.
If you want the cell references as strings, you can use something like this, where Location, StartCell, and EndCell are string variables.
Location = Selection.Address(False, False)
Colon = InStr(Location, ":")
If Colon <> 0 Then
StartCell = Left(Location, Colon - 1)
EndCell = Mid(Location, Colon + 1)
End If
If you want to set them as ranges, you could add this, where StartRange and EndRange are Range objects.
set StartRange = Range(StartCell)
set EndRange = Range (EndCell)
If you intend to loop through the merged cells, try this.
Sub LoopThroughMergedArea()
Dim rng As Range, c As Range
Set rng = [F5]
For Each c In rng.MergeArea
'Your code goes here
Debug.Print c.Address'<-Sample code
Next c
End Sub

Resources