I have a sub that takes a variant array generated in a userform and I would like to extract all of the values and return them as a single comma delimited string. This is probably pretty basic, but I'm having trouble getting the values from the array into a string. I'm getting a type mismatch when I try to cast the variant as a string. Any idea what I'm doing wrong?
Sub formSearch(ParamArray search() As Variant)
Dim returnString As String
returnString = ""
For i = LBound(search) To UBound(search)
returnString = returnString + CStr(search(i)) + ","
Next
MsgBox returnString
End Sub
I had the same problem because the input array was the contents of a NamedRange on a WorkSheet.
Even though the NamedRange was a single column of cells, the array returned by VBA was a 2-dimensional array of values and thus the code needed the i,1 adjustment in the CStr function to work :
Function getCellArrayAsString(RangeName As String) As String
Dim arr() As Variant
getCellArrayAsString = ""
arr = ThisWorkbook.Names(RangeName).RefersToRange.value
For i = LBound(arr) + 1 To UBound(arr)
getCellArrayAsString = getCellArrayAsString & CStr(arr(i, 1)) & ","
Next
End Function
or as it would be applied to the OP's code :
Sub formSearch(ParamArray search() As Variant)
Dim returnString As String
returnString = ""
For i = LBound(search) To UBound(search)
returnString = returnString + CStr(search(i,1)) + ","
Next
MsgBox returnString
End Sub
I suspect that your code suffered from the same problem in that your input was actually a 2-dimensional array.
Related
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 using VBA but not on excel.
I know that on VBA for Excel, you could do something like Split("String will be splitted") and obtain an array back.
Is there a way to perform the split without this function? Because it isn't recognize by the version of VBA I'm using.
Thank you.
something like this, returning a collection, for time as didn't want to code all the if's for redimming the o/p array.
Public Sub testing()
Dim c As New Collection
Set c = New_Split("test split function", " ")
End Sub
Public Function New_Split(strInput As String, strDelimiter As String) As Collection
Dim colDelimitPoints As New Collection
Dim intCounter As Integer
Dim intPrevPoint As Integer
For intCounter = 1 To Len(strInput)
If Mid(strInput, intCounter, 1) = strDelimiter Then
colDelimitPoints.Add intCounter, CStr(intCounter)
End If
Next intCounter
intPrevPoint = 1
Set New_Split = New Collection
For Each i In colDelimitPoints
New_Split.Add Mid(strInput, intPrevPoint, (i - intPrevPoint))
intPrevPoint = i + 1
Next i
End Function
You can combine the collection creation and the iteration of it later into one routine, I've left separate to show how it's working.
I am assuming you are using an early version of Excel in which Split doesn't exist, #Meehow and #Nathan_Sav are correct that you are best off writing your own, I using commands like mid, and instr.
There is not an equivalent, just a way to make an equivalent.
See the below equivalent: -
Public Sub Sample()
Dim ArySplit() As String
ArySplit = FnSplit("This|is|my||string", "|")
End Sub
Private Function FnSplit(ByVal StrContent As String, ByVal StrDelimiter As String) As String()
Dim AryTemp() As String
ReDim AryTemp(0)
'Work until we have nothing left to work with
Do Until StrContent = ""
'Only increase the array size if needed
If AryTemp(UBound(AryTemp, 1)) <> "" Then ReDim Preserve AryTemp(UBound(AryTemp, 1) + 1)
'if the delimiter is no longer there then output the remaining content
'and clear out the todo string
If InStr(1, StrContent, StrDelimiter) = 0 Then
AryTemp(UBound(AryTemp, 1)) = StrContent
StrContent = ""
Else
'If there is a delimiter then then add it to the array and take it and the delimiter
'off of the to do string
AryTemp(UBound(AryTemp, 1)) = Left(StrContent, InStr(1, StrContent, StrDelimiter) - 1)
StrContent = Right(StrContent, Len(StrContent) - ((InStr(1, StrContent, StrDelimiter) - 1) + Len(StrDelimiter)))
End If
Loop
'Return our array
FnSplit = AryTemp
End Function
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 wish to use an Excel array function to generate an array of strings and then pass this to a user defined function to strip blanks and concatenate the strings separated by a ",".
I have a function that does this when called from a VBA macro. When I try to use it as a user defined function, e.g. =ConcStr({"A","B","C"}), I get a #Value! error.
Function is below:
Sub StrTest()
Dim StaticArray(1 To 3) As String
Dim Result As String
StaticArray(1) = "A"
StaticArray(2) = "B"
StaticArray(3) = "C"
Result = ConcStr(Arr:=StaticArray)
MsgBox Result
End Sub
Function ConcStr(Arr() As String) As String
MsgBox "started"
Dim N As Long
Dim Total As String
For N = LBound(Arr) To UBound(Arr)
MsgBox Arr(N)
Total = Total & "," & Arr(N)
Next N
ConcStr = Total
End Function
If you rewrite your UDF to accept a Variant instead, it should work. Also, you can just use the Join function to accomplish what you need:
Function ConcStr(arr As Variant) As String
ConcStr = Join(arr, ",")
End Function
Declare, dim, assign and pass the array over as a variant.
Sub StrTest()
Dim StaticArray As Variant, Result As String
ReDim StaticArray(1 To 3)
StaticArray(1) = "A"
StaticArray(2) = "B"
StaticArray(3) = "C"
Result = ConcStr(Arr:=StaticArray)
MsgBox Result
Result = ConcStr2(Arr:=StaticArray)
MsgBox Result
End Sub
Function ConcStr(Arr As Variant) As String
MsgBox "started"
Dim N As Long, Total As String
For N = LBound(Arr) To UBound(Arr)
MsgBox Arr(N)
Total = Total & "," & Arr(N)
Next N
ConcStr = Mid(Total, 2) 'Mid to get rid of the first comma
End Function
Function ConcStr2(Arr As Variant) As String
'could just be like this,
ConcStr2 = Join(Arr, ",")
End Function
I've added an alternative Join Function version to simplfy things and modified your function with the Mid function to remove the leading comma.
I was able to get what you want with:
Public Function ConcatString(ByVal arr As Variant) As String
ConcatString = vbNullString
Dim i As Long, n As Long, z as Long
z = LBound(arr) : n = UBound(arr)
For i = z To n
ConcatString = ConcatString + arr(i)
Next i
End Function
I don't get what's false in my code. I searched the error the whole morning! So I hope you can help me.
First, here's the problem code (the names of the variables aren't their real names):
Sheets(sheet).Range(nameOfTheRange).FormulaR1C1 = _
functionReturningString(functionReturningStrArr( _
Range(nameOfAnotherRange).Value, AnInputWorkSheet, "colNameInInputSheet"))
So my description on that:
All functions work fine standing alone, but in combination there is always this error (Language: German):
Fehler beim Kompilieren:
Unverträglicher Typ: Datenfeld oder benutzerdefinierter Typ erwartet
functionReturningString is a function with the following parameters(strArr() as Variant) --> it returns a String like a bulletlist.
functionReturningStrArr(nameWhichISearchInSheet as String, dataSheet as Worksheet, dataColumn, as String) --> it returns a Variant() for the bulletListing
I'm not sure if the second method really works so here's the code of it.
Function functionReturningStrArr(ByVal nameWhichISearchInSheet As String, ByVal datasheet As Worksheet, ByVal datacolumn As String) As String()
Dim returnArray() As String
Dim rowindex As Integer
Dim ID As String
Sheets(rawdataOverall).Cells(1, getColNumFromColName("Project")).EntireColumn.Select
'search correct dataset
For Each cell In Selection
If cell.Value = nameWhichISearchInSheet Then
rowindex = cell.row
Exit For
End If
Next cell
'get ID
ID = Sheets(rawdataOverall).Cells(rowindex, getColNumFromColName("ID")).Value
'search data from file with this ID
datasheet.Cells(1, getColNumFromColName(datacolumn)).EntireColumn.Select
Selection.UsedRange.Select
For Each cell In Selection
rowindex = cell.row
'check if row contains to this project
If Cells(rowindex, getColNumFromColName("ID")) = ID Then
ReDim Preserve returnArray(UBound(returnArray) + 1)
returnArray(UBound(returnArray)) = cell.Value
End If
Next cell
functionReturningStrArr = returnArray()
If you are asking yourselves what is getColNumFromColName, it is a method which works really fine, I used it in other projects too.
You really have to start declaring everything explicitly using Dim -- and force yourself to do this by writing Option Explicit at the top of your module. That way you will identify errors much more quickly.
Here
'get ID
ID = Sheets(rawdataOverall).Cells(rowindex, getcolnumformcolname("ID")).Value
you call a function called getcolnumformcolname; presumably form is a typo and you meant From as in getColNumFromColName. Had you had Option Explicit, you would have detected that error immediately.
The following three variables/arrays are not declared: rawdataOverall, cell, getDataFromThisProject. You should declare them and assign them a type explicitly.
Try fixing those things and see where that brings you.
Is seems a small portion of the function code snippet is wrong. on the very last line, you should assign the value of returnArray() to your function name like so:
functionReturningStrArr = returnArray()
Otherwise, you would need to extract the array from a variable named "getDataFromActualProject", as is shown in the example.
EDIT:
Alter your function "functionReturningStrArr As Variant" to return "As String()" instead of Variant. It seems you cant cast a Variant to a string array as you would expect.
EDIT:
I created a function to test this. This compile error shows up when you try to cast Variant as Array of string. This also includes a fix, your function that returns Variant MUST return array of string instead.
Sub RunTest()
Debug.Print getStringFromArray(getArray())
Debug.Print getStringFromArray(getVariant()) ' compile error! you cannot cast variant to array of string
End Sub
Function getArray() As String()
Dim returnArray(2) As String
returnArray(0) = "A"
returnArray(1) = "B"
returnArray(2) = "C"
getArray = returnArray()
End Function
Function getVariant() As Variant()
Dim returnArray(2) As String
returnArray(0) = "A"
returnArray(1) = "B"
returnArray(2) = "C"
getArray = returnArray() ' Not a compile error, you can cast string array to variant
End Function
Function getStringFromArray(inputArray() As String) As String
Dim returnString As String
For i = LBound(inputArray()) To UBound(inputArray())
If returnString = "" Then
returnString = inputArray(i)
Else
returnString = returnString & "," & inputArray(i)
End If
Next i
getStringFromArray = returnString
End Function