Highlight cell if greater than today - excel

I'm trying to highlight cells that have a date greater than today's date.
Column H is formatted as Date.
I have the following:
Sub Test()
Dim lrow As Long
lrow = Cells(Rows.Count, 1).End(xlUp).Row
Columns("H:H").EntireColumn.AutoFit
If Range("H2:H" & lrow).Value > Date Then Cell.Interior.Color = vbYellow
End Sub
I get a "Type Mismatch" error.

Range("H2:H" & lrow).Value will be a 2D array (the Value of a Range is always a 2D array if more than a single cell is involved); you're getting a type mismatch error because you can't compare a 2D array to a Date; if you can't use a conditional formatting, you need to compare the individual array subscripts.
Last thing you want to do is to iterate each individual cells (otherwise your next question will be "how do I make this loop run faster?"). Get that array into a Variant, and iterate that array - since it's only 1 column, make it a 1D array with Application.Transpose:
Dim values As Variant
values = Application.Transpose(Range("H2:H" & lastRow).Value)
Dim i As Long, current As Long
For i = LBound(values) To UBound(values)
current = i + 1 'array would be 1-based, so to start at row 2 we need to offset by 1
If values(i) > Date Then
ActiveSheet.Cells(current, 8).Interior.Color = vbYellow
End If
Next
That way you only hit the worksheet when you have to.

In response to #MatthieuGuindon's suggestion to #CharlesPL's answer, here's some code that does the conditional formatting. I've set it so it highlights dates that are after the day you run it as a bright yellow.
Option Explicit
Sub setCondFormat()
Dim lrow As Long
lrow = ActiveSheet.Range("H" & ActiveSheet.Rows.Count).End(xlUp).Row
With Range("H2:H" & lrow)
.FormatConditions.Delete
.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=H2>TODAY()"
With .FormatConditions(.FormatConditions.Count)
.SetFirstPriority
With .Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
End With
End With
End With
End Sub

Use conditional formatting! As the name suggests, this is build for that!
Microsoft blog post on date conditional formating

I would recommend iterating over the range of cells and testing each cell individually. Please see below.
Dim rng As Range, cell As Range
Set rng = Range("H:H")
For Each cell In rng
If cell.Value > Date Then cell.Interior.Color = vbYellow
Next cell

Related

Copy and paste if one cell is blank and the other is not

So data gets pasted in to column B as the code keeps running it'll do a condition check to see there's any values in column B and paste a value in to the adjacent column A. I need to make it so it does two condition checks:
If there's values in column b, but then to check if there's values in column A before pasting so it doesn't overwrite different data that's been pasted already.
For Each Cell In y.Sheets("Compiled").Range("A:B")
If Range("B:B").Value <> "" And Range("A:A").Value = "" Then
Cell.Offset(0, -1).PasteSpecial xlPasteValues
End If
Next
You were close, don't try to loop over a multiple column range:
Sub Test()
For Each Cell In y.Sheets("Compiled").Range("B:B")
If Cell.Value <> "" And Cell.Offset(0, -1).Value = "" Then
Cell.Offset(0, -1).Value = Cell.Value
End If
Next
End Sub
NOTE: You are looping through every cell in Range("B:B") which is probably unnecessary. It'd be better if you use a lastrow value, or a static range like Range("B2:B1000"). Or you could use a criteria to exit your loop like If Cell.Value = "" Then Exit For.
Here's a version of the code that implements the lastrow value that dwirony mentioned in their answer. This also throws everything in arrays, so it might go a bit faster if you have a really large dataset.
Option Explicit
Sub test()
Dim ACol As Variant
Dim BCol As Variant
Dim lastrow As Long
Dim i As Long
lastrow = Range("B:B").Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).row
BCol = Range("B1:B" & lastrow).Value
ACol = Range("A1:A" & lastrow).Value
For i = LBound(BCol) To UBound(BCol)
If IsEmpty(ACol(i, 1)) And Not IsEmpty(BCol(i, 1)) Then
ACol(i, 1) = BCol(i, 1)
End If
Next i
Range("A1:A" & lastrow).Value = ACol
End Sub

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.

Conditional Formatting in VBA

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

Color formatting of Rows based on input values for a cell

