Excel function sheet gives errors - excel

My first attempt at user-defined functions in Excel (Mac) isn't going well. This gives "function or sub undefined":
Function CylArea(d0 As Double, theta As Double, y As Double) As Double
CylArea = Pi() * (d0 ^ 2 / 4 + d0 * Tan(Radians(theta)) * y + Tan(Radians(theta)) ^ 2 * y ^ 2)
End Function
Function CylVolume(d0 As Double, theta As Double, y As Double) As Double
CylVolume = Pi() * (d0 ^ 2 / 4 * y + 1 / 2 * d0 * Tan(Radians(theta)) * y ^ 2 + 1 / 3 * Tan(Radians(theta)) ^ 2 * y ^ 3)
End Function
Function CylAreaDeriv(d0 As Double, theta As Double, y As Double) As Double
CylAreaDeriv = Pi() * (d0 * Tan(Radians(theta)) + 2 * Tan(Radians(theta)) ^ 2 * y)
End Function
Curiously, the Pi in CylVolume is highlighted.

It looks like you are attempting to use Excel functions as you would in a worksheet within VBA code. This will likely not work.
Try changing all instances of Pi() to WorksheetFunction.Pi, all instances of Tan to Math.Tan and all instances of Radians to WorksheetFunction.Radians so that the code looks more like this:
Function CylVolume(d0 As Double, theta As Double, y As Double) As Double
CylVolume = WorksheetFunction.Pi * (d0 ^ 2 / 4 * y + 1 / 2 * d0 * Math.Tan(WorksheetFunction.Radians(theta)) * y ^ 2 + 1 / 3 * Math.Tan(WorksheetFunction.Radians(theta)) ^ 2 * y ^ 3)
End Function

Related

UDF value error for complex itterative function

I want to create an UDF for my excel worksheet. However when I select my input for my UDF I get a value error. Can someone help me?
Code and images below:
code:
Public Function pipediameter(Pth As Double) As Double
Dim D As Double
p = 150
Tv = 30
T = 55
k = 0.000045
vi = 4
a = (1.729 * (10 ^ (-6))) / ((1 + (T / 25)) ^ 1.165)
rho = 988
Cp = 4180
di = 1
i = 1
While i <= 10
v = 4 * Pth / (3.14 * di ^ 2 * Cp * rho * Tv)
Re = v * di / vi
B1 = (0.774 * Log(Re) - 1.41) / (1 + 1.32 * Sqr(k / di))
B2 = ((k * Re) / (3.7 * di)) + (2.51 * B1)
Y = (B1 - ((B1 + (2 * (Log(B2 / Re) / Log(10)))) / (1 + (2.18 / B2)))) ^ (-2)
D = (((8 * Y) / (p * rho)) * ((Pth) / (3.14 * Cp * Tv)) ^ 2) ^ 0.2
di = D
i = i + 1
Wend
pipediameter = D
End Function

VBA - Trying to get the root of a function

