Runtime 13 Type mismatch - vba

I get run time error 13 when executing following code
Dim sh, shmem As Worksheet
Dim rw As Range
Set shmem = Sheets("SHEET1")
Set sh = Sheets("SHEET2")
For Each rw In sh.Rows
If sh.Cells(rw.Row, 1).Value = "" And sh.Cells(rw.Row, 2).Value = "" Then
Exit For
End If
With Application.WorksheetFunction
Dim bdaytest As Variant
Dim match1 As Double
bdaytest = .Index((shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)) * (shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)), 0)
'match1 = .Match(1, .Index((shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)) * (shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)), 0), 0)
bdaytest = .Index(1, shmem.Range("D2:D121"), match1)
End With
Next rw
The Error Happens in following line which I extracted from the 2 line (commented out now)
bdaytest = .Index((shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)) * (shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)), 0)
'match1 = .Match(1, .Index((shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)) * (shmem.Range("A2:A121") = sh.Cells(rw.Row, 1)), 0), 0)
I understand that the error must happen because bdaytest is the wrong data type but I'm not sure and up to now I couldn't find any solution. Thanks in advance for any suggestions.
Edit: I want to find out the Row Number of the Line where 2 Columns (A & B) have a requested Value. The requested Value is found in sh.Cells(rw.Row, 1) and sh.Cells(rw.Row, 2)

You can't create arrays using = and * like that in VBA, unlike in a formula. What you can do is use Application.Countifs like this:
Dim sh As Worksheet
Dim shmem As Worksheet
Dim rw As Range
Set shmem = Sheets("SHEET1")
Set sh = Sheets("SHEET2")
For Each rw In sh.Rows
If sh.Cells(rw.Row, 1).Value = "" And sh.Cells(rw.Row, 2).Value = "" Then
Exit For
End If
With Application
Dim bdaytest As Variant
Dim match1 As Double
bdaytest = .Match(1, .CountIfs(sh.Cells(rw.Row, 1), shmem.Range("A2:A121"), _
sh.Cells(rw.Row, 2), shmem.Range("B2:B121")), 0)
If Not IsError(bdaytest) Then bdaytest = shmem.Range("D2:D121").Cells(bdaytest)
End With
Next rw
Note: WorksheetFunction.Countifs will not work.

Related

VBA EXCEL Compare Columns and bring over the value

Image1
Hi, Referring to the image, I am trying to compare column G and Column K, if the value is the same then copy the value in column J to column F. However, my code doesn't copy the value from Column J to F.
Sub createarray1()
Dim i As Integer
Dim j As Integer
Dim masterarray As Range
Set masterarray = Range("D3:G12")
Dim sourcearray As Range
Set sourcearray = Range("H3:K26")
For i = 1 To 10
For j = 1 To 25
If masterarray(i, 4).Value = sourcearray(j, 4).Value Then
masterarray(i, 3) = sourcearray(j, 3).Value
Else
masterarray(i, 3).Value = ""
End If
Next
Next
End Sub
Function concatenate()
Dim nlastrow As Long
For i = 2 To Cells(Rows.Count, "D").End(xlUp).Row
Cells(i, "G").Value = Cells(i, "D").Value & "_" & Cells(i, "E").Value
Next i
Dim nnlastrow As Long
For i = 2 To Cells(Rows.Count, "H").End(xlUp).Row
Cells(i, "K").Value = Cells(i, "H").Value & "_" & Cells(i, "I").Value
Next i
End Function
Use variant arrays, that way you limit the number of calls to the sheet to only 3.
When your positive is found you need to exit the inner loop.
Sub createarray1()
Dim i As Long
Dim j As Long
Dim masterarray As Variant
Dim sourcearray As Variant
With ThisWorkbook.Worksheets("Sheet1") ' change to your sheet
masterarray = .Range("D3:G12")
sourcearray = .Range("H3:K26")
For i = LBound(masterarray, 1) To UBound(masterarray, 1)
masterarray(i, 3) = ""
For j = LBound(sourcearray, 1) To UBound(sourcearray, 1)
If masterarray(i, 4) = sourcearray(j, 4) Then
masterarray(i, 3) = sourcearray(j, 3)
Exit For
End If
Next j
Next i
.Range("D3:G12") = masterarray
End With
End Sub
But this can all be done with the following formula:
=INDEX(J:J,MATCH(G3,K:K,0))
Put it in F3 and copy/drag down.

