VBA add array to a list - arrays

Sub RangeBulkAmend()
Set list = list.CreateInstance
Dim c As Range
Dim i As Long
Dim myarr() As Variant
For Each c In Selection
list.Add c.value
Next c
ReDim myarr(list.Count - 1)
For i = 1 To list.Count - 1
myarr(i) = list.Items(i)
msg = msg & vbCrLf & myarr(i)
Next i
{{ListWindow.ListBox1.list = myarr}}
Load ListWindow
ListWindow.Show
end sub
i have an error on the compile as I try to pass my array to a list the code with double braces that where the compiler points too but if I highlight i get the message Object variable or With block variable not set any help will be gladly appreciated thank you
in advance please note the list refereed to in the code above is my own custom list the issue is sending the array to the list box at the double braces checked the code it produces something now to extract that to a list box

If it is only your intention to load a list box with the selected cells values then:
Sub RangeBulkAmend()
Dim myarr() As Variant
myarr = Selection.Value
Load ListWindow
ListWindow.ListBox1.List = myarr
ListWindow.Show
End Sub
Will do it
Or for that matter simply skipping the whole and just assigning the selection.Value to the listbox also works:
Sub RangeBulkAmend()
Load ListWindow
ListWindow.ListBox1.List = Selection.Value
ListWindow.Show
End Sub
To mass add to an existing list in a list box try this:
Sub RangeBulkAmend()
Load ListWindow
Dim myarr() As Variant
Dim oldarr() As Variant
Dim t&, i&
myarr = Selection.Value
t = ListWindow.ListBox1.ListCount
ReDim oldarr(0 To (ListWindow.ListBox1.ListCount + UBound(myarr, 1) - 1)) As Variant
For i = 0 To UBound(oldarr)
If i < ListWindow.ListBox1.ListCount Then
oldarr(i) = ListWindow.ListBox1.List(i)
Else
oldarr(i) = myarr(i - t + 1, 1)
End If
Next i
ListWindow.ListBox1.List = oldarr
ListWindow.Show modal
End Sub

Related

Run-time error '381': Could not set the List property. Invalid property array index

