vba code to only highlight contiguous duplicates in one column - vba

I have the following code which highlights contiguous and non-contiguous cells that have the same contents in a single column with different colours. Could this code be modified to highlight only contiguous cells in one column with one colour (e.g. yellow)?
Sub HighlightSameValues()
Dim rngArea As Range
Dim rngCellA As Range
Dim rngCellB As Range
Dim colValue As New Collection
Dim intColor As Integer
Set rngArea = ActiveSheet.Range("F1:F65536")
intColor = 5
On Error Resume Next
For Each rngCellA In rngArea
If rngCellA.Value <> "" Then
Err.Clear
colValue.Add rngCellA.Value, "MB" & rngCellA.Value
If Err = 0 Then
intColor = intColor + 1
For Each rngCellB In rngArea
If rngCellB.Value = rngCellA.Value Then
rngCellB.Interior.ColorIndex = intColor
End If
Next rngCellB
End If
End If
Next rngCellA
End Sub
Assistance with this matter is highly appreciated. Thanks in advance.

The below code will highlight all non-blank and duplicate values for all cells in columns B through F:
Sub HighlightSameValues()
Dim rngArea As Range
Dim rngCellA As Range
Dim rngCellB As Range
'Narrow the search area to only that which has been used
Set rngArea = Intersect(ActiveSheet.UsedRange, ActiveSheet.Range("B:F"))
For Each rngCellA In rngArea
'No point in searching for blank cells or ones that have already been highlighted
If Not rngCellA.Value = vbNullString And Not rngCellA.Interior.Color = vbYellow Then
Set rngCellB = rngArea.Find(What:=rngCellA.Value, LookAt:=xlWhole, After:=rngCellA)
'Check if the value in rngCellA exists anywhere else
If Not rngCellB Is Nothing And Not rngCellB.Address = rngCellA.Address Then
'If another does exist, highlight it and every value that duplicates it
rngCellA.Interior.Color = vbYellow
Do While Not rngCellB.Address = rngCellA.Address
rngCellB.Interior.Color = vbYellow
Set rngCellB = rngArea.Find(What:=rngCellA.Value, LookAt:=xlWhole, After:=rngCellB)
Loop
End If
End If
Next rngCellA
End Sub
To only evaluate contiguous cells in the same column I would modify the code as such:
Sub HighlightSameValues()
Dim rngArea As Range
Dim rngCellA As Range
'Narrow the search area to only that which has been used
Set rngArea = Intersect(ActiveSheet.UsedRange, ActiveSheet.Range("B:F"))
For Each rngCellA In rngArea
'No point in searching for blank cells or ones that have already been highlighted
If Not rngCellA.Value = vbNullString And Not rngCellA.Interior.Color = vbYellow Then
If rngCellA.Offset(-1, 0).Value = rngCellA.Value Then
rngCellA.Offset(-1, 0).Interior.Color = vbYellow
rngCellA.Interior.Color = vbYellow
End If
If rngCellA.Offset(1, 0).Value = rngCellA.Value Then
rngCellA.Offset(1, 0).Interior.Color = vbYellow
rngCellA.Interior.Color = vbYellow
End If
End If
Next rngCellA
End Sub
This is what coding at 2am gets you with no sleep. =)
I was missing the all important Not in (Not rngCellA.Interior.Color = vbYellow). Also I noticed that I forgot to highlight the first cell identified.
I have retested both code segments and both are now working as intended.
Segment 1 will highlight anything that is duplicated within columns B through F.
Segment 2 will highlight anything that is duplicated only that is contiguous and in the same column.
If your data table starts in row 1 (No header) or goes to the last row available on the sheet:
If Not rngCellA.Row = 1 Then
If rngCellA.Offset(-1, 0).Value = rngCellA.Value Then
rngCellA.Offset(-1, 0).Interior.Color = vbYellow
rngCellA.Interior.Color = vbYellow
End If
End If
If Not rngCellA.Row = ActiveSheet.Rows.Count Then
If rngCellA.Offset(1, 0).Value = rngCellA.Value Then
rngCellA.Offset(1, 0).Interior.Color = vbYellow
rngCellA.Interior.Color = vbYellow
End If
End If