VBA - Set Range from Max in range 2

I edited my orignal post, it seems to be working for the most part, but only for the contract, and subsequent contracts it pulls the second to last number, not the last number. Also it will not work for one line contracts, ie. 1 year. This works only for the first contract.
The subsequent contracts are differentiated by the Column A. Where a new contract number begins. The goal is to have the last value from Column I for each contract. For example, the contract that is the area A11:L15, the value in J11 should equal the value in I15. And this should be true for later contracts including contracts that are only one year like A126 in the second image
.
If someone has any suggestions, it would be much appreciated.
Dim lngLastRow As Long, rngCell As Range, rngRange As Range, _
lngMin As Long, lngMax As Long, lngPreviousRow As Long, _
raw As Worksheet, data As Worksheet, dLRow As Double, endDate As Double, _
r As Range, n As Long
lngLastRow = lastRow(column_to_check:=2)
Set raw = Worksheets("Raw")
Set data = Worksheets("Data")
Set rngRange = raw.Range(raw.Cells(2, 1), raw.Cells(lngLastRow + 1, 1))
dLRow = data.Range("A1", data.Range("A1").End(xlDown)).Rows.Count
raw.Range("J:J").EntireColumn.Insert
raw.Range("C:E").EntireColumn.NumberFormat = "mm/dd/yyyy"
For Each rngCell In rngRange
If Len(rngCell) > 0 Then
If lngPreviousRow > 0 And (rngCell.Row - 1 <> lngPreviousRow) Then
raw.Cells(lngPreviousRow, 10) = s.Cells(n).Offset(0, 6)
End If
If (rngCell.Row = 1) Or lngPreviousRow = (rngCell.Row - 1) Then
Set r = raw.Range(rngCell.Offset(0, 1), rngCell(0, 2))
Set s = raw.Range(rngCell.Offset(0, 2), rngCell(0, 3))
lngMin = WorksheetFunction.Min(r)
lngMax = WorksheetFunction.Max(s)
m = Application.Match(lngMin, r, 0)
n = Application.Match(lngMax, s, 0)
raw.Cells(rngCell.Row, 10) = s.Cells(n).Offset(0, 6)
End If
lngPreviousRow = rngCell.Row
Set r = raw.Range(rngCell.Offset(0, 1), rngCell(0, 2))
Set s = raw.Range(rngCell.Offset(0, 2), rngCell(0, 3))
lngMin = WorksheetFunction.Min(r)
lngMax = WorksheetFunction.Max(s)
m = Application.Match(lngMin, r, 0)
n = Application.Match(lngMax, s, 0)
Else
Set r = raw.Range(rngCell.Offset(0, 1), rngCell(0, 2))
Set s = raw.Range(rngCell.Offset(0, 2), rngCell(0, 3))
lngMin = WorksheetFunction.Min(r)
lngMax = WorksheetFunction.Max(s)
End If
Next rngCell
Cells(lngPreviousRow, 10) = s.Cells(n).Offset(0, 6)
From what I understand, you want the first row of the contract to show the last contract value. Additionally, it appears that the contract description (column K) is consistent for a given contract. If I understand your question correctly, simply loop through the description to look for changes. Then input the value into the first unique cell corresponding to the given description.
Dim Rng As Range
Set Rng = Range("k2:k146")
Dim NextCell As Range
For Each Cell In Rng
Set NextCell = Cell
Do Until NextCell.Text <> Cell.Text
Set NextCell = NextCell.Offset(1, 0)
Loop
Set NextCell = NextCell.Offset(-1, 0)
If Cell.Offset(-1, 0).Text <> Cell.Text Then
Cell.Offset(0, -1).Value = NextCell.Offset(0, -2).Value
End If
Next Cell
I was able to solve it. Thanks to #E.Merckx for helping point me in the right direction. Although it wasn't exactly what I wanted, it works just fine for its purpose.
Sub NetValue()
Dim lngLastRow As Long, raw As Worksheet, data As Worksheet, rng As Range
lngLastRow = lastRow(column_to_check:=2)
Set raw = Worksheets("Raw")
Set data = Worksheets("Data")
Set rng = raw.Range(raw.Cells(3, 6), raw.Cells(lngLastRow + 1, 6))
raw.Range("J:J").EntireColumn.Insert
raw.Range("C:E").EntireColumn.NumberFormat = "mm/dd/yyyy"
For Each Cell In rng
If Cell.Value <> "" Then
Cell.Offset(-1, 4) = Cell.Offset(-1, 3).Value
End If
Next Cell
End Sub
Thanks again!

