error 424 object required error - arrays

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.

Related

Create a VBA Array from Column Headers?

I have a an export "NewExport" that always randomizes the columns of data I receive. I need these columns to align with the order of columns in "TheOrder", so this code will help to re-organize the export to align with the column headers I've already built.
I have 132 columns that need re-alignment, and while I can type it all out, there must be an easier way to align with the column headers I've already created. It should be noted that the below code is shamelessly copy/pasted from another StackOverflow answer.
Sub OrderColumns(ByVal NewExport As Workbook, ByVal TheOrder As Worksheet)
Dim correctOrder() As Variant
Dim lastCol As Long
Dim headerRng As Range, cel As Range
Dim mainWS As Worksheet
Set mainWS = NewExport.Worksheets("Sheet1")
'Need to figure out how to make this an array based on a Range
correctOrder() = Array(TheOrder.Range("A1:A132").Value)
With mainWS
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
Set headerRng = .Range(.Cells(1, 1), .Cells(1, lastCol))
End With
Dim newWS As Worksheet
Set newWS = Ninja.Sheets.Add
newWS.Name = "Rearranged Sheet"
Dim col As Long
With newWS
For col = 1 To lastCol
For Each cel In headerRng
If cel.Value = correctOrder(col - 1) Then
mainWS.Columns(cel.Column).Copy .Columns(col)
Exit For
End If
Next cel
Next col
End With
End Sub
While it's not as automated as I would have liked (and requires one piece of hard-coding), I was able to find a solution as such:
Dim correctOrder(132) As Variant
'132 will need to be changed if there's ever any more/less columns added/excluded
For i = 1 To 132
correctOrder(i - 1) = TheOrder.Range("A" & i).Value
Next
This solution gave me the array I was looking for for use later on.
I recently wrote a 'column finder' function for a project of mine.
I've modified it to suit your requirements below.
The function requires you pass the workbook your correct ordered headings are in to capture. You could modify this to require your TargetWorksheet instead so it's a bit more dynamic.
The function returns a single dimension Array.
The function finds the last used Column in the Target Worksheet allowing for changes in the number of column headings (as mentioned in your own answer which has the column number hard coded).
Public Function CorrectOrderHeadingsArrayFunction(ByRef TargetWorkbook As Workbook) As Variant()
With TargetWorkbook.Sheets(1) 'Change this to target your correct sheet
Dim LastColumn As Long
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
CorrectOrderHeadingsArrayFunction= Application.Transpose(Application.Transpose(.Range(.Cells(1, 1), .Cells(1, LastColumn)).Value)) 'This returns the array as single dimension rather than 2D
End With
End Function
As an example, below is some sample 'Test' code to show the concept of using this function .
You could call it like so, and loop through each element perhaps comparing another arrays elements to the correct order elements and do something when the correct order value is found.
Sub TestSub()
Dim CorrectOrderArray As Variant
Dim TargetCorrectOrderElement As Variant
Dim RandomOrderArray As Variant
Dim TargetRandomOrderElement As Variant
CorrectOrderArray = CorrectOrderHeadingsArrayFunction(Workbooks("Export (4).csv")) 'Change this to target your correct workbook
RandomOrderArray = Sheet1.Range("A1:AZ1000") 'Change this to target the correct range for your data.
For Each TargetCorrectOrderElement In CorrectOrderArray
For TargetRandomOrderElement = LBound(RandomOrderArray) To UBound(RandomOrderArray)
If RandomOrderArray(TargetRandomOrderElement) = TargetCorrectorderValue Then
'Do some code to write that column to your worksheet
Exit For 'Leaves the current iteration of the random order array loop to go to the next iteration of the correct order array
End If
Next TargetRandomOrderElement
Next TargetCorrectOrderElement
End Sub

Delete all contents except for first row for specific sheets in Excel

Please assist. I have this code here and it works for first sheet however, does not execute in the 2nd sheet. I think i'm missing a sheet syntax. thanks.
Dim arrSheets As Variant, sht As Variant
arrSheets = Array("tl_1", "tl_2")
For Each sht In arrSheets
Sheets(sht).UsedRange.Offset(1).ClearContents
Next sht
My 2 cents: do not rely on worksheet names. Instead, work with their (Name) property as seen from the Visual Basic Editor. Note that you can give significant names yourself instead of the default Sheet1..N ones. This way, your code will survive modifications to the names as seen from Excel, in the tabs at the bottom.
Option Explicit
Public Sub DoTheClearThing()
Dim loopVariant As Variant
Dim loopWorksheet As Excel.Worksheet
Dim worksheetsToConsider As Variant
'Use the (Name) property, as seen from the Visual Basic Editor, of the worksheets you're interested in.
'The array below is not a string array; it is an array of worksheet objects.
worksheetsToConsider = Array(TL_1, TL_2)
'The For's variable must be a Variant; you can then Set it to a variable of the Worksheet type and enjoy Intellisense.
For Each loopVariant In worksheetsToConsider
Set loopWorksheet = loopVariant
loopWorksheet.UsedRange.Offset(1).ClearContents
Next
End Sub
Here's what the worksheets' (Name) properties look like in my test Excel workbook:
From within your workbook's code, you can directly interact with worksheet objects using their (Name) property. Avoid ThisWorkbook.Worksheets("tl_1").SomeMethod and directly go with TL_1.SomeMethod. By the way, a worksheet's (Name) property can be read by code using its CodeName property.
Option Explicit
'This will do something to your target sheets,
'just make sure your "something" is what you want
Dim N As Long
Dim wsName As String
'Optional if included
For N = 1 To ThisWorkbook.Sheets.Count
wsName = ThisWorkbook.Worksheets(N).Name
If wsName = "tl_1" or wsName = "tl_2" Then
ThisWorkbook.Worksheets(N).UsedRange.Offset(1).ClearContents
Else 'Do Nothing
End If
Next N
Note: This is very worksheet name dependent and users can change those if you are not the only user. You may want to CodeName your sheets (properties Explorer and change the Name) then pull the CodeName.
You can use an array to hold the sheets names but it seems like more trouble than its worth unless you are going to load the names into the array.
-WWC
Worksheet.UsedRange does not always return the correct address. Consider the results of the test below:
Test Used Range
Sub Test()
Application.ScreenUpdating = False
Dim cell As Range, target As Range
Debug.Print "Data Range", "|"; "UsedRange"
Debug.Print String(24, "_")
With Worksheets.Add
Set target = .Range("B2:D2")
target.Value = 1
Debug.Print target.Address, "|"; .UsedRange.Address
End With
With Worksheets.Add
.Range("A1:G10").Interior.Color = 65535
Set target = .Range("B2:D2")
target.Value = 1
Debug.Print target.Address, "|"; .UsedRange.Address
End With
End Sub
Clear Non-Headers
Sub ClearNonHeaderRows()
Dim arrSheets As Variant, sht As Variant
Dim cell As Range
arrSheets = Array("tl_1", "tl_2")
For Each sht In arrSheets
With Worksheets(sht).UsedRange
Set cell = .Find("*", .Cells(1, 1))
If Not cell Is Nothing Then
cell.Offset(1).Resize(.Cells.Rows.Count - cell.row + .Cells(1, 1).row).EntireRow.ClearContents
End If
End With
Next sht
End Sub

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

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

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

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