How to insert data in the array (inside a loop)? - arrays

I have a problem with inserting data to the array. In the program I search all cells with "Data:" value. If this value appear I jump to the cell on the right and mark it. I want to collect all marked values (all of them are dates) in the array but with my code (enclosed below) I have an error. I have tried ReDim and setting an exact number of objects in the array. I would be grateful for a help.
Sub CheckData()
Dim FindIt As Range
Dim EndIt As Range
Dim StartAddress As String
With Range("A1:A100")
Set EndIt = .Cells(.Cells.Count)
End With
Set FindIt = Range("A1:A100").Find(what:="Data:", after:=EndIt)
If Not FindIt Is Nothing Then
StartAddress = FindIt.Address
End If
Dim Tabel() As Variant
Tabel = Array()
i = 0
Do Until FindIt Is Nothing
Set FindIt = Range("A1:A100").FindNext(after:=FindIt)
Data = FindIt.Address
Range(Data).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.Interior.ColorIndex = 6
'Debug.Print ActiveCell.Value
Tabel(i) = ActiveCell.Value
i = i + 1
'Debug.Print i
If FindIt.Address = StartAddress Then
Exit Do
End If
Loop
End Sub

You never sized your array.
Dim Tabel() As Variant
Use ReDim to resize a dynamically-sized array.
ReDim Preserve Tabel(0 To UBound(Tabel)+1)
However that's a terribly inefficient thing to do in a loop (you're copying the same elements over and over and over and over again, at every single iteration).
Rule of thumb, if you don't know from the start how many elements you're going to need, it's probably best to use a Collection instead of an array.
Dim items As Collection
Set items = New Collection
'...
items.Add ActiveCell.Value

