Loop through cells in column, store specific value in array - arrays

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

Related

Finding Cells in which all values of fixed array are present

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,

Implanting an extra variable to count the number of times an "unique" item is found in an array.

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

Adding values to a dynamic array and then printing to specified cell

I'm searching a range in my sheet for certain values when either of these values is found I want to add the value from column A of that row to an array, only adding values that are not already present in the array. Once the range has been searched, I want to print the arrays to specified cells in the worksheet in 2 different columns.
Here's my code so far:
Dim Ws As Worksheet
Set Ws = Sheets("Sheet1")
Dim Leave() As Variant, Join() As Variant
Dim LastCol As Integer, LastRow As Integer, i As Integer, Z As Integer
Dim J As Long, L As Long
With Sheets("Sheet1")
'Find Last Col
LastCol = Sheets("Sheet1").Cells(3, Columns.Count).End(xlToLeft).Column
'Find last Row
LastRow = Sheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row
LastRow = LastRow - 1
'ReDim Leave(1 To (LastRow - 1), LastCol)
'ReDim Join(1 To (LastRow - 1), LastCol)
For i = 5 To LastCol
For Z = 4 To LastRow
If Sheets("Sheet1").Cells(Z, i).Value = "0" Then
Leave(L) = Ws.Cells(Z, 1).Value
ElseIf Sheets("Sheet1").Cells(Z, i).Value = "-2" Then
Join(J) = Ws.Cells(Z, 1).Value
End If
Next Z
Next i
'Print array
End With
Thanks for any pointers/help in advance!
I believe this procedure accomplishes what you are looking for. You will need to modify the range in which you are searching and the destination sheet information, but the meat of the procedure is here:
Sub abc_Dictionary()
Dim oWS As Worksheet
Dim RangeToSearch As Range
Dim myCell As Range
Dim UniqueDict As Object
Set oWS = Worksheets("Sheet1")
Set RangeToSearch = oWS.Range("B1:B26") 'You can set this dynamically however you wish
Set UniqueDict = CreateObject("Scripting.Dictionary")
'Now we search the range for the given values.
For Each myCell In RangeToSearch
If (myCell.Text = "0" Or myCell.Text = "-2") And Not UniqueDict.exists(oWS.Range("A" & myCell.Row).Text) Then
UniqueDict.Add oWS.Range("A" & myCell.Row).Text, oWS.Range("A" & myCell.Row).Text
End If
Next
'Now we have a dictionary object with the unique values of column a
'So we just iterate and dump into Sheet2
Dim d As Variant
Dim Val As Variant
Dim DestRow As Integer
DestRow = 1 'This is the first row of data we will use on Sheet 2
d = UniqueDict.Items
For Each Val In d
Worksheets("Sheet2").Range("A" & DestRow).Value = Val
DestRow = DestRow + 1
Next
Set UniqueDict = Nothing
Set RangeToSearch = Nothing
Set oWS = Nothing
End Sub

Store unique values in an array then print them in another sheet

I am working on a project that involves finding a particular column in a spreadsheet, then storing only unique values in that column into an array and then printing that array on another sheet. My code is erroring out due to both a type mismatch and a with block not being set, but I can't seem to figure out why. Any help would be greatly appreciated.
Option Explicit
Sub Find_Distincts_Policies()
Dim aCell As Range, rng As Range
Dim varIn As Variant, varUnique As Variant, element As Variant
Dim isUnique As Boolean
Dim ws As Worksheet
Dim wkb As Workbook
Dim colName As Long
Dim i As Long, j As Long, k As Long
Dim iInCol As Long, iInRow As Long, iUnique As Long, nUnique As Long, LastRow As Long
Set wkb = ThisWorkbook
Set ws = wkb.Worksheets("Sheet2")
With ws
Set aCell = .Range("A1:ZZ4").Find(what:="Unique Number", LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False)
If Not aCell Is Nothing Then
colName = Split(.Cells(, aCell).Address, "$")(1)
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set rng = .Range(colName & "2:" & colName & LastRow)
varIn = rng.Value
ReDim varUnique(1 To UBound(varIn, 1) * UBound(varIn, 2))
nUnique = 0
For iInRow = LBound(varIn, 1) To UBound(varIn, 1)
For iInCol = LBound(varIn, 2) To UBound(varIn, 2)
isUnique = True
For iUnique = 1 To nUnique
If varIn(iInRow, iInCol) = varUnique(iUnique) Then
isUnique = False
Exit For
End If
Next iUnique
If isUnique = True Then
nUnique = nUnique + 1
varUnique(nUnique) = varIn(iInRow, iInCol)
End If
Next iInCol
Next iInRow
ReDim Preserve varUnique(1 To nUnique)
MsgBox varUnique
Else: Exit Sub
End If
End With
With wkb
.Worksheets.Add.Name = "Unique values"
ActiveSheet.Range("A1") = varIn
End With
End Sub

