I'm trying to get a grasp of the VBA Dictionary.
I believe I have succeeded into storing the text of multiple cells into an array into the dictionary. But I can't find any way to get it out of there.
End goal is the ability to add multiple sources into 1 dictionary and then extract them by key or item or all at once into a new tab.
Here is the code I'm working on:
Sub tutorial_dictionary_Select()
'Must add reference to Tools > References > Microsoft Scripting Runtime
Dim dict As New Dictionary
dict.CompareMode = CompareMethod.TextCompare
Dim source As Worksheet
Set source = ActiveSheet
Dim last_row As Long
last_row = Cells(Rows.Count, 1).End(xlUp).Row
Dim last_col As Long
last_col = ActiveSheet.UsedRange.Columns.Count
Dim i As Long, n As Long
Dim hasHeader As Boolean
Dim arr(0 To 99) As Variant
If IsNumeric(Range("B1").Value) Or IsNumeric(Range("C1").Value) Then
i = 0
Else
hasHeader = True
i = 1
n = 1
For Each rngCell In Range(Cells(1, 2), Cells(1, last_col))
arr(n) = rngCell.Text
'MsgBox arr(n)
Range("I" & n) = arr(n)
Range("J" & n) = n
n = n + 1
Next rngCell
End If
Dim strVal As String
Dim Item(0 To 99) As Variant
Dim header As Range
Dim rng As Range
Dim rngTemp As Range
For Each rngCell In Range(Cells(1 + i, 1), Cells(last_row, 1))
i = i + 1
strVal = rngCell.Text
If Not dict.Exists(strVal) Then
n = 0
For Each headerCell In Range(Cells(i, 2), Cells(i, last_col))
n = n + 1
Item(n) = headerCell.Text
MsgBox headerCell.Text
Next headerCell
dict(strVal) = Item
Else
MsgBox "already exists"
End If
Next rngCell
sFruit = InputBox("Check value of key")
MsgBox "The value of " & sFruit & " is " & dict(sFruit)
The message box gives a type mismatch and I feel like I've tried everything to get those values either put in a cell or debugged and I'm clueless.
As you can see, the code it totally flexible checking for height and width (and a header). And it generates the correct items and their position in the array on the right:
https://i.imgur.com/5Ba6jaN.png
Yes!! That did the trick! I've been stuck on this for days, thank you so much.
Could you maybe elaborate what this code does? The script will run without the first line, but not without the second.
ar = Array()
ReDim ar(lastCol)
In case a key already exists, I want to add the amounts of the 2nd entry to what was already stored in the dictionary. I was able to figure this out myself:
Dim ws As Worksheet
Set ws = ActiveSheet
Dim dict As New Dictionary
Set dict = New Dictionary
dict.CompareMode = TextCompare
Dim lastRow As Long
lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
Dim lastCol As Long
lastCol = ws.UsedRange.Columns.Count
Dim i As Integer
Dim startRow As Long
startRow = 2
Dim ar As Variant
Dim sKey As String
For iRow = startRow To lastRow
sKey = ws.Cells(iRow, 1).Text
If Not dict.Exists(sKey) Then
ar = Array()
ReDim ar(lastCol)
For i = 2 To lastCol
ar(i) = ws.Cells(iRow, i)
Next
dict(sKey) = ar
Else
ar = dict(sKey)
For i = 2 To lastCol
ar(i) = ar(i) + ws.Cells(iRow, i)
Next
End If
Next
Is this the right way to do it? I expected to do something like dict(sKey)(3) = dict(sKey)(3) + ws.Cells(iRow, 3) but that didn't work.
You can't assign the same array to every key in the dictionary, you have to create a new one each time.
Sub tutorial_dictionary_Select()
'Must add reference to Tools > References > Microsoft Scripting Runtime
Dim dict As New Dictionary
dict.CompareMode = CompareMethod.TextCompare
Dim wb As Workbook, ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.ActiveSheet
Dim last_row As Long, last_col As Long, start_row As Long
Dim hasHeader As Boolean, i As Integer, iRow As Long
last_row = ws.Cells(Rows.Count, 1).End(xlUp).Row
last_col = ws.Range("A1").CurrentRegion.Columns.Count
Debug.Print "last_col", last_col
' check for header
hasHeader = True
start_row = 2
For i = 2 To last_col
If IsNumeric(ws.Cells(1, i)) Then
hasHeader = False
start_row = 1
End If
Next
Dim ar As Variant, sKey As String
For iRow = start_row To last_row
sKey = ws.Cells(iRow, 1).Text
If Not dict.Exists(sKey) Then
ar = Array()
ReDim ar(last_col)
For i = 2 To last_col
ar(i) = ws.Cells(iRow, i)
Next
dict(sKey) = ar
End If
Next
Dim sFruit As String
sFruit = InputBox("Check value of key")
MsgBox "The value of " & sFruit & " is " & dict(sFruit)(3)
End Sub
Okay I've been trying to store my item + properties into an array and then multiple items in an array in a dictionary if that makes sense.
Dim ws As Worksheet
Set ws = ActiveSheet
Dim dict As New Dictionary
Set dict = New Dictionary
dict.CompareMode = TextCompare
Dim lastRow As Long
lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
Dim lastCol As Long
lastCol = ws.UsedRange.Columns.Count
Dim i As Long, u As Long
Dim startRow As Long
startRow = 2
Dim ar As Variant, items As Variant, item As Variant
Dim sKey As String
Dim itemAdded As Boolean
For iRow = startRow To lastRow
sKey = ws.Cells(iRow, 1).Text
item = ws.Cells(iRow, 2).Text
If Not dict.Exists(sKey) Then
MsgBox "adding new customer"
items = Array()
ReDim items(99)
ar = Array()
ReDim ar(lastCol)
'--------------------
For i = 2 To lastCol
ar(i) = ws.Cells(iRow, i)
Next
items(0) = ar
dict(sKey) = items
Else
MsgBox "customer already exists"
items = dict(sKey)
For u = LBound(items) To UBound(items)
If item = items(u)(2) Then
MsgBox "item already exists"
ar = items(u)
For i = 3 To lastCol
ar(i) = ar(i) + ws.Cells(iRow, i)
Next
items(u) = ar
dict(sKey) = items
itemAdded = True
End If
Next
If Not itemAdded = True Then
MsgBox "adding new item"
For i = 2 To lastCol
ar(i) = ws.Cells(iRow, i)
Next
items(u) = ar
dict(sKey) = items
End If
End If
Next
What is working is that I can recall Items(u)(2) and see the name of an item. But the If item = items(u)(2) Then statement is giving me a type mismatch even though it passes as true on the first loop, why? I tried declaring as String and as Variant but neither combination is working.
https://imgur.com/4eKak8q
Related
Hey I am a trainee as an IT-Specialist and my trainer gave me a task to complete a macro for excel. (I don't know anything about VBA)
I have to check the cells in a column for the value 1. If there is a 1 I need to store that value in a array.
That's what I did till now.
Sub test()
Dim sht As Worksheet
Dim LastColumn As Long
Dim LastRow As Long
Dim MyArray() As Single
Set sht = ThisWorkbook.Worksheets("Tabelle1")
LastRow = sht.Cells.SpecialCells(xlCellTypeLastCell).Row
MsgBox LastRow
MsgBox Join(MyArray)
End Sub
Sub createArray(x As Variant)
Dim sht As Worksheet
Dim LastRow As Long
Dim tempArray() As String
Dim rowVal As String
Dim MyArray() As Single
Dim i As Integer
Dim j As Integer
Dim rang As Range
Dim arrayEntry As String
Set sht = ThisWorkbook.Worksheets("Tabelle1")
Set rang = sht.Range("A:A") ' // SET RANGE TO LOOK FOR VALUES
LastRow = rang.SpecialCells(xlCellTypeLastCell).Row
arrayEntry = ""
For i = 1 To LastRow
If sht.Cells(i, 1).Value = x Then ' // (i, 1) <---- '1' references column A -
change to numerical column that you want to loop through
If arrayEntry = "" Then
arrayEntry = x
rowVal = i
Else
arrayEntry = arrayEntry & "," & x
rowVal = rowVal & "," & i
End If
End If
Next i
tempArray = Split(arrayEntry, ",")
ReDim MyArray(UBound(tempArray))
For j = 0 To UBound(tempArray)
MyArray(j) = CInt(tempArray(j))
Next j
Erase tempArray
MsgBox LastRow
MsgBox arrayEntry
MsgBox rowVal
MsgBox (UBound(MyArray) + 1)
End Sub
I am unsure if you wanted the value '1' in the array or the row it appears on, swap x with i if you wanted the row number.
Sub TESTFORMULA()
createArray (1)
End Sub
I am trying to work through a code that utilizes a system to check two different worksheets by using a for loop and highlight the differences/edits made in the second sheet ("Version 2") onto the first sheet ("Original"). I have a feeling that I need to utilize an array but I'm not advanced enough where I know how to store the values and then later write them onto another sheet (down below).
I've gotten the code so that it highlights all the relevant cells, but now I'm trying to output it into a report (on another sheet called 'Logged Changes') which will summarize all the cell addresses where edits were made. Please forgive all the variables as this is from an old code set where variables are not explicitly defined:
Private Sub CompareBasic()
Dim actSheet As Range
Dim k As Integer
Dim o As Long
Dim p As Long
Dim i As Integer
Dim change As Integer
o = Worksheets("Original").Cells(2, Columns.Count).End(xlToLeft).Column
p = Worksheets("Original").Range("A" & Rows.Count).End(xlUp).Row
change = 0
Sheets("Original").Select
For i = 2 To p
For k = 1 To o
If IsNumeric(Worksheets("Original").Cells(i, k).Value) = True Then
If Worksheets("Original").Cells(i, k).Value <> Worksheets("Version 2").Cells(i, k).Value Then
Worksheets("Original").Cells(i, k).Interior.ColorIndex = 37
change = change + 1
End If
Else
If StrComp(Worksheets("Original").Cells(i, k), Worksheets("Version 2").Cells(i, k), vbBinaryCompare) <> 0 Then
Worksheets("Original").Cells(i, k).Interior.ColorIndex = 37
change = change + 1
End If
End If
Next k
Next i
Unload Me
MsgBox "Number of cells edited counted: " & change, vbOKOnly + vbExclamation, "Summary"
b = Empty
answer = MsgBox("Do you want to run the Report?", vbYesNo + vbQuestion)
If answer = vbYes Then
If Sheet_Exists("Logged Changes") = False Then
Sheet_Name = "Logged Changes"
Worksheets.Add(After:=Sheets(Sheets.Count)).Name = Sheet_Name
End If
Worksheets("Logged Changes").Range("A1") = "Edited Requirements"
Else
Unload Me
End If
End Sub
I have tried fiddling around with the code, but didn't want to clog it up with any unnecessary/broken lines. Any help would be greatly appreciated!
Try this:
Option Explicit
Private Sub CompareBasic()
Const SHT_REPORT As String = "Logged Changes"
Dim actSheet As Range
Dim c As Integer
Dim o As Long
Dim p As Long
Dim r As Long
Dim change As Long, wsOrig As Worksheet, wsNew As Worksheet, wsReport As Worksheet
Dim dataOrig, dataNew, rngData As Range, v1, v2, bDiff As Boolean
Dim arrUpdates
Set wsOrig = Worksheets("Original")
Set wsNew = Worksheets("Version 2")
o = wsOrig.Cells(2, Columns.Count).End(xlToLeft).Column
p = wsOrig.Range("A" & Rows.Count).End(xlUp).Row
Set rngData = wsOrig.Range("A2", wsOrig.Cells(p, o))
dataOrig = rngData.Value 'get an array of data
dataNew = wsNew.Range(rngData.Address).Value 'array of new data
ReDim arrUpdates(1 To rngData.Cells.Count, 1 To 3) 'for change info
change = 0
For r = 1 To UBound(dataOrig, 1)
For c = 1 To UBound(dataOrig, 2)
v1 = dataOrig(r, c)
v2 = dataNew(r, c)
If Len(v1) > 0 Or Len(v2) > 0 Then
If IsNumeric(v1) Then
bDiff = v1 <> v2
Else
bDiff = StrComp(v1, v2, vbBinaryCompare) <> 0
End If
End If
'any difference?
If bDiff Then
change = change + 1
With rngData.Cells(r, c)
arrUpdates(change, 1) = .Address
.Interior.ColorIndex = 37
End With
arrUpdates(change, 2) = v1
arrUpdates(change, 3) = v2
End If
Next c
Next r
If MsgBox("Do you want to run the Report?", vbYesNo + vbQuestion) = vbYes Then
With GetSheet(SHT_REPORT, ThisWorkbook)
.UsedRange.ClearContents
.Range("A1") = "Edited Requirements"
.Range("A3").Resize(1, 3).Value = Array("Address", wsOrig.Name, wsNew.Name)
.Range("A4").Resize(change, 3).Value = arrUpdates
End With
Else
'Unload Me
End If
End Sub
'return as sheet from wb by name (and create it if it doesn't exist)
Function GetSheet(wsName, wb As Workbook) As Worksheet
Dim rv As Worksheet
On Error Resume Next
Set rv = wb.Worksheets(wsName)
On Error GoTo 0
If rv Is Nothing Then
Set rv = wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count))
rv.Name = "Logged Changes"
End If
Set GetSheet = rv
End Function
Sheet Differences
Option Explicit
Sub logChanges()
Const ws1Name As String = "Original"
Const ws2Name As String = "Version 2"
Const wsResult As String = "Logged Changes"
Const FirstRow As Long = 2
Const FirstColumn As Long = 1
Const LastRowColumn As Long = 1
Const LastColumnRow As Long = 2
Const ResultFirstCell As String = "A2"
Dim Headers As Variant
Headers = Array("Id", "Address", "Original", "Version 2")
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(ws1Name)
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, LastRowColumn).End(xlUp).Row
Dim LastColumn As Long
LastColumn = ws.Cells(LastColumnRow, ws.Columns.Count) _
.End(xlToLeft).Column
Dim rng As Range
Set rng = ws.Range(ws.Cells(FirstRow, FirstColumn), _
ws.Cells(LastRow, LastColumn))
Dim Data1 As Variant: Data1 = rng.Value
Set ws = wb.Worksheets(ws2Name)
Dim Data2 As Variant: Data2 = ws.Range(rng.Address).Value
Dim Result() As Variant
Dim i As Long, j As Long, k As Long
For i = 1 To UBound(Data1)
For j = 1 To UBound(Data1, 2)
If Data1(i, j) <> Data2(i, j) Then GoSub writeResult
Next j
Next i
If k > 0 Then
transpose2D Result
On Error GoTo MissingResultSheet
Set ws = wb.Worksheets(wsResult)
On Error GoTo 0
ws.Range(ws.Range(ResultFirstCell), _
ws.Cells(ws.Rows.Count, ws.Columns.Count)).Clear
ws.Range(ResultFirstCell).Resize(k, UBound(Result, 2)).Value = Result
MsgBox "Found '" & k & "' difference(s) in range '" _
& rng.Address(False, False) & "'.", vbInformation
Else
MsgBox "Found no differences in range '" _
& rng.Address(False, False) & "'.", vbExclamation
End If
Exit Sub
writeResult:
k = k + 1
ReDim Preserve Result(1 To 4, 1 To k)
Result(1, k) = k
Result(2, k) = getAddress(i + FirstRow - 1, j + FirstColumn - 1)
Result(3, k) = Data1(i, j)
Result(4, k) = Data2(i, j)
Return
MissingResultSheet:
If Err.Number = 9 Then
wb.Worksheets.Add After:=wb.Sheets(wb.Sheets.Count)
With ActiveSheet
.Name = wsResult
If .Range(ResultFirstCell).Row > 1 Then
.Range(ResultFirstCell).Offset(-1) _
.Resize(, UBound(Headers) + 1).Value = Headers
End If
End With
Resume ' i.e. the code continues with Set ws = wb.Worksheets(wsResult)
Else
'?
Exit Sub
End If
End Sub
Function getAddress(aRow As Long, aColumn As Long) As String
getAddress = ActiveSheet.Cells(aRow, aColumn).Address(False, False)
End Function
Sub transpose2D(ByRef Data As Variant)
Dim i As Long, j As Long
Dim Result As Variant
ReDim Result(LBound(Data, 2) To UBound(Data, 2), _
LBound(Data) To UBound(Data))
For i = LBound(Data) To UBound(Data)
For j = LBound(Data, 2) To UBound(Data, 2)
Result(j, i) = Data(i, j)
Next j
Next i
Data = Result
End Sub
This solution for converting a column number to a string without using objects Function to convert column number to letter? could be used to write a descent getAddress function.
I have an array with fixed values. How can I find cells in Column B that contain all the 'String' values present in array?
Here is my code
With Worksheets("Data")
Dim kwrSets As Variant
.Activate
kwrSets = .Range("B2:B" & Application.WorksheetFunction.Max(2, .Range("A100000").End(xlUp).Row)).Value
For k = LBound(kwrSets) To UBound(kwrSets)
For i = LBound(arr) To UBound(arr)
Delete entire row if all values of arr not found in kwrSets
Next i
Next k
End With
Following is the updated code based on the answer below but it is giving error "Subscript out of range" in inStr line.
Sub Extractor()
Dim ws As Worksheet, wsd As Worksheet
Dim cell As Variant
Dim tmp As Variant
Dim blnFound As Boolean
Dim j As Long, i As Long
Dim kwrSets() As Variant
Dim arr() As String
Set ws = Worksheets("Sheet1")
With ws
.Activate
For Each cell In .Range("A1:A" & .Cells(.Rows.Count, "B").End(xlUp).Row)
If (cell.Offset(0, 2) = 1) Then
tmp = tmp & cell & "|"
End If
Next cell
If Len(tmp) > 0 Then tmp = Left(tmp, Len(tmp) - 1)
arr = Split(tmp, "|")
End With
Set wsd = Worksheets("Data")
With wsd
.Activate
kwrSets = .Range("B2:B" & Application.WorksheetFunction.Max(2, .Range("A100000").End(xlUp).Row)).Value
For k = LBound(kwrSets) To UBound(kwrSets)
blnFound = True
For i = LBound(arr) To UBound(arr)
If InStr(kwrSets(j, 1), arr(i)) = 0 Then
blnFound = False
Exit For
End If
Next i
Next k
End With
End Sub
Below is some VBA code that gets all of the data in column B into an array, then loops this array checking for the existence of each of the elements in the search array. If any of the search elements are not found, then it exits that loop. If all elements are found then it highlights the cell.
Sub sFindArray()
Dim ws As Worksheet
Dim aSearch() As Variant
Dim aData() As Variant
Dim lngLoop1 As Long
Dim lngLoop2 As Long
Dim lngFirstRow As Long
Dim lngLastRow As Long
Dim lngLBound As Long
Dim lngUBound As Long
Dim blnFound As Boolean
aSearch = Array("a", "b", "c")
lngLBound = LBound(aSearch)
lngUBound = UBound(aSearch)
Set ws = Worksheets("Sheet1")
lngLastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
aData() = ws.Range("B1:B" & lngLastRow)
lngFirstRow = LBound(aData, 1)
lngLastRow = UBound(aData, 1)
For lngLoop1 = lngFirstRow To lngLastRow
blnFound = True
For lngLoop2 = lngLBound To lngUBound
If InStr(aData(lngLoop1, 1), aSearch(lngLoop2)) = 0 Then
blnFound = False
Exit For
End If
Next lngLoop2
If blnFound = True Then
ws.Cells(lngLoop1, 2).Interior.Color = vbRed
End If
Next lngLoop1
End Sub
Regards,
I've got a sub representing a commandbutton of my userform, this userform has the perpose of listing (in a listbox) all unique items found in a column of a two-dimensional array. At frst I would like to implant an extra variable to hold and thus represent the number of times the unique item appears in the array. Secondly I would like the (Unique) items listed as:
Unique item 1 (number of appearances).
Example 1 (23)
Example 2 (39)
Example 3 (101)
Example 4 (9)
...
Example n (#)
Here is the code, can some body help me out?
Private Sub CommandButton5_Click()
Dim ws As Worksheet
Dim dictUnq As Object
Dim UnqList() As String
Dim aData As Variant
Dim vData As Variant
Dim pData As Variant
Dim i As Variant
Dim PrintString1() As String
i = 1
Set ws = ActiveWorkbook.Sheets("Sheet3")
Set dictUnq = CreateObject("Scripting.Dictionary")
Application.ScreenUpdating = False
Application.EnableEvents = False
With ws.Range("G2", ws.Cells(ws.Rows.Count, "G").End(xlUp))
If .Row < 2 Then Exit Sub 'No data
If .Cells.Count = 1 Then
ReDim aData(1 To 1, 1 To 1)
aData(1, 1) = .Value
Else
aData = .Value
End If
End With
SBI_Omschrijving.ListBox1.Clear
For Each vData In aData
If Len(vData) > 0 Then
If Not dictUnq.exists(vData) Then dictUnq.Add vData, vData
End If
Next vData
Debug.Print dictUnq(vData)
SBI_Omschrijving.ListBox1.List = dictUnq.keys
MsgBox "Unique findings: " & dictUnq.Count
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Use a dictionary to store the count? This demonstrates the principle. Note in your example I think you may only be adding one column G so I don't know of you intended more?
Sub test()
Dim myArray()
myArray = ActiveSheet.Range("A1").CurrentRegion.Value
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim i As Long
For i = LBound(myArray, 1) To UBound(myArray, 1) 'Depending on column of interest. Loop that
If Not dict.Exists(myArray(i, 1)) Then
dict.Add myArray(i, 1), 1
Else
dict(myArray(i, 1)) = dict(myArray(i, 1)) + 1
End If
Next i
Dim key As Variant
For Each key In dict.keys
Debug.Print key & "(" & dict(key) & ")"
Next key
End Sub
Your example might be something like (can't test dictionary on a mac I'm afraid so coding in my head)
Sub test()
Dim aData()
Dim ws As Worksheet
Dim targetRange As Range
Dim lastRow As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, "G").End(xlUp).Row
If lastRow = 1 Then Exit Sub
Set targetRange = ws.Range("G2:G" & lastRow)
If targetRange.Cells.Count = 1 Then
ReDim aData(1 To 1, 1 To 1)
aData(1, 1) = targetRange.Value
Else
aData = targetRange.Value2
End If
Dim dictUnq As Object
Set dictUnq = CreateObject("Scripting.Dictionary")
Dim i As Long
For i = LBound(aData, 1) To UBound(aData, 1) 'Depending on column of interest. Loop that
If Not dictUnq.Exists(aData(i, 1)) Then
dictUnq.Add aData(i, 1), 1
Else
dictUnq(aData(i, 1)) = dictUnq(aData(i, 1)) + 1
End If
Next i
Dim key As Variant
For Each key In dictUnq.keys
Debug.Print key & "(" & dictUnq(key) & ")"
Next key
End Sub
another possibility
Option Explicit
Private Sub CommandButton5_Click()
Dim dictUnq As Object
Set dictUnq = CreateObject("Scripting.Dictionary")
Dim cell As Range
With ActiveWorkbook.Sheets("Sheet3")
For Each cell In .Range("G2", .Cells(.Rows.Count, "G").End(xlUp))
dictUnq(cell.Value) = dictUnq(cell.Value) + 1
Next
End With
If dictUnq.Count = 0 Then Exit Sub
Dim key As Variant
With SBI_Omschrijving.ListBox1
.Clear
.ColumnCount = 2
For Each key In dictUnq.keys
.AddItem key
.List(.ListCount - 1, 1) = dictUnq(key)
Next
End With
MsgBox "Unique findings: " & dictUnq.Count
End Sub
I have the following code below,
I want to filter the array (not the sheet) for the word "phone" which sits in column 3 of the array. The output would then go to my destination sheet("L")
how would i modify the code below to filter for the word? I must state i want to filter the array not the sheet.
Sub Example1()
Dim arrValues() As Variant
Dim lastRow As Long
Dim filteredArray()
Dim lRow As Long
Dim lCount As Long
Dim alength As Long
lastRow = Sheets("Raw Data").UsedRange.Rows(Sheets("Raw Data").UsedRange.Rows.Count).Row
arrValues = Sheets("Raw Data").Range(Cells(2, 1), Cells(lastRow, 21)).Value
ReDim filteredArray(1 To UBound(arrValues), 1 To 1)
alength = UBound(arrValues)
For lCount = 1 To UBound(arrValues) Step 1
lRow = lRow + 1
filteredArray(lRow, 1) = arrValues(lCount, 1)
Next
Sheets("L").Range("A2:U" & 1 + alength) = filteredArray
End Sub
You could do something like this:
Sub Example1()
Dim arrValues() As Variant
Dim lastRow As Long
Dim filteredArray()
Dim lRow As Long
Dim lCount As Long
Dim tempArray()
lastRow = Sheets("Raw Data").UsedRange.Rows(Sheets("Raw Data").UsedRange.Rows.Count).Row
arrValues = Sheets("Raw Data").Range(Cells(2, 1), Cells(lastRow, 21)).Value
' First use a temporary array with just one dimension
ReDim tempArray(1 To UBound(arrValues))
For lCount = 1 To UBound(arrValues)
If arrValues(lCount, 3) = "phone" Then
lRow = lRow + 1
tempArray(lRow) = arrValues(lCount, 1)
End If
Next
' Now we know how large the filteredArray needs to be: copy the found values into it
ReDim filteredArray(1 To lRow, 1 To 1)
For lCount = 1 To lRow
filteredArray(lCount, 1) = tempArray(lCount)
Next
Sheets("L").Range("A2:U" & 1 + lRow) = filteredArray
End Sub