Run Time error 9:Array - excel

I am new to VBA programming and am trying to develop a simple code for RCC design. Most of the values are assigned directly from the excel sheet. I am getting this error that says "division by zero".The line within ** ** is highlighted while debugging. it seems there is some problem with declaration or looping but i am not being able to identify. Pls help. Thanx in advance. The code is as follows:
Private Sub CommandButton1_Click()
Dim a As Double, b As Double, result As String, Mu As Double
Dim i As Integer, j As Integer, c As Integer, Xu1, Xu, es, d, f, fs As Double
Dim strain1(1 To 6) As Double, stress1(1 To 6) As Double
a = Range("E30").Value
b = Range("O30").Value
If a < b Then
result = "Under Reinforced Section"
Mu = Range("E32").Value * Range("E34").Value
ElseIf a = b Then
result = "Balanced Secction"
Mu = Range("E32").Value * Range("E34").Value
ElseIf a > b Then
result = "Over Reinforced Section"
j = 31
For i = 1 To 6
strain1(i) = Cells(j, 7)// loop to assign values in array from excel sheet
j = j + 1
Next
j = 31
For i = 1 To 6
stress1(i) = Cells(j, 8)
j = j + 1
Next
c = 1
Xu1 = Range("O30").Value
d = Range("E31").Value
Do While c = 1
Xu = Xu1
**es = 0.0035 * (d - Xu) / (Xu)**// Shows error apparently Xu is taking value zero
If Range("E22").Value = 250 Then
fs = es * Range("E23").Value
f = 0.87 * Range("E22").Value
If fs > f Then
fs = f
End If
ElseIf Range("E22").Value = 415 Then
f = 0.696 * Range("E22").Value / Range("E23").Value
If es > f Then
For i = 1 To 6
If es > strain1(i) And es < strain1(i + 1) Then// to locate es in the array and then interpolate
fs = stress1(i) + ((stress1(i + 1) - stress1(i)) / (strain1(i + 1) - strain1(i))) * (es - strain1(i))// linear interpolation formulae
End If
Next
ElseIf es < f Then
fs = es * Range("E23").Value
End If
Xu1 = Range("O29").Value * fs / (0.36 * Range("E21").Value * Range("E16").Value)
If Xu1 = Xu Then
c = 0
End If
Mu = 0.36 * Range("E21").Value * Range("E16").Value * Xu1 * Range("E34").Value
End If
Loop
End If
Range("O21").Value = Mu
MsgBox result
End Sub

strain1(1 To 6) has 6 elements 1 to 6, for i=6 you're trying to access a 7th element (strain1(i + 1)) in the highlighted row. (the same holds true for stress1 in the next line)

Related

Simulate M Geometric Brownian motion paths in VBA

I'm new to VBA and I'm currently trying to simulate M paths of GBM(Geometric Brownian motions) in VBA. I know this can be done with excel, but I would still like to know how we can get this done in VBA for my personal knowledge. Here is my code:
Sub test()
Dim dt As Double, T As Integer, N As Integer, M As Integer, S As Double, mu As Double _
, sig As Double, drift As Double, diff As Double, i As Integer, j As Integer
mu = 0.15
sig = 0.2
T = 1
N = 365
M = 100
S = 150.5
dt = T / N
Dim mat() As Variant
ReDim mat(1 To M, 1 To (N + 1)) As Variant
For i = 1 To UBound(mat)
mat(i, 1) = S
Next
For i = 1 To M
For j = 2 To (T + 1)
drift = (mu + 0.5 * sig^(2)) * dt
diff = Sqr(dt) * WorksheetFunction.Norm_Inv(Rnd, 0, 1)
mat(i, j) = mat(i, j - 1) * Exp(drift + diff)
Next
Next
End Sub
First issue
My equations seem to be correct. The main issue that I'm having is with variable types. For instance, I get an overflow error when assigning the value 0.15 to mu, 0.2 to sig (mu = 0.15, sig = 0.2, etc.). I don't really understand why I get that error since mu and sig are defined as doubles, just like the values that I want to assign to them (0.15 and 0.20).
Second issue
A non-efficient way to get around my first issue is to declare all variables as variants. Even when all my variables are declared as variants, my second loop does not run.
Here is my second loop:
For i = 1 To M
For j = 2 To (T + 1)
drift = (mu + 0.5 * sig^(2)) * dt
diff = Sqr(dt) * WorksheetFunction.Norm_Inv(Rnd, 0, 1)
mat(i, j) = mat(i, j - 1) * Exp(drift + diff)
Next
Next
More specifically, I get the same overflow error when i try to assign a value to a specific element of my array (i.e. mat(i, j) = mat(i, j - 1) * Exp(drift + diff)).
Does anyone know how I can solve those issues?
Note that I'm using the latest VBA version for Macbook.
With VBA 7.1 (Windows), I made it work with adding some space in your exponent formula ( sig ^ (2) ):
For i = 1 To M
For j = 2 To (T + 1)
drift = (mu + 0.5 * sig ^ (2)) * dt
diff = Sqr(dt) * WorksheetFunction.Norm_Inv(Rnd, 0, 1)
mat(i, j) = mat(i, j - 1) * Exp(drift + diff)
Debug.Print mat(i, j)
Next
Next
I don't see any problem with double type, you're right.
No overflow error...