Can't retrieve a value from my dictionary using its key using vba

I am completely stumped on this problem here. I created a macro that will read values from the current spreadsheet, place those values into a dictionary using row numbers as keys, create a new spreadsheet, grab the values from those dictionaries, and add them to the new spreadsheet. There are three dictionaries that are filled. I have no problem getting the values from two of the dictionaries and I even have no problems getting the first couple of values from the problematic dictionaries. But when I try to retrieve the last two values in the last For Next loop, the values are read as "" instead of an actual value. The image below is a message that I built from looping the problematic dictionary.
I had the debug loop that produced this message within the last For Next loop. As you can see each key has a value, but when I use dataN.Exist(key) for just the last two values I get "" as the value. I don't understand. The exact same code works to pull the first couple of values but not the last couple. I have even moved those values to different rows but still got the same "". Here is the entire code here below:
Sub Transfer2NewWorkbook()
Dim currentsheet As String
Dim newsheet As String
Dim analysisDate As String
Dim initial As String
Dim aInitial() As String
Dim analystInit As String
Dim aBatch() As String
Dim batch As String
Dim batchNo As String
Dim key As Variant
Dim ikey As Variant
Dim SrowN As String
Dim rowN As Integer
Dim rowD As String
Dim wb As Object
Dim dataRangeN As Range, dataRangeB As Range, dataRangeI As Range
Dim dataN As Object
Set dataN = CreateObject("Scripting.Dictionary")
Dim dataB As Object
Set dataB = CreateObject("Scripting.Dictionary")
Dim dataI As Object
Set dataI = CreateObject("Scripting.Dictionary")
Dim teststring As String
' Grab and Create filenames
currentsheet = ActiveWorkbook.Name
newsheet = currentsheet & "-" & "uploadable"
' Grab data from original spreadsheet
analysisDate = ActiveWorkbook.Sheets(1).Cells(1, 9).Value
initial = ActiveWorkbook.Sheets(1).Cells(1, 2).Value
aInitial = Split(initial, "/")
analystInit = aInitial(1)
batch = ActiveWorkbook.Sheets(1).Cells(1, 4).Value
aBatch = Split(batch, ":")
batchNo = aBatch(1)
Set dataRangeN = Range("A:A")
Set dataRangeB = Range("B:B")
Set dataRangeI = Range("I:I")
For i = 4 To dataRangeB.Rows.Count
If Not IsEmpty(dataRangeB(i, 1)) Then
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "End") = 0 Then
Exit For
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "Blank") = 0 Then
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "Unseeded") = 0 Or StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "Seeded") = 0 Then
If Not IsEmpty(dataRangeI(i, 1)) Then
dataN.Add i, ActiveWorkbook.Sheets(1).Cells(i, 1).Value
dataB.Add i, ActiveWorkbook.Sheets(1).Cells(i, 2).Value
dataI.Add i, ActiveWorkbook.Sheets(1).Cells(i, 9).Value
End If
End If
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "Check") = 0 Then
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "Std") = 0 Then
If Not IsEmpty(dataRangeI(i, 1)) Then
dataN.Add i, ActiveWorkbook.Sheets(1).Cells(i, 1).Value
dataB.Add i, ActiveWorkbook.Sheets(1).Cells(i, 2).Value
dataI.Add i, ActiveWorkbook.Sheets(1).Cells(i, 9).Value
End If
End If
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i, 2).Value, "DUP") = 0 Then
rowD = dataB.Keys()(dataB.Count - 1)
If StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "CBOD") = 0 Then
dataN.Add rowD, "DUP-CBOD"
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "BOD") = 0 Then
dataN.Add rowD, "DUP-BOD"
End If
Else
dataB.Add i, ActiveWorkbook.Sheets(1).Cells(i, 2).Value
dataI.Add i, ActiveWorkbook.Sheets(1).Cells(i, 9).Value
End If
Else
If StrComp(ActiveWorkbook.Sheets(1).Cells(i, 1).Value, "DUP") = 0 Then
rowD = dataB.Keys()(dataB.Count - 1)
If StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "CBOD") = 0 Then
dataN.Add rowD, "DUP-CBOD"
ElseIf StrComp(ActiveWorkbook.Sheets(1).Cells(i - 1, 1).Value, "BOD") = 0 Then
dataN.Add rowD, "DUP-BOD"
End If
End If
End If
Next i
' Open new spreadsheet
Set wb = Workbooks.Add("C:\Users\dalythe\documents\uploadtemp.xlsx")
ActiveWorkbook.Sheets(1).Cells(2, 2).Value = analysisDate
ActiveWorkbook.Sheets(1).Cells(2, 4).Value = analystInit
ActiveWorkbook.Sheets(1).Cells(3, 5).Value = batchNo
rowN = 4
For Each key In dataB.Keys
If dataI.Exists(key) Then
SrowN = CStr(rowN)
If dataN.Exists(key) Then
ActiveWorkbook.Sheets(1).Cells(SrowN, 1).Value = dataN(key)
End If
ActiveWorkbook.Sheets(1).Cells(SrowN, 2).Value = dataB(key)
ActiveWorkbook.Sheets(1).Cells(SrowN, 3).Value = dataI(key)
rowN = CInt(SrowN)
rowN = rowN + 1
End If
Next
ActiveWorkbook.SaveAs (newsheet & ".xlsx")
End Sub

