Trying to find unique IDs with all of the values it qualifies for in excel - excel

To be quite honest I am not entirely sure how to describe what it is I am trying to accomplish? But, here it goes anyway. I have an excel sheet containing one column of IDs and a second column of values that need to be associated to the first column. The problem is that the IDs in column A contain duplicates, which is okay because one ID can qualify for multiple values. What I need is to have a third column pull back the unique id, and a fourth column pull back a semi-colon delimited list of all of the values the id qualifies for. Hopefully the attached image makes sense? For what it's worth I have tried every formula I can think of, and I really know nothing about macros, which is what I am thinking needs to be implemented.

Try below code :
Sub sample()
Dim lastRowA As Long, lastRowC As Long
lastRowA = Range("A" & Rows.Count).End(xlUp).Row
lastRowC = Range("C" & Rows.Count).End(xlUp).Row
Dim rng As Range, cell As Range
Set rng = Range("C2:C" & lastRowC)
Dim rngSearch As Range
Set rngSearch = Range("A1:A" & lastRowA)
Dim rngFind As Range
Dim firstCell As String
For Each cell In rng
Set rngFind = rngSearch.Find(What:=cell, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)
If Not rngFind Is Nothing Then
temp = rngFind.Offset(0, 1)
firstCell = rngFind.Address
Do While Not rngFind Is Nothing
Set rngFind = rngSearch.FindNext(After:=rngFind)
If rngFind.Address <> firstCell Then
temp = temp & ";" & rngFind.Offset(0, 1)
Else
Set rngFind = Nothing
End If
Loop
End If
cell.Offset(0, 1) = temp
Next
End Sub

Here's an alternative approach, that has several advantages
it builkds the list of unique sku's
it clear old data from columns C:D
it will run much faster than looping over a range
Sub Demo()
Dim rngA As Range, rng as Range
Dim datA As Variant
Dim i As Long
Dim sh As Worksheet
Dim dic As Object
Set sh = ActiveSheet ' can change this to your worksheet of choice
Set dic = CreateObject("Scripting.Dictionary")
With sh
' Get data from columns A:B into a variant array
Set rngA = .Range(.Cells(2, 2), .Cells(.Rows.Count, 1).End(xlUp))
datA = rngA
' Create list of unique sku's and built value strings
For i = 1 To UBound(datA)
If dic.Exists(datA(i, 1)) Then
dic(datA(i, 1)) = dic(datA(i, 1)) & ";" & datA(i, 2)
Else
dic.Add datA(i, 1), datA(i, 2)
End If
Next
' Clear exisating data from columns C:D
Set rng = .Range(.Cells(2, 4), .Cells(.Rows.Count, 3).End(xlUp))
If rng.Row > 1 Then
rng.Clear
End If
' Put results into columns C:D
.Range(.Cells(2, 3), .Cells(dic.Count + 1, 3)) = Application.Transpose(dic.Keys)
.Range(.Cells(2, 4), .Cells(dic.Count + 1, 4)) = Application.Transpose(dic.Items)
End With
End Sub
How to add this:
Start the VBS editor (Alt+F11 from excel)
show project explorer, if its not already visible (Ctrl+R)
add a Module (right click on your workbook, Insert, Module)
open the module (dbl click)
Add Option Explicit as the first line, if not already there
copy paste this code into module
How to run it, from Excel
activate the sheet with your data
open macro dialog (Alt+F8)
select Demo from list and run

Related

VBA why do I have blank rows after appending tables?