There is some data in the worksheet, which includes a column for time. Time Range is provided as an Input to format the color of the time cells within that time range. Color formatting of the rows containing those cells is also desired but is not observed in the output. It is to mention that the start time or end time provided as input is sometimes not matching value of any time cell.
Attached is the code and is not giving desired output.
Any kind of help will be appreciated.
Dim ws As Worksheet
Dim timeRange As Range
Set ws = Sheets("Worksheet") 'Name of my worksheet goes here.
Set timeRange = ws.Range("D:D")
'input the lower limit and the upper limit of the search range
Dim Start_Time As Variant
Dim End_Time As Variant
Start_Time = InputBox(prompt:="Enter the Start_Time(hh:mm:ss.000)")
End_Time = InputBox(prompt:="Enter the End_Time(hh:mm:ss.000)")
timeRange.FormatConditions.Add Type:=xlCellValue, Operator:=xlBetween, _
Formula1:=Start_Time, Formula2:=End_Time
timeRange.FormatConditions(timeRange.FormatConditions.Count).SetFirstPriority
With timeRange.FormatConditions(1).Font
.Color = -16383844
.TintAndShade = 0
End With
With timeRange.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 13551615
.TintAndShade = 0
End With
timeRange.FormatConditions(1).StopIfTrue = False
'Loop to format the rows that contains those time values
Dim Range_Search As String
For Each c In Range("D:D")
If c.Interior.Color = 13551615 Then
Range_Search = "A" & c.Row & ":" & "H" & c.Row
ws.Range(Range_Search).Interior.Color = 13551615
End If
Next c
The final loop in your code won't work. You need to change it to:
For Each c In Range("D:D")
If c.Interior.Color = 13551615 Then
Range_Search = "A" & c.Row & ":" & "H" & c.Row
Range(Range_Search).Select
Selection.Interior.Color = 13551615
End If
Next c
I'm not sure what the "Let" is supposed to do in your statement, but it's not necessary. Also, you need to get the Row from cell c, not just c.
To make this even better, I would reference the cells by the worksheet as this will prevent possible problems from selecting different worksheets:
Dim ws As worksheet
Dim timeRange As Range
Set ws = Sheets("mySheet") 'Obviously change this to your sheet name
Set timeRange = ws.Range("D:D")
Then replace "Selection." with "timeRange." in your code, so
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlBetween, _
Formula1:=Start_Time, Formula2:=End_Time
becomes:
timeRange.FormatConditions.Add Type:=xlCellValue, Operator:=xlBetween, _
Formula1:=Start_Time, Formula2:=End_Time
Then change your final loop to do something similar:
For Each c In timeRange
If c.Interior.Color = 13551615 Then
ws.Range("A" & c.Row & ":" & "H" & c.Row).Interior.Color = 13551615
End If
Next c
Selecting cells is not efficient and can cause problems if something else inadvertently gets selected while you are trying to run the code.
I figured it out. Thanks to OpiesDad for help.
Basically the format condition color is not recognize by the vba until you add DisplayFormat. before the interior.color command. so something like.
For Each c In timeRange
If c.**DisplayFormat**.Interior.Color = 13551615 Then
ws.Range("A" & c.Row & ":" & "H" & c.Row).Interior.Color = 13551615
End If
Next c

Finding Last Row With Data With Formatted Cells Below

I need to identify, (by highlighting), when there is data missing from a certain column. In other words, I have a column of data specifying a country. Above this column there are blanks and below this column there are blanks. The topmost row of the data stays the same (the data always starts at row 4), but the bottom is variable. Also, due to the way this data is output, there seems to be 3 or so rows of blank but formatted cells at the bottom of the table which excel recognizes as 'used'. Here is my code thus far:
With ThisWorkbook.ActiveSheet
LastRowCountry = .Range("H" & .Rows.Count).End(xlUp).Row
End With
The Piece of code that is specific to my goal is:
'Search for blank Geo tags
With ThisWorkbook.ActiveSheet
If IsEmpty(Cells(LastRowCountry, "H")) = True Then
'Highlight Columns
With Range(Cells(4, "H"), Cells(LastRow, "H")).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent2
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
End With
End If
End With
In this form it fails to recognize any blanks in the column and never highlights. Before this I preceded the code with:
With ActiveSheet.Cells.SpecialCells(xlLastCell)
LastRow = .Row
LastCol = .Column
End With
which always highlighted the column (I assume because it was detecting the blank but formatted cells hanging off the bottom of the table. Thanks in advance to anyone who takes this on.
Steve
I have tried this here and it works
Sub CheckForEmptyCells(Byref sh as Worksheet, ByRef col as string)
Dim lastR&
lastR = sh.Range(col & Rows.Count).End(xlUp).Row
Dim r As Range: Set r = Range(col & "5:" & col & lastR)
If Not r.Find("") Is Nothing Then
With r.Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent2
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
End With
End If
End Sub
Note: this routine checks only if the given column has empty cells in between its own first and last cells. If the goal is to check the whole column (last cell of the column might itself be empty), then you should use instead: lastR = sh.UsedRange.Rows.Count

Resources