You could also use a for loop instead of a find (also using Mat's Mug idea about collections)
Sub CheckData1()
Dim ws As Worksheet
Dim searchRng As Range
Dim cell As Range
Dim tabel As Collection 'incorrectly spelt table?
Set ws = ActiveSheet
Set tabel = New Collection
Set searchRng = ws.Range("A1:A100")
For Each cell In searchRng.Cells
If cell.Value = "Data:" Then
tabel.Add cell.Offset(, 1)
cell.Offset(, 1).Interior.ColorIndex = 6 'If you still need it highlighted
End If
Next
End Sub

Related

Reduce Array to only unique values

I have an array that looks like this:
ABCZZZZDEFGHGAAA
I want to shrink it down to each letter only once:
ABCZDEFGH
It doesn't need to be alphabetically sorted.
I want to fill a ListBox so it is important that no empty values are included.
Nothing like:
ABCZ____DEFGH____
Even Though its a little bit late here a code example I did myself to compenasate for prior mistakes (this could be used as a pretty universal solution for the Problem, hopefully helpfull for somebody in the future)
Dim i As integer
For i = LBound(ExampleArray) To UBound(ExampleArray)
d(ExampleArray(i)) = 1
Next i
At least for me this dictionary method did the trick.
You can easily get a list of unique values with a dictionary
Dim Uniques As Object
Set Uniques = CreateObject("Scripting.Dictionary")
For Each c In YourArray
If Not Uniques.exists(c) Then
Uniques.Add c, c
End If
Next c
YourListBox.List = Uniques.keys
'Not sure if this is what you are looking for but this delete duplicates in column A
Option Explicit
Sub dupedelete()
Dim ws As Worksheet
Dim dict As Object
Dim lastrow As Long
Dim str As String
Set ws = Worksheets("Sheet1")
Set dict = CreateObject("Scripting.Dictionary")
lastrow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Do While lastrow > 1
str = ws.Cells(lastrow, 1).Value
If dict.exists(str) Then
ws.Rows(lastrow).EntireRow.Delete
Else
dict.Add str, 0
End If
lastrow = lastrow - 1
Loop
Set dict = Nothing
End Sub

VBA Copy/paste static ranges to static ranges in dynamically built array of worksheets

I am trying to copy the cell values of 4 static ranges from one worksheet and paste those values into the cells within 4 static ranges for each worksheet that is included in my dynamically built list.
Here is my code:
Sub retpsh()
Dim Home As Worksheet: Set Home = Worksheets("Home")
Dim s3 As Worksheet: Set s3 = Worksheets("Sheet3")
Dim s9 As Worksheet: Set s9 = Worksheets("Sheet9")
Dim s5 As Worksheet: Set s5 = Worksheets("Sheet5")
Dim s7 As Worksheet: Set s7 = Worksheets("Sheet7")
Dim Back As Worksheet: Set Back = Worksheets("Home Backstage")
Dim wsarray As Variant
Dim message As String: message = Back.Cells(18, 13)
Dim ws As Variant
If Back.Cells(18, 19) = 0 Then
If MsgBox("Nothing selected!", vbOKOnly) = vbOK Then Exit Sub
Else
If MsgBox(message + " Do you wish to continue?", vbYesNo) = vbNo Then Exit Sub
wsarray = Array(Back.Cells(18, 19)) 'Doesn't work properly
End If
For Each ws In wsarray
ws.Range("C2:C5", "C8:C11", "C13", "B18:C22") = Worksheets("Home Backstage").Range("B1:B4", "B6:B9", "B11", "B18:C22").Value '''''450 error with or without "Set" before line
Next ws
End Sub
First, wsarray = Array(Back.Cells(18, 19)) does not work as it is not parsing that cell value, it takes the whole thing as a single value (i.e. "s3","s5","s7","s9" or whatever the cell value is). Back.Cells(18, 19) has a formula that builds the list based on the 4 options selected on the "Home" page. The formula builds the list to be any of the 16 combinations of: s3, s5, s7, or s9. The final cell value looks like: "s3" or like "s3","s7","s9". Using just Dim wsarray() or wsarray() = doesn't change the behavior. Any time I use wsarray() without Array(...) I get a '13' Type mismatch error.
Is this a matter of dynamically defining the dimensions of the array
first?
If not, is there a way to parse the cell value into the array?
If not, how would I build the array list dynamically in VBA?
Second, even bypassing the above issues by specifying the array manually, I still get a '450' Wrong number of arguments or invalid property assignment error. I know setting one range with multiple nonconsecutive cells = another range setup the same way works fine (e.g. Range("K15:C18","C29") = Range("C1:C4","C15")), so:
Why is that syntax not working within the For loop?
Third, the statement within the For loop needs the fully qualified name Worksheets("Home Backstage") and did not accept the alias Back.
Why does the For not accept the worksheet alias Back?
Does the For loop act outside of the Dim's that are setup prior to it thus needing the Dim within the loop?
I know I could get around all of this with a bunch of If statements and referencing the state of each of the 4 options on the "Home" page to determine which worksheets to copy to, but I don't like that idea. That doesn't seem to be the right way to go about this, having a bunch of duplicated code with slight changes to predicates hence my desire to use an array. Nevertheless, my questions are more "why" than "how", but I appreciate any guidance or explanations all the same!
Here's another option, very similar to Scott's, but making use of a few more arrays to handle your ranges:
Sub retpsh()
Dim Back As Worksheet: Set Back = Worksheets("Home Backstage")
Dim wsarray As Variant
Dim fromRangeArray As Variant
Dim toRangeArray As Variant
Dim message As String: message = Back.Cells(18, 13)
Dim ws As Variant
If Back.Cells(18, 19) = 0 Then
If MsgBox("Nothing selected!", vbOKOnly) = vbOK Then Exit Sub
Else
If MsgBox(message + " Do you wish to continue?", vbYesNo) = vbNo Then Exit Sub
wsarray = Split(Back.Cells(18, 19).Value, ",")
End If
'Could do this into a single multidimensional array if you are a sadist
fromRangeArray = Array("B1:B4", "B6:B9", "B11", "B18:C22")
toRangeArray = Array("C2:C5", "C8:C11", "C13", "B18:C22")
'loop through sheet names
For Each ws In wsarray
For rngIndex = 0 To UBound(fromRangeArray)
Sheets(ws).Range(toRangeArray(rngIndex)).Value = Back.Range(fromRangeArray(rngIndex)).Value
Next rngIndex
Next ws
End Sub
You will need to enter the actual sheet names in the cell:
sheet9,sheet7
equating a string or variable with a variable name does not work, so you will need to loop through the array created by Split and make sure the sheet exists, then use it.
You cannot use range with more than two cell references. Range expects a start and a finish.
Sub retpsh()
Dim Home As Worksheet: Set Home = Worksheets("Home")
Dim Back As Worksheet: Set Back = Worksheets("Home Backstage")
Dim wsarray() As String
Dim message As String: message = Back.Cells(18, 13)
Dim i As Long
If Back.Cells(18, 19) = 0 Then
If MsgBox("Nothing selected!", vbOKOnly) = vbOK Then Exit Sub
Else
If MsgBox(message + " Do you wish to continue?", vbYesNo) = vbNo Then Exit Sub
wsarray = Split(Back.Cells(18, 19).Value, ",")
End If
For i = LBound(wsarray) To UBound(wsarray)
If Not IsError(Application.Evaluate("'" & wsarray(i) & "'!A1")) Then
With Worksheets(wsarray(i))
.Range("C2:C5").Value = Back.Range("B1:B4").Value
.Range("C8:C11").Value = Back.Range("B6:B9").Value
.Range("C13").Value = Back.Range("B11").Value
.Range("B18:C22").Value = Back.Range("B18:C22").Value
End With
End If
Next i
End Sub

Trouble filtering out rows on one worksheet based on an array with values from another worksheet in VBA

My intention was to have the following code compile data from my "Low CPM 1" worksheet into an array and then filter my active worksheet based on this array. While the macro does seem to affect the filters, none of the values get filtered out. Any help on this matter would be greatly appreciated
Sub Macro1()
Dim CPM1Array(0 To 300) As Variant
For i = 2 To UBound(CPM1Array)
CPM1Array(i) = Sheets("Low CPM 1").Cells(i, 2).Value
Next i
ActiveSheet.Range("$A$1:$H$251").AutoFilter Field:=3, Criteria1:=("<>1 to Ubound(CPM1Array)"), Operator:=xlFilterValues
End Sub
There is no simple way with autofilter to achieve what you want. You cannot use Criteria1:="<>MyArray"
Alternative
We know which values we do not want. We can find out what are the values of the relevant column
Simply store the values of the relevant column in an array and then remove the unnecessary values from it by comparing it with the array which has values we do not want.
Remove blank cells from the array
Pass the final array to the autofilter.
In Action
Let's say our worksheet looks like as shown in the below image. I am taking an example of only 15 rows.
Code
Sub Sample()
Dim ws As Worksheet
Dim MyAr(1 To 5) As String
Dim tmpAr As Variant, ArFinal() As String
Dim LRow As Long
ReDim ArFinal(0 To 0)
Set ws = ActiveSheet
'~~> Creating an array of values which we do not want
For i = 1 To 5
MyAr(i) = i
Next i
With ws
'~~> Last Row of Col C sice you will filter on 3rd column
LRow = .Range("C" & .Rows.Count).End(xlUp).Row
'~~> Storing the values form C in the array
tmpAr = .Range("C2:C" & LRow).Value
'~~> Compare and remove values which we do not want
For i = 1 To LRow - 1
For j = 1 To UBound(MyAr)
If tmpAr(i, 1) = MyAr(j) Then tmpAr(i, 1) = ""
Next j
Next i
'~~> Remove blank cells from the array by copying them to a new array
For i = LBound(tmpAr) To UBound(tmpAr)
If tmpAr(i, 1) <> "" Then
ArFinal(UBound(ArFinal)) = tmpAr(i, 1)
ReDim Preserve ArFinal(0 To UBound(ArFinal) + 1)
End If
Next i
'~~> Filter on values which you want. Change range as applicable
.Range("$A$1:$H$15").AutoFilter Field:=3, Criteria1:=ArFinal, Operator:=xlFilterValues
End With
End Sub
Output

error 424 object required error

I'm trying to input the values in a range of cells into an array.
the following code give me an error 424 object required message. Please help
feedingtypes() = wbfeedingtypes.Range("A2:A" & lrowfeedingtypes).Value
I have run and tested the following
Sub RangeToArray()
Dim i As Long
Dim ws As Worksheet
Dim myRange As Range, cell As Range
Dim feedingtypes() As String
Set ws = ThisWorkbook.Worksheets(1)
Set myRange = ws.Range("A1:A20")
i = 1
For Each cell In myRange
'Only add non blanks
If cell.Value <> "" Then
'Resize the array each time another cell is added
ReDim Preserve feedingtypes(i)
feedingtypes(i) = cell.Value
i = i + 1
End If
Next cell
End Sub
I believe this is what you're looking for:
Dim feedingtypes() As Variant
feedingtypes = wbfeedingtypes.Sheets(1).Range("A2:A" & lrowfeedingtypes)
Note, that there are not brackets in the second line of code after the variable name.
Based on your comments it seems there is only one worksheet. Hence, you can also refer to the sheet by number. I changed the answer accordingly.

How to assign excel cell with string to array value in visual basic?

I'm pretty new to visual basic, but I'm having trouble assigning cell values to members of an array. Basically what I am doing is looping through a column and assigning each cell to a new part of the array. Test code is posted below:
Sub Test()
Dim List(5) As String
Dim celltext As String
For i = 1 To 5
celltxt = ActiveSheet.Range("K" & i).Text
List(i) = celltext
MsgBox List(i)
Next i
End Sub
Each time the message box pops up though, it is blank, meaning that the assignment didn't work. The cells at those coordinates DO have values. Any clues?
You are assigning to "celltxt" but reading from "celltext".
Add Option Explicit at the top of every module -- that will make these types of errors more obvious.
When you Dim List(5) As String. The lowest element in the array is 0 and not 1. You might want to change that to Dim List(1 to 5) As String else your first element will always be blank in the array.
You are using ActiveSheet. Are you sure it is the right sheet?
Try this code
Sub Test()
Dim List(1 To 5) As String
Dim ws As Worksheet
Dim i as Long
Set ws = ThisWorkbook.Sheets("Sheet1")
For i = 1 To 5
List(i) = ws.Range("K" & i).Value
MsgBox List(i)
Next i
End Sub
You might also with to try:
Dim List As Variant
Dim i As Long
List = ActiveSheet.Range("K1:K5")
For i = 1 To UBound(List)
MsgBox List(i, 1)
Next i
This will add performance by only reading from the worksheet once instead of each time the loop is looped.

Resources