How can I get the criteria to change in a CountIf function in VBA as a loop progresses?

week = 1
y = 3
z = 18
For l = LBound(arr1) To UBound(arr1)
Range("A1").Value = WorksheetFunction.CountIfs(Range("B2:B250"), week)
x = Range("A1").Value
pf1 = "=IF("
pf2 = l
pf3 = "3=1,VLOOKUP($L3,$C$"
pf4 = y
pf5 = ":$F$"
pf6 = z
pf7 = ",3,FALSE),VLOOKUP($L3,$D$"
pf8 = ":$F$"
pf9 = ",3,FALSE))"
pf = pf1 + pf2 + pf3 + pf4 + pf5 + pf6 + pf7 + pf4 + pf8 + pf6 + pf9
If x = 14 Then
y = 14 + y
z = 13 + z
End If
If x = 15 Then
y = 15 + y
z = 14 + z
End If
If x = 16 Then
y = 16 + y
z = 15 + z
End If
pfrng.Offset(0, j * 6) = pf
j = j + 1
week = week + 1
Range("A1").ClearContents
Next l
I want the script above to recognize and change the value of the variable "week" as I loop through the lower bound of my array (arr1) to the upper bound. While doing so, it must also increase the y and z values accordingly.
Also, is this the correct method I should be using, or is there something better/more efficient or something with a cleaner appearance?
Thank you in advance!

I can't print the values to "arka" at excel VBA

Dim i As Double
Dim x As Double
Dim y As Integer
Dim araba As Integer
Dim n As Integer
Dim bobin As Integer
Dim iplik As Integer
n = Sheets("kaynak").Cells(21, 1)
bobin = ((630 - n) / 2)
Dim j As Integer
For j = 1 To 10
iplik = Sheets("kaynak").Cells(j, 1)
For i = bobin To bobin + iplik
If i <= 315 Then
x = 7 - Int(i / 45) 'kaçıncı satır'
y = 45 - (i Mod 45)
Sheets("front").Cells(x, y) = Sheets("kaynak").Cells(j, 2)
Else
If i = 630 Then
x = 7
Else
x = Int(i / 45) - 6
End If
y = 46 - (i Mod 45)
Sheets("arka").Cells(x, y) = Sheets("kaynak").Cells(j, 2)
End If
Next i
bobin = bobin + iplik
Next j
my problem is at the title actually i want to print values to "arka" but it does just to "front" it works truely for front but doesn't go for further and i stopts at 315 ,i got error 1004 application defined or object defined error
When i = 315 (the last pass when i <= 315) then
x = 7 - Int(i / 45) 'kaçıncı satır'
gives x the value 0, since 315/45 = 7 exactly.
This causes the line
Sheets("front").Cells(x, y) = Sheets("kaynak").Cells(j, 2)
to error-out. You never progress beyond that line in that pass through the loop. Thus your code never even attempts to write to sheet "arka".
Perhaps replacing the line
x = 7 - Int(i / 45)
with
x = Application.Max(1,7 - Int(i / 45))
will fix the error.

VBA results in #VALUE! only when For loop is used