VBA newb here.
Essentially, I'm collecting weekly compliance records for week over week data.
My main issue is that I have a queried table that is dynamic and on a good week it's empty.
I would like to be able to pull the contents of this table and paste them to the first empty row below a static table that contains year to date data.
This step is an easy one to accomplish manually, but I'm looking to automate for the sake of handing this report off to my less-than-tech-savvy team members.
This question: How to copy and paste two separate tables to the end of another table in VBA? has given me most of what I'm using so far. I've swapped a few of their values and declarations to be relevant to my sheet and ranges, but for the most part it's copy/paste with the listed solution for "Destination: ="
For the most part, this block does the exact thing I'm after:
(I've commented out GCC's second range, but intend to utilize it once this one's settled.)
Sub Inv_Copy_Paste()
Dim TC As Worksheet
'Dim Chart As Worksheet
Dim lr2 As Long
Set TC = Worksheets("TC Data Dump")
'Set Chart = Worksheets("Inventory for Charts")
lr2 = TC.Cells(Rows.Count, 1).End(xlUp).Row
With TC
.Range("O2", ("W2" & .Range("O" & Rows.Count).End(xlUp).Row)).Copy Destination:=TC.Cells(Rows.Count, 1).End(xlUp).Offset(1)
'.Range("K2", ("S2" & .Range("K" & Rows.Count).End(xlUp).Row)).Copy Destination:=Chart.Range("A" & lr2 + 1)
End With
End Sub
The one exception that I'm running into is that once the code copies populated data over, it adds a handful of blank lines below the data:
20 Blank Rows
Is this something I'm overlooking in the code that's already here?
I'll grant that I barely understand what the code is doing in the With TC portion, so any additional context would be greatly appreciated.
Bonus question: Will I need a separate Sub/Worksheet when I attempt to copy another dynamic query table to a second static table?
Dealing With Blanks
If your data is in Excel tables, you should use their methods and properties.
If you don't wanna, you'll need to write special, often complicated codes.
End(xlUp) will only go up to the last row (cell) in the table. If there are empty or blank rows at the bottom, they will also be copied.
The Find method with xlFormulas will go up to the last non-empty row while with xlValues, it will go up (further) to the last non-blank row.
Initial
Result
Main
Sub InvCopyPaste()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim wsTC As Worksheet: Set wsTC = wb.Sheets("TC Data Dump")
Dim wsInv As Worksheet: Set wsInv = wb.Sheets("Inventory for Charts")
Dim srg As Range, drg As Range
' Source: 'wsTC' to Destination: 'wsTC'
Set srg = RefNonBlankRange(wsTC.Range("O2:W2"))
If Not srg Is Nothing Then
Set drg = RefFirstNonBlankRowRange(wsTC.Range("A2") _
.Resize(, srg.Columns.Count)).Resize(srg.Rows.Count)
drg.Value = srg.Value ' for only values (most efficient)
'srg.Copy drg ' instead: for values, formulas and formats
Debug.Print "Copied from " & srg.Address & " to " & drg.Address & "."
End If
' Source: 'wsTC' to Destination: 'wsInv'
Set srg = RefNonBlankRange(wsTC.Range("K2:S2"))
If Not srg Is Nothing Then
Set drg = RefFirstNonBlankRowRange(wsInv.Range("A2") _
.Resize(, srg.Columns.Count)).Resize(srg.Rows.Count)
drg.Value = srg.Value ' for only values (most efficient)
'srg.Copy drg ' instead: for values, formulas and formats
Debug.Print "Copied from " & srg.Address & " to " & drg.Address & "."
End If
End Sub
The Help
Function RefNonBlankRange( _
ByVal FirstRowRange As Range) _
As Range
With FirstRowRange
Dim cel As Range: Set cel = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlValues, , xlByRows, xlPrevious)
If Not cel Is Nothing _
Then Set RefNonBlankRange = .Resize(cel.Row - .Row + 1)
End With
End Function
Function RefFirstNonBlankRowRange( _
ByVal FirstRowRange As Range) _
As Range
Dim rg As Range: Set rg = FirstRowRange.Rows(1)
With rg
Dim cel As Range: Set cel = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlValues, , xlByRows, xlPrevious)
If Not cel Is Nothing Then Set rg = .Offset(cel.Row - .Row + 1)
End With
Set RefFirstNonBlankRowRange = rg
End Function
Debug.Print Results in the Immediate window (Ctrl+G)
Copied from $O$2:$W$6 to $A$4:$I$8.
Copied from $K$2:$S$6 to $A$6:$I$10.
Firstly, the row count is counting the number of lines in the first column.
-lr2 = TC.Cells(Rows.Count, 1).End(xlUp).Row
Here.
Rather than counting the number of rows in the tablese you're trying to copy.
If you change the number 1 in this line to the column you are copying. I think its "O" which would be 15.
Then I'm afraid you'd have to redefine the lr2 for the second table or make another variable for it.
lr3 = TC.Cells(Rows.Count, 11).End(xlUp).Row '11 for the k column
Please let me know if this helps.
Sub oddzac()
Dim RowCount As Integer
ActiveSheet.Range("O2", Cells(Range("W" & Rows.Count).End(xlUp).Row, "W")).Copy Cells(Range("A" & Rows.Count).End(xlUp).Row, 1)
ActiveSheet.Range("K2", Cells(Range("S" & Rows.Count).End(xlUp).Row, "S")).Copy Cells(Range("A" & Rows.Count).End(xlUp).Row + 1, 1)
End Sub
This more what you're looking for?
Another forum responded with this solution:
Sub TC_Copy_Paste()
Dim TC As Worksheet, RowNum As Long
'
Set TC = Worksheets("TC Data Dump")
On Error Resume Next
With TC.Range("P3").ListObject
RowNum = Application.WorksheetFunction.CountA(.ListColumns(1).DataBodyRange)
.DataBodyRange.Cells(1, 1).Resize(RowNum, 9).Copy Destination:=TC.Cells(Rows.Count, 5).End(xlUp).Offset(1)
End With
With TC.Range("AJ3").ListObject
RowNum = Application.WorksheetFunction.CountA(.ListColumns(1).DataBodyRange)
.DataBodyRange.Cells(1, 1).Resize(RowNum, 9).Copy Destination:=TC.Cells(Rows.Count, 26).End(xlUp).Offset(1)
End With
End Sub
Again, I'm not sure why this works and the other doesn't but I wanted to share the end result.

