I reviewed this question/answer here before writing this: Declare and Initialize String Array in VBA
I am trying to understand the proper way to declare and initialize an array WITHOUT resorting to data type VARIANT.
This is my code, and it does work as it is:
Function MakeLegalFilename(legalname As String) As String
Dim MyArray() As Variant
Dim x As Integer
MyArray = Array("<",">","?","#","%")
For x = LBound(MyArray) To UBound(MyArray)
legalname = Replace(legalname, MyArray(x), "", 1)
Next x
MakeLegalFilename = legalname
End Function
If I change "Variant" to "String," the code fails at MyArray = Array(... with a runtime error 13 type mismatch.
If I define the array size to match the number of characters in the string (5 total, but array starts at 0):
Dim MyArray(4) As String
MyArray = Array("<",">","?","#","%")
Now I get a compile error at MyArray = Array(... that says "Can't assign to array."
I know that I could declare the array this way and make it work (I tested it this way):
MyArray(0) = "<"
MyArray(1) = ">"
MyArray(2) = "?"
...
MyArray(4) = "%"
But if I am coding in a whole list of characters (say 20), then doing this is cumbersome, and plus, I would like to know why the other way doesn't work, since it suggests I have a fundamental misunderstanding. In it's most basic form, my question really is, why doesn't this:
Dim MyArray(4) As String
MyArray = Array("<",">","?","#","%")
work?
Thank you.
Array returns a Variant.
So you can't use it if you don't what a variant.
Split can split a string.
Split Function
Description
Returns a zero-based, one-dimensional array containing a specified number of substrings.
Syntax
Split(expression[, delimiter[, limit[, compare]]])
Put comma delimited string into split containing your characters.
Use a helper function:
Dim MyArray() As String
MyArray = StrArray("<", ">", "?", "#", "%")
...
Public Function StrArray(ParamArray args() As Variant) As String()
Dim i As Long
ReDim temp(UBound(args)) As String
For i = 0 To UBound(args)
temp(i) = args(i)
Next
StrArray = temp
End Function
To initialize static-size string array, use:
Dim MyArray(4) As String
MyArray(0) = "<"
MyArray(1) = ">"
MyArray(2) = "?"
MyArray(3) = "#"
MyArray(4) = "%"
To initialize dynamic-size string array, use:
Dim MyArray() As String
For i = 0 to 10
Redim Preserve MyArray(i) 'increase the size
MyArray(i) = Char(64 + i)
Next
For further information, please see: http://msdn.microsoft.com/en-us/library/wak0wfyt.aspx
Related
I am trying to create a TextSplit function in Excel that can accept either a single reference or a range.
If it is a single string it returns an array of sub strings.
If it is a range it should return an array of sub string arrays.
A single string works but when I pass it a single column range it give me a #VALUE! error.
The commented lines work.
If I store the result of Array to arr Excel displays a grid of "test" strings.
If instead I set TextSplit to just arr(1) I get a single array of substrings similar to the single string version.
Function TextSplit(text, delimiter)
If IsArray(text) Then
Dim arr() As Variant: ReDim arr(0 To text.Count - 1)
For i = 1 To text.Count
arr(i-1) = Split(text(i), delimiter)
'arr(i-1) = Array("test", "test")
Next
TextSplit = arr
'TextSplit = arr(1)
Else
TextSplit = Split(text, delimiter)
End If
With the help of a different question Array and Split commands to create a 2 dimensional array
I was able to work your question out a bit, however I'm still unable to fill out the array from the cell where you'd call the function like with your single string which fills out in the columns next to it.
If it's for a column, you could just autofill text.split(cell,delimiter) if you're working from Excel.
If you're working from out vba and want to return the split array (2D like #Tim said) back to a sub:
Sub testingTextSplitter()
Dim arr As Variant, tArr As Variant
Dim testStr As String
testStr = Range("A1").Value 'Testing single cell
Range("G2").Value = TextSplit(testStr, "-")
arr = Range("A1:A8").Value
tArr = TextSplit(arr, "-")
For i = 0 To UBound(tArr, 1)
For j = 0 To UBound(tArr, 2)
Cells(i + 3, j + 3).Value = "'" & tArr(i, j) 'fills out from Range("C3"), adjust as needed
' This writing out is basically the same as fillingdown the formule of text.split() btw
Next j
Next i
End Sub
With the Function
Function TextSplit(tArray As Variant, delimiter As String) As String()
If IsArray(tArray) Then
Dim uBoundInput As Long, uBoundCells As Long 'I couldn't get your arr.Count to work on my end so gotta use the UBound
Dim arr() As String, testArr() As String
Dim i As Long, j As Long, maxColumns As Long
uBoundInput = UBound(tArray)
maxColumns = 0
For i = 0 To uBoundInput - 1
Debug.Print (tArray(i + 1, 1))
testArr = Split(tArray(i + 1, 1), "-")
uBoundCells = UBound(testArr)
If maxColumns < uBoundCells Then
maxColumns = uBoundCells
End If
Next i
ReDim arr(0 To uBoundInput - 1, 0 To maxColumns)
For i = 0 To uBoundInput - 1
testArr = Split(tArray(i + 1, 1), "-")
For j = 0 To UBound(testArr)
arr(i, j) = testArr(j)
Next j
Next i
TextSplit = arr()
Else
TextSplit = Split(tArray, delimiter)
End If
End Function
I'm quite new to VBA as well so apologies in advance for redundancies like not filling testArray when figuring out the maxColumns, I couldn't figure that one out. First time working with 2D arrays.
Other question that might help:
VBA UDF Return Array
(I tried using the array formulay with {} but got same Value error as before)
Hope this helps.
I don't know what happened, but the array branch of my code is now working. I have been messing with a few things, but I am not sure why it is working. The "As Variant()" declaration is new from the above code, but that may have been omitted before. (This code is on my work machine but I wrote the original post from my personal computer so I couldn't copy and paste. I am on my work computer now.)
The only other change that I made was to the index values of the arr array.
Thanks for your help, not sure what was wrong or how it got fixed though.
Function TextSplit(text, delimiter) As Variant()
If IsArray(text) Then
Dim arr() As Variant: ReDim arr(1 To text.Count)
For i = 1 To text.Count
arr(i) = Split(text(i), delimiter, -1, 1)
Next
TextSplit = arr
Else
TextSplit = Split(text, delimiter, -1, 1)
End If
End Function
Let's say I have the following Array, arr that contains a maximum of 20 substrings. In this example, the array will have 4 substrings:
arr = {"AAAA: 1234567" , "BBBB: 2345678" , "CCCC: 98765432" , "DDDD: 87654321"}
Note: Capitalization is not important.
I am needing assistance with finding a substring inside an array (again, up to 20 strings possible), that Starts With CCCC:, and then assigning that entire string to it's own variable, let's call it Var1.
I understand I could assign Var1 = arr(2), but I need to figure out how to determine the index number in the array that meets my criteria.
What I would really appreciate (although any method I will be happy with), is making a stand alone function such as:
Function ArrayIndex(ArrayInput as Variant, StartsWith as String) as Byte
'Arguments Here
End Function
Then I could just use this in my Subroutine:
Var1 = arr(ArrayIndex(arr, "CCCC:"))
Update 1
Here is a snippet of my current code
Sub T_Report
'<Shortcut = Shift+Ctrl+T>
Dim Data as String, DataArray as Variant
With ActiveSession
.Copy 0, 2, 80, 21 'Just a big block of text with multiple lines, copied to clipboard
Data = Clipboard 'Set Data to the clipboard value
DataArray = Split(Data,vbCrLf) 'This is "Data" in an Array, separated by line breaks
'Just checking to see if the Array was successful (it is)
Debug.Print DataArray(0) & vbNL & DataArray(1) & vbNL & DataArray(2) & _
vbNL & DataArray(3) & vbNL & DataArray(4) & vbNL & vbNL
'Misc code here
Dim sF1 as String, sF2 as String, sF3 as String
Dim Rslt1 as String, Rslt2 as String, Rslt3 as String
sF1 = "Field1:"
sF2 = "Field2:"
sF3 = "Field3:"
MsgBox DataArray(0) ' This works fine, giving me first substring
Rslt1 = FindMyString(sF1, DataArray)
' Misc Code
End With
End Sub
However, when I use the following function, I get Type Mismatch error on the MsgBox arr(0) line, although it should be giving me the very first substring of DataArray in the above sub (should be an exact match, the array has not been modified).. However, when I do MsgBox DataArray(0) above, I do get the first substring.
Private Function FindMyString(strToFind As String, ParamArray arr() As Variant) As String
Dim i As Integer
Dim iLen As Integer
Dim strArr As String
FindMyString = "" ' Returns Blank String if not found
' I get type mismatch here (Doesn't appear Array from sub loaded into this function)
MsgBox arr(0)
iLen = Len(strToFind)
For i = 0 To UBound(arr)
strArr = CStr(arr(i))
If strToFind = Left$(strArr, iLen) Then
FindMyString = strArr
Exit Function
End If
Next i
End Function
EDIT - FIX YOUR ARRAY LOAD
Change this (it MUST give you an error!):
arr = {"AAAA: 1234567" , "BBBB: 2345678" , "CCCC: 98765432" , "DDDD: 87654321"}
To This:
Dim arr As Variant
arr = Split("AAAA: 1234567,BBBB: 2345678,CCCC: 98765432,DDDD: 87654321", ",")
If you want to use a function to do your bidding you can pass an array of data using the ParamArray type. It has to be the last parameter in your function
This should do what you want:
Private Function FindMyString(strToFind as string, ParamArray arr() As Variant) As String
Dim i As Integer
Dim iLen as Integer
Dim strArr as String
FindMyString = "" ' Returns Blank String if not found '
Debug.Print arr(0)(0) ' Print first element of array
iLen = Len(strToFind)
For i = 0 To UBound(arr(0))
strArr = CStr(arr(0)(i))
If strToFind = Left$(strArr, iLen) Then
FindMyString = strArr
Exit Function
End If
Next i
End Function
In your example you can test it by:
Var1 = FindMyString("CCCC:", arr)
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.
I m trying to find out array index using visual basic. I tried some code with VB.Net and getting correct output. Below is the code I am using,
Dim FindThisString as String="EFGH"
Dim MyArray() As String={"ABCD","EFGH","IJKLM"}
For Each Str As String In MyArray
If Str.Contains(FindThisString) Then
MsgBox(Str.IndexOf(FindThisString))
End If
Next
Now I want to try the same method with VB 6.0. I am using Instr function but it is giving me string index in entire string and I am looking for array index i.e. index of string "EFGH" in MyArray.
Here is the VB6 code I'm trying:
Dim MyString as String
Dim str as Variant
MyString="ABCD/EFGH/IJKLM"
Dim MyArray() as String
MyArray = split(MyString,"/")
Dim inIndex as Integer
For Each Str In MyArray
inIndex= Instr(str,"EFGH")
MsgBox inIndex
Next
You would basically use the same algorithm:
Loop through the array (you'll need to use a Variant as the loop variable for VB Classic For Each),
verify if the array entry contains the substring in question (you need to use InStr here, since VB Classic does not have String.Contains),
return the index (which you already determined with InStr).
The implementation is left as an exercise.
Function IndexOf(ByRef arr() As String, ByVal str As String) As Integer
Dim joinedStr As String
Dim strIndex As Integer
joinedStr = "|" & Join(arr, "|")
strIndex = InStr(1, joinedStr, str)
If strIndex = 0 Then
IndexOf = -1
Exit Function
End If
joinedStr = Mid(joinedStr, 1, strIndex - 1)
IndexOf = UBound(Split(joinedStr, "|")) - 1
End Function
I've been coding a Film Search thing for School, and I've came across this problem and I'm not sure how to solve it.
While Not FilmSearcher.EndOfData 'loop until end of file
currentRow = FilmSearcher.ReadFields() 'read in the fields of each line
For j = 0 To 3
Films(i, j) = currentRow(j) 'put the fields into film array
Next
i = i + 1
End While
currentRow = FilmSearcher.ReadFields() is the part that isn't working
If the error message is in your title, then I bet you have declared the currentRow as
Dim currentRow As String
instead you need to declare it as a 1-dimensional array
Dim currentRow() as String
Your currentRow variable is not declared correctly. Instead of this:
Dim currentRow As String
You need one of these:
Dim currentRow() As String
Dim currentRow As String()
Which one you choose is a matter of preference. They mean the same thing. You can also avoid the variable entirely:
While Not FilmSearcher.EndOfData
'read in the fields of each line and put into film array
Films(i) = FilmSearcher.ReadFields()
i = i + 1
End While
In my case, I had declared my method incorrectly to return an array:
Function GetById(ByVal id As Integer) As String
and the syntax should be:
Function GetById(ByVal id As Integer) As String()
whereas I can return an array of strings:
Dim arrayOfStrings() As String
arrayOfStrings = {"John", "Josh", "Jason", "Jill", "Kunta Kinte"}
Return arrayOfStrings