As a single-column listbox, this works and brings back all the data I need, however, upon making this a multi-column listbox, it throws me the error "Run-time error '381': Could not set the List property. Invalid property array index" - see code line ListBox1.List(1, 0) = MyArray(i, 1)
Columns are correctly shown when I add the incorrect List Property and I've tried adding the List Property where I think it should be, but it shows the whole list again and replaces the 2nd row with one of the correct search results, the 1st row never changes.
Main code is from How to filter listbox values based on a Textbox value and I've used the comment by #xris23 to amend into the multi-column listbox thus far.
Please help!
Sub CommandButton1_Click()
Dim i As Long, j As Long, rw As Long
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim ws As Excel.Worksheet
Dim rng As Range
Dim MyArray As Variant
Dim sPath As String
sPath = "U:\GroupEmailDataCut.xlsx"
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
On Error GoTo 0
If xlApp Is Nothing Then
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
End If
Set xlBook = xlApp.Workbooks.Open(sPath)
Set ws = xlBook.Sheets("GroupEmailDataCut")
Set rng = ws.Range("A2:D" & ws.Range("A" & ws.Rows.Count).End(xlUp).Row)
MyArray = rng
With UserForm1.ListBox1
.Clear
.ColumnHeads = False
.ColumnCount = rng.Columns.Count
If ws.Range("A" & ws.Rows.Count).End(xlUp).Row > 1 And Trim(UserForm1.TextBox1.Value) <> vbNullString Then
MyArray = ws.Range("A2:D" & ws.Range("A" & ws.Rows.Count).End(xlUp).Row).Value2
For i = LBound(MyArray) To UBound(MyArray)
For j = LBound(MyArray, 1) To UBound(MyArray, 1)
If InStr(1, MyArray(i, 1), Trim(UserForm1.TextBox1.Value), vbTextCompare) Then
UserForm1.ListBox1.AddItem
ListBox1.List(1, 0) = MyArray(i, 1) '<----Error is across ListBox1.List (MyArray is working as intended)
ListBox1.List(1, 1) = MyArray(i, 2)
ListBox1.List(1, 2) = MyArray(i, 3)
ListBox1.List(1, 3) = MyArray(i, 4)
End If
Next
Next
End If
.List = MyArray
If UserForm1.ListBox1.ListCount = 1 Then UserForm1.ListBox1.Selected(0) = True
End With
End Sub
There are several points to observe to make the command button event readable or even runnable:
Don't address controls by referencing the Userform's default instance (returning the public members of that object),
reference instead the current instance starting either with the Me. qualifier or simply by naming the userform control alone. Understand the Userform (class) code behind as sort of pattern which is blue-printed to the current instance(s).
You are using .AddItem to fill a listbox with items (which is okay for e.g. 4 columns); consider, however that this method automatically builds 10 list columns, but not less or more; this can be avoided .. a) by assigning an entire 2-dim array to the .List (or .Column) property or .. b) by a workaround assigning an empty array plus immediate clearing which allows .AddItem also for greater column numbers (integrated in section 2a)
.List indices are zero-based, i.e. they start with 0 whereas the datafield array with its row and column indices is one-based: .List(cnt, c - 1) = data(r, c) - See section 2b)
Furthermore I separated the check for findings into a help function IsFound(), integrated list assignments into loops and tried to make code more readable by some other intermediate variable declarations.
Private Sub CommandButton1_Click()
'~~~~~~~~~~~~~~
'1) Define data
'~~~~~~~~~~~~~~
'1a)Define search string
Dim srch As String: srch = Trim(Me.TextBox1.Value)
'1b)Define data range
Dim ws As Worksheet: Set ws = Tabelle1
Dim lastRow As Long: lastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Dim rng As Range: Set rng = ws.Range("A2:D" & lastRow)
'1c)Provide for possible exit
If rng.Row < 1 Or srch = vbNullString Then Exit Sub
'1d)Get 1-based 2-dim datafield array
Dim data() As Variant: data = rng.Value
'~~~~~~~~~~~~~~
'2) Fill ListBox
'~~~~~~~~~~~~~~
With Me.ListBox1
'2a)Set listbox properties & clear list
.ColumnHeads = False
.MultiSelect = fmMultiSelectMulti
'Provide for ColumnCount > 10
Dim ColCnt As Long: ColCnt = rng.Columns.Count
.ColumnCount = ColCnt
If ColCnt > 10 Then
Dim tmp(): ReDim tmp(1 To 1, 1 To ColCnt)
.List = tmp
End If
.Clear ' clear the ListBox
'2b)Loop through rows & add findings to list
Dim r As Long, c As Long, cnt As Long
For r = LBound(data) To UBound(data) ' 1 ..
If IsFound(srch, data, r) Then ' << help function IsFound()
.AddItem ' add item
For c = LBound(data, 2) To UBound(data, 2)
.List(cnt, c - 1) = data(r, c) '<< .List is zero-based!
Next
cnt = cnt + 1 ' increment counter
End If
Next
If .ListCount = 1 Then .Selected(0) = True
End With
End Sub
Help function IsFound()
Function IsFound(srch As String, arr, ByVal r As Long) As Boolean
'Purp.: check if search string is found in given 2-dim array row
Dim c As Long ' column index
For c = LBound(arr, 2) To UBound(arr, 2)
If InStr(1, arr(r, c), srch, vbTextCompare) Then
IsFound = True ' positive function result
Exit For ' one finding suffices
End If
Next
End Function
Further links
You'll find an outstanding article giving you some insight at UserForm1.Show?
Treating the different show modes you might be interested also in Destroy a modeless Userform instance properly

Error 9 displayed when using my own defined arrays in this code in VBA