Excel button that shows the elements of the previous row

I used the code from https://stackoverflow.com/a/34454648/11447549
I got it to use dynamic column length and take values from a cell in another sheet. This code currently gives me the element of the next row(i.e., A1 -> click -> A2) and then if the last element, it returns to the first one.
Know I need this to go backward. It needs to go from bottom to up and if it hits the first one, go to the last one. I tried my reversing the parameters of Rangebut got an error.
Any ideas or hints will be very useful.
Sub Button8_Click()
Set wsh = ActiveWorkbook.Worksheets("Sheet1")
Column = wsh.Range("A" & Rows.Count).End(xlUp).Row
If IsError(Application.Match(Range("B2").Value, wsh.Range(wsh.Cells(2, 1), wsh.Cells(Column, 1)), 0)) Then
Range("B2").Value = wsh.Cells(2, 1).Value
ElseIf Application.Match(Range("B2").Value, wsh.Range(wsh.Cells(2, 1), wsh.Cells(Column, 1)), 0) = wsh.Range(wsh.Cells(2, 1), wsh.Cells(Column, 1)).Cells.Count Then
Range("B2").Value = wsh.Cells(2, 1).Value
Else
Range("B2").Value = wsh.Cells(2, 1).Offset(Application.Match(Range("B2").Value, wsh.Range(wsh.Cells(2, 1), wsh.Cells(Column, 1)), 0), 0).Value
End If
End Sub
If you are absolutely certain there are no duplicates, you can use the Range.Find method, which is a built-in VBA function.
Option Explicit
Private Sub CommandButton1_Click()
Dim rDest As Range, rCol As Range, C As Range
Dim wsSrc As Worksheet
Dim myRow As Long, LR As Long
Set wsSrc = Worksheets("sheet2") 'or whatever
With wsSrc
Set rCol = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With
Set rDest = Cells(2, 2)
With rCol
Set C = .Find(what:=rDest, after:=rCol(1, 1), LookIn:=xlValues, _
lookat:=xlWhole, searchorder:=xlByRows, searchdirection:=xlPrevious)
If Not C Is Nothing Then
If C.Row = 1 Then Set C = rCol(rCol.Rows.Count + 1, 1)
rDest = C.Offset(-1, 0)
Else
rDest = rCol(rCol.Rows.Count, 1)
End If
End With
End Sub
I find your code cumbersome (or perhaps not complicated enough :-)). Here is another version. It works on double-click on A1. It needs to be installed in the code sheet of the worksheet on which you want the action.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Const Rstart As Long = 2 ' set as required
Dim Rng As Range
Dim Rcount As Long
Dim R As Variant
With Target
If .Address = Range("A1").Address Then
' from Rstart to last row in column B
Set Rng = Range(Cells(Rstart, "B"), Cells(Rows.Count, "B").End(xlUp))
Rcount = Rng.Cells.Count
On Error Resume Next
R = Application.Match(.Value, Rng, 0)
If Err Then
R = Rcount
Else
R = R + 1
If R > Rcount Then R = 1
End If
.Value = Rng.Cells(R).Value
.Offset(1).Select
End If
End With
End Sub
Once you understand the code it is both easier to read and to modify. For example, to change the cell A1, all you need to do is to change the reference to A1 in this line of code. If .Address = Range("A1").Address.
Your list of choices need not start in row 1. Const Rstart now has a value of 2, meaning your list starts in row 2, allowing for a column caption, but you can change it to 1, if you prefer, or 3.
The line of code Set Rng = Range(Cells(Rstart, "B"), Cells(Rows.Count, "B").End(xlUp)) sets the range of your list to column B. Change the two "B"s to move it to another column. It finds the end dynamically. The beginning is taken from the setting of Rstart.
Finally, there is no button. But if you prefer a button to double-click it will be easy to adapt the code to the use of one.
What would be the good of "finally" if there weren't one more word to say. This code can easily be adapted to have different triggers referring to different lists on the same sheet. For example, you could move the list now in column B to be below A1. In column B you could have another list that responds to a double-click in B1 etc.

