Respected Experts, I want to store each value in VBA-Array which is calculated by VBA Loop. after the looping is Done I would like to use that VBA-Array for my further Calculations.Below example explain my question more specifically.
Sub macro3()
For x = 1 To 5
xx = 1 + x
Next
End Sub
Basically the each Answer which derived i.e.(2,3,4,5,6) from above loop has to be stored in Particular Array OR in something which help me out to use each value's i.e.(2,3,4,5,6) again for my further calculations.The whole activity has to be done from VBA memory Only.Basically i don't want to use Excel Spreadsheet range to store the each Loop Value and then define that spreadsheet range as Array.
If you know the number of elements, then the following would create an array called 'answer' (see DIM statement) that holds the five evaluations:
Sub macro3()
Dim answer(1 To 5)
For x = 1 To 5
answer(x) = 1 + x
Next
End Sub
I suspect though that what you're after might be a little more complicated than that, so give more detail if this is the case.
In addition to CLR's answer - if you dont' know the number of elements the basic formula to ReDim the array would look something like this -
Sub macro3()
Dim x As Integer
Dim xx() As Variant
For x = 1 To 5
ReDim Preserve xx(0 To x - 1)
xx(x - 1) = 1 + x
Next
End Sub
Related
This question already has an answer here:
Search for an element in the VBA ArrayList
(1 answer)
Closed 2 years ago.
I was trying to delete the specific element in the array vba when certain condition are true but i end up getting error 424. May I know the right way to do it? I tired to use redim, however it doesn't suit my condition as after the comparing with others array i need to store the data back into excel file where the location in the excel file is already sorted.
Before changing the remarkRange to array variant, I used it as Dim remarkRange
As Range where I can just use .Clear to clear the range item in a specific element.
I tried remarkRange(I, 1)=" " it runs without error but im not sure if its suitable. May I know the correct way to do it? Thanks.
Dim remarkRange() As Variant
remarkRange= wb.Sheets("wb").Range("A1:A5").Value2
For I = LBound(remarkRange) To UBound(remarkRange)
If (some condition is true) then
remarkRange(I, 1).Delete
End If
Next I
I expected the element in the specific cell in the array to be empty, but I got error 424
An array doesn't have a Delete method. It's also misleading to have the Range in remarkRange when it's an array, not a Range. Maybe a different name, e.g. remarks or whatever is clear to you.
If you're going to write the array back to the worksheet, then I see no problem changing an element to a blank string.
For i = LBound(remarks, 1) To UBound(remarks, 1)
If some condition Then
remarks(i, 1) = ""
End If
Next i
It seems you'll need to decide what you mean by 'delete'. I'm not aware of a Delete property of an array of variants so while your code might compile it would throw an object required error.
However, your point about previously using the Clear method on a Range object, suggests that you just want to read your range values into an array, remove the contents if certain conditions aren't me, and then re-write your array to the range. If that's the case, you probably wouldn't want to resize your array as the rows or columns wouldn't line up - more commonly, you'd set the item of your variant array to Empty.
The code below shows how to do this in a simple routine of taking 10 numbers from column A, removing all odd numbers and re-writing the numbers to Column C - but with the rows still matching:
Public Sub EmptyItemsAndKeepArraySize()
Dim inArr() As Variant
Dim i As Long
'Read range into arrays.
inArr = Sheet1.Range("A1:A10").Value2
'Clear all numbers that are not even.
For i = 1 To UBound(inArr, 1)
If inArr(i, 1) Mod 2 <> 0 Then inArr(i, 1) = Empty
Next
'Write cleared array to column C
Sheet1.Range("c1").Resize(UBound(inArr, 1)).Value = inArr
End Sub
If, however, you really do want to remove and resize your array, then a simple way of doing it is to populate a temporary collection first, resizing an output array and then populating that with the collection items. In the example below the code removes all odd numbers and then writes the array to column B - but as an array reduced in size (ie contiguous rows):
Public Sub DeleteItemsAndShrinkArray()
Dim inArr() As Variant, outArr() As Variant
Dim i As Long
Dim temp As Collection
Dim v As Variant
'Read range into arrays.
inArr = Sheet1.Range("A1:A10").Value2
'Keep all even numbers in a temporary collection.
Set temp = New Collection
For i = 1 To UBound(inArr, 1)
If inArr(i, 1) Mod 2 = 0 Then temp.Add inArr(i, 1)
Next
'Dimension the output array.
ReDim outArr(1 To temp.Count, 1 To 1)
'Populate new array from temp collection.
i = 1
For Each v In temp
outArr(i, 1) = v
i = i + 1
Next
'Write reduced array to column B
Sheet1.Range("B1").Resize(UBound(outArr, 1)).Value = outArr
End Sub
I have a column of data with unique strings where the first 4 characters in the string may be a repeat of the first 4 characters in another string, in a format similar to:
ABCDEF
ABCDXY
ABCDKL
DTYTZF
DTYTSD
I am attempting to loop through this data to identify which 4 starting characters appear more then three times. If the first 4 digits of the string occur 3 times or more, I would like to remove these from the array entirely, and end up with an array that excludes these values. For example, in my column above, as 3 strings or more begin with 'ABCD', I would like to remove all strings that begin with this code, and have only every other value remain, such that my result would be:
DTYTZF
DTYTSD
I am currently looping through the array, pushing any value that occurs three times or more into a NEW array, and plan to then use that list to do a second pass on the original array, and remove any matches. This may not be the most efficient way, but I've not been able to determine a better way that is guaranteed not to mess my data up.
I have worked through looping through the strings to identify which strings occur more then once, but when I try to push them to an array, the string successfully is pushed to the array, but is then replaced with the next value as soon as it is pushed to the array. I know the value is pushed correctly, because if I view the array immediately afterwards, I see the value in the array. When the next value is pushed and you view the array again, only the new value is displayed (The older ones are not).
I believe this is due to my limited understanding of ReDim-ing arrays, and me not fully understanding a code snippet for pushing this value into an array. My (condensed) code is as follows:
Sub pickupValues()
Dim valuesArray()
Dim i As Long
Dim y As Long
Dim sizeCheck As Long
Dim tempArray() As String
valuesArray() = Worksheets("Sheet1").Range("A1:A10").Value
For i = LBound(valuesArray) To UBound(valuesArray)
sizeCheck = 0
For y = LBound(valuesArray) To UBound(valuesArray)
If Left(valuesArray(i, 1), 4) = Left(valuesArray(y, 1), 4) Then
sizeCheck = sizeCheck + 1
i = y
If sizeCheck >= 3 Then
ReDim tempArray(1 To 1) As String 'I'm not sure why I need to do this.
tempArray(UBound(tempArray)) = Left(valuesArray(i, 1), 4) 'I believe this is what pushes the value into the array.
ReDim Preserve tempArray(1 To UBound(tempArray) + 1) As String 'Again unsure on what the purpose of this is.
viewArray (tempArray)
End If
End If
Next y
Next i
End Sub
Function viewArray(myArray)
Dim txt As String
Dim i As Long
For i = LBound(myArray) To UBound(myArray)
txt = txt + myArray(i) + vbCrLf
Next i
MsgBox txt
End Function
What am I doing wrong?
I would like to re-use the same basic code later in the function to push other values OUT of an array based on if they match the string or not, but it seems VBA does not like to move values out of arrays either. Is there an easy solution that would match both scenarios?
I've rewritten what you are trying to do. I'm using the filter function to quickly get your results in the array
Option Explicit
Public Sub pickupValues()
Dim tmp As Variant
Dim results As Variant
Dim i As Long
Dim v
' Make sure this matches your range
With ThisWorkbook.Sheets("Sheet1")
' Important to transpose the input here as Filter will only take a 1D array. Even though it's only 1 column, setting an array this way will generate a 2D array
tmp = Application.Transpose(.Range(.Cells(1, 1), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, 1)).Value2)
End With
' ReDiming to the maximum value and slimming down afterwards is much quicker then increasing your array each time you've found a new value
ReDim results(1 To UBound(tmp))
For Each v In tmp
' Less then 2 as first result is '0'. Will return '-1' if can't be found but as test criteria is in the array it will always be at least 0
If UBound(Filter(tmp, Left(v, 4))) < 2 Then
i = i + 1
results(i) = v
End If
Next v
' Redim Preserve down to actual array size
If i > 0 Then
ReDim Preserve results(1 To i)
viewArray (results)
Else
MsgBox "Nothing Found"
End If
End Sub
' Should really be a sub as doesn't return anything back to caller
Public Sub viewArray(myArray)
MsgBox Join(myArray, vbCrLf)
End Sub
Your algorithm is not helping you.
Option 1:
Sort your array. Then you can make a single pass to find sequential values with the same first four characters and count them.
Option 2:
Use a Dictionary object: first four characters as key, number of occurrences as value.
I am attempting to check if any value in a dynamic array of size "i" by one is greater than zero where "i" is a user input. If false, the value of the first element in the array would show in the next column. If true, the values of the array update by essentially moving down one element. I believe I have found answers for this question in java here, but haven't had any luck finding it in vba. I believe this could be done with a for loop as done here, but would like something more efficient if it exists. Since I do not know any syntax which may work the code hangs at "If any x > 0 Then"
Dim i, z, u As Integer
Dim fir As Integer
Dim las As Integer
Dim n As Long
Dim x As Variant
'SET VALUE OF ROWS FOR ARRAY
i = Worksheets("INPUTS").Range("C6").Value
Set s = Worksheets("DATA")
'FIND LAST VALUE IN DATA
n = s.Cells(s.Rows.Count, "A").End(xlUp).Row
'BEGIN LOOP THROUGH DATA SET
For z = 1 To n
'SET/RESET RANGE TO CHECK FOR CONSECUTIVE VALUES LESS THAN ZERO
fir = z
las = i + z - 1
x = (s.Range("C" & fir, "C" & las).Value)
u = s.Range("C" & UBound(x)).Value
If any x > 0 Then
Else: s.Cells(4, z) = x(1, 1).Value
End If
Next z
I'm a beginner and new to the forum so feel free to tear me a new one on anything against best practices relating to the code or the question, thank you.
use worksheet function
If Application.WorksheetFunction.Max(Range("a1:a100")) > 0 Then
MsgBox "value higher than zero"
end if
In order to speed up the processing you may consider converting Excel Range (for example A1:A100) into array Arr and then iterating through array:
Dim Arr() As Variant
Arr = Range("A1:A100")
Also, you may consider setting property Application.ScreenUpdating = False prior to starting the iterations (in case you change the cells' values during iteration as per your example) and resetting it to True afterwards.
Hope this may help.
I'm working with arrays and I'm sorry but I'm a bit new to it and still confused. I have already this code to store the values in a range in an array and if I run it, it is empty.
attPresent = ws.Range("H4:H" & lastrow)
ReDim attPresent(1 To UBound(attPresent))
For k = LBound(attPresent) To UBound(attPresent)
MsgBox attPresent(k)
Next
Can someone please tell me where I'm wrong? I've read any other posts and gather some ideas, but still not working.
You can go like this
Dim attPresent as Variant
attPresent = ws.Range("H4:H" & lastrow).Value '<-- this will automatically size the array to a 2dimensional array of as many rows as the range ones and one column
For k = LBound(attPresent,1) To UBound(attPresent,1)
MsgBox attPresent(k,1)
Next
Or
Dim attPresent as Variant
attPresent=Application.Transpose(Range("H4:H" & lastrow).Value) '<-- this will automatically size the array to a 1dimensional array of as many elements as the range
For k = LBound(attPresent) To UBound(attPresent)
MsgBox attPresent(k)
Next
Reference MSDN: ReDim Statement (Visual Basic)
When you Redim the array you are erasing all the values. Use ReDim Preserve to resize the last dimension of the Array and still preserve the values of the array.
After the dynamic array has been allocated(the first time Redim is used) you can only resize the last dimension of a array and you cannot change the number of dimensions. In your code you are trying to convert a 2 Dimensional array to a 1 Dimensional array, you can not do that.
You should watch this complete series: Excel VBA Introduction. This is the relevant video: Excel VBA Introduction Part 25 - Arrays
'Try this code example to suit your case
Sub StoreRangeofCellsToAnArray()
'presumes optionbase=0
'presume Range("a1:c3") contain number 1 to 9
Dim MyRange, MyArray(9), n
n = 0
For Each c In Range("a1:c3")
MyArray(n) = c
n = n + 1
Next
'testing: reprint array
For n = 0 To 8
Debug.Print MyArray(n)
Next
End Sub
Is it possible to name an array variable using a different variable? For example, if I define variable "i" as an integer with a value equal to the number of columns I've used it a sheet:
Sub varNameTest
Dim i, j, As Integer
i = ActiveSheet.UsedRange.Columns.Count
...
Is it possible to then establish "i" number of arrays named something like myArray1 through i? Possibly something like:
For j = 1 to i
Dim (myArray & j())
Next i
Though this example immediately above is incorrect syntax, I'm just trying illustrate what I'm trying to do.
edit: so to be more clear, using the above example, say I have 4 sheets in a workbook. The variable i would then be 4, and I would have some code that generates myArray1(), myArray2(), myArray3() and myArray4().
You can create an array of arrays (though your question is a little unclear..)
Sub MyArrays()
Dim arrays()
Dim arr
Dim i, j
i = 5 'e.g.
ReDim arrays(1 To i)
For j = 1 To i
arr = Array()
ReDim arr(1 To j)
arrays(j) = arr
Next j
'reference an array by its position in "arrays"
Debug.Print UBound(arrays(3))
End Sub
Yes.
Dim i(5) As Integer
In VBA you can then access elements from i(0) to i(5).
Based on your edited question, the answer is no. You must explicitly define each variable in your code.
The other option would be to write code that writes your code - a form of code generation. Effectively that lets you write very long and complex code by repeating code "templates". But I don't think this would help in your case.