Related

Search row for cell color and color a given range if condition is true

I have a code in which if the cells in a given range have the word "Yes" they highlight in red. Since the range is really big I also want to shade in red columns A to I if any cell in the same row is filled in red. Here I leave my code.
Sub ChangeColor()
Set MR = Range("A2:CC127")
For Each cell In MR
If cell.Value = "Yes" Then
cell.Interior.ColorIndex = 3
ElseIf cell.Value = "No" Then
cell.Interior.ColorIndex = 15
End If
Next
End Sub
You simply add a line to color also the corresponding cell in A when coloring your cell
Sub ChangeColor()
Set MR = Range("A2:CC127")
For Each cell In MR
If cell.Value = "Yes" Then
cell.Interior.ColorIndex = 3
cells(cell.row,1).Interior.ColorIndex = 3 ' NEW LINE HERE
ElseIf cell.Value = "No" Then
cell.Interior.ColorIndex = 15
End If
Next
End Sub
The following code also colors the entire column of the input range in light red (and all others in light green) as you mentioned:
Const RNG As String = "B1:L6"
Sub ChangeColor()
Range(RNG).Interior.Color = RGB(191, 255, 191)
For Each col In Range(RNG).Columns
alreadycolored = False
For Each cel In col.Cells
If InStr(1, cel.Text, "yes", vbTextCompare) > 0 Then 'found
If Not alreadycolored Then
col.Interior.Color = RGB(255, 191, 191)
alreadycolored = True
End If
cel.Interior.Color = RGB(127, 0, 0)
End If
Next cel
Next col
End Sub
Please feel free to ask if it is unclear why/how it works.
you could process only relevant cells
Sub ChangeColor()
Dim f As Range
Dim firstAddress As String
With Range("A2:CC127") ' reference your range
Set f = .Find(what:="yes", lookat:=xlWhole, LookIn:=xlValues, MatchCase:=False) ' try and find first cell whose content is "yes"
If Not f Is Nothing Then ' if found
firstAddress = f.Address ' store first found cell address
Do
f.Interior.ColorIndex = 3 'color found cell
Range("A:I").Rows(f.Row).Interior.ColorIndex = 3 ' color columns A to I cells of the same row of found cell
Set f = .FindNext(f) ' try and find next "yes"
Loop While f.Address <> firstAddress ' stop at wrapping back to first found value
End If
End With
End Sub

How to Highlight all the zeros in the table with vba

I have a table that has a header and the first column has student names. the rest of the table has student scores.
I need to highlight all the cells with zeros in them so far this is what i got
Sub HighLightZeros()
Dim region As Range
Set region = ActiveSheet.Range("a1").End(xlDown)
If region.Value = 0 Then
region.Interior.Color = vbYellow
Else
region.Interior.ColorIndex = xlColorIndexNone
End If
End Sub
Also I have to make the macro so that when I add more scores to end on the table that it still highlights all the zero values. I am having trouble in figuring out how to select the entire table.
you could like follows
Sub HighLightZeros()
With ActiveSheet.UsedRange
With .Resize(, .Columns.Count - 1).Offset(, 1) 'reference all "used" cells except column A ones
.Interior.ColorIndex = xlColorIndexNone ' uncolor referenced range
.Replace what:=0, lookat:=xlWhole, replacement:="XXX" ' replace 0's with "XXX"
.SpecialCells(XlCellType.xlCellTypeConstants, xlTextValues).Interior.Color = vbYellow ' color referenced range cells with text content in yellow
.Replace what:="XXX", lookat:=xlWhole, replacement:=0 ' replace "XXX"'s with 0
End With
End With
End Sub
trying to build up some working code from your skeleton in the question, it could be
Sub HighLightZeros2()
Dim region As Range, cell As Range
Set region = Range("a1", Range("A1").End(xlDown))
For Each cell In region
If cell.Value = 0 Then
cell.Interior.Color = vbYellow
Else
cell.Interior.ColorIndex = xlColorIndexNone
End If
Next
End Sub
but it'd scan the first column cells only
This is less efficient than #DisplayName's method but another way. Assumes table is an actual table (List object. Created with Ctrl + T)
Option Explicit
Sub HighlightZeroes()
Dim table As ListObject
Dim currentCell As Range
Set table = ThisWorkbook.Worksheets("Sheet1").ListObjects("Table1") 'change as required
For Each currentCell In table.DataBodyRange
With currentCell
.Interior.ColorIndex = xlColorIndexNone
If .Value = 0 Then .Interior.Color = vbYellow
End With
Next currentCell
End Sub