Error in converting Range to arrays

Anybody please help me figure my problem out?
Dim attPresent as Variant ' attpresent()
Set ws = thisworkbook.sheets("Sheet1")
lastrow = ws.cells(Rows.count, 8).end(xlup).row
attPresent = ws.Range("H4:H" & lastrow).Value 'errors if I use Dim attPresent() As Variant
For k = LBound(attPresent, 1) To UBound(attPresent, 1) ' Dim attPresent As Variant'errors if I use
msgbox attpresent(k,1)
Next
This line attPresent = ws.Range("H4:H" & lastrow).Value returns an error if I declare the variable as Dim attPresent() As Variant. Whereas, if declare the variable as Dim attPresent As Variant, this line For k = LBound(attPresent, 1) To UBound(attPresent, 1) errors.
Can anyone please help me clear this out?Thanks
As a good practice, try to remember to use Option Explicit, and also declare all your variables.
When you use Dim attPresent() As Variant to declare you array , and later on you insert values from a Range to your Array with attPresent = .Range("H4:H" & lastrow).Value, it will automatically Redim your array to 2-dimensinal array (1 to Row number, 1 to Column Number).
Option Explicit
Sub RngtoArray()
Dim attPresent() As Variant
Dim ws As Worksheet
Dim lastrow As Long
Dim k As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lastrow = .Cells(.Rows.Count, 8).End(xlUp).Row
attPresent = .Range("H4:H" & lastrow).Value
End With
For k = 1 To UBound(attPresent, 1)
MsgBox attPresent(k, 1)
Next
End Sub
Edit 1: A slightly different approach, in case there is only 1 cell in the Range:
With ws
lastrow = .Cells(.Rows.Count, 8).End(xlUp).Row
' for single column only - create a 1-Dimension array
ReDim attPresent(1 To lastrow - 4 + 1) ' when the Range starts from "H4"
For k = 1 To UBound(attPresent)
attPresent(k) = .Cells(4 + k - 1, "H")
Next k
End With
For k = 1 To UBound(attPresent)
MsgBox attPresent(k)
Next
I tried to separate the stuff that you had already defined but for clarity I thought I'd provide my full code:
Sub test()
Dim lastrow, i As Integer
Dim ws As Worksheet
Set ws = ActiveWorkbook.Worksheets("Sheet1")
Dim attPresent() As Variant
lastrow = ws.Cells(Rows.Count, "H").End(xlUp).Row
ReDim attPresent(lastrow - 4)
For i = 4 To lastrow
attPresent(i - 4) = ws.Range("H" & i).Value
Next
msg = Join(attPresent, " ")
MsgBox "The array holds: " & vbNewLine & msg
End Sub
I defined the array without a size to begin with then redefined it to the size it needs to be at a later stage once you know the lastrow (as you started on 4 i deducted 4 from lastrow).
I guessed the msgBox was to test what you had gathered so I created a dump that prints them all into one box but obviously change that if you have a lot of data. xD
To work with arrays I always loop through each individual entry, storing them one at a time. I'm not even sure whether you can dump an entire range into one in one step as I've never even looked into it. Anyway, I hope this solves your problem kupo.
Function RangeToArray(rng As Range)
Dim myArray() As Variant, ws As Worksheet
fr = rng.Row
fc = rng.Column
r = rng.Rows.Count
c = rng.Columns.Count
Set ws = rng.Worksheet
ReDim myArray(r - 1, c - 1)
For i = 0 To r - 1
For j = 0 To c - 1
myArray(i, j) = ws.Cells(fr + i, fc + j).Value2
Next j
Next i
RangeToArray = myArray
End Function
Sub f()
Dim rng As Range, attPresent() As Variant ' attpresent()
Set ws = ThisWorkbook.ActiveSheet 'Sheets("Sheet1")
lastrow = ws.Cells(Rows.Count, 8).End(xlUp).Row
Set rng = ws.Range("H4:H" & lastrow)
attPresent = RangeToArray(rng)
For k = LBound(attPresent, 1) To UBound(attPresent, 1) ' Dim attPresent As Variant'errors if I use
MsgBox attPresent(k, 0)
Next
End Sub
I created a more generic function that you can call in this specific case as well.

Resources