I got this equation to solve in VBA:
Energy = y + (0.5) ^ 2 / ( 2 * 9.81 * y ^ 2 )
but I got the Energy value and want to solve for the y value.
In R is easy: uniroot. There is something like this?
The equation is a cubic polynomial with two positive roots and one negative. We can eliminate the negative one, and consider a direct evaluation of the two positive roots with the following VBA code in a Module.
Global Const g As Double = 9.81
Global Const PI As Double = 3.14159265358979
Public Function CalcE(ByVal y As Double) As Double
CalcE = y + (0.5) ^ 2 / (2# * g * y ^ 2)
End Function
Public Function SolveForY(ByVal E As Double, Optional ByVal second As Boolean = False) As Double
' Solve "E = y + (0.5) ^ 2 / ( 2 * g * y ^ 2 )" for "y"
If Not second Then
SolveForY = E / 3# - 2# * E * Sin(Asin((16# * E ^ 3# * g - 27#) / (16# * E ^ 3# * g)) / 3#) / 3#
Else
SolveForY = E / 3# + 2# * E * Sin(Asin((16# * E ^ 3 * g - 27#) / (16# * E ^ 3 * g)) / 3# + PI / 3#) / 3#
End If
End Function
and the supporting Asin() function defined in terms of Atn().
Public Function Asin(ByVal x) As Double
If Abs(x) < 1# Then
Asin = Atn(x / Sqr(1# - x * x))
Else
Asin = 2 * Atn(1) * Sgn(x)
End If
End Function
Some example results are
? SolveForY(1#)
0.12035578724076
? SolveForY(1#, True)
0.986917853921696
And checking the solutions
? CalcE(0.12035578724076)
0.999999999999997
? CalcE(0.986917853921696)
1
Consider using algebra:
Energy = y + (0.5)^2 / ( 2 * 9.81 * y^2 )
Energy = y + .25 / ( 19.62 * y^2 )
Energy * ( 19.62 * y^2 ) = y * ( 19.62 * y^2 ) + .25
Energy * 19.62 * y^2 = 19.62 * y^3 + .25
0 = 19.62 * y^3 - Energy * 19.62 * y^2 + .25
and apply standard techniques:
Previous Post
Here's a translation of John Alexiou's answer from VBA to Excel formulas. If energy in in cell B2 then the three solutions are given by:
=B2/3-2*B2*SIN((ASIN((16*B2^3*9.81-27)/(16*B2^3*9.81))+0*PI())/3)/3
=B2/3-2*B2*SIN((ASIN((16*B2^3*9.81-27)/(16*B2^3*9.81))+4*PI())/3)/3
=B2/3-2*B2*SIN((ASIN((16*B2^3*9.81-27)/(16*B2^3*9.81))+2*PI())/3)/3
The third equation gives negative y.

How to declare variables inside Excel Function?

Updated Post
I have changed the code like.
Option Explicit
Public Function Isokinectic(streamVelocity As Double, sampleVelocity As Double, probeDiameter As Double, density As Double, particleDiameter As Double, viscosity As Double)
Dim s As Double
Dim stk_coefficent As Double
Dim stk As Double
Dim d As Double
s = ((0.16 * 10 ^ -4) / particleDiameter) + 1
stk_coefficent = (1 / (18 * viscosity)) * density * particleDiameter * particleDiameter * s
stk = (streamVelocity / probeDiameter) * stk_coefficent
d = 1 + (2 + 0.62 * (sampleVelocity / streamVelocity)) * stk
Isokinectic = 1 + ((streamVelocity / sampleVelocity) - 1) * (1 - 1 / (d))
End Function
But it does not work. However, when add the sub MAIN (), like this. It works.
Option Explicit
Function Isokinectic(streamVelocity As Double, sampleVelocity As Double, probeDiameter As Double, density As Double, particleDiameter As Double, viscosity As Double)
Dim s As Double
Dim stk_coefficent As Double
Dim stk As Double
Dim d As Double
s = ((0.16 * 10 ^ -4) / particleDiameter) + 1
stk_coefficent = (1 / (18 * viscosity)) * density * particleDiameter * particleDiameter * s
stk = (streamVelocity / probeDiameter) * stk_coefficent
d = 1 + (2 + 0.62 * (sampleVelocity / streamVelocity)) * stk
Isokinectic = 1 + ((streamVelocity / sampleVelocity) - 1) * (1 - 1 / (d))
End Function
Sub MAIN()
MsgBox Isokinectic(0.1, 0.2, 0.3, 0.4, 0.5, 0.6)
End Sub
Original Post:
I tried to code an equation in excel function. But I got #value
Function Isokinectic(streamVelocity As Double, sampleVelocity As Double, probeDiameter As Double, density As Double, particleDiamter As Double, visocity As Double)
Dim s As Double
Dim stk_coefficent As Double
Dim stk As Double
Dim d As Double
s = (0.16 * 10^ - 4 / particleDiameter) + 1
stk_coefficent = (1 / (18 * viscosity)) * density * particleDiamter * particleDiameter * s
stk = (streamVelocity / probeDiameter) * stk_coefficent
d = 1 + (2 + 0.62 * (sampleVelocity / streamVelocity)) * stk
Isokinectic = 1 + ((streamVelocity / sampleVelocity) - 1) * (1 - 1 / (1 + d))
End Function
Anything I did wrong in this code?
With a little cleanup:
Option Explicit
Function Isokinectic(streamVelocity As Double, sampleVelocity As Double, probeDiameter As Double, density As Double, particleDiameter As Double, viscosity As Double)
Dim s As Double
Dim stk_coefficent As Double
Dim stk As Double
Dim d As Double
s = ((0.16 * 10 ^ -4) / particleDiameter) + 1
stk_coefficent = (1 / (18 * viscosity)) * density * particleDiameter * particleDiameter * s
stk = (streamVelocity / probeDiameter) * stk_coefficent
d = 1 + (2 + 0.62 * (sampleVelocity / streamVelocity)) * stk
Isokinectic = 1 + ((streamVelocity / sampleVelocity) - 1) * (1 - 1 / (1 + d))
End Function
Sub MAIN()
MsgBox Isokinectic(0.1, 0.2, 0.3, 0.4, 0.5, 0.6)
End Sub
In your original post your have calculated s, d, stk but in no where in later stage you are getting the value for Velocity & other, is reason for the Value error.
Since with a subroutine as you have put Value in formula it's working,, please write that command line in Function your Function will work, don't forget to pass value for Velocity from Cells.

VBA: Run time error 13 type mismatch

I want to calculate the time to expiration on a few call options using newton's method. I tried recreating this method in the code below.
I get an odd type mismatch for the variable called functionDerived. This variable is the derived form of variable function0. The error 13 occurs at that point.
The variables in the calculation are the following types:
opT integer;
S double;
sigma double;
K double;
rf double;
q double;
T integer;
optionbidprice double;
Here is my code:
Public Function calculateOptionExpiration(opT, S, sigma, K, rf, q, T, optionBidPrice)
'************************************************************************
'Variables
'************************************************************************
Dim function0 As Double
Dim functionDerived As Double
Dim optionPrice As Double
Dim differenceZero As Double
Dim Tnext As Integer
Dim Pii As Double
Dim d1 As Double
Dim d2 As Double
Dim ND1 As Double 'Cumulative standard normal probability for value d1
Dim ND2 As Double 'Cumulative standard normal probability for value d2
Dim Nd1accent As Double 'Derivation, N'(x), see book page 456
Dim Nd2accent As Double
'************************************************************************
'Newton's method to calculate time to option expiration T
'************************************************************************
'theta formula page 456, use this in newton's method
'Step 1: f(T) = 0
Pii = Application.WorksheetFunction.Pi
d1 = BSD1(S, K, rf, q, T, sigma)
d2 = BSD2(S, K, rf, q, T, sigma)
ND1 = Application.NormSDist(d1)
ND2 = Application.NormSDist(d2)
Nd1accent = (1 / Sqr(2 * Pii)) * Exp(-d1 ^ 2 / 2)
function0 = ((-S * Nd1accent * sigma * Exp(-q * T)) / (2 * Sqr(T))) + _
(q * S * ND1 * Exp(-q * T)) - (rf * K * Exp(-rf * T) * ND2)
'Step 2 : f'(T)
Nd2accent = (1 / Sqr(2 * Pii)) * Exp(-d2 ^ 2 / 2)
functionDerived = (q / 2) * (S * Nd1accent * sigma * Exp(-q * T) * 2 ^ (-1) * T ^ (-3 / 2)) _
- q * (q * S * Nd1accent * Exp(-q * T)) + rf(rf * K * Exp(-rf * T) + Nd2accent)
'step 3: Tnext = T - function0/functionderived, find the T so that option bid - optionprice = 0
Do Until differenceZero = 0
optionPrice = BSMOptPrice(opT, S, sigma, K, rf, q, T)
differenceZero = optionBidPrice - optionPrice
Tnext = T - (function0 / functionDerived)
T = Tnext
Loop
calculateOptionExpiration = Tnext
This part in the assignment of functionDerived was incorrect:
rf(rf * K * Exp(-rf * T) + Nd2accent)
rf(...) is a function call, but the parameter rf is a double, so that's the type mismatch.

Arithmetic Asian Option Pricing

I keep getting the invalid procedure call or argument error on the definition of sigma2d line.
Any idea how to avoid this code error?
Private Sub CommandButton4_Click()
Application.Range("E19").value = ""
Application.Range("F19").value = ""
S0 = Application.Range("C5").value 'arithmetic average of underlying 1
K = Application.Range("C6").value 'strike
T = Application.Range("C10").value 'maturity
sigma = Application.Range("C8").value 'volatility
r = Application.Range("C8").value 'risk free rate
nsteps = Application.Range("C12").value 'no of timesteps
nsimulations = Application.Range("C13").value ' no of mc simulations
div = Application.Range("C9").value 'dividends
Randomize
Dim M1 As Double, M2 As Double, sigma2d As Double
Dim d1 As Double, d2 As Double, Nd1 As Double, Nd2 As Double
M1 = (Exp((r - div) * T) - 1) / (r - div) * T
v = (2 * Exp((2 * r) - (2 * div) + (sigma * sigma) * T)) * S0 * S0
w = (r - div + (sigma * sigma)) * (2 * r - 2 * q + (sigma * sigma)) * T * T
Z = 2 * S0 * S0 / ((r - div) * T * T)
y = (1 / 2 * (r - div) + sigma * sigma)
h = Exp((r - div) * T) / (r - div + (sigma * sigma))
M2 = (v / w) + Z * (y - h)
M3 = M1 * M1
sigma2d = Log(M2 / M3)
d1 = (Log(M1 / K) + (sigma2d * T) / 2) / sigma * Sqr(T)
d2 = d1 - sigma * Sqr(T)
callArith = Exp(-r * T) * (M1 * Nd1 - K * Nd2)
Application.Range("E19").value = Application.Max(ExactCall, 0)
Are you trying to do the log of a negative number? Set a breakpoint and check variables before that line. Maybe you have an error before that generating a negative.
First check the argument to the Log function is positive.
Failing that, it could be due to a missing reference in the project. This manifests itself in this curious way. Have a look at "Tools", "References" and see if there is one missing.
You can write sigma2d = Vba.Log(M2 / M3) instead but that's only really a short fix since missing references will cause you headaches elsewhere.
One more thing, why not create a function instead, passing in all the variables as function parameters? Your spreadsheet will be more stable if you do that.
(Also, at the end of your code, d1 definition is incorrect. You need brackets around sigma * Sqr(T)).
I think you need a pair of () or do "/T" as you are multiplying by T here:
M1 = (Exp((r - div) * T) - 1) / (r - div) * T

Resources