How to correct a userform when error 13 is displayed in VBA?

I'm currently on a project that search in a product database all non-referenced product (blank fields). When I click on the button that opens a userform, error 13 is displayed, here is the code:
Dim i As Integer
Dim j As Integer
Dim t As Integer
Dim r As Integer
t = 1
While Feuil3.Cells(t, 1) <> ""
t = t + 1
Wend
t = t - 1
For r = 2 To t
If Feuil3.Cells(r, 3) = "" Then
i = 1
While Feuil2.Cells(i, 1) <> ""
i = i + 1
Wend
Feuil2.Cells(i, 1) = Feuil3.Cells(r, 2)
End If
Next
i = 1
While Feuil2.Cells(i, 1) <> ""
i = i + 1
Wend
For j = 2 To i
If Feuil2.Cells(j, 2) = "" Then
list51.AddItem Feuil2.Cells(j, 1)
End If
Next
End Sub
It appears that the error comes from this line:If Feuil3.Cells(r, 3) = "" Then
My skills in VBA are limited, do you have any idea on how to fix this problem?
Thanks,
Have a look at this. Should do the same just a lot less iteratively
Dim Feuil2Rng As Range, Feuil3Rng As Range
Dim c
With Feuil3
Set Feuil3Rng = .Range(.Cells(2, 1), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, 1))
End With
For Each c In Feuil3Rng
If c.Offset(0, 2) = vbNullString Then
With Feuil2
.Cells(.Cells(.Rows.Count, 1).End(xlUp).Row + 1, 1) = c.Offset(0,1)
End With
End If
Next
With Feuil2
Set Feuil2Rng = .Range(.Cells(2, 1), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, 1))
End With
For Each c In Feuil2Rng
If c.Offset(0, 1) = vbNullString Then
list51.AddItem c.Value2
End If
Next

VBA Copy Specific Cells To Specific Sheets