I have 2 arrays taken from 2 ranges in a sheet. I'm trying to create a third array that contains only the values contained in array 1 that are missing in array 2 (I found this code online).
Array 2´s size will vary and depends on this code:
Dim iListaIncompleta() As Variant
Dim iCountLI As Long
Dim iElementLI As Long
iCountLI = Range("B1").End(xlDown).Row
ReDim iListaIncompleta(iCountLI)
For iElementLI = 1 To iCountLI
iListaIncompleta(iElementLI - 1) = Cells(iElementLI, 2).Value
Next iElementLI
and Array 1's size is always from A1:A7, and I use this code to create it:
Dim iListaCompleta() As Variant
Dim iElementLC As Long
iListaCompleta = Range("A1:A7")
This is the original code I found online to extract missing values:
Dim v1 As Variant, v2 As Variant, v3 As Variant
Dim coll As Collection
Dim i As Long
'Original Arrays from the code:
v1 = Array("Bob", "Alice", "Thor", "Anna") 'Complete list
v2 = Array("Bob", "Thor") 'Incomplete list
Set coll = New Collection
For i = LBound(v1) To UBound(v1)
If v1(i) <> 0 Then
coll.Add v1(i), v1(i) 'Does not add value if it's 0
End If
Next i
For i = LBound(v2) To UBound(v2)
On Error Resume Next
coll.Add v2(i), v2(i)
If Err.Number <> 0 Then
coll.Remove v2(i)
End If
If coll.Exists(v2(i)) Then
coll.Remove v2(i)
End If
On Error GoTo 0
Next i
ReDim v3(LBound(v1) To (coll.Count) - 1)
For i = LBound(v3) To UBound(v3)
v3(i) = coll(i + 1) 'Collections are 1-based
Debug.Print v3(i)
Next i
End Sub
However, this code has arrays defined like this:
v1 = Array("Bob", "Alice", "Thor", "Anna")
And the actual arrays I wanna use are defined differently (as you can see in the first two pieces of code). When I try to run the code with them, it displays
Error 9: Subscript out of range.
The code works well as it originally is, but when I try to use MY arrays, it's when I get this error.
Obviously, I've tried it changing the names of the variables (v1 and v2) to my own 2 arrays (iListaCompleta and iListaIncompleta), and still doesn't work.
Any ideas??
Thank you in advance!
Here's a function that can be used to compare arrays of any dimension size to pull out differences and put only the differences in a one-dimensional array:
Public Function ArrayDifference(ByVal arg_Array1 As Variant, ByVal arg_array2 As Variant) As Variant
If Not IsArray(arg_Array1) Or Not IsArray(arg_array2) Then Exit Function 'Arguments provided were not arrays
Dim vElement As Variant
Dim hDifference As Object: Set hDifference = CreateObject("Scripting.Dictionary")
For Each vElement In arg_Array1
If Not hDifference.exists(vElement) Then hDifference.Add vElement, vElement
Next vElement
For Each vElement In arg_array2
If hDifference.exists(vElement) Then
hDifference.Remove vElement
Else
hDifference.Add vElement, vElement
End If
Next vElement
ArrayDifference = hDifference.Keys
End Function
Here's how you would call the function to compare two different arrays. It also includes how to populate the initial arrays using your provided setup:
Sub arrays()
Dim ws As Worksheet: Set ws = ActiveWorkbook.ActiveSheet
Dim rList1 As Range: Set rList1 = ws.Range("A1", ws.Cells(ws.Rows.Count, "A").End(xlUp))
Dim rList2 As Range: Set rList2 = ws.Range("B1", ws.Cells(ws.Rows.Count, "B").End(xlUp))
Dim aList1 As Variant
If rList1.Cells.Count = 1 Then
ReDim aList1(1 To 1, 1 To 1)
aList1(1, 1) = rList1.Value
Else
aList1 = rList1.Value
End If
Dim aList2 As Variant
If rList2.Cells.Count = 1 Then
ReDim aList2(1 To 1, 1 To 1)
aList2(1, 1) = rList2.Value
Else
aList2 = rList2.Value
End If
Dim aList3 As Variant
aList3 = ArrayDifference(aList1, aList2)
MsgBox Join(aList3, Chr(10))
End Sub

Excel VBA, Autofilter with the output from a loop