I am writing a function with a For loop, and ultimately the value of the function will depend on the output of the For loop. For now as a test, the value of the function is a constant. If the For loop is in the code, the function results in #Value!. If I remove the For loop, the output is the specified constant value. How does the For loop need to be specified to avoid this? Good values for Tc and Th as a test would be 100 and 300, respectively.
Function kndT(material As Integer, Tc As Double, Th As Double) As Variant
Dim x As Double
Select Case material
Case 4
If Th > 300 Then
Tmax = 300
Else
Tmax = Th
End If
A = 0.07918
b = 1.0957
c = -0.07277
D = 0.08084
e = 0.02803
f = -0.09464
g = 0.04179
h = -0.00571
i = 0
End Select
hh = (Tmax - Tc) / 999
fi = 0
nc = 1
For i = 1 To 999
Temp = (Tc + i * hh)
x = Log(Temp) / Log(10#)
y = A + b * x + c * x ^ 2 + D * x ^ 3 + e * x ^ 4 + f * x ^ 5 + g * x ^ 6 + h * x ^ 7 + i * x ^ 8
fn = 10 ^ y
If nc = 3 Then
fi = fi + 2 * fn
nc = 1
Else
fi = fi + 3 * fn
nc = nc + 1
End If
Next i
kndT = 2
End Function

Creating values with loop in vba and storing them in a column in the worksheet?

I am trying to calculate velocity and acceleration, with the variable being the time t. I'd like to write these in vba, to make it faster, because later on I'll need velocity and acceleration for several other calculations combined with different logical conditions. I would like the results to be printed in the worksheet, to double check during calculation if the results are realistic.
example of how it should like more or less
t vel a
0.002 39 -777
0.004 38.6 -802
0.006 35 -500
0.008 33.4 -400
0.01 32.1 -12297.1
So I have tried a few different things based on comments:
This first code example works fine I think from the results, but I still can see any of the results in between > so main question: any chance I can change the commend to write to the worksheet without changing much else?
The second code example is an attempt to write everything into arrays: I do understand the principle I think, but here the main error seems to be that my variable t is not getting generated properly and therefore the formulas are not calculated: can't find the mistakes here and I would be grateful for some more help...
Kinematics Calculation
'Set t from 0 to 2 s with time step of 0.002s; Calculate Rot_vel until <= 0,
'Find index t_2 when Rot_vel <= 0
t = 0
Do
t = t + 0.002
Rot_vel = -10356# * t ^ 6 + 24130# * t ^ 5 - 19002# * t ^ 4 + 4933# * t ^ 3 +
362# * t ^ 2 - 213# * t + 39
Worksheets("test").Range(Cells(3, 2), Cells(1003, 2)) = Rot_vel
Loop Until Rot_vel <= 0
If Rot_vel <= 0 Then
t_2 = t
If t_2 > 0 Then
Debug.Print t_2
End If
End If
'Continue calculations for t 0 to t_2 with 0.002 steps
t = 0
Do
t = t + 0.002
A_rot = -62136# * t ^ 5 + 120650# * t ^ 4 - 76008# * t ^ 3 + 14797.8 * t
^ 2 + 723.26 * t - 212.7
Worksheets("test").Range(Cells(3, 3), Cells(1003, 3)).value = A_rot
L = MoI * Rot_vel / 1000
M = MoI * A_rot / 1000
Worksheets("test").Range(Cells(3, 8), Cells(1003, 8)).value = L
Worksheets("test").Range(Cells(3, 9), Cells(1003, 9)).value = M
G = L / t_2
Worksheets("test").Range(Cells(3, 10), Cells(1003, 10)).value = G
Loop Until t = t_2
Second version:
Kinematics Calculation
'Set t from 0 to 2 s with time step of 0.002s; Calculate Rot_vel until <= 0,
'Find index t_2 when Rot_vel <= 0
Dim arrCalc As Variant
Dim i As Integer
Dim j As Integer
ReDim arrCalc(i To 1003, j To 13)
For i = LBound(arrCalc, 2) To UBound(arrCalc, 2)
t = 0
Do
t = t + 0.002
arrCalc(i, 1) = t
arrCalc(i, 2) = -10356# * t ^ 6 + 24130# * t ^ 5 - 19002# * t ^ 4 + 4933#
* t ^ 3 + 362# * t ^ 2 - 213# * t + 39 'Rot_vel
Loop Until arrCalc(i, 2) < 0
Dim pos, val
val = 0
pos = Application.Match(val, arrCalc(i, 2), False)
pos = t_2
t = 0
Do
t = t + 0.002
arrCalc(i, 3) = -62136# * t ^ 5 + 120650# * t ^ 4 - 76008# * t ^ 3 +
14797.8 * t ^ 2 + 723.26 * t - 212.7
arrCalc(i, 8) = MoI * Rot_vel / 1000 'L
arrCalc(i, 9) = MoI * A_rot / 1000 'M
arrCalc(i, 10) = 1 / t_2 * L 'G
Loop Until t = t_2
Next i
With Worksheets("test")
.Cells(2, "A") = 0
.Cells(3, "A").Resize(UBound(arrCalc, 1), UBound(arrCalc, 2)) = Rot_vel
.Cells(2, "A").Resize(UBound(arrCalc, 1) + 1, 1) = t
'.Cells(3, "C").Resize(UBound(arrCalc, 1), UBound(arrCalc, 3)) = A_rot
End With
Your variables a_rot and rot_val don't look to me like arrays but normal variables. Therefore, only one value is stored in them and of course you get only one value as an output.
I see two options: 1) You write all of your values into an array and then copy the array to the sheet. 2) You write each calculation line by line to the sheet. Number 1) is much much faster.
A solution could look something like this:
ReDim Array (Lines, Columns)
For each line
Array (line, Columns1) = Formula1
Array (line, Columns2) = Formula2
Array (line, Columns3) = Formula3
Next
Build a 2-D array with times and calculations then dump the results back onto the worksheet.
Sequential time is very prone to 15 significant digit floating point errors. These errors can be minimized with a form of datum dimensioning that creates all new entries relative to the original starting point instead of the previous value. The former method can have no error greater than a single calculation while the latter can compounding errors by carrying them into the next calculation.
Sub kinematicsCalculation()
Dim t As Double, start As Double, i As Long, arr As Variant
start = TimeSerial(0, 0, 0) 'start at 0 second mark
ReDim arr(1 To 1000, 1 To 2)
For i = LBound(arr, 1) To UBound(arr, 1)
arr(i, 1) = start + TimeSerial(0, 0, 2 * i) / 1000
'cannot attempt velocity calc without Rot_vel_i
arr(i, 2) = "<velocity calculation here>"
Next i
With Worksheets("sheet")
.Cells(2, "B") = start
.Cells(3, "B").Resize(UBound(arr, 1), UBound(arr, 2)) = arr
.Cells(2, "B").Resize(UBound(arr, 1) + 1, 1).NumberFormat = "[hh]:mm:ss.000"
End With
End Sub

Resources