Array Fails to Change Value - arrays

I am trying to compare two different dynamic arrays in two different excel sheets I was able to assign value to the first but for the second one I am getting a run time error 9 subscript out of range
Sub sortandmark()
Dim x As Long, xg As Long
Dim Lfo() As String
Dim Greenlfo() As String
Dim i As Long, ig As Long
Dim j As Integer, jg As Long
Dim site As Long
'Get the main array
Windows("Test LFO sheet .xlsm").Activate
'x = ActiveSheet.UsedRange.SpecialCells(xlCellTypeVisible).Rows.Count
ReDim Lfo(2 To 2, 3 To 5) As String
For i = 2 To 2
For j = 3 To 5
Lfo(i, j) = Cells(i, j).Value
Next j
Next i
Windows("LFO LIST FOR OCT test.xlsx").Activate
'Greenville array set up
Sheets("GRE").Select
xg = ActiveSheet.UsedRange.SpecialCells(xlCellTypeVisible).Rows.Count
ReDim Greenlfo(2 To xg, 4 To 5)
For ig = 2 To xg
For jg = 3 To 4
Greenlfo(ig, jg) = ActiveSheet.Cells(ig, jg).Value ' Where the error occurs
Next jg
Next ig
'Testing and highlighting
If Lfo(i, 3) = Greenwood Then
Sheets("GRE").Select
End If
End Sub

Related

VBA array inverse

I am trying in Excel VBA to get some values from a spreadsheet in a square array invert this array. I have the following code:
Private Sub CommandButton1_Click()
Dim A As Variant
Dim i As Integer, j As Integer
ReDim A(1 To 3, 1 To 3) As Double
For i = 1 To 3
For j = 1 To 3
A(i, j) = Cells(i, j).Value
Next j
Next i
A = Application.WorksheetFunction.MInverse(A)
End Sub
In the line:
A = Application.WorksheetFunction.MInverse(A)
I get the error:
run-time error 1004: application defined or object defined error
Can anyone assist me on this?
Try the code below to read a 3×3 array from cell A1 and write the inverse on cell A5.
Private Sub CommandButton1_Click()
Dim A() as Variant, B() as Variant
A = Range("A1").Resize(3,3).Value
B = WorksheetFunctions.MMinverse(A)
Range("A5").Resize(3,3).Value = B
End Sub
There is no need to loop through each cell, which is a slow operation. Read and write whole tables with one command using the Range().Resize().Value syntax.
You may be trying to invert an ill-conditioned matrix. I tried your code on an easy example:
Sub dural()
Dim A As Variant
Dim i As Integer, j As Integer
ReDim A(1 To 3, 1 To 3) As Double
For i = 1 To 3
For j = 1 To 3
A(i, j) = Cells(i, j).Value
Next j
Next i
A = Application.WorksheetFunction.MInverse(A)
For i = 1 To 3
For j = 1 To 3
Cells(i + 5, j + 5).Value = A(i, j)
Next j
Next i
End Sub
and got:
which appears to be correct. (the product of the two matrices is very close to a unit matrix)

VBA datatype mismatch

I am working with Dates as my data and I think this may be causing some issues.
Sub test()
Dim counter As Long
For counter = 1 to 10
Dim fltArr(0 to 9)
Dim X
Dim Largest As Date
For items = 3 to 12
fltArr(items-3) = Cells(items, 6)
Next
X = fltArr
Largest = Application.Large(X, counter)
Next
End Sub
A mismatch Error seems to occur in the line
Largest = Application.Large(X, counter)
I think this may be due to Application.Large giving an integer instead of a Date. How could I fix this?
The only difference between Value2 property and the Value property is that the Value2 property doesn't use the Currency and Date data types. You can return values formatted with these data types as floating-point numbers by using the Double data type. Reference
All you have to do is change the line
fltArr(items-3) = Cells(items, 6)
to
fltArr(items-3) = Cells(items, 6).Value2
Try this
Sub test()
Dim counter As Long
Dim Largest As Date
For counter = 1 To 10
Dim fltArr(0 To 9) As Variant
Dim X As Variant
For items = 3 To 12
fltArr(items - 3) = Cells(items, 6).Value2
Next
X = fltArr
Largest = Application.Large(X, counter)
Debug.Print Largest
Next
End Sub
Large does not like to work with Date Arrays. If you declare the arrays as doubles it will return the values you want(Using your code):
Sub test()
Dim counter As Long
For counter = 1 To 10
Dim fltArr(0 To 9) As Double
Dim X() As Double
Dim Largest As Date
For items = 3 To 12
fltArr(items - 3) = Cells(items, 6)
Next
X = fltArr
Largest = Application.Large(Range("F3:F12"), counter)
Debug.print Largest
Next
End Sub

