Referencing the same array in different Subs in VBA Excel - arrays

I have a function that fills a certain array with cell values depending on which OptionButton is selected. How would I reference those same arrays in a seperate function which would feed those values back into the cells? Here is my (working) code so far.
Private Sub CommandButton1_Click()
Dim wave1Array(0 To 30) As String
Dim wave2Array(0 To 30) As String
Dim wave3Array(0 To 30) As String
Dim wave4Array(0 To 30) As String
Dim wave5Array(0 To 30) As String
Dim rng As Range
Dim cell As Range
Dim counter As Long
Set rng = Range("B2", "AF2")
counter = 0
If OptionButton6.Value = True Then
For Each cell In rng
wave1Array(counter) = cell.Value
counter = counter + 1
Next cell
ElseIf OptionButton7.Value = True Then
For Each cell In rng
wave2Array(counter) = cell.Value
counter = counter + 1
Next cell
ElseIf OptionButton8.Value = True Then
For Each cell In rng
wave3Array(counter) = cell.Value
counter = counter + 1
Next cell
ElseIf OptionButton9.Value = True Then
For Each cell In rng
wave4Array(counter) = cell.Value
counter = counter + 1
Next cell
ElseIf OptionButton10.Value = True Then
For Each cell In rng
wave5Array(counter) = cell.Value
counter = counter + 1
Next cell
End If
End Sub

You have a few different options that I can think of.
As others have mentioned, make a module-level variable(s) as needed. These declarations should go in the same code module as your form controls. If the form controls are on a userform, then they should be declared in the form's code module, not a "standard" module.
'-------------------------------- all in the same code module -------------
Option Explicit
Dim myVariable as String
Private Sub CommandButton1_Click()
myVariable = "Hello, world!"
End Sub
Private Sub CommandButton2_Click()
msgBox myVariable
End Sub
'------------------------------- end of this example ----------------------
Public/GLobal variable may be an option but I recall there are some limitations using these with UserForms, and since I'm not sure if you're using a UserForm, I won't recommend that.
A third option would be to pass the arguments from one procedure to another, but that usually only works with "chained" procedures/functions, like when one function calls another function and that does not seem to be what you're doing at all.
For your specific case:
You can also streamline your code to avoid using the counter and cell variables, using direct range-to-array assignment.
'Module-level array variables, accessible by other procedures in this module:
Dim wave1Array()
Dim wave2Array()
Dim wave3Array()
Dim wave4Array()
Dim wave5Array()
Dim wave6Array()
Private Sub CommandButton1_Click()
Dim rng As Range
Dim arr()
Set rng = Range("B2", "AF2")
'## Converts the row to an array (0 to 30)
arr = Application.Transpose(Application.Transpose(rng.Value))
'## Assigns the array from above to one of the module-level array variables:
If OptionButton6.Value = True Then wave1Array = arr
If OptionButton7.Value = True Then wave2Array = arr
If OptionButton8.Value = True Then wave3Array = arr
If OptionButton9.Value = True Then wave4Array = arr
If OptionButton10.Value = True Then wave5Array = arr
If OptionButton11.Value = True Then wave6Array = arr
End Sub
Note that to do this, you will have to declare them as variant arrays, since a range of cells .Value is a variant type (cells can contain error values which I believe will fail if you try to assign to a string array).
IF you must use strict String arrays, then you will need to use the counter and cell iteration.

Related

get array into new sheet?