Comparing all cells in 2 different sheets and finding mismatch list isn't working

I have a data set with columns from A to AZ. I want to find if any cell value in Columns A & B is found in Columns AA:AZ and I want a list of those unique not found values from all the compared columns.
What I did first is create 2 new sheets to separate the comparison. 1st sheet (SKUReference) which is copied from column A & B. Second sheet is (SKUNewList) which is copied from AA till AZ. I created a 3rd sheet (NotFoundSKU) to have the desired output which is the Not Found values from the comparison.
The data in the 1st sheet (SKUReference) looks like below :
The data in the 2nd sheet (SKUNewList) looks like below :
The issue I'm facing is : 1- the code isn't finding the Mismatches. 2- It's not storing the unique mismatches correctly. 3- It's not generating those mismatches in the 3rd sheet (NotFoundSKU).
Sub yg23iwyg()
Dim wst As Worksheet
Dim wet As Worksheet
Set wst = Worksheets.Add
Set wet = Worksheets.Add
Set wrt = Worksheets.Add
wst.Name = "SKUReference"
wet.Name = "SKUNewList"
wrt.Name = "NotFoundSKU"
With Worksheets("Sheet1")
.Range(.Cells(1, "A"), .Cells(.Rows.Count, "B").End(xlUp)).Copy _
Destination:=wst.Cells(1, "A")
.Range(.Cells(1, "AA"), .Cells(.Rows.Count, "AZ").End(xlUp)).Copy _
Destination:=wet.Cells(1, "A")
'alternate with Union'ed range - becomes a Copy, Paste Special, Values and Formats because of the union
.Range("AA:AZ").Copy _
Destination:=wet.Cells(1, "A")
End With
Dim wksMaster As Worksheet, wksSearch As Worksheet
Dim rngMaster As Range, rngSearch As Range
Set wksMaster = Sheets("SKUReference")
Set wksSearch = Sheets("SKUNewList")
With wksMaster
Set rngMaster = .Range("A1:B100" & .Range("A1").SpecialCells(xlCellTypeLastCell).Row)
End With
With wksSearch
Set rngSearch = .Range("A1:Y100" & .Range("A1").SpecialCells(xlCellTypeLastCell).Row)
End With
With rngMaster
For Each cll In rngSearch
Set c = .Find(cll.Value2, LookIn:=xlValues)
If c Is Nothing Then
'MsgBox cll.Value2 & " not found in the SKU Reference List."
Sheets("NotFoundSKU").Range("A1") = cll.Value2
End If
Next
End With
End Sub
Try this, which incorporates comments above (to set rngMaster and rngSearch) and will list values not found in a list going down by finding the first empty cell.
Sub yg23iwyg()
Dim wst As Worksheet
Dim wet As Worksheet, c as range, cll as range
Set wst = Worksheets.Add
Set wet = Worksheets.Add
Set wrt = Worksheets.Add
wst.Name = "SKUReference"
wet.Name = "SKUNewList"
wrt.Name = "NotFoundSKU"
With Worksheets("Sheet1")
.Range(.Cells(1, "A"), .Cells(.Rows.Count, "B").End(xlUp)).Copy _
Destination:=wst.Cells(1, "A")
.Range(.Cells(1, "AA"), .Cells(.Rows.Count, "AZ").End(xlUp)).Copy _
Destination:=wet.Cells(1, "A")
'alternate with Union'ed range - becomes a Copy, Paste Special, Values and Formats because of the union
.Range("AA:AZ").Copy _
Destination:=wet.Cells(1, "A")
End With
Dim wksMaster As Worksheet, wksSearch As Worksheet
Dim rngMaster As Range, rngSearch As Range
Set wksMaster = Sheets("SKUReference")
Set wksSearch = Sheets("SKUNewList")
With wksMaster
Set rngMaster = .Range("A1:B" & .Range("B" & .Rows.Count).End(xlUp).Row)
End With
With wksSearch
Set rngSearch = .Range("A1:Y" & .Range("Y" & .Rows.Count).End(xlUp).Row)
End With
With rngMaster
For Each cll In rngSearch
Set c = .Find(cll.Value2, LookIn:=xlValues) 'i would consider adding more parameters here
If c Is Nothing Then
Sheets("NotFoundSKU").Range("A" & Rows.Count).End(xlUp)(2).Value = cll.Value2
End If
Next
End With
End Sub

