Column A in sheet1 has the values [1,2,3,4,5,6] in range("A1:A6") and what I am trying to do is to get all the combinations of summing each two numbers and each three numbers and each four numbers and each five numbers
This is what I did till now but the results are not as I expected
Sub Test()
Dim a, b, lr As Long, i As Long, j As Long, k As Long, ii As Long
lr = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lr
For j = i To lr
For ii = j To lr
Cells(i, ii + 1) = i & "+" & j & "+" & ii & "=" & i + j + ii
Next ii
Next j
Next i
With Range("A1").CurrentRegion
a = .Offset(, 1).Resize(, .Columns.Count - 1).Value
ReDim b(1 To UBound(a, 1) * UBound(a, 2), 1 To 1)
For i = LBound(a) To UBound(a)
For j = LBound(a, 2) To UBound(a, 2)
If a(i, j) <> "" Then
k = k + 1
b(k, 1) = a(i, j)
End If
Next j
Next i
.Cells(1, .Columns.Count + 2).Resize(k).Value = b
End With
End Sub
Example of the desired output:
Each two numbers together >>
Sub Test()
Dim a, b, lr As Long, i As Long, j As Long, k As Long, ii As Long
lr = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lr
For j = i To lr
Cells(i, j + 1) = i & "+" & j & "=" & i + j
Next j
Next i
With Range("A1").CurrentRegion
a = .Offset(, 1).Resize(, .Columns.Count - 1).Value
ReDim b(1 To UBound(a, 1) * UBound(a, 2), 1 To 1)
For i = LBound(a) To UBound(a)
For j = LBound(a, 2) To UBound(a, 2)
If a(i, j) <> "" Then
k = k + 1
b(k, 1) = a(i, j)
End If
Next j
Next i
.Cells(1, .Columns.Count + 2).Resize(k).Value = b
End With
End Sub
The results would be like that in column J
1+1=2
1+2=3
1+3=4
1+4=5
1+5=6
1+6=7
2+2=4
2+3=5
2+4=6
2+5=7
2+6=8
3+3=6
3+4=7
3+5=8
3+6=9
4+4=8
4+5=9
4+6=10
5+5=10
5+6=11
6+6=12
This is OK for each two numbers .. How can I get the results for each three numbers and for each four numbers and for each five numbers?
** #Vityata
Public Sub PrintArrayOnSingleLine(myArray As Variant)
Dim i As Long, x As Long
Dim textArray As String, temp As String
For i = LBound(myArray) To UBound(myArray)
textArray = textArray & myArray(i)
x = x + Val(myArray(i))
temp = temp & "+" & myArray(i)
Next i
Dim myLastRow As Long
myLastRow = LastRow(Worksheets(1).Name) + 1
ActiveSheet.Cells(myLastRow, 1) = Mid(temp, 2) & "=" & x
End Sub
I have edited the procedure as you told me, but just one note, I can't get the same number to be summed. Example: 1+1=2
Combination (not repeating same values):
Copy the code below and run it. Then change the variable in size = n. The given numbers are in the initialArray. In the end, instead of printing the array as a textArray, add a variable to sum it:
Sub Main()
Dim size As Long: size = 2
Dim initialArray As Variant: initialArray = Array(1, 2, 3, 4, 5, 6)
Dim arr As Variant: ReDim arr(size - 1)
Dim n As Long: n = UBound(arr) + 1
EmbeddedLoops 0, size, initialArray, n, arr
End Sub
Function EmbeddedLoops(index As Long, size As Long, initialArray As Variant, n As Long, arr As Variant)
Dim p As Variant
If index >= size Then
If Not AnyValueBiggerThanNext(arr) And Not AnyValueIsRepeated(arr) Then
PrintArrayOnSingleLine arr
End If
Else
For Each p In initialArray
arr(index) = p
EmbeddedLoops index + 1, size, initialArray, n, arr
Next p
End If
End Function
Public Function AnyValueBiggerThanNext(arr As Variant) As Boolean
Dim i As Long
For i = LBound(arr) To UBound(arr) - 1
If arr(i) > arr(i + 1) Then
AnyValueBiggerThanNext = True
Exit Function
End If
Next i
AnyValueBiggerThanNext = False
End Function
Public Function AnyValueIsRepeated(arr As Variant) As Boolean
On Error GoTo AnyValueIsRepeated_Error:
Dim element As Variant
Dim testCollection As New Collection
For Each element In arr
testCollection.Add "item", CStr(element)
Next element
AnyValueIsRepeated = False
On Error GoTo 0
Exit Function
AnyValueIsRepeated_Error:
AnyValueIsRepeated = True
End Function
Public Sub PrintArrayOnSingleLine(myArray As Variant)
Dim i As Long
Dim textArray As String
For i = LBound(myArray) To UBound(myArray)
textArray = textArray & myArray(i)
Next i
Debug.Print textArray
End Sub
Permutation (repeating same values)
Sub Main()
Static size As Long
Static c As Variant
Static arr As Variant
Static n As Long
size = 3
c = Array(1, 2, 3, 4, 5, 6)
n = UBound(c) + 1
ReDim arr(size - 1)
EmbeddedLoops 0, size, c, n, arr
End Sub
Function EmbeddedLoops(index, k, c, n, arr)
Dim i As Variant
If index >= k Then
PrintArrayOnSingleLine arr
Else
For Each i In c
arr(index) = i
EmbeddedLoops index + 1, k, c, n, arr
Next i
End If
End Function
Public Sub PrintArrayOnSingleLine(myArray As Variant)
Dim counter As Integer
Dim textArray As String
For counter = LBound(myArray) To UBound(myArray)
textArray = textArray & myArray(counter)
Next counter
Debug.Print textArray
End Sub
Sources (Disclaimer - from my blog):
VBA Nested Loop with Recursion
VBA All Combinations
Related
I am trying to devise a code that enables me to repeat a range (of one column) to be repeated Nth times. This is my try (and it is working) but I need your ideas to improve the code if possible
Sub Test()
Const N As Integer = 3
Dim a, i As Long, ii As Long, k As Long
a = ActiveSheet.Range("A1:A" & ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row).Value
ReDim b(1 To UBound(a, 1) * N, 1 To 1)
For i = 1 To N
For ii = LBound(a, 1) To UBound(a, 1)
k = k + 1
b(k, 1) = a(ii, 1)
Next ii
Next i
Range("C1").Resize(UBound(b, 1), UBound(b, 2)).Value = b
End Sub
I would do it similarly...
Sub Test()
Dim a, c&, i&, k&
Const n& = 3
a = [a1].Resize(Cells(Rows.Count, 1).End(xlUp).Row)
ReDim b(1 To n * UBound(a), 1 To 1)
For k = 1 To n
For i = 1 To UBound(a)
c = c + 1
b(c, 1) = a(i, 1)
Next
Next
[c1].Resize(UBound(b)) = b
End Sub
But it would be best to make it into an encapsulated procedure...
Sub Test()
CloneRange [a1], [c1], 3
End Sub
Sub CloneRange(rSrc As Range, rDst As Range, Optional n& = 1)
Dim a, c&, i&, k&
a = rSrc.Resize(Cells(Rows.Count, 1).End(xlUp).Row)
ReDim b(1 To n * UBound(a), 1 To 1)
For k = 1 To n
For i = 1 To UBound(a)
c = c + 1
b(c, 1) = a(i, 1)
Next
Next
rDst.Resize(UBound(b)) = b
End Sub
as a beginner in VBA programming I have a hard time figuring out what the problem is. The code works perfectly when the values increase in order, but when there are values in the array that are not similar then I get an error.
When the problematic values are loaded, an error occurs Run time error 9, subscript out of range and this line is highlighted in the code sequenceArr(counter) = arr(i + 1) The main task of the code is to make short notations of long strings of numbers and to make a separation between different strings.
For example: i have box ID numbers: M0054515, M0054516, M0054517, M0054620, M0054621, M0054622, M0054751, M0054752, M0054753
When i run macro i get output result like this:
M0054515-517 // M0054620-622 // M0054751-753.
But when i have some random numbers in middile of ID number series i get an error... M0046552, M0047396, M0047399, M0047802, M0047803 instead of separated values i get run time error message.
At this link is an example version of my book, if anyone wants to help solve the problem.
For this job I use this code written a long time ago by another member of this forum
Sub Generate()
Dim ws As Worksheet
Dim arr() As String, result As String, letter As String, cellValue As String, tempLastElement As String
Dim lastColumn As Long, counter As Long
Dim firstColumn As Integer, targetRow As Integer, i As Integer
Set ws = Worksheets("KreirajRadniNalog")
firstColumn = 1
targetRow = 1
lastColumn = ws.Range(ws.Cells(targetRow, firstColumn), ws.Cells(targetRow, Columns.Count).End(xlToLeft).Columns).Count
ReDim arr(1 To lastColumn - firstColumn + 1)
letter = Left(ws.Cells(targetRow, firstColumn).Value, 1)
For i = 1 To UBound(arr)
cellValue = ws.Cells(targetRow, i).Value
arr(i) = Right(cellValue, Len(cellValue) - 1)
Next i
ReDim sequenceArr(1 To UBound(arr))
sequenceArr(1) = arr(1)
counter = 2
For i = 1 To UBound(arr) - 1
If CLng(arr(i)) + 1 = CLng(arr(i + 1)) Then
tempLastElement = arr(i + 1)
sequenceArr(counter) = tempLastElement
Else
counter = counter + 1
sequenceArr(counter) = arr(i + 1) '<<<this line here is highlighted
counter = counter + 1
End If
Next
ReDim Preserve sequenceArr(1 To counter)
result = ""
counter = 1
For i = 1 To UBound(sequenceArr) - 1
If counter > UBound(sequenceArr) Then Exit For
If result = "" Then
result = letter & sequenceArr(counter) & "-" & Right(sequenceArr(counter + 1), 3)
counter = counter + 2
Else
result = result & "//" & letter & sequenceArr(counter) & "-" & Right(sequenceArr(counter + 1), 3)
counter = counter + 2
End If
Next
ws.Range("C4").Value = result
End Sub
Please, try the next updated code. Since you did not answer my clarification question, I (only) hope that I could deduce what you want accomplishing...
Sub Generate()
Dim ws As Worksheet
Dim arr, sequenceArr, letter As String, cellValue As String, tempLastElement As String
Dim lastColumn As Long, counter As Long, firstColumn As Long, targetRow As Integer, i As Long, j As Long
Set ws = Worksheets("KreirajRadniNalog")
firstColumn = 1: targetRow = 1
lastColumn = ws.Range(ws.Cells(targetRow, firstColumn), ws.Cells(targetRow, Columns.Count).End(xlToLeft).Columns).Count
ReDim arr(1 To lastColumn - firstColumn + 1)
letter = Left(ws.Cells(targetRow, firstColumn).Value, 1)
For i = 1 To UBound(arr)
cellValue = ws.Cells(targetRow, i).Value
arr(i) = Right(cellValue, Len(cellValue) - 1)
Next i
ReDim sequenceArr(1 To UBound(arr))
counter = 1
For i = 1 To UBound(arr) - 1
If CLng(arr(i)) + 1 = CLng(arr(i + 1)) Then
For j = 0 To UBound(arr)
If i + j + 1 > UBound(arr) Then Exit For
If CLng(arr(i)) + j + 1 = CLng(arr(i + 1 + j)) Then
tempLastElement = arr(i + 1 + j)
Else
Exit For
End If
Next j
sequenceArr(counter) = arr(i) & "-" & Right(tempLastElement, 3)
counter = counter + 1: i = i + j
Else
sequenceArr(counter) = arr(i): counter = counter + 1
End If
Next
ReDim Preserve sequenceArr(1 To counter - 1)
ws.Range("C4").Value = letter & Join(sequenceArr, "//" & letter)
MsgBox "Success!"
End Sub
A more compact version, working with 0 based arrays:
Sub Generate2()
Dim ws As Worksheet
Dim arr, sequenceArr, letter As String, cellValue As String, tempLastElement As String
Dim lastColumn As Long, counter As Long, firstColumn As Long, targetRow As Integer, i As Long, j As Long
Set ws = Worksheets("KreirajRadniNalog")
firstColumn = 1: targetRow = 1
lastColumn = ws.Range(ws.Cells(targetRow, firstColumn), ws.Cells(targetRow, Columns.Count).End(xlToLeft).Columns).Count
letter = Left(ws.Cells(targetRow, firstColumn).Value, 1)
With Application
arr = .Transpose(.Transpose(ws.Range(ws.Cells(targetRow, firstColumn), ws.Cells(targetRow, lastColumn)).Value))
End With
arr(1) = Mid(arr(1), 2)
arr = Split(Join(arr, "|"), "|" & letter)
ReDim sequenceArr(UBound(arr))
counter = 0
For i = 0 To UBound(arr) - 1
If CLng(arr(i)) + 1 = CLng(arr(i + 1)) Then
For j = 0 To UBound(arr)
If i + j + 1 > UBound(arr) Then Exit For
If CLng(arr(i)) + j + 1 = CLng(arr(i + 1 + j)) Then
tempLastElement = arr(i + 1 + j)
Else
Exit For
End If
Next j
sequenceArr(counter) = arr(i) & "-" & Right(tempLastElement, 3)
counter = counter + 1: i = i + j
Else
sequenceArr(counter) = arr(i): counter = counter + 1
End If
Next
ReDim Preserve sequenceArr(1 To counter)
ws.Range("C4").Value = letter & Join(sequenceArr, "//" & letter)
MsgBox "Success!"
End Sub
The problem with your code is here
Else
counter = counter + 1
sequenceArr(counter) = arr(i + 1) '<<<this line here is highlighted
counter = counter + 1
End If
because for every single number the counter is incremented twice and so exceeds the array size. However you don't really need arrays
Sub Generate()
Dim ws As Worksheet, arr
Dim lastColumn As Long, letter As String, tmp As String
Dim result As String, i As Long, m As Long, n As Long
Set ws = Worksheets("KreirajRadniNalog")
Const firstColumn = 1
Const targetRow = 1
lastColumn = ws.Cells(targetRow, Columns.Count).End(xlToLeft).Column
arr = ws.Cells(targetRow, 1).Resize(, lastColumn)
result = arr(1, 1)
m = Mid(arr(1, 1), 2)
For i = 2 To UBound(arr, 2)
n = Mid(arr(1, i), 2)
If n = m + 1 Then
tmp = "-" & Right(Val(Mid(arr(1, i), 2)), 3)
Else
result = result & tmp & "//" & arr(1, i)
tmp = ""
End If
m = n
Next
result = result & tmp
ws.Range("C4").Value = result
End Sub
The code I have takes cells containing the delimiter (; ) from a column, and creates new rows (everything except the column is duplicated) to separate those values.
What I have
I need this for multiple columns in my data, but I don't want the data to overlap (ex: for 3 columns, I want there to be only one value per row in those 3 columns). It would be ideal if I could select multiple columns instead of only one as my code does now.
What I want
Sub splitByCol()
Dim r As Range, i As Long, ar
Set r = Worksheets("Sheet").Range("J2000").End(xlUp)
Do While r.Row > 1
ar = Split(r.Value, "; ")
If UBound(ar) >= 0 Then r.Value = ar(0)
For i = UBound(ar) To 1 Step -1
r.EntireRow.Copy
r.Offset(1).EntireRow.Insert
r.Offset(1).Value = ar(i)
Next
Set r = r.Offset(-1)
Loop
End Sub
Try this code
Sub Test()
Dim a, x, e, i As Long, ii As Long, iii As Long, k As Long
a = Range("A1").CurrentRegion.Value
ReDim b(1 To 1000, 1 To UBound(a, 2))
For i = LBound(a) To UBound(a)
For ii = 2 To 3
x = Split(a(i, ii), "; ")
For Each e In x
k = k + 1
b(k, 1) = k
b(k, 2) = IIf(ii = 2, e, Empty)
b(k, 3) = IIf(ii = 3, e, Empty)
b(k, 4) = a(i, 4)
Next e
Next ii
Next i
Range("A5").Resize(UBound(b, 1), UBound(b, 2)).Value = b
End Sub
I'd go this way
Sub SplitByCol()
With Worksheets("Sheet")
With .Range("B2", .Cells(.Rows.Count, "B").End(xlUp))
Dim firstColValues As Variant
firstColValues = .Value
Dim secondColValues As Variant
secondColValues = .Offset(, 1).Value
Dim thirdColValues As Variant
thirdColValues = .Offset(, 2).Value
.Offset(, -1).Resize(, 4).ClearContents
End With
Dim iRow As Long
For iRow = LBound(firstColValues) To UBound(firstColValues)
Dim currFirstColValues As Variant
currFirstColValues = Split(firstColValues(iRow, 1), "; ")
Dim currSecondColValues As Variant
currSecondColValues = Split(secondColValues(iRow, 1), "; ")
With .Cells(.Rows.Count, "C").End(xlUp).Offset(1, -1)
With .Resize(UBound(currFirstColValues) + 1)
.Value = currFirstColValues
.Offset(, 2).Value = thirdColValues(iRow, 1)
End With
End With
With .Cells(.Rows.Count, "B").End(xlUp).Offset(1, 1)
With .Resize(UBound(currSecondColValues) + 1)
.Value = currSecondColValues
.Offset(, 1).Value = thirdColValues(iRow, 1)
End With
End With
Next
End With
End Sub
Follow the code step by step by pressing F8 while the cursor is in any code line in the VBA IDE and watch what happens in the Excel user interface
EDIT
adding edited code for a more "parametric" handling by means of a helper function
Sub SplitByCol()
With Worksheets("Sheet")
With .Range("B2", .Cells(.Rows.Count, "B").End(xlUp))
Dim firstColValues As Variant
firstColValues = .Value
Dim secondColValues As Variant
secondColValues = .Offset(, 1).Value
Dim thirdColValues As Variant
thirdColValues = .Offset(, 2).Value
.Offset(, -1).Resize(, 4).ClearContents
End With
Dim iRow As Long
For iRow = LBound(firstColValues) To UBound(firstColValues)
Dim currFirstColValues As Variant
currFirstColValues = Split(firstColValues(iRow, 1), "; ")
Dim currSecondColValues As Variant
currSecondColValues = Split(secondColValues(iRow, 1), "; ")
WriteOne .Cells(.Rows.Count, "C").End(xlUp).Offset(1), _
currFirstColValues, thirdColValues(iRow, 1), _
-1, 2
WriteOne .Cells(.Rows.Count, "B").End(xlUp).Offset(1), _
currSecondColValues, thirdColValues(iRow, 1), _
1, 1
Next
End With
End Sub
Sub WriteOne(refCel As Range, _
currMainColValues As Variant, thirdColValue As Variant, _
mainValuesOffsetFromRefCel As Long, thirdColValuesOffsetFromRefCel As Long)
With refCel.Offset(, mainValuesOffsetFromRefCel)
With .Resize(UBound(currMainColValues) + 1)
.Value = currMainColValues
.Offset(, thirdColValuesOffsetFromRefCel).Value = thirdColValue
End With
End With
End Sub
Please, use the next code. It uses arrays and should be very fast for big ranges to be processed, working mostly in memory:
Sub testSplitInsert()
Dim sh As Worksheet, lastR As Long, arr, arrSp, arrFin, i As Long, j As Long, k As Long
Set sh = ActiveSheet
lastR = sh.Range("B" & sh.rows.count).End(xlUp).row
arr = sh.Range("B1:D" & lastR).Value
ReDim arrFin(1 To UBound(arr) * 10, 1 To 3) 'maximum to keep max 10 rows per each case
k = 1 'initialize the variable to load the final array
For i = 1 To UBound(arr)
arrSp = Split(Replace(arr(i, 1)," ",""), ";") 'trim for the case when somebody used Red;Blue, instead of Red; Blue
For j = 0 To UBound(arrSp)
arrFin(k, 1) = arrSp(j): arrFin(k, 3) = arr(i, 3): k = k + 1
Next j
arrSp = Split(Replace(arr(i, 1)," ",""), ";")
For j = 0 To UBound(arrSp)
arrFin(k, 2) = arrSp(j): arrFin(k, 3) = arr(i, 3): k = k + 1
Next j
Next
sh.Range("G1").Resize(k - 1, 3).Value = arrFin
End Sub
It processes the range in columns "B:D" and returns the result in columns "G:I". It can be easily adapted to process any columns range and return even overwriting the existing range, but this should be done only after checking that it return what you need...
I have a 3 by 3 matrix, where elements (1,1), (2,1), (2,2), (3,1), (3,2), (3,3) are given:
X . .
X X .
X X X
I need to write a program that writes out the missing elements, where (1,2)=(2,1), (1,3)=(3,1) and (2,3)=(3,2). I have written the following code:
Function kiegeszito(a)
For i = 1 To 3
For j = 1 To 3
If i < j Then
a(i, j) = a(j, i)
Else
a(i, j) = a(i, j)
End If
Next j
Next i
kiegeszito = a
End Function
However, this does not seem to work, could anybody help me why is this not working?
Just remove the Else condition:
Function kiegeszito(a)
For i = 1 To 3
For j = 1 To 3
If i < j Then a(i, j) = a(j, i)
Next j
Next i
kiegeszito = a
End Function
Get twin data in 2-dim matrix avoiding extra n*(n-1)/2 condition checks
The following approach
reduces the number of unnecessary condition checks by incrementing the 2nd loop starts
accepts any wanted base of 2-dim data:
Sub CompleteMatrix(ByRef data)
'count row|=column elements
Dim cnt As Long: cnt = UBound(data) - LBound(data) + 1
'fill missing twin data (identified by inverted indices)
Dim i As Long, j As Long
For i = LBound(data) To cnt - 1
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'next column starts from incremented row index
'(thus avoiding n*(n-1)/2 IF-conditions)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For j = i + 1 To UBound(data, 2)
data(i, j) = data(j, i) ' assign twin data
Next j
Next i
End Sub
An example call creating e.g. a 1-based 2-dim datafield array might be
Sub ExampleCall()
Dim v: v = Tabelle3.Range("A1:C3").Value
CompleteMatrix v
End Sub
Further link
A practical example using such a mirrored array might be a distance array; a related post demonstrates how to apply the FilterXML() function thereon.
Fill Array
Using a method (fillArray) you could modify the array 'in place':
The Code
Option Explicit
Sub fillArrayTEST()
Dim Data As Variant: Data = Range("A1:C3").Value
debugPrint2D Data
fillArray Data
debugPrint2D Data
End Sub
Sub fillArray(ByRef Data As Variant)
Dim cCount As Long: cCount = UBound(Data, 2)
Dim i As Long, j As Long
For i = 1 To UBound(Data, 1)
For j = 1 To cCount
If i < j Then Data(i, j) = Data(j, i)
Next j
Next i
End Sub
Sub debugPrint2D(ByVal Data As Variant)
Dim i As Long, j As Long
For i = LBound(Data, 1) To UBound(Data, 1)
For j = LBound(Data, 2) To UBound(Data, 2)
Debug.Print "[" & i & "," & j & "]", Data(i, j)
Next j
Next i
End Sub
A Homage to T.M.'s Brilliant Solution
Sub completeMatrix(ByRef Data As Variant)
Dim rLower As Long: rLower = LBound(Data, 1)
Dim cLower As Long: cLower = LBound(Data, 2)
Dim iDiff As Long: iDiff = cLower - rLower
Dim cStart As Long: cStart = iDiff + 1
Dim cUpper As Long: cUpper = UBound(Data, 2)
Dim r As Long, c As Long
For r = rLower To UBound(Data, 1) - rLower
For c = cStart + r To cUpper
Data(r, c) = Data(c - iDiff, r + iDiff)
Next c
Next r
End Sub
Sub completeMatrixTEST()
Dim Data As Variant: ReDim Data(0 To 2, 2 To 4)
Data(0, 2) = 1
Data(1, 2) = 2
Data(1, 3) = 3
Data(2, 2) = 4
Data(2, 3) = 5
Data(2, 4) = 6
debugPrint2D Data
completeMatrix Data
'Range("G1").Resize(UBound(Data, 1) - LBound(Data, 1) + 1, _
UBound(Data, 2) - LBound(Data, 2) + 1).Value = Data
Debug.Print
debugPrint2D Data
End Sub
I have a spreadsheet containing a column of numbers.
For every value within the reference column, I need the to excel to produce a row of number in the adjacent column with values starting from the number 1, incrementally increasing by 1 and ending once the reference value is reach. This then needs to be repeated for the next value in the reference column and so on, continuing to expand in the adjacent column.
Below is an example of the reference column containing 3 values and what i did manually adjacent. Can some please help me write function in VBA so that i dont need to do this manually.
Thanks for the help in advanced.
Sub main()
Dim cell As Range, i As Long
For Each cell In Range("I2", Cells(Rows.Count, "I").End(xlUp))
For i = 1 To cell.Value
Cells(Rows.Count, "J").End(xlUp).Offset(1).Value = i
Next
Next
End Sub
Larger grouped series would benefit from an array.
sub main()
dim i as long, j as long, k as long, vals as variant
redim vals(1 to application.sum(range(cells(2, "i"), cells(rows.count, "i").end(xlup))), 1 to 1)
for i=2 to cells(rows.count, "i").end(xlup).row
for j=1 to cells(i, "i").value2
k=k+1
vals(k, 1) = j
next j
next i
cells(2, "j").resize(ubound(vals, 1), ubound(vals, 2)) = vals
end sub
This doesn't allow you to go beyond last Excel row
Option Explicit
Public Sub ExpandReferenceNumbers()
Const REF_COL = 9 'I
Dim arr As Variant, lr As Long, i As Long, j As Long, k As Long
Dim maxRows As Long, maxVal As Long, maxXLRows As Long
maxXLRows = Rows.Count
lr = Sheet1.Cells(maxXLRows, REF_COL).End(xlUp).Row
arr = Sheet1.Range(Sheet1.Cells(2, REF_COL), Sheet1.Cells(lr, REF_COL))
For i = 1 To lr - 1
maxRows = maxRows + arr(i, 1)
Next
If maxRows > maxXLRows Then maxRows = maxXLRows - 2
arr = Sheet1.Range(Sheet1.Cells(2, REF_COL), Sheet1.Cells(maxRows + 1, REF_COL + 1))
k = 1
For i = 1 To lr
For j = 1 To arr(i, 1)
If k + j - 1 > maxRows Then Exit For
arr(k + j - 1, 2) = j
Next
k = k + arr(i, 1)
Next
Sheet1.Range(Sheet1.Cells(2, REF_COL), Sheet1.Cells(maxRows + 1, REF_COL + 1)) = arr
End Sub
Result
Or with arrays
Option Explicit
Sub test()
Dim arr(), i As Long, j As Long, output As String
With ThisWorkbook.Worksheets("Sheet1")
arr = .Range("I2", .Cells(.Rows.Count, "I").End(xlUp)).Value
For i = LBound(arr, 1) To UBound(arr, 1)
j = 0
Do While j < arr(i, 1)
j = j + 1
output = output & CStr(j) & ","
Loop
Next i
.Range("J2").Resize(UBound(Split(output, ",")), 1) = Application.WorksheetFunction.Transpose(Split(output, ","))
End With
End Sub