I have a function that loads certain data from a dynamic table into an array. The function works fine, when I check the local window I get the correct data. Also when I call the data from a sub, everything seems to work fine till I write the array to a new sheet, then I only get the first record repeatedly.
This is my code:
Function LoadData() As String()
Dim rng2 As Range, intJaNein As Integer, rngZelle As Range, X As Integer, cntAnzahl As Integer
Dim strAusgabe() As String 'R?ckgabe Array
intJaNein = 1
X = 0
Set rng2 = Range("tblMaschinen[DisplayList]")
cntAnzahl = WorksheetFunction.CountIfs(rng, m_intListIndex, rng2, intJaNein)
ReDim strAusgabe(cntAnzahl)
For Each rngZelle In rng2.Cells
If rngZelle.Offset(, -2).value = 0 And _
rngZelle.value = 1 And _
X <= cntAnzahl Then
strAusgabe(X) = rngZelle.Offset(, -1).value
X = X + 1
End If
Next rngZelle
LoadData = strAusgabe
End Function
Sub Test()
Dim sht As Worksheet, rng As Range, arr() As String
If ThisWorkbook.Worksheets("Loeschen") Is Nothing Then
Set sht = ActiveWorkbook.Worksheets.Add
sht.Name = "Loeschen"
End If
Set rng = Range("A1:A19")
arr = cls.LoadData
rng.value = arr
End Sub
This is the locals output when getting to the last row of code (rng.value = arr)
And this is what appears in my worksheet.

How to store Global Array

In my Workbook i have an Array which stores machines. With a button i am able to add some machines to the array.
The final array is used in three other buttons, each button is on a different worksheet. My question now is, how do i store the array global with its changing value?
this is my code for adding some value to the array:
Private Sub Add_Machine_Click()
Dim ws As Worksheet
Dim lastrow As Long
Dim Machine() As Variant
Dim DataRange As Range
Set ws = Worksheets("MachineTemplate")
lastrow = ws.Cells(Rows.Count, "A").End(xlUp).Row
Set DataRange = ws.Range("A1:A" & lastrow)
Set Cell = DataRange.Find(What:=ComboBox1.Value, LookIn:=xlFormulas, lookat:=xlWhole)
If Cell Is Nothing Then
ws.Range("A" & lastrow + 1) = ComboBox1.Value
End If
ReDim Machine(DataRange.Cells.Count)
For Each Cell In DataRange.Cells
Machine(x) = Cell.Value
x = x + 1
Next Cell
End Sub
Right now i use the same code for the other three buttons. is there a way i can store this code as global?
I allready tried it in the WorkbookSheet like this:
Option Explicit
Public Machine() As Variant
Public ws As Worksheet
Public lastrow As Long
Public DataRange As Range
ws = Worksheets("MachineTemplate")
lastrow = ws.Cells(Rows.Count, "A").End(xlUp).Row
Set DataRange = ws.Range("A1:A" & lastrow)
ReDim Machine(DataRange.Cells.Count)
x = 0
For Each Cell In DataRange.Cells
Machine(x) = Cell.Value
x = x + 1
Next Cell
But i know that this is totally wrong.
You do not need a Global Array for this. Since you are using Redim without Preserve, then it means it is getting initialzed everytime from the range DataRange
Also to create the array, you do not need to loop trough it everytime. You can directly create a 2D array in one line
Dim Machine as Variant
Machine = DataRange.Value
You may also want to see VBA Arrays And Worksheet Ranges
I usually avoid using Global variables. They get reset very easily during runtime if an error happens.

How to insert data in the array (inside a loop)?