How can I delete all rows that do not include a specific value?

I have been struggling with this for a few hours and think it's probably time to ask for help.
I have hundreds of spreadsheets that I would like to manually open and then simplify using a macro. Each spreadsheet has a list of hospitals (approx 400) and I would like to limit each one to only showing data about 100 hospitals. The hospitals are identified by a three letter acronym in a column that varies in location (row/column) but is always titled "Code".
So, for example, I would like the macro to delete all rows that do not contain the values "Code", "ABC", "DEF", "GEH", etc.
I am not a regular Excel user and only need to use it to solve this one problem...!
I have tried the code attached but it has a couple of bugs:
It deletes rows that contain "ABC" as well. This problem goes away if I define Range("B1:B100") but not if the range extends across multiple columns (e.g. "A1:E100"). Frustratingly the "Code" column varies across the spreadsheets.
As I want to save 100 hospital codes, it feels as if there ought to be a better way than using the "Or" operator 100 times.
Can anyone help?
Sub Clean()
Dim c As Range
Dim MyRange As Range
LastRow = Cells(Cells.Rows.Count, "D").End(xlUp).Row
Set MyRange = Range("A1:E100")
For Each c In MyRange
If c.Value = "Code" Then
c.EntireRow.Interior.Color = xlNone
ElseIf c.Value = "ABC" Or c.Value = "DEF" Then
c.EntireRow.Interior.Color = vbYellow
Else
c.EntireRow.Delete
End If
Next
End Sub
Try this:
Option Explicit
Sub Clean()
Dim rngRow As Range
Dim rngCell As Range
Dim MyRange As Range
Dim blnDel As Boolean
Dim lngCount As Long
Set MyRange = Range("A1:E8")
For lngCount = MyRange.Rows.Count To 1 Step -1
blnDel = False
For Each rngCell In MyRange.Rows(lngCount).Cells
If rngCell = "ABC" Then
rngCell.EntireRow.Interior.Color = vbRed
blnDel = True
ElseIf rngCell = "DEF" Then
rngCell.EntireRow.Interior.Color = vbYellow
blnDel = True
End If
Next rngCell
If Not blnDel Then Rows(lngCount).Delete
Next lngCount
End Sub
In general, you need to loop through the rows, and then through each cell in every row. In order for the program to remember whether something should be deleted or not on a given row, between the two loops there is a blnDel, which deletes the row, if no DEF or ABC was found.
The problematic part in rows deletion in VBA, is that you should be careful to delete always the correct one. Thus, you should make a reversed loop, starting from the last row.
Option Explicit
Sub Clean()
Dim c As Range, MyRange As Range, DelRng As Range, Code As Range, CodeList As Range
Dim CodeCol As Long, LastRow As Long
''Uncomment the below. I'd put all of your codes into one sheet and then test if the value is in that range
'With CodeListSheet
' Set CodeList = .Range(.Cells(1, 1), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, 1))
'End With
' Update this to point at the relevant sheet
' If you're looking at multiple sheets you can loop through the sheets starting your loop here
With Sheet1
Set Code = .Cells.Find("Code")
If Not Code Is Nothing Then
CodeCol = Code.Column
LastRow = .Cells(Cells.Rows.Count, CodeCol).End(xlUp).Row
Set MyRange = .Range(.Cells(1, CodeCol), .Cells(LastRow, CodeCol))
For Each c In MyRange
If c.Value2 = "Code" Then
c.EntireRow.Interior.Color = xlNone
'' Also uncomment this one to replace your current one
'ElseIf WorksheetFunction.CountIf(CodeList, c.Value2) > 0 Then
ElseIf UCase(c.Value2) = "ABC" Or c.Value2 = "DEF" Then
c.EntireRow.Interior.Color = vbYellow
Else
If DelRng Is Nothing Then
Set DelRng = c
Else
Set DelRng = Union(DelRng, c)
End If
End If
Next c
If Not DelRng Is Nothing Then DelRng.EntireRow.Delete
Else
MsgBox "Couldn't find correct column"
Exit Sub
End If
End With
End Sub