Excel - VBA - Search for a specific value within a cell

Is it possible to search for a specific value in a column?
I want to be able to search all of the cells in column "B" and look for the 'word' "pip" in it (without being case sensitive). I've got everything else, just need to know if this is possible or how it can be done.
My Current code looks as follows:
Sub A()
ActiveSheet.Name = "Data"
Dim ws As Worksheet
Set ws = Sheets("Data")
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Sheets.Add(After:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws1.Name = "pip"
ws.Activate
Row = 2
Dim i As Integer
For i = 1 To 10
If (Cells(i, 2).Value = (HAS pip IN IT) Then 'This is the part that i'm struggling with
Copied = ws.Range(Cells(i, 1), Cells(i, 17)).Value 'If possible, this would cut and paste so it deleted the original
ws1.Activate
ws1.Range(Cells(Row, 1), Cells(Row, 17)).Value = Copied
Row = Row + 1
ws.Activate
End If
Next i
End Sub
Edit: Just to clarify, the value in column B will never just be "pip". It will be a full sentence but if it contains "pip" then i would like the IF function to work.
Find and FindNext work nicely (and quickly!)
'...
Dim copyRange As Range
Dim firstAddress As String
Set copyRange = ws.Range("B1:B1500").Find("pip", , , xlPart)
If Not copyRange Is Nothing Then
firstAddress = copyRange.Address
Do
ws2.Range(Cells(Row, 1), Cells(Row, 17)).Value = Intersect(copyRange.EntireRow, ws.Columns("A:Q")).Value
Row = Row + 1
Set copyRange = Range("B1:B10").FindNext(copyRange)
Loop While copyRange.Address <> firstAddress
End If
'...

VBA Find Next Occurrence

Hey I'm currently writing a macro in VBA (which I'm quite new at). The macro looks at a spreadsheet and finds specific column headers. It then clears the contents of any cell containing a zero. This part of my code works exactly how I want, the only issue is that it does not hand multiple occurrences of the column header...so it finds the first header, clears the contents, and ignores the second occurrence. I have tried multiple avenues whether it be looping to find it or using the .FindNext function. Any help would be appreciated. Thank you! My code is posted below:
Sub DeleteRows2()
Application.ScreenUpdating = True
Dim lastrow As Long
With ActiveSheet
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
'~~>Start of First Instance
'~~>dim variables and set initial values
Dim delaymaxheader As Range
Set delaymaxheader = Worksheets(ActiveSheet.Name).Range("A4:Z4").Find(what:="DELAY Spec Max", LookAt:=xlWhole, MatchCase:=False)
Dim delaymaxcolumn As Range
Set delaymaxcolumn = Range(Cells(5, delaymaxheader.Column), Cells(lastrow, delaymaxheader.Column))
'Set delaymaxcolumn = Range(delaymaxheader.Offset(1, 0), delaymaxheader.End(xlDown))
'~~>dim variables and set initial values
Dim delayminheader As Range
Set delayminheader = Worksheets(ActiveSheet.Name).Range("A4:Z4").Find(what:="DELAY Spec Min", LookAt:=xlWhole, MatchCase:=False)
Dim delaymincolumn As Range
Set delaymincolumn = Range(Cells(5, delayminheader.Column), Cells(lastrow, delayminheader.Column))
'Set delaymincolumn = Range(delayminheader.Offset(1, 0), delayminheader.End(xlDown))
'~~>dim variables and set initial values
Dim phasemaxheader As Range
Set phasemaxheader = Worksheets(ActiveSheet.Name).Range("A4:Z4").Find(what:="PHASE Spec Max", LookAt:=xlWhole, MatchCase:=False)
Dim phasemaxcolumn As Range
Set phasemaxcolumn = Range(Cells(5, phasemaxheader.Column), Cells(lastrow, phasemaxheader.Column))
'Set phasemaxcolumn = Range(phasemaxheader.Offset(1, 0), phasemaxheader.End(xlDown))
'~~>dim variables and set initial values
Dim phaseminheader As Range
Set phaseminheader = Worksheets(ActiveSheet.Name).Range("A4:Z4").Find(what:="PHASE Spec Min", LookAt:=xlWhole, MatchCase:=False)
Dim phasemincolumn As Range
Set phasemincolumn = Range(Cells(5, phaseminheader.Column), Cells(lastrow, phaseminheader.Column))
'Set phasemincolumn = Range(phaseminheader.Offset(1, 0), phaseminheader.End(xlDown))
'~~>Loop to delete rows with zero
'~~>Dim delaycount(5 To lastrow) As Integer
For i = 5 To lastrow
If Cells(i, delaymaxheader.Column) = 0 Then
Cells(i, delaymaxheader.Column).ClearContents
End If
If Cells(i, delayminheader.Column) = 0 Then
Cells(i, delayminheader.Column).ClearContents
End If
If Cells(i, phasemaxheader.Column) = 0 Then
Cells(i, phasemaxheader.Column).ClearContents
End If
If Cells(i, phaseminheader.Column) = 0 Then
Cells(i, phaseminheader.Column).ClearContents
End If
Next i
End Sub
You need to use the FindNext method to keep going (https://msdn.microsoft.com/en-us/library/office/ff839746.aspx)
LastRow is only the last row of column A though - what happens if another column goes further?
Also Worksheets(ActiveSheet.Name).Range("A4:Z4") is the same as ActiveSheet.Range("A4:Z4").
Public Sub DeleteRows()
Dim colAllRanges As Collection
Dim colHeadings As Collection
'Declared as variants as they're used to step through the collection.
Dim vHeading As Variant
Dim vRange As Variant
Dim vCell As Variant
Dim rDelayMaxHeader As Range
Dim sFirstAddress As String
Dim lLastRow As Long
With ActiveSheet
lLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Set colAllRanges = New Collection
Set colHeadings = New Collection
colHeadings.Add "DELAY Spec Max"
colHeadings.Add "DELAY Spec Min"
colHeadings.Add "PHASE Spec Max"
colHeadings.Add "PHASE Spec Min"
For Each vHeading In colHeadings
With ActiveSheet.Range("A4:Z4")
'Find the first instance of the heading we're looking for.
Set rDelayMaxHeader = .Find(What:=vHeading, LookIn:=xlValues, LookAt:=xlWhole)
If Not rDelayMaxHeader Is Nothing Then
sFirstAddress = rDelayMaxHeader.Address
Do
'Resize the range from heading to last row and add it to the collection.
colAllRanges.Add rDelayMaxHeader.Resize(lLastRow - rDelayMaxHeader.Row + 1, 1)
'Find the next occurrence.
Set rDelayMaxHeader = .FindNext(rDelayMaxHeader)
'Keep going until nothings found or we loop back to the first address again.
Loop While Not rDelayMaxHeader Is Nothing And rDelayMaxHeader.Address <> sFirstAddress
End If
End With
Next vHeading
'Now to go through each cell in the range we've added to the collection and check for 0's.
For Each vRange In colAllRanges
For Each vCell In vRange
If vCell = 0 Then
vCell.ClearContents
End If
Next vCell
Next vRange
End Sub
With the above method you can add extra columns if needed - just add another colHeadings.Add "My New Column Header" row in the code.

Resources