I have a problem with inserting data to the array. In the program I search all cells with "Data:" value. If this value appear I jump to the cell on the right and mark it. I want to collect all marked values (all of them are dates) in the array but with my code (enclosed below) I have an error. I have tried ReDim and setting an exact number of objects in the array. I would be grateful for a help.
Sub CheckData()
Dim FindIt As Range
Dim EndIt As Range
Dim StartAddress As String
With Range("A1:A100")
Set EndIt = .Cells(.Cells.Count)
End With
Set FindIt = Range("A1:A100").Find(what:="Data:", after:=EndIt)
If Not FindIt Is Nothing Then
StartAddress = FindIt.Address
End If
Dim Tabel() As Variant
Tabel = Array()
i = 0
Do Until FindIt Is Nothing
Set FindIt = Range("A1:A100").FindNext(after:=FindIt)
Data = FindIt.Address
Range(Data).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.Interior.ColorIndex = 6
'Debug.Print ActiveCell.Value
Tabel(i) = ActiveCell.Value
i = i + 1
'Debug.Print i
If FindIt.Address = StartAddress Then
Exit Do
End If
Loop
End Sub
You never sized your array.
Dim Tabel() As Variant
Use ReDim to resize a dynamically-sized array.
ReDim Preserve Tabel(0 To UBound(Tabel)+1)
However that's a terribly inefficient thing to do in a loop (you're copying the same elements over and over and over and over again, at every single iteration).
Rule of thumb, if you don't know from the start how many elements you're going to need, it's probably best to use a Collection instead of an array.
Dim items As Collection
Set items = New Collection
'...
items.Add ActiveCell.Value
You could also use a for loop instead of a find (also using Mat's Mug idea about collections)
Sub CheckData1()
Dim ws As Worksheet
Dim searchRng As Range
Dim cell As Range
Dim tabel As Collection 'incorrectly spelt table?
Set ws = ActiveSheet
Set tabel = New Collection
Set searchRng = ws.Range("A1:A100")
For Each cell In searchRng.Cells
If cell.Value = "Data:" Then
tabel.Add cell.Offset(, 1)
cell.Offset(, 1).Interior.ColorIndex = 6 'If you still need it highlighted
End If
Next
End Sub

Moving an Array to a Range VARIABLE

I am trying to find this but I can't! Is it possible to move/copy and VBA Array to a Range Variable, I am not saying a Range cells, it's a Range that you declare (ex: DIM ran as Range)
I want something like this:
Public Function test()
Dim ran As Range
Dim myArray(4) As Integer
myArray(1) = 1
myArray(2) = 2
myArray(3) = 3
myArray(4) = 4
'If I do this, it works!
Range("A1:A4") = myArray
'But I want this and it does not work!
ran = myArray
End Function
Thanks!
Even though the Range is declared in code, it's still a Range, not an array. If myArray is actually a Range object (in which case you should re-think your naming conventions) you should be able to do what your example showed.
However if your variable myArray is some other type of object (like and array) you can't just set it like that, you would have to write a method that converts myArray to a range.
EDIT:
I'm guessing that the reason that Range("A1:A4") = myArray works is because the assignment operator has been overloaded to support it as short-hand for Range("A1:A4").Value = myArray.
A Range however is not just an array, it's a data structure specific to Ranges of a workbook
When you declare Dim ran As Range you haven't actually initialized your Range object yet. I'm guessing that if you did the following it would work:
Dim ran As Range("A1:A4")
Dim myArray(4) As Integer
myArray(1) = 1
myArray(2) = 2
myArray(3) = 3
myArray(4) = 4
ran = myArray
If you set a variant to a worksheet range you get a 2 dimensional array. Try this
Sub MoveArray()
Dim myArray
myArray = Range("A1:B3").Value
Range("A6:B8").Value = myArray
End Sub
Or this
Sub MoveArray2()
Dim myArray
Dim myArray2
Dim myRange
Dim i As Integer
Dim j As Integer
myArray = Range("A1:B3").Value
Set myRange = Range("A6:B8")
For i = 1 To myRange.Rows.Count
For j = 1 To myRange.Columns.Count
myRange.Cells(i, j) = myArray(i, j)
Next j
Next i
myArray2 = myRange
End Sub
In either case the variant becomes an array rather than a range object and the loops set the values of the range from the array.
Edit
As you can see from the comments in the questions/answers in this thread a range is not an array, it is a complex object that has many properties and methods. One of the properties (I think the default property) is value. This property is in fact a 2 dimensional array (or at least behaves like one) of the values of the cells in the range. As such if myArray is also a 2 dimsensional aray the code myRange = myArray will execute. What will happen is the value of the cells that the range refers to will be set to the values in the array. The range refers to these cells, but it is the values in the cells that change rather than the range object.
As such if if you transfer a range to a diferent set of cells the new set of cells retains it's values.
On a practical side if you want to change the values of the cells that a range referes to you can do it as shown below:
Sub Test1()
Dim myArray(1 To 4, 1 To 1)
Dim myRange As Range
myArray(1, 1) = 1
myArray(2, 1) = 2
myArray(3, 1) = 3
myArray(4, 1) = 4
Set myRange = Range("A1:A4")
myRange = myArray
End Sub

Excel VBA - Pass a Row of Cell Values to an Array and then Paste that Array to a Relative Reference of Cells

Using Excel (2010) VBA, I am trying to copy (pass) a constant range of cells (whose values recalculate) to an array. Then I am trying to pass that array to a new range of cells, directly below it. After I have done this, I want to again copy (pass) the constant range's new values to the array, and pass these new values to a range directly below the one I previously passed.
I know this code is atrocious (I am new to arrays in VBA).
Sub ARRAYER()
Dim anARRAY(5) As Variant
Number_of_Sims = 10
For i = 1 To Number_of_Sims
anARRAY = Range("C4:G4")
Range("C4").Select
ActiveCell.Offset(Number_of_Sims, 0).Select
ActiveCell = anARRAY
Range("C4").Select
Next
End Sub
I sure do appreciate your help!
Thank you.
Respectfully,
Jonathan
You are off slightly on a few things here, so hopefully the following helps.
Firstly, you don't need to select ranges to access their properties, you can just specify their address etc. Secondly, unless you are manipulating the values within the range, you don't actually need to set them to a variant. If you do want to manipulate the values, you can leave out the bounds of the array as it will be set when you define the range.
It's also good practice to use Option Explicit at the top of your modules to force variable declaration.
The following will do what you are after:
Sub ARRAYER()
Dim Number_of_Sims As Integer, i As Integer
Number_of_Sims = 10
For i = 1 To Number_of_Sims
'Do your calculation here to update C4 to G4
Range(Cells(4 + i, "C"), Cells(4 + i, "G")).Value = Range("C4:G4").Value
Next
End Sub
If you do want to manipulate the values within the array then do this:
Sub ARRAYER()
Dim Number_of_Sims As Integer, i As Integer
Dim anARRAY as Variant
Number_of_Sims = 10
For i = 1 To Number_of_Sims
'Do your calculation here to update C4 to G4
anARRAY= Range("C4:G4").Value
'You can loop through the array and manipulate it here
Range(Cells(4 + i, "C"), Cells(4 + i, "G")).Value = anARRAY
Next
End Sub
No need for array. Just use something like this:
Sub ARRAYER()
Dim Rng As Range
Dim Number_of_Sims As Long
Dim i As Long
Number_of_Sims = 10
Set Rng = Range("C4:G4")
For i = 1 To Number_of_Sims
Rng.Offset(i, 0).Value = Rng.Value
Worksheets("Sheetname").Calculate 'replacing Sheetname with name of your sheet
Next
End Sub
Since you are copying tha same data to all rows, you don't actually need to loop at all. Try this:
Sub ARRAYER()
Dim Number_of_Sims As Long
Dim rng As Range
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Number_of_Sims = 100000
Set rng = Range("C4:G4")
rng.Offset(1, 0).Resize(Number_of_Sims) = rng.Value
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
When i Tried your Code i got en Error when i wanted to fill the Array.
you can try to fill the Array like This.
Sub Testing_Data()
Dim k As Long, S2 As Worksheet, VArray
Application.ScreenUpdating = False
Set S2 = ThisWorkbook.Sheets("Sheet1")
With S2
VArray = .Range("A1:A" & .Cells(Rows.Count, "A").End(xlUp).Row)
End With
For k = 2 To UBound(VArray, 1)
S2.Cells(k, "B") = VArray(k, 1) / 100
S2.Cells(k, "C") = VArray(k, 1) * S2.Cells(k, "B")
Next
End Sub

Resources