Set variable column in search looping through worksheets not working, - excel

I'm working on a macro that needs to find every value in a range in "sheet1" and search for it in all the sheets of the workbook (may be up to 7 sheets), as it takes too long, looking for the values in the entire sheets, I would like to reduce the search field on each sheet up to one variable column with header IP.
This is the macro I have so far, but I can't get it to work only on that specified range, however, removing those lines makes the macro work ok.
Thank you in advance.
Sub findInventory()
Dim ws As Worksheet
Dim strWhat, rngFound, mString As String
Dim rngSearch, osfind, rfind, rfcol As Range
Dim i, x As Integer
Dim LastRow, oscol, lcol, e, lrowA, remChar, fcol As Long
Sheets("GVM Report").Cells(1, 1).Offset(0, 1).Resize(, 2).EntireColumn.Insert
Sheets("GVM Report").Cells(1, 1).Offset(0, 1).Value = "INVENTORY"
Sheets("GVM Report").Cells(1, 1).Offset(0, 2).Value = "OPSDB"
Set rfind = ActiveWorkbook.Sheets("GVM Report").Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
lcol = rfind.Column
Set osfind = ActiveWorkbook.Sheets("GVM Report").Rows("1:3").Find(What:="OS*", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
oscol = osfind.Column
LastRow = Sheets("GVM Report").Range("A" & Rows.Count).End(xlUp).Row
For x = 2 To LastRow
strWhat = Sheets("GVM Report").Cells(x, lcol)
For Each ws In Worksheets
Set rfcol = ws.Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
fcol = rfcol.Column
With ws.Columns(fcol)
Select Case ws.name
Case "Operations", "Data", "FYI all OS", "Unique Values", "GVM Report"
Case Else
Set rngSearch = ws.Cells.Find(What:=strWhat)
If strWhat <> "" Then
If Not rngSearch Is Nothing Then
i = i + 1
If i = 1 Then
rngFound = rngSearch.Worksheet.name
Else
rngFound = rngFound & " | " & rngSearch.Worksheet.name
End If
End If
End If
Sheets("GVM Report").Cells(x, 2) = rngFound
End Select
End With
Next ws
rngFound = ""
i = 0
Next x
End Sub

I'm not sure if I can replicate your error, but I've tidied up your code a little and it might be useful for you, so here it goes:
Sub findInventory()
Dim ws As Worksheet
Dim wsGVM As Worksheet: Set wsGVM = ThisWorkbook.Sheets("GVM Report")
Dim strWhat As String, rngFound As String, mString As String
Dim rngSearch As Range, osfind As Range, rfind As Range, rfcol As Range
Dim i As Integer, x As Long, LastRow As Long, oscol As Long, lcol As Long, fcol As Long
wsGVM.Cells(1, 1).Offset(0, 1).Resize(, 2).EntireColumn.Insert
wsGVM.Cells(1, 1).Offset(0, 1).Value = "INVENTORY"
wsGVM.Cells(1, 1).Offset(0, 2).Value = "OPSDB"
Set rfind = wsGVM.Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rfind Is Nothing Then lcol = rfind.Column
Set osfind = wsGVM.Rows("1:3").Find(What:="OS*", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not osfind Is Nothing Then oscol = osfind.Column
LastRow = wsGVM.Range("A" & Rows.Count).End(xlUp).Row
For x = 2 To LastRow
strWhat = wsGVM.Cells(x, lcol)
For Each ws In Worksheets
Set rfcol = ws.Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rfcol Is Nothing Then
fcol = rfcol.Column
With ws.Columns(fcol)
Select Case ws.Name
Case "Operations", "Data", "FYI all OS", "Unique Values", "GVM Report"
''''
Case Else
If strWhat <> "" Then
Set rngSearch = .Find(What:=strWhat)
If Not rngSearch Is Nothing Then
i = i + 1
If i = 1 Then
rngFound = rngSearch.Worksheet.Name
Else
rngFound = rngFound & " | " & rngSearch.Worksheet.Name
End If
End If
End If
wsGVM.Cells(x, 2) = rngFound
End Select
End With
End If
Next ws
rngFound = ""
i = 0
Next x
End Sub

I did a test with dummy'ed up data and got the following results:
INVENTORY
Sheet2 | Sheet3
Sheet2
Sheet3
which is consistent with what I would expect given the dummy data I created. Perhaps there are leading, trailing spaces or other non-visible difference that cause a data mismatch on cells that appear to be equal?

Related

VBA excel search tool

Tried doing a search tool to the excel sheet (VBA) I'm working on.
So far every time I search for the text, it ends up filtering only the first row and not any row that has the value I'm looking for. I added a picture to show what it returns and the code as well. Is there anything I need to change to the code to make it search for all the data in the sheet instead of having it to show only one row? Any help is appreciated.
Search result of only the first row:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range
Dim strName As String
Dim count As Long, LastRow As Long
Dim IsValueFound As Boolean
IsValueFound = False
Set OutputWs = Worksheets("sheet1") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).Row
On Error Resume Next
strName = InputBox("What are you looking for?")
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> "Output" Then
With ws.UsedRange
Set rFound = .Find(What:=strName, After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
If Not rFound Is Nothing Then
Application.Goto rFound, True
IsValueFound = True
'MsgBox rFound.Row
rFound.EntireRow.Copy
OutputWs.Cells(LastRow + 1, 1).PasteSpecial xlPasteAll
Application.CutCopyMode = False
LastRow = LastRow + 1
End If
End With
End If
Next ws
On Error GoTo 0
If IsValueFound Then
OutputWs.Select
MsgBox "Result pasted to Sheet Output"
Else
MsgBox "Value not found"
End If
End Sub
Try this:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range, IsValueFound As Boolean
Dim strName As String
Dim count As Long, LastRow As Long
Set OutputWs = Worksheets("Output") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).row
strName = Trim(InputBox("What are you looking for?"))
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> OutputWs.Name Then
Debug.Print "Checking " & ws.Name
Set rFound = FindAll(ws.UsedRange, strName)
If Not rFound Is Nothing Then
Set rFound = rFound.EntireRow
count = rFound.Cells.count / Columns.count 'how many matched rows?
Debug.Print "Found " & count & " rows"
rFound.Copy OutputWs.Cells(LastRow + 1, 1)
LastRow = LastRow + count
IsValueFound = True
End If
End If
Next ws
If IsValueFound Then
OutputWs.Select
MsgBox "Result(s) pasted to Sheet " & OutputWs.Name
Else
MsgBox "Value not found"
End If
End Sub
'find all cells in range `rng` with value `val` and return as a range
Public Function FindAll(rng As Range, val As String) As Range
Dim rv As Range, f As Range
Dim addr As String
Set f = rng.Find(what:=val, After:=rng.Cells(rng.Cells.count), _
LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not f Is Nothing Then addr = f.Address()
Do Until f Is Nothing
If rv Is Nothing Then
Set rv = f
Else
Set rv = Application.Union(rv, f)
End If
Set f = rng.FindNext(After:=f)
If f.Address() = addr Then Exit Do
Loop
Set FindAll = rv
End Function

Using Application.WorksheetFunction.Match returns type mismatch

I am trying to get Application.WorksheetFunction.Match to find a value in the next row in a range, in a specific column and match it to a list of values in another worksheet column, setting a = a specific value, if no error is returned.
The code I currently have is:
Dim caseSearch As String
Dim caseCell As Range
Dim moveSearch As String
Dim moveCell As Range
caseSearch = "caseset"
moveSearch = "movementset"
Set caseCell = ws.Rows(1).Find(What:=caseSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
Set moveCell = ws.Rows(1).Find(What:=moveSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If caseCell Is Nothing Then
MsgBox "caseset column not found"
ElseIf moveCell Is Nothing Then
MsgBox "movementset column not found"
End If
Dim rng As Range
Dim row As Range
Dim cell As Range
Dim lRow As Long
Dim a As Integer
Dim b As Integer
lRow = Cells(Rows.Count, 1).End(xlUp).row
Set rng = ws.Range("A2:A" & lRow)
For Each row In rng.Rows
If Not IsError(Application.WorksheetFunction.Match(row.Columns(caseCell).Value, tcc.Columns(1), 0)) Then
a = tcc.Cells("C2")
Else:
a = tcc.Cells("C3")
End If
Next row
Match with Application.Match
Here's an example of how you could 'set it up'.
Option Explicit
Sub UseApplicationMatch()
Const caseSearch As String = "caseset"
Const moveSearch As String = "movementset"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Dim caseCell As Range
Set caseCell = ws.Rows(1).Find(What:=caseSearch, LookIn:=xlValues, _
LookAt:=xlWhole)
If caseCell Is Nothing Then
MsgBox "caseset column not found"
Exit Sub
End If
Dim caseCol As Long: caseCol = caseCell.Column
Dim moveCell As Range
Set moveCell = ws.Rows(1).Find(What:=moveSearch, LookIn:=xlValues, _
LookAt:=xlWhole)
If moveCell Is Nothing Then
MsgBox "movementset column not found"
Exit Sub
End If
Dim moveCol As Long: moveCol = moveCell.Column
Dim tcc As Worksheet: Set tcc = wb.Worksheets("Sheet2")
Dim t1 As Long: t1 = tcc.Cells("C2").Value
Dim t2 As Long: t2 = tcc.Cells("C3").Value
Dim lRow As Long: lRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim rng As Range: Set rng = ws.Range("A2:A" & lRow)
Dim fCell As Range
Dim Result As Long
For Each fCell In rng.Cells
If IsNumeric(Application.Match(fCell.EntireRow.Columns(caseCol).Value, _
tcc.Columns(1), 0)) Then
Result = t1
Else
Result = t2
End If
Next fCell
End Sub

find and select the finding until the next find

Basically, I'm writing a code that finds text in a Master sheet, I am looking for "Admin" after finding the admin I need to select from this cell unit next find and paste in separate sheets.
I tried different ways but now work, any suggestions?
Example
Sub FindNext_Example()
Dim FindValue As String
FindValue = "Bangalore"
Dim Rng As Range
Set Rng = Range("A2:A11")
Dim FindRng As Range
Set FindRng = Rng.Find(What:=FindValue)
Dim FirstCell As String
FirstCell = FindRng.Address
Do
Range(FristCell).Select
Selection.Copy
Worksheets.Add
ActiveSheet.Paste
Sheets("Sheet0").Select
Set FindRng = Rng.FindNext(FindRng)
Loop While FirstCell <> FindRng.Address
MsgBox "Search is over"
End Sub
Example
Example of finding and select the find row until next find
paste in new sheet
next find
until the end
Try this code:
Sub SubChopList()
'Declarations.
Dim DblColumnOffset As Double
Dim RngSource As Range
Dim RngSearch As Range
Dim RngTop As Range
Dim RngBottom As Range
Dim StrSearch As String
Dim StrDestinationAddress As String
Dim WksSource As Worksheet
'Settings.
Set WksSource = ActiveSheet
Set RngSource = WksSource.Range("A1")
Set RngSource = Range(RngSource, RngSource.End(xlDown).End(xlToRight))
'Setting DblColumnOffset equal to the offset from the first column of RngSource and the column to be searched.
DblColumnOffset = 2
'Setting the column to be searched.
Set RngSearch = RngSource.Columns(1).Offset(0, DblColumnOffset)
'Setting the value to be searched.
StrSearch = "Admin"
'Setting the address of the cell where the data will be pasted in the new sheets.
StrDestinationAddress = "A1"
'Setting RngTop as the first cell that contains StrSearch after the first cell of RngSearch.
Set RngTop = RngSearch.Find(What:=StrSearch, _
After:=RngSearch.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
)
'Setting RngBottom as the cell in the row upon the first cell that contains StrSearch after RngTop.
Set RngBottom = RngSearch.Find(What:=StrSearch, _
After:=RngTop, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
).Offset(-1, 0)
'Repeating until the last block is reached.
Do
'Creating a new sheet.
Worksheets.Add
'Copy-pasting the block delimited by RngTop and RngBottom in the new sheet at the address specified in StrDestinationAddress.
WksSource.Range(RngTop, RngBottom).Offset(0, -DblColumnOffset).Resize(, RngSource.Columns.Count).Copy Range(StrDestinationAddress)
'Setting RngTop as the first cell that contains StrSearch after RngBottom.
Set RngTop = RngSearch.Find(What:=StrSearch, _
After:=RngBottom, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
)
'Setting RngBottom as the cell in the row upon the first cell that contains StrSearch after RngTop.
Set RngBottom = RngSearch.Find(What:=StrSearch, _
After:=RngTop, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
).Offset(-1, 0)
Loop Until RngTop.Row > RngBottom.Row
'Reporting the last block as did for all the previous blocks in the Do Loop cycle.
Set RngBottom = RngSearch.Cells(RngSearch.Rows.Count, 1)
Worksheets.Add
WksSource.Range(RngTop, RngBottom).Offset(0, -DblColumnOffset).Resize(, RngSource.Columns.Count).Copy Range(StrDestinationAddress)
End Sub
Select the sheet with the data you want to chop and run it.
Create Criteria Worksheets
Adjust the values in the constants section.
The Code
Option Explicit
Sub addCriteriaWorksheets()
Const wsName As String = "Sheet1"
Const sCellAddress As String = "A1"
Const Criteria As String = "Admin*"
Const CriteriaColumn As Long = 3
Const dCellAddress As String = "A1"
Dim wb As Workbook: Set wb = ThisWorkbook
Application.ScreenUpdating = False
With wb.Worksheets(wsName).Range(sCellAddress).CurrentRegion
.Worksheet.AutoFilterMode = False
.AutoFilter CriteriaColumn, Criteria
Dim rg As Range
On Error GoTo SpecialCellsError
Set rg = .Columns(CriteriaColumn).Resize(.Rows.Count - 1).Offset(1) _
.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
Dim nCount As Long: nCount = rg.Cells.Count
Dim Coord As Variant: ReDim Coord(1 To nCount, 1 To 3)
Dim arg As Range
Dim cel As Range
Dim n As Long
For Each arg In rg.Areas
For Each cel In arg.Cells
n = n + 1
Coord(n, 1) = cel.Row
If n > 1 Then
Coord(n - 1, 2) = Coord(n, 1) - 1
Coord(n - 1, 3) = Coord(n - 1, 2) - Coord(n - 1, 1) + 2
End If
Next cel
Next arg
n = n + 1
Coord(n - 1, 2) = .Rows.Count
Coord(n - 1, 3) = Coord(n - 1, 2) - Coord(n - 1, 1) + 2
.Worksheet.AutoFilterMode = False
Dim cCount As Long: cCount = .Columns.Count
Dim Data As Variant: Data = .Value
Dim Result As Variant
Dim i As Long, j As Long, k As Long
For n = 1 To nCount
ReDim Result(1 To Coord(n, 3), 1 To cCount)
For j = 1 To cCount
Result(1, j) = Data(1, j)
Next j
k = 1
For i = Coord(n, 1) To Coord(n, 2)
k = k + 1
For j = 1 To cCount
Result(k, j) = Data(i, j)
Next j
Next i
With wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
.Range(dCellAddress).Resize(k, cCount).Value = Result
End With
Next n
.Worksheet.Select
End With
ProcExit:
Application.ScreenUpdating = True
Exit Sub
SpecialCellsError:
Resume ProcExit
End Sub

How can I use advanced filter if I have the criteria in a cell?

The cell is going to change the value and it is in different locations of the worksheet. The point is that I haven't been able that my macro understand that criteria that is located in the last cell of a column, the second in this case
This is the code that I am using
Public Sub Excel()
Dim T#, crit As Range, Data As Range, ws As Worksheet
Dim r&, fc As Range, lc As Range, fr1 As Range, fr2 As Range
Dim year%
year = 2019
Set fc = ActiveSheet.UsedRange.Item(1)
Set lc = GetMaxCell
Set Data = ActiveSheet.Range(fc, lc)
Set ws = Sheets.Add
With Data
Set fr1 = Data.Worksheet.Range(fc, fc.Offset(, lc.Column))
Set fr2 = ws.Range(ws.Cells(fc.Row, fc.Column), ws.Cells(fc.Row, lc.Column))
With fr2
fr1.Copy
.PasteSpecial xlPasteColumnWidths: .PasteSpecial xlPasteAll
.Item(1).Select
End With
Set crit = .Resize(2, 1).Offset(, lc.Column + 1)
'This is the part that I need to understand
crit = [{"AÑO";<>lRow)}]
.AdvancedFilter xlFilterCopy, crit, fr2
.Worksheet.Delete
End With
End Sub
Public Function GetMaxCell(Optional ByRef rng As Range = Nothing) As Range
'Returns the last cell containing a value, or A1 if Worksheet is empty
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ActiveWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
If Not lRow Is Nothing Then
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell = .Parent.Cells(lRow.Row, lCol.Column)
End If
End With
End If
End Function
Thanks for your help

Summarize data using Excel VBA

I am a beginner to VBA. On sheet one I have data formatted like this:
SHEET 1
What I want to do is use VBA to spit out the following graph which dynamically populates the region depending on how many it finds:
SHEET 2
This is my first bit of VBA so I am struggling a bit. This is my idea of how to approach this problem:
My idea was to scroll down the string in my data in sheet1 col A and determine if it's a date we have seen before or not:
Public Sub Test()
ActiveSheet.Range("Sheet1!A1:A5000").AdvancedFilter Action:=xlFilterCopy, CopyToRange.Range("Sheet2!A1"), Unique:=True
End Sub
Questions
Is this flow diagram taking the right approach?
If so, how do I implement this kind of "Is this unique, if so do this, if not do this" kind of setup.
How can I start this code so I have something to build on?
This is what I have so far:
https://gist.githubusercontent.com/employ/af67485b8acddce419a2/raw/6dda3bb1841517731867baec56a0bf2ecf7733a7/gistfile1.txt
For different approach please see below:
Sheet 1 layout (Source):
Sheet 2 Layout (Target):
Sub SalesRegion()
Dim ws1, ws2 As Worksheet
Dim wb As Workbook
Dim ws1LastRow, ws2LastRow, salesVal As Long
Dim destFind, dateFind As Range
Dim destStr As String
Dim dateStr As Date
Dim targetCol, targetRow As Long
Set wb = ActiveWorkbook '<- Your workbook
Set ws1 = wb.Sheets("Sheet1") '<- Your source worksheet
Set ws2 = wb.Sheets("Sheet2") '<- Your destination worksheet
ws1LastRow = ws1.Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To ws1LastRow
destStr = ws1.Range("C" & i).Value
dateStr = ws1.Range("A" & i).Value
salesVal = ws1.Range("B" & i).Value
With ws2.Rows("1:1") '<- row on destination sheet which contains countries
Set destFind = .Find(What:=destStr, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not destFind Is Nothing Then
targetCol = destFind.Column
With ws2.Columns("A:A") '<- Column on destination sheet which contains months
'You may need to adjust date format below depending on your regional settings
Set dateFind = .Find(What:=Format(ws1.Range("A" & i).Value, "MMM-yy"), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not dateFind Is Nothing Then
targetRow = dateFind.Row
ws2.Cells(targetRow, targetCol).Value = ws2.Cells(targetRow, targetCol).Value + salesVal
Else
ws2.Range("A" & Rows.Count).End(xlUp).Offset(1, 0).Value = dateStr
targetRow = ws2.Range("A" & Rows.Count).End(xlUp).Offset(1, 0).Row
ws2.Cells(targetRow, targetCol).Value = salesVal
End If
End With
Else
ws2.Cells(1, Columns.Count).End(xlToLeft).Offset(0, 1).Value = destStr
targetCol = ws2.Cells(1, Columns.Count).End(xlToLeft).Column
With ws2.Columns("A:A") '<- Column on destination sheet which contains months
'You may need to adjust date format below depending on your regional settings
Set dateFind = .Find(What:=Format(ws1.Range("A" & i).Value, "MMM-yy"), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not dateFind Is Nothing Then
targetRow = dateFind.Row
ws2.Cells(targetRow, targetCol).Value = ws2.Cells(targetRow, targetCol).Value + salesVal
Else
ws2.Range("A" & Rows.Count).End(xlUp).Offset(1, 0).Value = dateStr
targetRow = ws2.Range("A" & Rows.Count).End(xlUp).Row
ws2.Cells(targetRow, targetCol).Value = salesVal
End If
End With
End If
End With
Next
End Sub
First, I agree with the others that you should look for a solution using the built-in capabilities of the Pivot Table.
Since you've mentioned that it does not meet your expectations, I threw together some code that works to summarize the data as you've requested. Let me know if it does the trick, if you need any added help adjusting it for your needs, or if you have any other general questions.
Sub SummarizeInNewSheet()
Dim wsOrigin As Worksheet
Dim wsDest As Worksheet
Dim rngOrigin As Range
Dim oDict As Object
Dim cel As Range
Dim rngLocations As Range
Dim nLastRow As Long
Dim nLastCol As Long
Dim rngInterior As Range
Dim rngAllDates As Range
Dim rngAllLocations As Range
Dim rngAllSales As Range
Application.ScreenUpdating = False
Set wsOrigin = Worksheets("Sheet1")
Set wsDest = Worksheets("Sheet2")
Set rngOrigin = wsOrigin.Range("A1").CurrentRegion
Intersect(rngOrigin, wsOrigin.Columns(1)).Copy wsDest.Range("A1")
wsDest.Range(wsDest.Range("A1"), wsDest.Range("A1").End(xlDown)).RemoveDuplicates Columns:=1, Header:=xlYes
Set oDict = CreateObject("Scripting.Dictionary")
Set rngLocations = wsDest.Range("B1")
For Each cel In Intersect(rngOrigin, wsOrigin.Columns(3))
If cel.Row = 1 Then
Else
If oDict.exists(cel.Value) Then
'Do nothing for now
Else
oDict.Add cel.Value, 0
rngLocations.Value = cel.Value
Set rngLocations = rngLocations.Offset(, 1)
End If
End If
Next cel
nLastRow = wsDest.Cells(Rows.Count, 1).End(xlUp).Row
nLastCol = wsDest.Cells(1, Columns.Count).End(xlToLeft).Column
Set rngInterior = wsDest.Range(wsDest.Range("B2"), wsDest.Cells(nLastRow, nLastCol))
Set rngAllDates = wsOrigin.Range(wsOrigin.Range("A2"), wsOrigin.Range("A2").End(xlDown))
Set rngAllSales = wsOrigin.Range(wsOrigin.Range("B2"), wsOrigin.Range("B2").End(xlDown))
Set rngAllLocations = wsOrigin.Range(wsOrigin.Range("C2"), wsOrigin.Range("C2").End(xlDown))
For Each cel In rngInterior
cel.Value = Application.WorksheetFunction.SumIfs(rngAllSales, rngAllDates, wsDest.Cells(cel.Row, 1), rngAllLocations, wsDest.Cells(1, cel.Column))
Next cel
Application.ScreenUpdating = True
End Sub

Resources