Sub Projektlaufzeit()
Dim Datum1 As Date, msg As String
Dim Datum2 As Date
Dim Rest As Long
Dim Projektname As String
Dim i As Integer
Dim c As Integer
Dim ber As Range
Projektname = Range("A2")
Datum1 = Date
'Datum2 = Tabelle1.Range("C2")
c = Sheets("tabelle1").UsedRange.SpecialCells(xlCellTypeLastCell).Column
For i = 2 To c
Projektname = Cells(i, 1)
Datum2 = Cells(i, 3)
Rest = DateDiff("d", Datum1, Datum2)
If Rest > 7 And Rest < 30 Then MsgBox "something"
If Rest >= 0 And Rest <= 7 Then MsgBox "something"
If Rest <= 0 Then MsgBox "something"
Next i
Dim FilterArray
Dim List As Range
Set List = ActiveSheet.Range("A:A")
List.AutoFilter
FilterArray = Array(Projektname)
List.AutoFilter Field:=1, Criteria1:=Array(FilterArray)
End Sub
So that is my code so far. I have a Loop which tells me when a certain project will come to an end. That works so far.
The next step is, that the macro will autofilter all projects that have a remaining duration of < 30 days.
In my code obviously only the last project that was affected by the loop will be filtered. Is it possible to create an array with all affected projects?
I attached a screenshot of the Excel Worksheet.
Thanks in advance.
If you imagine that all your dates are numbers and your target is to create an array of the values in column A, that
correspond to some condition, then this is a possible input:
With the code below, the condition is translated as:
Projects with remaining duration less or equal than 2 days and not finished with today's date.
Option Explicit
Sub ProjectTime()
Dim lngDateToday As Long
Dim lngRemainingDuration As Long
Dim lngLastRow As Long
Dim lngCounter As Long
Dim varProjects() As Variant
Dim blnFirst As Boolean
blnFirst = True
lngDateToday = Range("D2")
lngRemainingDuration = Range("E2")
lngLastRow = 13
ReDim varProjects(0)
For lngCounter = 2 To lngLastRow
If Cells(lngCounter, 3) < (lngDateToday + lngRemainingDuration) And _
Cells(lngCounter, 3) >= lngDateToday Then
If Not blnFirst Then
ReDim Preserve varProjects(UBound(varProjects) + 1)
End If
blnFirst = False
varProjects(UBound(varProjects)) = Cells(lngCounter, 1)
End If
Next lngCounter
For lngCounter = LBound(varProjects) To UBound(varProjects)
Debug.Print varProjects(lngCounter)
Next lngCounter
End Sub
Thus, projects E,G and I (highlighted) are the one matched and added to the array of values. As far as we are not using a collection, but an array, I am redim-ing and preserving on every step (except for the first one).
To filter the array, you need to add the array as a parameter to the filter. Add the following to the end of the code:
Dim List As Range
Set List = ActiveSheet.Range("A:A")
List.AutoFilter
List.AutoFilter field:=1, Criteria1:=Array(varProjects), Operator:=xlFilterValues
This is how it should look like:

Access VBA loop through listbox select items and add to array

I'm trying to loop through a listbox and add the contents to an array....
My code is this:
Private Sub exportfolders_Click()
Dim list As String
Dim folderlist As String
Dim folderarray() As String
'Dim i As Interger
For i = 0 To Me.selectedfolders.ListCount - 1
'folderlist = (Me.selectedfolders.Column(0, i))
'folderarray() = Join(Me.selectedfolders.Column(0, i), ",")
list = (Me.selectedfolders.Column(0, i))
folderarray() = Join(list, ",")
ReDim Preserve folderarray(i)
Next i
folderlist = folderarray
'folderarray() = Join(folderlist, ",")
MsgBox (folderlist)
End Sub
You can see the bits I have commented out, trying all sorts to get it to work. But I keep getting the message "Can't assign to array" at folderarray(i) = Join(list, ","). Any pointers as to where I am failing?
You can concatenate the list box items into a string, and then use Split() to load your array. That way, the array is sized automagically without you needing to ReDim.
I tested this code in Access 2010:
Dim folderarray() As String
Dim i As Long
Dim strList As String
For i = 0 To Me!selectedfolders.ListCount - 1
strList = strList & "," & Me!selectedfolders.Column(0, i)
Next
' use Mid() to exclude the first comma ...
folderarray = Split(Mid(strList, 2), ",")
Note I don't know what you want to do with the array after loading it. MsgBox folderarray would throw Type mismatch error. MsgBox Mid(strList, 2) would be valid, but if that's what you want, you wouldn't need the array.
1) declare the array. Take a look at https://msdn.microsoft.com/en-us/library/wak0wfyt.aspx
2) No need of support variable
3) Assign the values to your array with the correct syntax
Private Sub exportfolders_Click()
Dim folderarray() As String
Dim i As Interger
Redim folderarray (Me.selectedfolders.ListCount-1)
For i = 0 To Me.selectedfolders.ListCount - 1
folderarray(i) = Me.selectedfolders.Column(0, i)
Next i
' Write here what you want to do with your array
End Sub
You could try something like this:
Private Sub ListToArray()
Dim folderArray() As Variant
Dim currentValue As String
Dim currentIndex As Integer
Dim topIndex As Integer
topIndex = Me.selectedfolders.ListCount - 1
ReDim folderArray(0 To topIndex, 0 To 1)
For i = 0 To topIndex
currentValue = Me.selectedfolders.Column(0, i)
folderArray(i, 0) = i
folderArray(i, 1) = currentValue
Next i
End Sub
Note my example is a multi-dimensional array which will give you the ability to add more than one item should you chose to do so. In this example I added the value of "i" as a placeholder/ index.

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