Loop to replicate values into an array

I’m in a situation where I need to reproduce something in VBA and a bit stuck given my lack of understanding of object oriented language and VBA in general.
Problem:
I need to produce an array or vector based on a 2 column table.
The first range (column) contains unit counts.
The second range (column) contains numeric values.
I need to replicate the value based on the number of units.
For example,
if the first row contains 3 units with a value of $100
I need the array to contain $100, $100, $100.
This will need to be looped thru each row containing units.
So if row 2 contains 2 units with a value of $50
I need to complete array to be $100, $100, $100, $50, $50, and so on.
I understand this situation will require ReDim the array based on the total values. My struggle is I’ve been unable to figure out the nested for loops.
I get how to replicate the value based on the number of “units” like the below...
ReDim arr(0 To x - 1)
For i = 0 To x - 1
arr(i) = rng.Offset(0, 1).Value
Next
What is the best way to loop thru each row and replicate the values for each row in the range based on the unit count?
If anyone is familiar with R, I'm essentially looking for something that achieves the rep() function (e.g., rep(df$b, df$a)) and return the values in a single array.
Any help is greatly appreciated. Thanks
Or a one liner which uses the REPT function as you would have used in r :)
This assumes your data is in A1:B10 - the length can be made variable
s = Split(Join(Application.Transpose(Evaluate("=INDEx(REPT(B1:B10&"","",A1:A10),,1)"))), ",")
An an example, to dump the new to array to C1
s = Split(Join(Application.Transpose(Evaluate("=INDEx(REPT(B1:B10&"","",A1:A10),,1)"))), ",")
[c1].Resize(UBound(s), 1) = Application.Transpose(s)
When you say Row contains 3 units, do you mean the cell has value 3 or 3 Units? If it is 3 then you may not have to Redim the array in the loop. Simply find the sum of values in Col A which has units and Redim it in one go as shown below.
Sub Sample()
Dim ws As Worksheet
Dim Ar() As String
Dim n As Long, i As Long, lRow As Long
'~~> Change this to the relevant sheet
Set ws = Sheet6
With ws
n = Application.WorksheetFunction.Sum(.Columns(1))
ReDim Ar(t To n)
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
n = 1
For i = 1 To lRow
If Len(Trim(.Range("A" & i).Value)) <> 0 Then
For j = 1 To .Range("A" & i).Value
Ar(n) = .Range("B" & i).Value
n = n + 1
Next j
End If
Next i
For i = LBound(Ar) To UBound(Ar)
Debug.Print Ar(i)
Next i
End With
End Sub
Screenshot
And if the cell has 3 Units then you will have to store the values of Col A in an array, do a replace on Unit/Units, find the sum and finally use the above code. Here is an example
Sub Sample()
Dim ws As Worksheet
Dim Ar() As String, tmpAr As Variant
Dim n As Long, i As Long, j As Long, k As Long, lRow As Long
'~~> Change this to the relevant sheet
Set ws = Sheet6
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
tmpAr = .Range("A1:A" & lRow).Value
For i = LBound(tmpAr) To UBound(tmpAr)
tmpAr(i, 1) = Replace(tmpAr(i, 1), "Units", "")
tmpAr(i, 1) = Trim(Replace(tmpAr(i, 1), "Unit", ""))
n = n + Val(tmpAr(i, 1))
Next i
ReDim Ar(t To n)
n = 1
For i = 1 To lRow
If Len(Trim(.Range("A" & i).Value)) <> 0 Then
k = Val(Trim(Replace(Replace(.Range("A" & i).Value, "Units", ""), "Unit", "")))
For j = 1 To k
Ar(n) = .Range("B" & i).Value
n = n + 1
Next j
End If
Next i
For i = 1 To UBound(Ar)
Debug.Print Ar(i)
Next i
End With
End Sub
Screenshot
if your data is already in an array then ReDim'ing will delete it's contents. You can ReDim Preserve but it's an expensive operation, better to create a new array to put the results into.
I have assumed the data is contained within a Named Range called "Data" with Units being the first column and Values being the second column.
if your data changes regularly you can create a dynamic range using the OFFSET function i.e. =OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),2) assuming your data starts in cell A1 and there is no header row.
Sub ProcessData()
Dim DataArr() As Variant
Dim QtyColArr() As Variant
Dim ResultArr() As Variant
Dim TotalQty As Long
Dim i As Long, j As Long, k As Long
'store data into array
DataArr = Range("Data") 'assume data stored in named range called "Data"
'store Qty col into 1D array
QtyColArr = Range("Data").Resize(, 1)
'sum all qty vals
TotalQty = Application.Sum(QtyColArr)
're-size ResultsArray
ReDim ResultArr(1 To TotalQty)
'Initialize ResultsArr counter
k = LBound(ResultArr)
'loop DataArr
For i = LBound(DataArr) To UBound(DataArr)
'loop qty for current row
For j = 1 To DataArr(i, 1)
'copy value
ResultArr(k) = DataArr(i, 2)
'iterate ResultsArr counter
k = k + 1
Next j
Next i
'output to intermediate window
Debug.Print "{" & Join(ResultArr) & "}"
End Sub

