After populating my arrays based on some criteria I am attempting to write two temporary arrays to two different ranges on the worksheet. Using my current method with the transposed arrays I begin to get #N/A values after row 24,392. I'm not sure how to get past the size limitations of Application.Transpose.
LastRowA and LastRowB are declared globally as long. The value of LastRowA is >11,000 and LastRowB is >80,000
Sub Test()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'call subs to find last rows for each sheet
LastRowASub
LastRowBSub
Dim i As Long
Dim j As Long
Dim x As Double
Dim y As Double
Dim Arr1() As Variant
Dim Arr2() As Variant
Dim Temp1() As String
Dim Temp2() As String
ReDim Arr1(1 To LastRowA - 1, 3)
ReDim Arr2(1 To LastRowB - 1)
ReDim Temp1(1 To LastRowB - 1)
ReDim Temp2(1 To LastRowB - 1)
'populate first array
For x = 1 To LastRowA - 1
Arr1(x, 1) = sheet1.Range("k" & x + 1)
Arr1(x, 2) = sheet1.Range("c" & x + 1)
Arr1(x, 3) = sheet1.Range("a" & x + 1)
Next x
'populate second array
For y = 1 To LastRowB - 1
Arr2(y, 1) = sheet2.Range("f" & y + 1)
Next y
'populate two temporary arrays based on matching between arrays 1 and 2
For i = 1 To UBound(Arr2)
For j = 1 To UBound(Arr1)
If Arr1(j, 1) = Arr2(i, 1) And Not IsEmpty(Arr1(j, 2)) Then
Temp1(i) = Arr1(j, 2)
Temp2(i) = Arr1(j, 3)
End If
Next j
Next i
'write temp arrays to sheet2
sheet2.Range("C2:C" & ExtLRow) = Application.Transpose(Temp1)
sheet2.Range("G2:G" & ExtLRow) = Application.Transpose(Temp2)
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Everything is working as expected other than the transposed arrays returning #N/A.
Make the arrays 2 dimensional with one column:
ReDim Temp1(1 To LastRowB - 1,1 to 1)
ReDim Temp1(1 To LastRowB - 1,1 to 1)
Then when you assign the values:
Temp1(i,1) = Arr1(j, 2)
Temp2(i,1) = Arr1(j, 3)
Then you do not need the Application.Transpose
sheet2.Range("C2:C" & ExtLRow) = Temp1
sheet2.Range("G2:G" & ExtLRow) = Temp2
Also to speed things up avoid the loops altogether:
Sub Test()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'call subs to find last rows for each sheet
LastRowASub
LastRowBSub
Dim i As Long
Dim j As Long
Dim x As Double
Dim y As Double
Dim Arr1() As Variant
Dim Arr2() As Variant
Dim Temp1() As Variant
Dim Temp2() As Variant
ReDim Temp1(1 To LastRowB - 1, 1 To 1)
ReDim Temp2(1 To LastRowB - 1, 1 To 1)
'populate first array
Arr1 = Sheet1.Range("A2:K" & lastrowa).Value
'populate second array
Arr2 = sheet2.Range("F2:F" & LastRowB).Value
'populate two temporary arrays based on matching between arrays 1 and 2
For i = 1 To UBound(Arr2, 1)
For j = 1 To UBound(Arr1, 1)
If Arr1(j, 11) = Arr2(i, 1) And Not IsEmpty(Arr1(j, 3)) Then
Temp1(i, 1) = Arr1(j, 3)
Temp2(i, 1) = Arr1(j, 1)
End If
Next j
Next i
'write temp arrays to sheet2
sheet2.Range("C2:C" & ExtLRow).Value = Temp1
sheet2.Range("G2:G" & ExtLRow).Value = Temp2
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Related
I need to find values and test few conditions and insert row into an Excel sheet(file is heavy 65 MB). I have 7 such sheets where I need to insert data. And the reference basedata sheet inside the same file is 75k+ rows(wsSrcREDW)
My code runs really slow. Can someone please suggest faster algorithm. Thanks
Edit: the part that runs really slow is not the array assignments but the insertion of row loop in the end. It takes more than 5 mins to find new accounts and insert information.
Dim Curr() As String
For Each c In wsSrcREDW.Range("J2:J" & lrow1).Cells
ReDim Preserve Curr(2 To c.Row)
Curr(c.Row) = c.Value
Next c
Dim Entity() As String
For Each c In wsSrcREDW.Range("C2:C" & lrow1).Cells
ReDim Preserve Entity(2 To c.Row)
Entity(c.Row) = c.Value
Next c
Dim M9() As String
For Each c In wsSrcREDW.Range("F2:F" & lrow1).Cells
ReDim Preserve M9(2 To c.Row)
M9(c.Row) = c.Value
Next c
''' ECL Wback
Set wsECLWMBB = wbREDWMBB.Sheets("ECL WBack")
lrowECLWOrg = wsECLWMBB.Range("A" & Rows.Count).End(xlUp).Row
Dim I7() As String
For Each c In wsSrcREDW.Range("S2:S" & lrow1).Cells
ReDim Preserve I7(2 To c.Row)
I7(c.Row) = c.Value
Next c
For i = 2 To UBound(I7)
Set c = wsECLWMBB.Range("B2:B" & lrowECLWOrg).Find(I7(i))
If c Is Nothing And Entity(i) = "MIB" Then
lrowECLW = wsECLWMBB.Range("A" & Rows.Count).End(xlUp).Row
wsECLWMBB.Range("A" & (lrowECLW + 1)).EntireRow.Insert
wsECLWMBB.Range("A" & (lrowECLW + 1)).Value = M9(i)
wsECLWMBB.Range("B" & (lrowECLW + 1)).Value = I7(i)
wsECLWMBB.Range("C" & (lrowECLW + 1)).Value = Curr(i)
wsECLWMBB.Range("D" & (lrowECLW + 1)).Formula = "=MID(B" & (lrowECLW + 1) & ",1,7)"
End If
Next i
Use a variant array. Fill it and write the whole array in one operation. The following code should do it.
Option Explicit
Sub TEST()
Dim dataSrcEDW As Variant, dataECLWMBB As Variant, dataNew As Variant
Dim wsSrcREDW As Worksheet, wsECLWMBB As Worksheet
Dim colEntity As Long, colCurr As Long, colM9 As Long, colI7 As Long
Dim iSrcRow As Long, iTargetRow As Long, iNewRow As Long
Dim bFound As Boolean
Dim rgNew As Range
dataSrcEDW = wsSrcREDW.Range("A1").CurrentRegion ' Retrives all the source data
dataECLWMBB = wsECLWMBB.Range("A1").CurrentRegion ' Retrieves all the target data
ReDim dataNew(0, 1 To 4) ' This will contain the new rows you are adding at the end of wsECLWMBB
' Identify the columnns of interest
colCurr = Asc("J") - 64: colEntity = Asc("C") - 64: colM9 = Asc("F") - 64: colI7 = Asc("S") - 64
For iSrcRow = 2 To UBound(dataSrcEDW, 1) ' Scane through the source
bFound = False
If dataSrcEDW(iSrcRow, colEntity) = "MIB" Then
For iTargetRow = 2 To UBound(dataECLWMBB, 1)
If dataSrcEDW(iSrcRow, colI7) = dataECLWMBB(iTargetRow, 2) Then
bFound = True
Exit For
End If
Next
If Not bFound Then ' Check if this is a duplicate add
For iNewRow = 1 To UBound(dataNew, 1)
If dataSrcEDW(iSrcRow, colI7) = dataNew(iNewRow, 2) Then
bFound = True
Exit For
End If
Next
End If
If Not bFound Then
dataNew = AddRowToArray(dataNew)
iNewRow = UBound(dataNew, 1)
dataNew(iNewRow, 1) = dataSrcEDW(iSrcRow, colM9)
dataNew(iNewRow, 2) = dataSrcEDW(iSrcRow, colI7)
dataNew(iNewRow, 3) = dataSrcEDW(iSrcRow, colCurr)
dataNew(iNewRow, 4) = "=MID(B" & UBound(dataECLWMBB, 1) + iNewRow & ",1,7)"
End If
End If
Next
' Write out the new rows
If UBound(dataNew, 1) > 0 Then
Set rgNew = wsECLWMBB.Range("A" & UBound(dataECLWMBB, 1) + 1).Resize(UBound(dataNew, 1), UBound(dataNew, 2))
rgNew = dataNew
End If
End Sub
Public Function AddRowToArray(vArray) As Variant
' Can't do a redim preserve on a multi dimensional array. Add a row manually.
Dim vNewArray As Variant, iRow As Long, iCol As Long
ReDim vNewArray(1 To UBound(vArray, 1) + 1, 1 To UBound(vArray, 2))
For iRow = 1 To UBound(vArray, 1)
For iCol = 1 To UBound(vArray, 2)
vNewArray(iRow, iCol) = vArray(iRow, iCol)
Next
Next
AddRowToArray = vNewArray
End Function
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...
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
I am trying to use a loop with vba to sum values from one worksheet to another. I am struggling with writing my code to match values from Sheet 4 and if the value matches then sum the categories from Sheet 1, if not then skip to the next office. I would also like to exclude certain categories from being included in the SUM loop for example, exclude "Book". Currently my macro is writing to Sheet3. Here is my code:
Option Explicit
Sub test()
Dim a, i As Long, ii As Long, dic As Object
Set dic = CreateObject("Scripting.Dictionary")
dic.CompareMode = 1
a = Sheets("sheet1").Cells(1).CurrentRegion.Value
With CreateObject("Scripting.Dictionary")
.CompareMode = 1
For i = 2 To UBound(a, 1)
If Not dic.Exists(a(i, 1)) Then dic(a(i, 2)) = dic.Count + 2
If Not .Exists(a(i, 1)) Then
Set .Item(a(i, 1)) = CreateObject("Scripting.Dictionary")
.Item(a(i, 1)).CompareMode = 1
End If
.Item(a(i, 1))(a(i, 2)) = .Item(a(i, 1))(a(i, 2)) + a(i, 3)
Next
ReDim a(1 To .Count + 1, 1 To dic.Count + 1)
a(1, 1) = Sheets("sheet1").[a1]
For i = 0 To dic.Count - 1
a(1, i + 2) = dic.Keys()(i)
Next
For i = 0 To .Count - 1
a(i + 2, 1) = .Keys()(i)
For ii = 2 To UBound(a, 2)
a(i + 2, ii) = .items()(i)(a(1, ii)) + 0
Next
Next
End With
With Sheets("sheet3").Cells(1).Resize(UBound(a, 1), UBound(a, 2))
.EntireColumn.ClearContents
Sheets("sheet1").[a1].Copy .Rows(1)
.Value = a: .Columns.AutoFit: .Parent.Activate
End With
End Sub
This is how the data looks
and this is the output that is desired
In this example, we will use arrays to achieve what you want. I have commented the code so that you shall not have a problem understanding it. However if you still do then simply ask :)
Input
Output
Logic
Find last row and last column of input sheet
Store in an array
Get unique names from Column A and Row 1
Define output array
Compare array to store sum
Create new sheet and output to that sheet
Code
Option Explicit
Sub Sample()
Dim ws As Worksheet, wsNew As Worksheet
Dim tempArray As Variant, OutputAr() As Variant
Dim officeCol As New Collection
Dim productCol As New Collection
Dim itm As Variant
Dim lrow As Long, lcol As Long, totalsum As Long
Dim i As Long, j As Long, k As Long
'~~> Input sheet
Set ws = Sheet1
With ws
'~~> Get Last Row and last column
lrow = .Range("A" & .Rows.Count).End(xlUp).Row
lcol = .Cells(1, Columns.Count).End(xlToLeft).Column
'~~> Store it in a temp array
tempArray = .Range(.Cells(2, 1), .Cells(lrow, lcol)).Value
'~~> Create a unique collection using On error resume next
On Error Resume Next
For i = LBound(tempArray) To UBound(tempArray)
officeCol.Add tempArray(i, 1), CStr(tempArray(i, 1))
productCol.Add tempArray(i, 2), CStr(tempArray(i, 2))
Next i
On Error GoTo 0
End With
'~~> Define you new array which will hold the desired output
ReDim OutputAr(1 To officeCol.Count + 1, 1 To productCol.Count + 1)
'~~> Store the rows and columns in the array
i = 2
For Each itm In officeCol
OutputAr(i, 1) = itm
i = i + 1
Next itm
i = 2
For Each itm In productCol
OutputAr(1, i) = itm
i = i + 1
Next itm
'~~> Calculate sum by comparing the arrays
For i = 2 To officeCol.Count + 1
For j = 2 To productCol.Count + 1
totalsum = 0
For k = LBound(tempArray) To UBound(tempArray)
If OutputAr(i, 1) = tempArray(k, 1) And _
OutputAr(1, j) = tempArray(k, 2) Then
totalsum = totalsum + tempArray(k, 3)
End If
Next k
OutputAr(i, j) = totalsum
Next j
Next i
'~~> Create a new sheet
Set wsNew = ThisWorkbook.Sheets.Add
'~~> Outout the array
wsNew.Range("A1").Resize(officeCol.Count + 1, productCol.Count + 1).Value = OutputAr
End Sub
I have comments set up to run in and out of IBM Cognos formulas as needed.
To do so, I am putting the ranges into an array (LCogRng).
I am getting "Subscript out of range." once I get to ReDim Preserve LCogRng(1 To N, 1 To 2) As Range.
It works without Preserve, but that defeats the point.
Dim wb As Workbook
Dim ws As Worksheet
Dim rng As Range, N As Integer
Dim CogArr() As String
Dim LCogRng() As Range
Sub AddTM1()
Set wb = ActiveWorkbook
For Each ws In wb.Worksheets
ReDim CogArr(1 To 1) As String
ReDim LCogRng(1 To 1, 1 To 2) As Range
ws.Activate
For Each rng In ws.UsedRange
N = Mid(rng.Comment.Text, 3, InStr(rng.Comment.Text, ":") - 3)
cFormula = Mid(rng.Comment.Text, 5 + N, Len(rng.Comment.Text))
If CogArr(1) = "" Then
CogArr(1) = cFormula
Set LCogRng(1, 1) = rng
ElseIf UBound(CogArr) < N Then
ReDim Preserve CogArr(1 To N) As String
ReDim Preserve LCogRng(1 To N, 1 To 2) As Range 'Error row
CogArr(N) = cFormula
Set LCogRng(N, 1) = rng
End If
ElseIf InStr(rng.Comment.Text, "TM") > 0 And Len(rng.Comment.Text) <= 6 Then
N = Mid(rng.Comment.Text, 5, 2)
Set LCogRng(N, 2) = rng
End If
End If
Next rng
Any help is much appreciated.
For a 2D array as you have you can use TRANSPOSE to reorder the first dimesion, i.e.:
Sub UpdateArray()
Dim X
'çreate 4*2 array
X = [{"Apple","2";"Bananna","3";"Don","Bradman";"#Fail","PUA"}]
MsgBox UBound(X, 1) & " " & UBound(X, 2)
ReDim Preserve X(1 To UBound(X, 1), 1 To UBound(X, 2) + 1)
X = Application.Transpose(X)
ReDim Preserve X(1 To UBound(X, 1), 1 To UBound(X, 2) + 1)
X = Application.Transpose(X)
'you now have a 5*3 array
MsgBox UBound(X, 1) & " " & UBound(X, 2)
End Sub