Loop through list and hide blanks

I have a list called "District List" on one tab and a Template that is driven by putting the name of a district into Cell C3. Each District has a wildly varying number of branches (between 1 & 500+ branches depending on the District) so the report template has a lot of blank space in some cases. I came up with this to loop through the District List, copy the Template tab, rename it the District Name, insert the name of the district into Cell C3, and then I have another loop to hide the blank rows.
It works, but it takes forever, like 5 minutes per tab, then after about four tabs, I get an object error at the first like of Sub CreateTabsFromList.
Is there a problem with the code, or is this just a really inefficient way to do this? If so can anyone help with a better method?
Sub HideRows()
Dim r As Range, c As Range
Set r = Range("a1:a1000") 'Sets range well beyond the last possible row with data
Application.ScreenUpdating = False
For Each c In r
If Len(c.Text) = 0 Then
c.EntireRow.Hidden = True 'Hide the row if the cell in A is blank
Else
c.EntireRow.Hidden = False
End If
Next c
Application.ScreenUpdating = True
End Sub
Sub CreateSheetsFromAList()
Dim MyCell As Range, MyRange As Range
Set MyRange = Sheets("District List").Range("A1")
Set MyRange = Range(MyRange, MyRange.End(xlDown))
For Each MyCell In MyRange
Sheets("Template").Copy After:=Sheets(Sheets.Count) 'creates a new worksheet
Range("C3").Value = MyCell.Value 'Pastes value in C3
Sheets(Sheets.Count).Name = MyCell.Value 'renames worksheet
HideRows 'Hides rows where cell in column A is ""
Next MyCell
End Sub
Deleting/Hiding rows, 1 by 1 is the slowest method. Always club them in one range and delete/hide them in one go, also looping through cells is slower than looping array.
Sub HideRows()
Dim lCtr As Long
Dim rngDel As Range
Dim r As Range
Dim arr
Set r = Range("a1:a1000") 'Sets range well beyond the last possible row with data
Application.ScreenUpdating = False
arr = r
For lCtr = LBound(arr) To UBound(arr)
If arr(lCtr, 1) = "" Then
If rngDel Is Nothing Then
Set rngDel = Cells(lCtr, 1) 'harcoded 1 as you are using column A
Else
Set rngDel = Union(rngDel, Cells(lCtr, 1))
End If
End If
Next
If Not rngDel Is Nothing Then
rngDel.EntireRow.Hidden=True
End If
Application.ScreenUpdating = True
End Sub
takes fraction of a second for 1000 rows.

How to delete entire row if two consecutive blanks exist in a column? VBA Excel

I want to delete the row if two consecutive cells in a column are both blank.
Dim rngE As Range
Set rngE = Intersect(Range("E:E"), ActiveSheet.UsedRange)
If del Is Nothing Then
Set del = cell
Else: Set del = Union(del, cell)
End If
End If
Next cell
On Error Resume Next
del.EntireRow.Delete
Here is how it should look when complete:
'this sub routines deletes all consecutive blank rows except one from
'current sheet
'prakash b bajaj
Sub Delete_Consecutive_BlankRows_Except_One()
Dim WorkRng As Range
Dim LastUsedRow As Long
On Error Resume Next
Dim i As Long
Application.ScreenUpdating = False
LastUsedRow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count
Set WorkRng = Range(Cells(1, 1), Cells(LastUsedRow, 1))
For i = LastUsedRow To 1 Step -1
If Application.WorksheetFunction.CountA(WorkRng.Rows(i)) = 0 Then
If Application.WorksheetFunction.CountA(WorkRng.Rows(i - 1)) = 0 Then
WorkRng.Rows(i).EntireRow.Delete XlDeleteShiftDirection.xlShiftUp
End If
End If
Next
Cells(1, 1).Select
Application.ScreenUpdating = True
MsgBox "Done"
End Sub