Let assume I have an array something like this:
Dim Arr() As Variant
arr(0)= "Text<&>data"
arr(1)= "<&>recombining"
arr(2)= "that libraries<&>"
arr(3)= "<&>professional<&>user "
I would like to search inside the values and find all <&> and then replace them with and.
My efforts by .find were unsuccessful. :(
Use Replace$. Not sure if you wanted to add any whitespace? I use constants as you have fixed bounds so no calls to UBound and LBound when looping the array. Also, use typed function Replace$ as more efficient.
Option Explicit
Public Sub test()
Const START_POINT As Long = 0
Const END_POINT As Long = 3
Dim Arr(START_POINT To END_POINT) As Variant, i As Long
Arr(0) = "Text<&>data"
Arr(1) = "<&>recombining"
Arr(2) = "that libraries<&>"
Arr(3) = "<&>professional<&>user "
For i = START_POINT To END_POINT
Arr(i) = Replace$(Arr(i), "<&>", "and")
Next
For i = START_POINT To END_POINT
Debug.Print Arr(i)
Next
End Sub
You could avoid loop turning array into a string with Join(), making the replacement and finally turning it back to an array with Split() (Not tested):
Dim Arr As Variant
Arr = Array("Text<&>data", _
"<&>recombining", _
"that libraries<&>", _
"<&>professional<&>user ")
Arr = Split(Replace$(Join(Arr, "|"), "<&>", "and"), "|")
Related
I have an array like this
dim arr(1 to 5) as string
arr(1)="a"
arr(3)="b"
arr(5) = "c"
(arr(2),arr(4) are empty).
How can I redim this arr(1to5) to exclude empty values and save also values "a","b","c" (I want the output like arr(1to3), arr(1)="a", arr(2)="b", arr(3)="c")?
In general I do not know how many of them will be empty, so I need some general code for this (not for this specific example).
I was thinking about new temporary array to save all nonempty values and then redim arr(1to5).
Maybe it is a better (quick) way to do it?
I wrote sth similar:
Sub test()
Dim myArray() As String
Dim i As Long
Dim y As Long
ReDim Preserve myArray(3)
myArray(1) = "a"
myArray(3) = "c"
Dim myArray2() As String
y = 1
For i = LBound(myArray) To UBound(myArray)
If myArray(i) <> "" Then
ReDim Preserve myArray2(y)
myArray2(y) = myArray(i)
y = y + 1
End If
Next i
ReDim myArray(UBound(myArray2))
myArray = myArray2
End Sub
However I would like to avoid creating new array.
create a new array of the same size. Loop the first array and insert the values when not empty into the new array keeping track of the last spot with value in the new array, then redim preserve the new array to only the size that has values.
Sub kjlkj()
Dim arr(1 To 5) As String
arr(1) = "a"
arr(3) = "b"
arr(5) = "c"
Dim newArr() As String
ReDim newArr(1 To UBound(arr))
Dim j As Long
j = LBound(newArr)
Dim i As Long
For i = LBound(arr) To UBound(arr)
If arr(i) <> "" Then
newArr(j) = arr(i)
j = j + 1
End If
Next i
ReDim Preserve newArr(LBound(newArr) To j - 1)
'do what you want with the new array.
End Sub
Alternative via Filter() function
"However I would like to avoid creating new array."
A negative filtering allows a basically simple alternative, however you have to
declare your array dynamically (i.e. without preset number of elements) to allow a rebuild overwriting the original array,
execute a double replacement over the joined array elements to allow insertion of a unique character that can be filtered out.
Sub testFilter()
Dim arr() As String
ReDim arr(1 To 5)
arr(1) = "a"
arr(3) = "b"
arr(5) = "c"
'Debug.Print Join(arr, ",") ' ~~> a,,b,,c
'rearrange arr via RemoveEmpty()
arr = RemoveEmpty(arr) ' >> function RemoveEmpty()
Debug.Print Join(arr, ",") ' ~~> a,b,c
End Sub
Help function RemoveEmpty()
Adding an unused unique character, e.g. $, to the empty elements plus eventual negative filtering allows to remove these marked elements.
Note that the double replacement is necessary to allow to mark consecutive empty elements by the $ mark, as VBA would skip additional characters here.
Function RemoveEmpty(arr)
Dim tmp
tmp = Replace(Replace(Join(arr, "|"), "||", "|$|"), "||", "|$|")
RemoveEmpty = Filter(Split(tmp, "|"), "$", False)
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 need to know how can I add an item to an existing array using a user input.
I tried something like this:
Dim MyArray(100) as String
UBound(MyArray) = Inputbox("What's the name of your new array item?")
Ubound(myArray) returns a Long datatype, it literally return the length/size of the array.
If you want to read or assign a value then you must fully qualify the array ie.
MyArray(ubound(myArray)) = "new Value" or MyArray(100) = "new Value"
Sub Main()
Dim MyArray(100) As String
MyArray(UBound(MyArray)) = InputBox("What's the name of your new array item?")
MsgBox MyArray(UBound(MyArray))
End Sub
You could use a dynamic array instead:
Dim MyArray() As String
' Then to add a new element:
Redim Preserve MyArray(1 to SafeUBound(MyArray) + 1)
MyArray(SafeUBound(MyArray)) = InputBox("Who's yer daddy?")
Function SafeUBound(vArray As Variant) As Long
Dim x As Long
On Error Resume Next
x = UBound(vArray)
If Err.Number = 0 Then
SafeUBound = x
Else
SafeUBound = 0
End If
End Function
The call to SafeUbound is necessary because calling UBound or LBound on an uninitialized array will throw an error.
Using this very simple function:
Function WriteArray() as Variant
Dim array(0 To 2)
array(0) = "A"
array(1) = "B"
array(2) = "C"
WriteArray = array
End Function
I was expecting to see in result the whole array in my Excel spreadsheet, but that's not the case: I get only the first string. I know there is trick to show the whole array in the spreadsheet (by selecting a range of cells with the formula + F2 + CTRL+SHIFT+ENTER), but I would prefer VBA to handle it all.
I also tried to use the Application.Caller variable to write directly in the "Caller" range but the code breaks.
Thanks a lot for your help!
EDIT:
Here is another code I tried to use:
Function WriteArray() As Variant
Dim arr(0 To 2)
arr(0) = "A"
arr(1) = "B"
arr(2) = "C"
WriteArray = arr
Dim StartRow, i As Integer
For i = 0 To UBound(arr)
Range("A" & i).Value = arr(i)
Next
End Function
It breaks at the line "Range("A" & i).Value = arr(i)". Is my Excel broken?!
The following code writes the array to a range of cells beautifully:
Function WriteArray() As Variant
Dim AbcList(0 To 2) as Variant
AbcList(0) = "A"
AbcList(1) = "B"
AbcList(2) = "C"
WriteArray = AbcList
End Function
Function WriteArrayToSpreadsheet()
Dim MyArray As Variant
MyArray = WriteArray()
Dim StartRow, i As Integer
StartRow = 1
For i = 0 To UBound(MyArray)
Range("A" & i + StartRow).Value = MyArray(i)
Next
End Function
That being said, I'd like to see the part of the code where you're actually trying to get it onto the spreadsheet, not where you build the array. Then I can help you out!
You are not allowed to write to non-caller cells directly from a worksheet function in Excel.
If you want to use an array function (using the Shift-Ctrl-Enter) you need to change your code to:
Function WriteArray() As Variant
Dim arr(0 To 2, 0 To 1)
arr(0, 0) = "A"
arr(1, 0) = "B"
arr(2, 0) = "C"
WriteArray = arr
End Function
If you want to write outside of the calling cells you would need to implement some form of callback which would use automation to write to the other cells. This is way more complicated and much more likely to break!
The secret is to define a two-dimensional array. The two dimensions of the array is simply the range which needs to be defined for a dataset. The first array dimension is the row offset and the second dimension is the column offset.
In you example the second dimension is just not "used":
Sub Ente()
Dim myArray(0 To 3, 0) As String
myArray(0, 0) = "A"
myArray(1, 0) = "B"
myArray(2, 0) = "C"
Range("B7:B" & UBound(myArray) + 6) = myArray
End Sub
So, no loops necessary! Simple and fast.
The best workaround I made so far was creating a procedure the get your range reference and your array and use it as a start point to show your data horizontaly or vertically...
As follows:
Sub LoadArray(ByRef oRange, ByRef vArray)
Dim I
For I = 0 To UBound(vArray)
oRange.Offset(I, 0).Value = vArray(I)
Next
End Sub
'How to call:
Dim anyArray
anyArray = Array(1,2,3)
Call LoadArray(Range("anyRange"), anyArray)
Hope it helps.