resizing range to enter array values into worksheet vba

If I wish to take an array and enter it into an Excel worksheet, how do I do that?
If I use my code below, they go into the wrong cell (G5 instead of F4) and cut off the last column and row of the array.
I can add 1 to each of the resize dimensions (which will give me all the values I need), but then the data still only starts in G5 rather than F4. How can I get the data to begin from F4? (I've condensed the problem to this from a much larger spreadsheet where I'm not able to just simply use the next cell). Code is as follows:
Public ArrayToPaste(4, 2) As Variant
Sub PasteTheArray()
Dim i, j As Integer
For i = 1 To 2
For j = 1 To 4
ArrayToPaste(j, i) = Cells(j, i).Value
Next j
Next i
Range("F4").Resize(UBound(ArrayToPaste, 1), UBound(ArrayToPaste, 2)) = ArrayToPaste
End Sub
You were very close:
Public ArrayToPaste(1 To 4, 1 To 2) As Variant
Sub PasteTheArray()
Dim i, j As Integer
For i = 1 To 2
For j = 1 To 4
ArrayToPaste(j, i) = Cells(j, i).Value
Next j
Next i
Range("F4").Resize(UBound(ArrayToPaste, 1), UBound(ArrayToPaste, 2)) = ArrayToPaste
End Sub
Just make ArrayToPaste 1-based rather than 0-based.

Can't cumulate the sum of array elements with VBA

I'm trying to cumulate the sums of values in an excel column of 4 values dimension (4,1).
So, I constructed the code below. For the first row in a column on the side Result, it is supposed to hold the same value as in the original Array.
But then, once it is greater than the first row, it is supposed to get the previous element of result (i-1) and add to it the current column element (i).
VBA is telling me that the subscript is out of range :/ and I cant figure out why... so I dont even know if my code does what I want.
Sub CumulativeSum()
Dim i As Integer
Dim j As Integer
Dim rColumn() As Variant
Dim result() As Variant
ReDim result(1 To 4)
rColumn = Worksheets("Sheet1").Range("E1:E4").Value2
For i = 1 To 4
result(1) = rColumn(1, 1)
For j = 2 To 3
result(j) = rColumn(j, 1) + result(j - 1)
Next j
Next i
Dim dest As Range
Set dest = Worksheets("Sheet1").Range("F1")
dest.Resize(4, 1).Value = result
End Sub
Sub CumulativeSum()
Dim dest As Range
Dim i As Integer
Dim j As Integer
Dim rColumn() As Variant
Dim result() As Variant
ReDim result(1 To 4)
rColumn = Worksheets("Sheet1").Range("E1:E4").Value2
result(1) = rColumn(1, 1)
For j = 2 To 4
result(j) = rColumn(j, 1) + result(j - 1)
Next j
Set dest = Worksheets("Sheet1").Range("F1")
dest.Resize(4, 1).Value = Application.Transpose(result)
End Sub
Don't have enough rep to add a comment but.. the reason why you're getting an error is because the Syntax for Cells is Cells([Row],[Column]). You're typing it in as Cells([Column],[Row]).
Try Range(Cells(1, 5), Cells(4, 5)) instead.

Resources