Trying to store array values into cells in an excel sheet - arrays

I've been having some problems with storing some calculated values into an excel sheet in specific cells. The complete code is lengthy but I've posted it below. While running with the debugger what I've found is that it is failing when it tries to store this first value in the first step of the following for loop:
For i = 1 To 100
Cells(i, 1).Value = Cmatrix(i, 1)
Cells(i, 2).Value = Cmatrix(i, 2)
Next i
I've also tried it with ActiveSheet.Cells(i, 1).Value but I still just get a #VALUE! error during the first line of the for loop. I've also tried with and without the .Value
The Cmatrix is declared as a variant but I've also declared it as a double before just to see. It is an array from 1-100 and 1-2. I've even tried just setting it equal to 1 but the same problem arrises.
The overall code is rather lengthy but is here with the problem area being closer to the bottom:
Option Explicit
Public Function Test(check As Integer) As Integer
Dim Response As Integer
If check = 1 Then
Response = MsgBox("Boundary Condition 1 selected, is this correct (select No for boundary condition 2)?", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 1
Else
Test = 2
End If
ElseIf check = 2 Then
Response = MsgBox("Boundary Condition 2 selected, is this correct (select No for boundary condition 1)?", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 2
Else
Test = 1
End If
Else
Response = MsgBox("Incorrect Boundary Condition, select Yes for condition 1 and No for condition 2", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 1
Else
Test = 2
End If
End If
End Function
Public Sub Check2(x)
MsgBox ("Value given is outside data range, answer may not be correct, extrapolating from calculated polynomial")
End Sub
Public Function cubic(ByVal r As Range, x As Double, Optional check As Integer = 1) As Double
Dim data() As Double
Dim check1 As Integer
Dim Smatrix() As Double
Dim Tmatrix() As Double
Dim Xmatrix() As Double
Dim Amatrix() As Double
Dim Hmatrix() As Double
Dim Cmatrix(1 To 100, 1 To 2) As Variant
Dim m As Integer
Dim i As Integer, j As Integer
Dim step As Double
Dim chart As Range, c As Range
m = r.Rows.Count
ReDim data(1 To m, 2)
ReDim Smatrix(1 To m, 1 To m)
ReDim Tmatrix(1 To m, 4)
ReDim Xmatrix(1 To m)
ReDim Amatrix(1 To m - 1, 1 To 4)
ReDim Hmatrix(1 To m)
check1 = Test(check)
For i = 1 To m
data(i, 1) = r(i, 1).Value
data(i, 2) = r(i, 2).Value
Next i
Smatrix(1, 1) = 1
Smatrix(m, m) = 1
For i = 1 To m - 1
Hmatrix(i) = data(i + 1, 1) - data(i, 1)
Next i
If check1 = 2 Then
Smatrix(1, 2) = -1
Smatrix(m, m - 1) = -1
End If
For i = 2 To m - 1
Smatrix(i, i - 1) = Hmatrix(i - 1)
Smatrix(i, i + 1) = Hmatrix(i)
Smatrix(i, i) = 2 * (Hmatrix(i - 1) + Hmatrix(i))
Next i
For i = 2 To m - 1
Tmatrix(i, 4) = 6 * ((data(i + 1, 2) - data(i, 2)) / Hmatrix(i) - (data(i, 2) - data(i - 1, 2)) / Hmatrix(i - 1))
Next i
For i = 1 To m
If i <> 1 Then
Tmatrix(i, 1) = Smatrix(i, i - 1)
End If
Tmatrix(i, 2) = Smatrix(i, i)
If i <> m Then
Tmatrix(i, 3) = Smatrix(i, i + 1)
End If
Next i
For i = 2 To m
Tmatrix(i, 1) = Tmatrix(i, 1) / Tmatrix(i - 1, 2)
Tmatrix(i, 2) = Tmatrix(i, 2) - Tmatrix(i, 1) * Tmatrix(i - 1, 3)
Tmatrix(i, 4) = Tmatrix(i, 4) - Tmatrix(i, 1) * Tmatrix(i - 1, 4)
Next i
Xmatrix(m) = Tmatrix(m, 4) / Tmatrix(m, 2)
For i = m - 1 To 1 Step -1
Xmatrix(i) = (Tmatrix(i, 4) - Tmatrix(i, 3) * Xmatrix(i + 1)) / Tmatrix(i, 2)
Next i
For i = 1 To m - 1
Amatrix(i, 1) = (Xmatrix(i + 1) - Xmatrix(i)) / 6 * Hmatrix(i)
Amatrix(i, 2) = Xmatrix(i) / 2
Amatrix(i, 3) = (data(i + 1, 2) - data(i, 2)) / Hmatrix(i) - Hmatrix(i) * Xmatrix(i) / 2 - Hmatrix(i) * (Xmatrix(i + 1) - Xmatrix(i)) / 6
Amatrix(i, 4) = data(i, 2)
Next i
step = (data(m, 1) - data(1, 1)) / 100
For i = 0 To (m - 1)
Cmatrix(i + 1, 1) = data(1, 1) + i * step
Next i
For j = 1 To m
If Cmatrix(j, 1) = data(m, 1) Then
Cmatrix(j, 2) = data(m, 2)
Else
For i = 1 To m - 1
If data(i, 1) < Cmatrix(j, 1) And Cmatrix(j, 1) < data(i + 1, 1) Then
Cmatrix(j, 2) = Amatrix(i, 1) * (Cmatrix(j, 1) - data(i, 1)) ^ 3 + Amatrix(i, 2) * (Cmatrix(j, 1) - data(i, 1)) ^ 2 + Amatrix(i, 3) * (Cmatrix(j, 1) - data(i, 1)) + Amatrix(i, 4)
ElseIf Cmatrix(j, 1) = data(i, 1) Then
Cmatrix(j, 2) = data(i, 2)
End If
Next i
End If
Next j
If x < data(1, 1) Or x > data(m, 1) Then
Call Check2(x)
If x < data(1, 1) Then
cubic = Amatrix(1, 1) * (x - data(1, 1)) ^ 3 + Amatrix(1, 2) * (x - data(1, 1)) ^ 2 + Amatrix(1, 3) * (x - data(1, 1)) + Amatrix(1, 4)
ElseIf x > data(m, 1) Then
cubic = Amatrix(m - 1, 1) * (x - data(m - 1, 1)) ^ 3 + Amatrix(m - 1, 2) * (x - data(m - 1, 1)) ^ 2 + Amatrix(m - 1, 3) * (x - data(m - 1, 1)) + Amatrix(m - 1, 4)
End If
ElseIf x = data(m, 1) Then
cubic = data(m, 2)
Else
For i = 1 To m - 1
If data(i, 1) < x And x < data(i + 1, 1) Then
cubic = Amatrix(i, 1) * (x - data(i, 1)) ^ 3 + Amatrix(i, 2) * (x - data(i, 1)) ^ 2 + Amatrix(i, 3) * (x - data(i, 1)) + Amatrix(i, 4)
ElseIf x = data(i, 1) Then
cubic = data(i, 2)
End If
Next i
End If
For i = 1 To 100
Cells(i, 1).Value = Cmatrix(i, 1)
Cells(i, 2).Value = Cmatrix(i, 2)
Next i
Set chart = Range("A1:B100")
Dim cht As Object
Set cht = ActiveSheet.Shapes.AddChart2(XlChartType:=xlXYScatterSmooth)
cht.chart.SetSourceData Source:=chart
End Function

Related

The loop over two arrays take LONG

Thanks for your helps,
I have two arrays: A (100k row, 10 col) and B (100k row, 12 col)
The following code (thanks to BSALV) loop through A and B => It takes really long to finish. Is there any way to speedup.
ReDim Preserve B(1 To UBound(B), 1 To UBound(B, 2) + 4)
ReDim arr(1 To UBound(B), 1 To 2)
For i = 1 To UBound(B)
iSell = B(i, 3): mysold = 0
r = Application.Match(B(i, 2), Application.Index(A, 0, 2), 0)
If IsNumeric(r) Then
For i1 = r To UBound(A)
If A(i1, 2) = B(i, 2) And A(i1, 1) <= B(i, 1) Then
x = Application.Max(0, Application.Min(A(i1, 3), iSell))
If x > 0 Then
mysold = mysold + x
iSell = iSell - x
MyValueSold = MyValueSold + x * A(i1, 4)
A(i1, 3) = A(i1, 3) - x
If A(i1, 3) <= 0 Then A(i1, 2) = "~"
End If
If A(i1, 3) > 0 Then Exit For
End If
Next
End If
arr(i, 1) = mysold: arr(i, 2) = MyValueSold
Next
This operation is really slow when using larger arrays:
r = Application.Match(B(i, 2), Application.Index(A, 0, 2), 0)
You can get much better performance just by replacing the Index/Match line with a dictionary lookup.
To illustrate:
Sub Tester()
Const NROWS As Long = 100000
Dim i As Long, r, t
Dim dict As Object
Set dict = CreateObject("scripting.dictionary")
Dim A(1 To NROWS, 1 To 10)
'populate some dummy data
For i = 1 To UBound(A, 1)
A(i, 2) = Application.RandBetween(1, NROWS)
A(i, 3) = i
Next i
'First your existing row lookup...
t = Timer
For i = 1 To 100 'only testing 100 lookups (too slow for more!)
r = Application.Match(i, Application.Index(A, 0, 2), 0)
Next i
Debug.Print "Index/Match lookup", Timer - t, "*100* lookups"
'populate a dictionary for lookups...
t = Timer
For i = 1 To NROWS
dict(A(i, 2)) = i 'mapping second column first occurences to row #
Next i
Debug.Print "Mapping done", Timer - t
'Now the dictionary lookup
t = Timer
For i = 1 To NROWS
If dict.Exists(i) Then
r = dict(i)
End If
Next i
Debug.Print "Dictionary lookup", Timer - t, NROWS & " lookups"
End Sub
Output:
Index/Match lookup 9.62 *100* lookups '<<< slow slow!
Mapping done 0.12
Dictionary lookup 0.26 100000 lookups
EDIT: changes in your existing code
Dim rngMatch As Range '<<< added
'...
'...
Set lo = Sheets("Exc").ListObjects("TBL_Buy")
Set rngMatch = lo.DataBodyRange.Columns(2) '<<< lookup range
With lo.Range
.Sort .Range("B1"), xlAscending, , .Range("A1"), xlAscending, Header:=xlYes
aBuy = lo.DataBodyRange.Value2
.Sort .Range("A1"), xlAscending, , .Range("B1"), xlAscending, Header:=xlYes
End With
'...
For i = 1 To UBound(aResult)
'...
r = Application.Match(aResult(i, 2), rngMatch, 0) '<<<
'...
'...

How to print array and values from new cycle to next rows

this is part of my code that i am working with and I have one problem. I have array with values (masyvas) and i started new loop to find other values by using masyvas(i,1) values and after that i need that new values would be printed in masyvas(i,2) and i need to group them. It need to look like this:
991988 Gaz.duon.sk"Giros"gaiv.g.1,5L 5_PETØFLAT1,5
PALINK
117388 Silp.gaz.nat.min.v"Tiche'1,5L 5_PETØFLAT1,5
PALINK
RIMI LIETUVA
ŠIAULIŲ TARA
111388 Gaz.nat.min.v"Tiche" 1,5L pet 5_PETØFLAT1,5
PALINK
AIBĖS LOGISTIKA
AIBĖS LOGISTIKA
RIMI LIETUVA
ŠIAULIŲ TARA
How it looks now from marked 1 it goes wrong
Data sheet where i get array values
Here is part of my code where i have this problem now it prints new values next to masyvas(i,2) but not below as I need.
lastrow2 = Sheets("lapas").Cells(Rows.Count, 1).End(xlUp).Row
rub = lastrow2
cub = 3
ReDim masyvas(1 To rub, 1 To cub)
For i = 1 To rub
For j = 1 To cub
masyvas(i, j) = Sheets("lapas").Cells(i, j).Value 'array gets values from filtered data in AKCIJOS sheet
Next
Next
Sheets("lapas").Range("A1:C100").Clear
For i = 1 To rub Step 1
Set rng2 = grafikas.Cells(6 + h, 2)
prekeskodas = masyvas(i, 1)
For m = 2 To lastrow
If akcijos.Cells(m, 8) >= laikas And akcijos.Cells(m, 8) <= laikas2 Then
If prekeskodas = akcijos.Cells(m, 4) Then
grafikas.Cells(7 + r, 2).EntireRow.Select
Selection.Insert Shift:=xlDown
grafikas.Cells(7 + r, 3) = akcijos.Cells(m, 3)
r = r + 1
h = r
End If
End If
Next m
For j = 1 To cub Step 1
rng2.Offset(i - 1, j - 1).Value = masyvas(i, j)
Next
Next
You didn't provide any screenshot of your data, so it's hard to say what exactly is your problem and desired output, but try the code below. I marked changed lines.
For i = 1 To rub
prekeskodas = masyvas(i, 1)
For m = 2 To lastrow
If akcijos.Cells(m, 8) >= laikas And akcijos.Cells(m, 8) <= laikas2 Then
If prekeskodas = akcijos.Cells(m, 4) Then
'masyvas(i, 2) = masyvas(i, 2) & akcijos.Cells(m, 3)
masyvas(i, m) = masyvas(i, m) & akcijos.Cells(m, 3) '<------
End If
End If
Next
For j = 1 To cub
rng2.Offset(j - 1, i - 1).Value = masyvas(i, j) '<-----
Next
Next

Consolidating values on an unevenly spaced spreadsheet Excel VBA

Writing rudimentary VBA to populate a 2 dimensional array filled with two sums one consisting of the odd columns the other is the sum of the even columns, totaled over a variable amount of rows stored in another array. the two dimensional array then prints on a seperate worksheet. I wrote code which succesfully completed this task on two other worksheets in the same file with slightly different sized arrays, but it populates the destination range with zeros when adjusted for the new input and output.
code in question:
Sub dad()
Dim i As Integer, j As Integer, units As Double, value As Double, mr(1 To 655, 1 To 3) As Double, u As Integer, here As Range
Dim thisone As String, there As Range
thisone = Worksheets("MB52 for 1010").Cells(1, 1).Address
Set here = Range(thisone)
MsgBox (here(1, 1).Address)
thisone = Worksheets("1010totals").Cells(1, 1).Address
Set there = Range(thisone)
MsgBox (there(1, 1).Address)
For i = 1 To 655
mr(i, 1) = Worksheets("1010totals").Cells(i + 1, 4).value
Next i
MsgBox ("array made")
i = 1
u = 1
MsgBox (i & " " & u)
For i = 1 To 655
For j = 1 To mr(i, 1)
u = u + 1
units = here(u, 6) + here(u, 9) + here(u, 11).value + here(u, 13) + here(u, 15) + here(u, 17)
value = here(u, 8) + here(u, 10) + here(u, 12).value + here(u, 14) + here(u, 16) + here(u, 18)
Next j
mr(i, 2) = units
mr(i, 3) = value
Next i
For i = 1 To 655
For j = 2 To 3
Worksheets("1010totals").Cells(i + 1, j).value = mr(i, j)
Next j
Next i
End Sub
Original code that works on the other worksheets:
Sub ded()
Dim i As Integer, j As Integer, units As Double, value As Double, n As Integer, mr(1 To 756, 1 To 3) As Double, u As Integer, here As Range
Dim thisone As String, there As Range
thisone = Worksheets("MB52 for 1030").Cells(1, 1).Address
Set here = Range(thisone)
MsgBox (here(1, 1).Address)
thisone = Worksheets("1030totals").Cells(1, 1).Address
Set there = Range(thisone)
MsgBox (there(1, 1).Address)
For i = 1 To 756
mr(i, 1) = Worksheets("1030totals").Cells(i + 1, 4).value
Next i
MsgBox ("array made")
i = 1
u = 1
MsgBox (i & " " & u)
For i = 1 To 756
For j = 1 To mr(i, 1)
u = u + 1
units = here(u, 6) + here(u, 9) + here(u, 11).value + here(u, 13) + here(u, 15) + here(u, 17)
value = here(u, 8) + here(u, 10) + here(u, 12).value + here(u, 14) + here(u, 16) + here(u, 18)
Next j
mr(i, 2) = units
mr(i, 3) = value
Next i
For i = 1 To 756
For j = 2 To 3
Worksheets("1030totals").Cells(i + 1, j).value = mr(i, j)
Next j
Next i
End Sub

Excel - VBA Converting matrix entries to percentages of row total

I have a matrix with an equal number of rows and columns of size numColors. The following code attempts to convert each entry from an integer to a percent of its row total. I receive a "Subscript out of range" error and need help fixing it. Thanks.
For i = 2 To numColors + 2
rowSum = 0
tempArray = Range(Cells(i, 2), Cells(i, numColors + 1))
For j = LBound(tempArray) To UBound(tempArray)
rowSum = rowSum + tempArray(j)
Next
For j = LBound(tempArray) To UBound(tempArray)
tempArray(j) = tempArray(j) / rowSum
Next
Range(Cells(i, 2), Cells(i, numColors + 1)) = tempArray
Next
Try this:
For i = 2 To numColors + 1
rowSum = 0
tempArray = Range(Cells(i, 2), Cells(i, numColors + 1))
For j = LBound(tempArray, 2) To UBound(tempArray, 2)
rowSum = rowSum + tempArray(1, j)
Next j
For j = LBound(tempArray, 2) To UBound(tempArray, 2)
tempArray(1, j) = tempArray(1, j) / rowSum
Next j
Range(Cells(i, 2), Cells(i, numColors + 1)) = tempArray
Next i
the reason is even though it is one row, tempArray is a 2D array.
Here is a slight modification to your code. It loads the whole matrix into the array, manipulates the data then puts the values back as a whole:
tempArray = Range(Cells(2, 2), Cells(numColors + 1, numColors + 1))
For i = LBound(tempArray, 1) To UBound(tempArray, 1)
rowSum = 0
For j = LBound(tempArray, 2) To UBound(tempArray, 2)
rowSum = rowSum + tempArray(i, j)
Next j
For j = LBound(tempArray, 2) To UBound(tempArray, 2)
tempArray(i, j) = tempArray(i, j) / rowSum
Next j
Next i
Range(Cells(2, 2), Cells(numColors + 1, numColors + 1)).value = tempArray
In this instance it will not make much difference in speed, but if the matrix were bigger, the fewer times referring to the spread sheet the better.

Why did my VBA array contents disappear when I wanted to reuse them?

I am a newbie to VBA and have been developing a macro that involves arrays.
In the array part, I need to copy some ranges from two excel workbooks into two separate arrays(timearray and guzikarray). Then I will try to match the two arrays and copied the results into a third array(masterarray). Lastly I will write the third array's contents back into the worksheet.
But I found that my first two arrays' contents are automatically erased when I started to do the matching. So nothing was written back to my worksheet. Anyone can tell me why?
'copy ranges to two arrays: timearray and guzikarray
masterrows = mastersheet.UsedRange.Rows.count
guzikrows = guziksheet.UsedRange.Rows.count
ReDim timearray(1 To masterrows, 1 To 2)
For i = 1 To i = masterrows
timearray(i, 1) = Cells(i, 6).Value
timearray(i, 2) = Cells(i, 10).Value
Next
ReDim guzikarray(1 To guzikrows, 1 To 6)
For i = 1 To i = guzikrows
guzikarray(i, 1) = guziksheet.Cells(i, 11).Value
guzikarray(i, 2) = guziksheet.Cells(i, 17).Value
guzikarray(i, 3) = guziksheet.Cells(i, 14).Value
guzikarray(i, 4) = guziksheet.Cells(i, 16).Value
guzikarray(i, 5) = guziksheet.Cells(i, 18).Value
guzikarray(i, 6) = guziksheet.Cells(i, 26).Value
Next
'match timearray and guzikarray, and then copied the results to masterarray
ReDim Preserve masterarray(1 To masterrows, 1 To 4)
For i = 2 To i = masterrows
min = 100000
For j = 2 To j = guzikrows
If timearray(i, 1) = guzikarray(j, 1) Then
If timearray(i, 2) = guzikarray(j, 2) Then
If guzikarray(j, 6) <> 0 Then
masterarray(i, 1) = guzikarray(j, 4)
masterarray(i, 3) = guzikarray(j, 3)
If guzikarray(j, 5) < min Then
min = guzikarray(j, 5)
masterarray(i, 2) = min
End If
If timearray(i, 1) <> timearray(i + 1, 1) Then
If timearray(i, 1) <> timearray(i - 1, 1) Then
If guzikarray(j, 2) <> guzikarray(j - 1, 2) Then masterarray(i, 4) = guzikarray(j - 1, 5)
End If
End If
End If
End If
End If
Next
Next
'write the results back to master array
Range(Cells(2, 17), Cells(masterrows, 20)).Value = masterarray
Your loops aren't working as the syntax is incorrect
For i = 1 To i = masterrows
exits immediately without populating the array. You should be using
For i = 1 To masterrows
For i = 1 To guzikrows
etc

Resources