I was wondering whether someone may be able to help me please.
I'm using the code below to copy data from one sheet to another upon specfic cell values being found.
Sub Extract()
Dim i As Long, j As Long, m As Long
Dim strProject As String
Dim RDate As Date
Dim RVal As Single
Dim BlnProjExists As Boolean
With Sheets("Enhancements").Range("B3")
For i = 1 To .CurrentRegion.Rows.Count - 1
For j = 0 To 13
.Offset(i, j) = ""
Next j
Next i
End With
With Sheets("AllData").Range("E3")
For i = 1 To .CurrentRegion.Rows.Count - 1
strProject = .Offset(i, 0)
RDate = .Offset(i, 3)
RVal = .Offset(i, 4)
If InStr(.Offset(i, 0), "Enhancements") > 0 Then
strProject = .Offset(i, 0)
ElseIf InStr(.Offset(i, 0), "OVH") > 0 And RVal > 0 Then
strProject = .Offset(i, -1)
Else
GoTo NextLoop
End If
With Sheets("Enhancements").Range("B3")
If .CurrentRegion.Rows.Count = 1 Then
.Offset(1, 0) = strProject
j = 1
Else
BlnProjExists = False
For j = 1 To .CurrentRegion.Rows.Count - 1
If .Offset(j, 0) = strProject Then
BlnProjExists = True
Exit For
End If
Next j
If BlnProjExists = False Then
.Offset(j, 0) = strProject
End If
End If
Select Case Format(RDate, "mmm yy")
Case "Apr 13"
m = 1
Case "May 13"
m = 2
Case "Jun 13"
m = 3
Case "Jul 13"
m = 4
Case "Aug 13"
m = 5
Case "Sep 13"
m = 6
Case "Oct 13"
m = 7
Case "Nov 13"
m = 8
Case "Dec 13"
m = 9
Case "Jan 14"
m = 10
Case "Feb 14"
m = 11
Case "Mar 14"
m = 12
End Select
.Offset(j, m) = .Offset(j, m) + RVal
End With
NextLoop:
Next i
End With
End Sub
The code works, but I've been trying to adapt a section of this script which I'm having a real difficulty in doing.
The piece of the script which I need to change is as below:
If InStr(.Offset(i, 0), "Enhancements") > 0 Then
strProject = .Offset(i, 0)
ElseIf InStr(.Offset(i, 0), "OVH") > 0 And RVal > 0 Then
strProject = .Offset(i, -1)
Else
GoTo NextLoop
End If
With Sheets("Enhancements").Range("B3")
If .CurrentRegion.Rows.Count = 1 Then
.Offset(1, 0) = strProject
j = 1
Else
In it's current format, if the text values of "Enhancements" or "OVH" are found the data is copied and pasted to the "Enhancements" sheet.
I'd like to change this, so if the text value "Enhancements" is found the information is pasted to the "Enhancements" page and if the text value of "OVH" is found, the information is pasted into the "Overheads" sheet. The rest of the code can remain as it is.
As I say I've tried to make the changes but I seem to fall foul to errors surrounding the use of the 'If', ElseIf' and 'Else' statements.
I just wondered whether someone may be able to look at this please and let me know where I'm going wrong.
I ended up rewriting a lot of your code to make it more efficient, this should accomplish what you're looking for, and it should run rather quickly also:
Sub Extract()
Dim cllProjects As Collection
Dim wsData As Worksheet
Dim wsEnha As Worksheet
Dim wsOver As Worksheet
Dim rngFind As Range
Dim rngFound As Range
Dim rngProject As Range
Dim arrProjects() As Variant
Dim varProjectType As Variant
Dim ProjectIndex As Long
Dim cIndex As Long
Dim dRVal As Double
Dim dRDate As Double
Dim strFirst As String
Dim strProjectFirst As String
Dim strProject As String
Set wsData = Sheets("AllData")
Set wsEnha = Sheets("Enhancements")
Set wsOver = Sheets("Overheads")
wsEnha.Range("B4:O" & Rows.Count).ClearContents
wsOver.Range("B4:O" & Rows.Count).ClearContents
With wsData.Range("E4", wsData.Cells(Rows.Count, "E").End(xlUp))
If .Row < 4 Then Exit Sub 'No data
On Error Resume Next
For Each varProjectType In Array("Enhancements", "OVH")
Set cllProjects = New Collection
ProjectIndex = 0
ReDim arrProjects(1 To WorksheetFunction.CountIf(.Cells, "*" & varProjectType & "*"), 1 To 14)
Set rngFound = .Find(varProjectType, .Cells(.Cells.Count), xlValues, xlPart)
If Not rngFound Is Nothing Then
strFirst = rngFound.Address
Do
strProject = vbNullString
dRDate = wsData.Cells(rngFound.Row, "H").Value2
dRVal = wsData.Cells(rngFound.Row, "I").Value2
If varProjectType = "OVH" And dRVal > 0 Then
strProject = wsData.Cells(rngFound.Row, "D").Text
Set rngFind = Intersect(.EntireRow, wsData.Columns("D"))
ElseIf varProjectType = "Enhancements" Then
strProject = wsData.Cells(rngFound.Row, "E").Text
Set rngFind = .Cells
End If
If Len(strProject) > 0 Then
cllProjects.Add LCase(strProject), LCase(strProject)
If cllProjects.Count > ProjectIndex Then
ProjectIndex = cllProjects.Count
arrProjects(ProjectIndex, 1) = strProject
Set rngProject = Intersect(rngFound.EntireRow, Columns(rngFind.Column))
strProjectFirst = rngProject.Address
Do
If LCase(rngProject.Text) = LCase(strProject) Then
dRDate = wsData.Cells(rngProject.Row, "H").Value2
dRVal = wsData.Cells(rngProject.Row, "I").Value2
cIndex = Month(dRDate) - 2 + (Year(dRDate) - 2013) * 12
arrProjects(ProjectIndex, cIndex) = arrProjects(ProjectIndex, cIndex) + dRVal
End If
Set rngProject = rngFind.Find(arrProjects(ProjectIndex, 1), rngProject, xlValues, xlPart)
Loop While rngProject.Address <> strProjectFirst
End If
End If
Set rngFound = .Find(varProjectType, rngFound, xlValues, xlPart)
Loop While rngFound.Address <> strFirst
End If
If cllProjects.Count > 0 Then
Select Case varProjectType
Case "Enhancements": wsEnha.Range("B4").Resize(cllProjects.Count, UBound(arrProjects, 2)).Value = arrProjects
Case "OVH": wsOver.Range("B4").Resize(cllProjects.Count, UBound(arrProjects, 2)).Value = arrProjects
End Select
Set cllProjects = Nothing
End If
Next varProjectType
On Error GoTo 0
End With
Set cllProjects = Nothing
Set wsData = Nothing
Set wsEnha = Nothing
Set wsOver = Nothing
Set rngFound = Nothing
Set rngProject = Nothing
Erase arrProjects
End Sub
Your sample data is a little confusing, I have presumed that on the overheads sheet you want the overheads code to be from the task column. For the enhancements you want the code to be the project name.
If that's is incorrect, please provide better sample data.
Try this code:
Sub HTH()
Dim rLookup As Range, rFound As Range
Dim lLastRow As Long, lRow As Long
Dim lMonthIndex As Long, lProjectIndex As Long
Dim vData As Variant, vMonths As Variant
Dim iLoop As Integer
Dim vbDict As Object
With Worksheets("AllData")
Set rLookup = .Range("E3", .Cells(Rows.Count, "E").End(xlUp))
Set rFound = .Range("E3")
End With
Set vbDict = CreateObject("Scripting.Dictionary")
vMonths = Array(4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3)
For iLoop = 0 To 1
lRow = 0: lLastRow = 3
vbDict.RemoveAll: ReDim vData(rLookup.Count, 13)
Do
Set rFound = Worksheets("AllData").Cells.Find(Array("Enhancements", "OVH")(iLoop), _
rFound, , , xlByRows, xlNext, False)
If rFound Is Nothing Then Exit Do
If rFound.Row <= lLastRow Then Exit Do
lMonthIndex = WorksheetFunction.Match(Month(CDate(rFound.Offset(, 4).Value)), vMonths, False)
If vbDict.exists(rFound.Offset(, -iLoop).Value) Then
lProjectIndex = vbDict.Item(rFound.Value)
vData(lProjectIndex, lMonthIndex) = _
vData(lProjectIndex, lMonthIndex) + rFound.Offset(, 4).Value
Else
vbDict.Add rFound.Offset(, -iLoop).Value, lRow
vData(lRow, 0) = rFound.Offset(, -iLoop).Value
vData(lRow, lMonthIndex) = rFound.Offset(, 4).Value
lRow = lRow + 1
End If
lLastRow = rFound.Row
Loop
If iLoop = 0 Then
With Worksheets("Enhancements")
.Range("B4:O" & Rows.Count).ClearContents
.Range("B4").Resize(vbDict.Count + 1, 13).Value = vData
End With
Else
With Worksheets("Overheads")
.Range("B4:O" & Rows.Count).ClearContents
.Range("B4").Resize(vbDict.Count + 1, 13).Value = vData
End With
End If
Next iLoop
End Sub
Commented version:
Sub HTH()
Dim rLookup As Range, rFound As Range
Dim lLastRow As Long, lRow As Long
Dim lMonthIndex As Long, lProjectIndex As Long
Dim vData As Variant, vMonths As Variant
Dim iLoop As Integer
Dim vbDict As Object
'// Get the projects range to loop through
With Worksheets("AllData")
Set rLookup = .Range("E3", .Cells(Rows.Count, "E").End(xlUp))
Set rFound = .Range("E3")
End With
'// Use a latebinded dictionary to store the project names.
Set vbDict = CreateObject("Scripting.Dictionary")
'// Create an array of the months to get the correct columns. Instead of your select case method
vMonths = Array(4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3)
'// Loop through both search requirements
For iLoop = 0 To 1
'// Set the counters - lLastRow is used to make sure the loop is not never ending.
lRow = 0: lLastRow = 3
'// Clear the dictionary and create the projects array.
vbDict.RemoveAll: ReDim vData(rLookup.Count, 13)
Do
'// Search using the criteria requried
Set rFound = Worksheets("AllData").Cells.Find(Array("Enhancements", "OVH")(iLoop), _
rFound, , , xlByRows, xlNext, False)
'// Make sure something was found and its not a repeat.
If rFound Is Nothing Then Exit Do
If rFound.Row <= lLastRow Then Exit Do
'// Get the correct month column using our months array and the project date.
lMonthIndex = WorksheetFunction.Match(Month(CDate(rFound.Offset(, 4).Value)), vMonths, False)
'// Check if the project exists.
If vbDict.exists(rFound.Offset(, -iLoop).Value) Then
'// Yes it exists so add the actuals to the correct project/month.
lProjectIndex = vbDict.Item(rFound.Value)
vData(lProjectIndex, lMonthIndex) = _
vData(lProjectIndex, lMonthIndex) + rFound.Offset(, 4).Value
Else
'// No it doesnt exist, create it and then add the actuals to the correct project/month
vbDict.Add rFound.Offset(, -iLoop).Value, lRow
vData(lRow, 0) = rFound.Offset(, -iLoop).Value
vData(lRow, lMonthIndex) = rFound.Offset(, 4).Value
'// Increase the project count.
lRow = lRow + 1
End If
'// Set the last row = the last found row to ensure we dont repeat the search.
lLastRow = rFound.Row
Loop
If iLoop = 0 Then
'// Clear the enhancements sheet and populate the cells from the array
With Worksheets("Enhancements")
.Range("B4:O" & Rows.Count).ClearContents
.Range("B4").Resize(vbDict.Count + 1, 13).Value = vData
End With
Else
'// Clear the overheads sheet and populate the cells from the array
With Worksheets("Overheads")
.Range("B4:O" & Rows.Count).ClearContents
.Range("B4").Resize(vbDict.Count + 1, 13).Value = vData
End With
End If
Next iLoop
End Sub