Write a subroutine in VBA to generate a winning lotto ticket consisting of 6 integer numbers randomly drawn from 1 to 40.
In order to have a small simulation animation, range("A1:E8") should contain the numbers 1 to 40 and the subroutine should then cycle through these numbers using a colored cell and then momentarily pause 2 seconds on a selected winning number. The list of winning numbers drawn should then be printed in the range("G2:G7"). In case a number drawn has already been drawn previously in the list, then a new number should be redrawn.
I have only been able to do as follows.
Option Explicit
Sub test1()
Sheet1.Cells.Clear
Dim i As Integer
For i = 1 To 40
Cells(i, 1) = i
Next
End Sub
'-----------------------------
Option Explicit
Option Base 1
Function arraydemo(r As Range)
Dim cell As Range, i As Integer, x(40, 1) As Double
i = 1
For Each cell In r
x(i, 1) = cell.Value
i = i + 1
Next cell
arraydemo = x
End Function
Sub test3()
Dim x() As String
chose = Int(Rnd * UBound(x))
End Sub
I got stuck elsewhere, the sub test3(), does not seem appropriate here. I need some suggestions. Also, I appologise for my poor formatting, I am new to this.
Populating your range like this:
range("A1:E8") should contain the numbers 1 to 40
Sheet1.Cells.Clear
Dim i As Integer
Dim rng as Range
Set rng = Range("A1:E8")
For i = 1 To 40
rng
Next
generate a winning lotto ticket consisting of 6 integer numbers randomly drawn from 1 to 40
Using a dictionary object to keep track of which items have been picked (and prevent duplicate) in a While loop (until there are 6 numbers chosen):
Dim picked as Object
Set picked = CreateObject("Scripting.Dictionary")
'Select six random numbers:
i = 1
While picked.Count < 6
num = Application.WorksheetFunction.RandBetween(1, 40)
If Not picked.Exists(num) Then
picked.Add num, i
i = i + 1
End If
Wend
Using the Application.Wait method to do the "pause", you can set up a procedure like so:
'Now, show those numbers on the sheet, highlighting each cell for 2 seconds
For Each val In picked.Keys()
rng.Cells(picked(val)).Interior.ColorIndex = 39 'Modify as needed
Application.Wait Now + TimeValue("00:00:02")
rng.Cells(picked(val)).Interior.ColorIndex = xlNone
Next
The list of winning numbers drawn should then be printed in the range("G2:G7").
Print the keys from the picked dictionary:
Range("G2:G7").Value = Application.Transpose(picked.Keys())
Putting it all together:
Sub Lotto()
Dim i As Integer, num As Integer
Dim rng As Range
Dim picked As Object 'Scripting.Dictionary
Dim val As Variant
'Populate the sheet with values 1:40 in range A1:E8
Set rng = Range("A1:E8")
For i = 1 To 40
rng.Cells(i) = i
Next
'Store which numbers have been already chosen
Set picked = CreateObject("Scripting.Dictionary")
'Select six random numbers:
i = 1
While picked.Count < 6
num = Application.WorksheetFunction.RandBetween(1, 40)
If Not picked.Exists(num) Then
picked.Add num, i
i = i + 1
End If
Wend
'Now, show those numbers on the sheet, highlighting each cell for 2 seconds
For Each val In picked.Keys()
rng.Cells(val).Interior.ColorIndex = 39 'Modify as needed
Application.Wait Now + TimeValue("00:00:02")
rng.Cells(val).Interior.ColorIndex = xlNone
Next
'Display the winning series of numbers in G2:G7
Range("G2:G7").Value = Application.Transpose(picked.Keys())
End Sub
NOTE This absolutely will not work on Excel for Mac, you would need to use a Collection instead of a Dictionary, as the Scripting.Runtime library is not available on Mac OS.
In addition to the excellent answer given by member David Zemens, following is the universal function written in "pure" Excel VBA, which does not contain any Excel Worksheet Functions, neither Dictionary Object (re: CreateObject("Scripting.Dictionary").
Option Explicit
'get N random integer numbers in the range from LB to UB, NO repetition
'general formula: Int ((UpperBound - LowerBound + 1) * Rnd + LowerBound)
Function RandomNumbers(LB As Integer, UB As Integer, N As Integer) As Variant
Dim I As Integer
Dim arrRandom() As Integer
Dim colRandom As New Collection
Dim colItem As Variant
Dim tempInt As Integer
Dim tempExists As Boolean
'check that ArraySize is less that the range of the integers
If (UB - LB + 1 >= N) Then
While colRandom.Count < N
Randomize
' get random number in interval
tempInt = Int((UB - LB + 1) * Rnd + LB)
'check if number exists in collection
tempExists = False
For Each colItem In colRandom
If (tempInt = colItem) Then
tempExists = True
Exit For
End If
Next colItem
' add to collection if not exists
If Not tempExists Then
colRandom.Add tempInt
End If
Wend
'convert collection to array
ReDim arrRandom(N - 1)
For I = 0 To N - 1
arrRandom(I) = colRandom(I + 1)
Next I
'return array of random numbers
RandomNumbers = arrRandom
Else
RandomNumbers = Nothing
End If
End Function
'get 5 Random numbers in the ranger 1...10 and populate Worksheet
Sub GetRandomArray()
Dim arr() As Integer
'get array of 5 Random numbers in the ranger 1...10
arr = RandomNumbers(1, 10, 5)
'populate Worksheet Range with 5 random numbers from array
If (IsArray(arr)) Then
Range("A1:A5").Value = Application.Transpose(arr)
End If
End Sub
The function
Function RandomNumbers(LB As Integer, UB As Integer, N As Integer)
returns array of N random numbers in the range LB...UB inclusively without repetition.
Sample Sub GetRandomArray() demonstrates how to get 5 random numbers in the range 1...10 and populate the Worksheet Range: it could be customized for any particular requirements (e.g. 8 from 1...40 in PO requirements).
APPENDIX A (Courtesy of David Ziemens)
Alternatively, you can do similar without relying on Collection object at all. Build a delimited string, and then use the Split function to cast the string to an array, and return that to the calling procedure.
This actually returns the numbers as String, but that shouldn't matter for this particular use-case, and if it does, can easily be modified.
Option Explicit
Sub foo()
Dim arr As Variant
arr = RandomNumbersNoCollection(1, 40, 6)
End Sub
'get N random integer numbers in the range from LB to UB, NO repetition
'general formula: Int ((UpperBound - LowerBound + 1) * Rnd + LowerBound)
Function RandomNumbersNoCollection(LB As Integer, UB As Integer, N As Integer)
Dim I As Integer
Dim numbers As String ' delimited string
Dim tempInt As Integer
Const dlmt As String = "|"
'check that ArraySize is less that the range of the integers
If (UB - LB + 1 >= N) Then
' get random number in interval
Do
Randomize
tempInt = Int((UB - LB + 1) * Rnd + LB)
If Len(numbers) = 0 Then
numbers = tempInt & dlmt
ElseIf InStr(1, numbers, tempInt & dlmt) = 0 Then
numbers = numbers & tempInt & dlmt
End If
Loop Until UBound(Split(numbers, dlmt)) = 6
numbers = Left(numbers, Len(numbers) - 1)
End If
RandomNumbersNoCollection = Split(numbers, dlmt)
End Function
Related
I am having trouble finding a way that takes the average from a list box and then displaying that average on the user form. I know you are supposed to use an array, but I am very confused at the moment how to array a second column on a list box. Below is an example the numbers in the text box need to be averaged up and then displayed in the circle I have
This may help clarify, it adds a Click Event Method to the ListBox ... so click on an entry in the ListBox and the messages tell you what they know about it
Private Sub ListBox1_Click()
MsgBox Me.ListBox1.Value
MsgBox Me.ListBox1.ListIndex
MsgBox Me.ListBox1.List(Me.ListBox1.ListIndex, 0) ' The Value of Column 1
MsgBox Me.ListBox1.List(Me.ListBox1.ListIndex, 1) ' The Value of Column 2
End Sub
Alternatively if you want to know the overall average you just add all column 2 entries and divide by the number of entries there are
Private Sub ListBox1_Click()
Dim i As Long
Dim iMax As Long
Dim SubTot As Double
SubTot = 0
iMax = UBound(Me.ListBox1.List)
For i = 0 To iMax
SubTot = SubTot + Me.ListBox1.List(i, 1)
Next i
MsgBox "The Average of ALL people is " & Round((SubTot / (iMax + 1)), 2)
End Sub
Get Average From a List Box Column
This example uses an Active-X list box and label on a worksheet. Surely you'll manage to apply this to your user form case.
It uses a loop to write the numbers from the 2nd column of the list box to an array and Application.Average to retrieve the average from the array and write it to the label.
Sub ListBoxAverage()
Dim Players() As Variant: Players = VBA.Array("Tim", "Jon", "Sue")
Dim Numbers() As Variant: Numbers = VBA.Array(1, 2, 4)
Dim rUpper As Long: rUpper = UBound(Players)
Dim Arr() As Double ' Array to Hold the Numbers
Dim r As Long ' List Box Row Counter
Dim n As Long ' Array Element Counter
With Sheet1.ListBox1
' Populate.
.Clear
.ColumnCount = 2
For r = 0 To rUpper
.AddItem
.List(r, 0) = Players(r) ' 1st column
.List(r, 1) = Numbers(r) ' 2nd column
Next r
' Write the values from the 2nd column to a Double array.
ReDim Arr(0 To rUpper)
Dim rValue As Variant
For r = 0 To rUpper ' .ListCount - 1
rValue = .List(r, 1) ' 2nd column
If IsNumeric(rValue) Then ' it's a number
Arr(n) = CDbl(rValue)
n = n + 1
'Else ' it's not a number; do nothing
End If
Next r
End With
With Sheet1.Label1
' Write the average to the label.
If n = 0 Then
.Caption = "No average."
Else
If n < r Then
ReDim Preserve Arr(0 To n - 1)
End If
.Caption = Format(Application.Average(Arr), "0.0")
End If
End With
End Sub
example2 example1 The file name I'm trying to match is on Row A and I'm looking through Row I to see if there is a match I found this code I can't recall where but I am trying to match row of part numbers to a row of its image file names. This code works, however, there is a problem when I run it it takes really long to calculate even just 1 column and when I do hundreds at a time my excel just stops responding, and I have thousands of products I need to match. I am really new with VBA so I can't even figure out the problem.
Please help, thank you.
'Name function and arguments
Function SearchChars(lookup_value As String, tbl_array As Range) As String
'Declare variables and types
Dim i As Integer, str As String, Value As String
Dim a As Integer, b As Integer, cell As Variant
'Iterste through each cell
For Each cell In tbl_array
'Save cell value to variable
str = cell
'Iterate through characters
For i = 1 To Len(lookup_value)
'Same character?
If InStr(cell, Mid(lookup_value, i, 1)) > 0 Then
'Add 1 to number in array
a = a + 1
'Remove evaluated character from cell and contine with remaning characters
cell = Mid(cell, 1, InStr(cell, Mid(lookup_value, i, 1)) - 1) & Mid(cell, InStr(cell, Mid(lookup_value, i, 1)) + 1, 9999)
End If
'Next character
Next i
a = a - Len(cell)
'Save value if there are more matching characters than before
If a > b Then
b = a
Value = str
End If
a = 0
Next cell
'Return value with the most matching characters
SearchChars = Value
End Function
EDIT (post seeing the data): The following should be notably faster (as well as notably simpler)
'Name function and arguments
Function SearchChars(lookup_value As String, tbl_array As Range) As String
'Declare variables and types
Dim inLenMatched%, vnVal, varLookupValues()
'Puts lookup cell values into a array (to speed things up)
varLookupValues = tbl_array.Value
'Iterate through each lookup value
For Each vnVal In varLookupValues
'Ignore empty cells
If vnVal <> "" Then
'Does part number appear in filename?
If InStr(lookup_value, vnVal) > 0 Then
'Is this match the most complete match so far?
If Len(vnVal) > inLenMatched Then
inLenMatched = Len(vnVal)
SearchChars = vnVal
End If
End If
End If
Next vnVal
'Return match value (or 'No Match' if not matched)
If SearchChars = "" Then SearchChars = "No Match"
End Function
The above is just one off-the-cuff approach.
There are other (and quite possible faster) ways to approach this.
The most obvious step (regardless of method) to improving performance would be to limit tbl_array to only the rows with data (not the entire column).
Separately: Without knowing all possible cases, it's impossible to say for sure. But, in all probability, this can be done with Native excel functions, and (if so) that will deliver the best performance.
As said, minimizing the interactions with the sheet by assigning the range to an array will structurally make your macros faster.
Not tested but these minor changes in your code should help you on the right track:
Option Explicit
'Name function and arguments
Function SearchChars2(lookup_value As String, tbl_array As Range) As String
'Declare variables and types
Dim i As Integer, str As String, Value As String
Dim a As Integer, b As Integer, cell As Variant
'Iterste through each cell => replace with array
'adapt to correct sheet
Dim arr
arr = tbl_array
For Each cell In arr 'tbl_array
'Save cell value to variable
str = cell
'Iterate through characters
For i = 1 To Len(lookup_value)
'Same character?
If InStr(cell, Mid(lookup_value, i, 1)) > 0 Then
'Add 1 to number in array
a = a + 1
'Remove evaluated character from cell and contine with remaning characters
cell = Mid(cell, 1, InStr(cell, Mid(lookup_value, i, 1)) - 1) & Mid(cell, InStr(cell, Mid(lookup_value, i, 1)) + 1, 9999)
End If
'Next character
Next i
a = a - Len(cell)
'Save value if there are more matching characters than before
If a > b Then
b = a
Value = str
End If
a = 0
Next cell
'Return value with the most matching characters
SearchChars2 = Value
End Function
I was trying to modify your existing code, but I found it easier to just rewrite it using what I consider to be a better structure. And After running the code over 26 columns & 432 rows, It only took 0.2 seconds to find the Closest Matching String.
I moved every value into an array.
I converted the lookup_value and the "cell values" into an array of bytes.
I compared the byte arrays to count matching "characters".
And then I return the string that had the highest number of matching "characters".
Sub Example()
Dim StartTime As Double
StartTime = Timer * 1000
Debug.Print SearchChars3("Toddleson", Range("A1:Z432"))
Debug.Print "Time Elapsed: " & Timer * 1000 - StartTime & " ms"
'Time Elapsed: 171.875 ms
End Sub
Function SearchChars3(lookup_value As String, tbl_array As Range) As String
Dim ClosestMatch As String, HighestMatchCount As Integer
Dim tbl_values() As Variant
tbl_values = tbl_array.Value
Dim LkUpVal_Bytes() As Byte
LkUpVal_Bytes = ToBytes(lookup_value)
Dim Val As Variant
For Each Val In tbl_values
If Val = "" Then GoTo nextVal
Dim Val_Bytes() As Byte
Val_Bytes = ToBytes(CStr(Val))
Dim MatchCount As Integer
MatchCount = CountMatchingElements(LkUpVal_Bytes, Val_Bytes)
If MatchCount > HighestMatchCount Then
HighestMatchCount = MatchCount
ClosestMatch = Val
End If
nextVal:
Next
SearchChars3 = ClosestMatch
End Function
Function ToBytes(InputStr As String) As Byte()
Dim ByteArr() As Byte
ReDim ByteArr(Len(InputStr) - 1)
Dim i As Long
For i = 0 To Len(InputStr) - 1
ByteArr(i) = AscW(Mid(InputStr, i + 1, 1))
Next
ToBytes = ByteArr
End Function
Function CountMatchingElements(Arr1 As Variant, Arr2 As Variant) As Integer
'As elements from Arr1 are found in Arr2, those elements are removed from Arr2, to prevent re-matching with the same elements
'To enable this feature, Arr2 is turned into a Collection
Dim Col2 As New Collection
Dim v As Variant
For Each v In Arr2
Col2.Add v
Next
Dim MatchCount As Integer, i As Long
For Each v In Arr1
For i = 1 To Col2.Count
If Col2.Item(i) = v Then
MatchCount = MatchCount + 1
Col2.Remove (i)
Exit For
End If
Next
Next
CountMatchingElements = MatchCount
End Function
A further optimization could be to have a second version of the ToBytes function that directly outputs the values into a Collection. Then, you can change CountMatchingElements to accept a collection and it wont need to convert the second array into a collection.
I will leave that as an idea for you to experiment with.
I'm new in VBA. I want to make a random pick cycle like that:
Let's say I have seven elements in an array(1,2,3,4,5,6,7), each time when I pick one element from the array, the total number of elements will decrease by 1. After picking every element, the array will be reset to what I initially defined (1,2,3,4,5,6,7) and do the random pick cycle again.
The result of every cycle should be different.
Is it possible to do that in VBA?
Here's a stateful function that does what you described each time it is called.
Option Base 1
Dim digits, NLeft
Function RemoveDigit() as Integer
Dim Element as Integer
If IsEmpty(digits) or NLeft = 0 Then
digits = array(1,2,3,4,5,6,7)
NLeft = 7
End If
Element = WorksheetFunction.RandBetween(1,NLeft)
RemoveDigit = digits(Element)
digits(Element) = digits(NLeft)
digits(NLeft) = RemoveDigit
NLeft = NLeft - 1
End Function
It uses a well known algorithm to arrange digits in a random order. Basically you choose to swap a random element number with the last element. Then you repeat it on an n - 1 sized array, making it a tail-recursive algorithm (although this implementation of it is not recursive).
Delete this if you want to, but here is a suggestion for a test sub:
Sub TestRemoveDigit()
NLeft = 0
For i = 1 To 7
d = RemoveDigit()
Debug.Print (d)
Next i
End Sub
I think this should do what you're asking for:
Option Explicit
Global vCurrentArray As Variant
Sub ResetArray()
vCurrentArray = Array(1, 2, 3, 4, 5, 6, 7)
End Sub
Sub RemoveElementWithIndex(lIndex As Long)
Dim vTemp() As Variant '* Change the type as needed
Dim lLBound As Long: lLBound = LBound(vCurrentArray)
Dim lUBound As Long: lUBound = UBound(vCurrentArray)
Dim i As Long, v As Variant
Dim blSkipped As Boolean
If lLBound = lUBound Then '* only 1 element
Call ResetArray
Else
ReDim vTemp(lLBound To lUBound - 1)
i = lLBound
For Each v In vCurrentArray
If i <> lIndex Or blSkipped Then
vTemp(i) = v
i = i + 1
Else
blSkipped = True
End If
Next v
vCurrentArray = vTemp
End If
End Sub
Function GetRandomElement() As Variant '* Change the type as needed
Dim lRandomIndex As Long
lRandomIndex = WorksheetFunction.RandBetween(LBound(vCurrentArray), UBound(vCurrentArray))
GetRandomElement = vCurrentArray(lRandomIndex)
RemoveElementWithIndex lRandomIndex
End Function
Sub TestCycles()
Dim lCycle As Long
Dim i As Long
ResetArray
For lCycle = 1 To 3
Debug.Print
For i = 1 To 7
Debug.Print "Cycle: " & lCycle, "i: " & i, "Random Elem: " & GetRandomElement
Next i
Next lCycle
End Sub
Note: There're many ways of achieving the end result. The above is almost a literal translation of your post.
We can not remove a random element from an array. We can redim array to remove last element(s). If you want to remove random element, you can use collection instead like ..
Option Explicit
Sub RemoveRandom()
Dim coll As Collection, cl As Variant, i As Long, j As Long
Set coll = New Collection
For Each cl In Range("A1:A7")
coll.Add cl.Value
Next cl
For j = 1 To coll.Count
i = WorksheetFunction.RandBetween(1, coll.Count)
Debug.Print coll(i)
coll.Remove (i)
Next j
End Sub
can you please guide how to put array values in multiple columns like first four values in first column , than 5 values in second column, and than may be 2 in second column….. and so on. i tried do while loop and for loop but the results are not satisfactory ————————-
Sub PickNamesAtRandom()
Dim HowMany As Long
Dim NoOfNames As Long
Dim RandomColumn As Integer
Dim RandomRow As Integer
Dim Names() As String ‘Array to store randomly selected names
Dim i As Byte
Dim CellsOutRow As Integer
Dim CellsOutColumn As Integer ‘Variable to be used when entering names onto worksheet
Dim ArI As Byte ‘Variable to increment through array indexes
Application.ScreenUpdating = False
HowMany = WorksheetFunction.Sum(Sheets(“test”).Range(“A2:E2”))
CellsOutRow = 3
CellsOutColumn = 1
ReDim Names(1 To HowMany) ‘Set the array size to how many names required
NoOfNames = Application.CountA(Sheets(“sheet1”).Range(“D4:L45”)) ‘ Find how many names in the list
i = 1
Do While i <= HowMany
RandomNo:
RandomRow = Application.RandBetween(1, 45)
RandomColumn = Application.RandBetween(1, 15)
'Check to see if the name has already been picked
For ArI = LBound(Names) To UBound(Names)
If Names(ArI) = Sheets("sheet1").Cells(RandomRow, RandomColumn).Value Then
GoTo RandomNo
End If
Next ArI
Names(i) = Sheets("sheet1").Cells(RandomRow, RandomColumn).Value ' Assign random name to the array
i = i + 1
Loop
Dim RequiredRows As Integer
RequiredRow = 2
'Loop through the array and enter names onto the worksheet
For ArI = LBound(Names) To UBound(Names)
Do
Cells(CellsOutRow, CellsOutColumn) = Names(ArI)
CellsOutRow = CellsOutRow + 1
Loop While CellsOutRow < Cells(RequiredRow, CellsOutColumn).Value
CellsOutColumn = CellsOutColumn + 1
Next ArI
Application.ScreenUpdating = True
End Sub
Option Explicit
Sub WriteValues(ByVal values As Collection)
Dim row As Long
Dim col As Long
Dim val As Variant
row = 1
For Each val In values
Select Case row
' first four values in first column
Case Is <= 4
col = 1
' than 5 values in second column,
Case Is <= 9
col = 2
' and than may be 2 in second column...
Case Is <= 11
col = 2
' row > 11
Case Else
col = 3
End Select
Cells(row, col).Value = val
row = row + 1
Next val
End Sub
I am new to VBA and I need to expand an existing Worksheet and keep its formatting. There are 7 sections with variable length (in rows) and a width of 14 columns that need to be completed. So what I am trying to do is the following:
find the lines where the sections start
select the data out of each section and save it into an array (i thought about this as an array of length 7 and each entry contains a 2-dim. array with the data in it)
select my new data and expand the existing array (created in the last step) with that new data
override the current sheet with my new created array
add formatting
I managed to do step 1 and am currently struggling at step 2: I need to create an array with variable length where I can insert the data.
My code so far:
' this should create the array with the 7 entries
' "myArray" contains the row-numbers where the sections start
Function GenerateSheetArray(sheet As Worksheet, myArray As Variant) As Variant
Dim finalArray As Variant
Dim myInt As Integer
'here each entry should be filled
For i = 0 To 6
myInt = myArray(i)
finalArray(i) = GenerateArrayPart(sheet, myInt)
Next
GenerateSheetArray = finalArray
End Function
'This should fill each entry with the data of corresponding section
Function GenerateArrayPart(sheet As Worksheet, headline As Integer) As Variant
Dim leftIndex As Integer, rightIndex As Integer, rowcount As Integer
Dim sheetArray() As Variant
rowcount = 0
leftIndex = 1
rightIndex = 14
i = headline + 1
Do While sheet.Cells(i, 1) <> ""
rowcount = rowcount + 1
i = i + 1
Loop
If (rowcount > 0) Then
For colIndex = leftIndex To rightIndex
For rowIndex = 1 To rowcount
Row = headline + rowIndex
sheetArray(rowIndex - 1, colIndex - 1) = sheet.Cells(Row, colIndex)
Next
Next
End If
GenerateArrayPart = sheetArray
End Function
Now my problem is, that VBA throws an error at this line:
'atm rowIndex and colIndex are 1, Row is 40
'I know that there is data in that cell
sheetArray(rowIndex - 1, colIndex - 1) = sheet.Cells(Row, colIndex)
VBA says:
Index out of range
in method GenerateArrayPart.
How can this happen? I thought that variant can be pretty much everything and also does not need bounds to be used?
You are not having any value in the array. Thus, the array is only declared and not dimensionized.
Try this:
Dim finalArray As Variant
Redim finalArray(6)
Now, the array would have 7 values inside. From 0 to 6. The same error happens in the Function GenerateArrayPart, with the array sheetArray. There you need to declare the array as a multidimensional array. E.g. Redim sheetArray (N, M).
To see some small working sample, take a look at the code below:
Sub TestMe()
Dim finalArr As Variant
ReDim finalArr(6)
Dim i As Long
For i = LBound(finalArr) To UBound(finalArr)
finalArr = GenerateArrPart(i)
Next i
For i = LBound(finalArr) To UBound(finalArr)
Debug.Print i; finalArr(i, i)
Next i
End Sub
Public Function GenerateArrPart(a As Long) As Variant
Dim i As Long
Dim arrReturn As Variant
ReDim arrReturn(a + 1, a + 1)
For i = LBound(arrReturn) To UBound(arrReturn)
arrReturn(i, i) = a * i
Next i
GenerateArrPart = arrReturn
End Function
This is the output:
0 0
1 6
2 12
3 18
4 24
5 30
6 36
7 42