Test Visual Basic Scripts behind an Excel Spreadsheet - excel

First of all I need to point out that I have never coded Visual Basic before.
I have an old spreadsheet which has some functions that are apparently written in Visual Basic. An example functions is:
Function Helmert_X(X, Y, Z, DX, Y_Rot, Z_Rot, s)
'Computed Helmert transformed X coordinate.
'Input: - _
cartesian XYZ coords (X,Y,Z), X translation (DX) all in meters ; _
Y and Z rotations in seconds of arc (Y_Rot, Z_Rot) and scale in ppm (s).
'Convert rotations to radians and ppm scale to a factor
Pi = 3.14159265358979
sfactor = s * 0.000001
RadY_Rot = (Y_Rot / 3600) * (Pi / 180)
RadZ_Rot = (Z_Rot / 3600) * (Pi / 180)
'Compute transformed X coord
Helmert_X = X + (X * sfactor) - (Y * RadZ_Rot) + (Z * RadY_Rot) + DX
End Function
I'm trying to convert these functions into C. I have almost finished but what I would like to do is to build a visual basic project that calls the functions with various parameters. Then I will have a C project which uses the same parameters and checks that the C gets the same answers as the Visual Basic.
When I put the Visual Basic functions into a Module in Visual Studio I get a lot of errors. Firstly the comments don't all register as comments, and the variables apparently need to be declared.
Am I using the functions properly? Is there anyway to use them in code without modifying them? Could I use Excel to run test parameters through the functions?

It seems you need to declare all variables that exist in that function. Try to add theses lines after the comments:
Dim Pi As Double
Dim sfactor As Double
Dim RadY_Rot As Double
Dim RadZ_Rot As Double
You can also specify type for variables that came with function, as well the function itself:
Function Helmert_X(X as Double, Y as Double, Z as Double, DX as Double, Y_Rot as Double, Z_Rot as Double, s as Double) as Double
Let me know if it works or if there is still some issue.

Related

How to declare numeric variables?

Numeric variables give
Run Time 6` error
It all seems to be related to the way Excel on MacOs handles these declarations. I find with Integer, Single, and Double if you do a division you get the error.
Dim x, y as double
x=2
y=2 'error 6
x=x/2
y=y/2 'error6
End Sub
If you put x and y in Watch window you will see they are not showing as Double; instead, x is displayed as Variant/String, y as String.
The Variant/String performs ok, the string does not.
MS Docs state that Dim x,y As Double will declare both to be doubles. Others, who I assume are on Windows, say not, that you must say Dim x As Double, y As Double; but in this case, even that does not work.
MacOs Excel Version 16.43
This is the correct syntax:
Dim x As Double
Dim y As Double
x = 2
y = 2
x = x / 2
y = y / 2
' No error.

How do i Square Root a Function in VBA

I am working on a MonteCarlo simulation model and part of it is to calculate the following formula:
X = Sqr(1-p)Y + Sqr(p)Z,
Where:
Y and Z are randomly obtained values based (idiosyncratic and systematic factors, respectviely) on a standard normal (inv.) distribution, calculated as:
Application.WorksheetFunction.NormInv (Rnd(), mean, sd)
p represents a correlation factor.
My aim is to square root a recalled formula, however when I try the following (inserting the first Sqr), it does not work and gives an error:
Matrix (n, sims) = (R * Sqr(Application.WorksheetFunction.NormInv(Rnd(), mean, sd))) + (Sqr(1 - R) * RandomS(s, x))
where:
R: Correlation factor
RandomS(s,x): generated matrix with Z values.
I don't want to go into too much details about the background and other variables, as the only problem I am getting is with Square Rooting the equation.
Error message I recieve reads:
Run-time error '5':
Invalid procedure call or argument
When I click debug it takes me to the formula, therefore there must be something wrong with the syntax.
Can you help with directly squaring the formula?
Thank you!
Andrew
Square root is simply Sqr.
It works fine in Excel VBA, so for example:
MsgBox Sqr(144)
...returns 12.
Just don't confuse it with the syntax for a worksheet function with is SQRT.
If you're still having an issue with your formula, tit must be with something other than the Square Root function, and I'd suggest you check the values of your variable, and make sure they are properly declared (preferably with Option Explicit at the top of the module).
Also make sure that you're passing Sqr a positive number.
Documentation: Sqr Function
I'm not a math major, but with your formula:
X = Sqr(1-p)Y + Sqr(p)Z,
...you specified how Y and Z are calculated, so calculate them separately to keep it simple:
Dim X as Double, Y as Double, Z as Double
Y = Application.WorksheetFunction.NormInv (Rnd(), mean, sd)
Z = Application.WorksheetFunction.NormInv (Rnd(), mean, sd)
Assuming the comma is not supposed to be in the formula, and having no idea what p is, your final code to calculate X is:
X = Sqr(1-p) * Y + Sqr(p) * Z

Scaled Complementary Error Function, erfcx(x), computation avoiding arithmetic overflow - VBA/Excel

I need an algorithm/approximation to compute the Scaled Complementary Error Function, erfcx(x) to double-float precision.
I'm on a work PC so I’m limited to using Excel and VBA and I cannot use external libraries or add-ins: I need to code this myself.
Excel only provides erf() and erfc() functions.
The relationship erfcx(x) = exp(x^2) erfc(x) is obviously useful, however there is arithmetic over/underflow for x larger than around 26.5 and I need to go larger than this.
The below post discussed a python implementation – but it doesn’t seem to resolve the issue from what I can tell. It provides solutions using other libraries or an approximation that isn’t precise enough for my needs.
Is there a scaled complementary error function in python available?
Any suggestions?
Update:
I used this Continued Fraction representation I found on Wikipedia
and a modified version of the algorithm for solving continued fractions found here http://finance4traders.blogspot.nl/2009/07/continued-fractions-and-modified-lentzs.html
The following code seems to work and actually takes fewer iterations for larger input parameters.
Function erfcx(x) As Variant
Dim Ai As Double
Dim Bi As Double
Dim Ci As Double
Dim Di As Double
Dim Ei As Double
Dim Fi As Double
Dim X2 As Double
Dim i As Long
Const SQRPI As Double = 1.7724538509055
Const MAX_ITERATIONS = 1000
If x < 26.5 Then
erfcx = Application.WorksheetFunction.ErfC_Precise(x) * Exp(x ^ 2)
Else
X2 = x ^ 2
Bi = X2
Fi = X2
Ci = X2
Di = 0
Do
i = i + 1
Ai = i / 2
If i Mod 2 = 0 Then
Bi = X2
Else
Bi = 1
End If
Di = 1 / (Bi + Ai * Di)
Ci = Bi + Ai / Ci
Ei = Ci * Di
Fi = Fi * Ei
Loop While Ei <> 1 And i < MAX_ITERATIONS
Debug.Print i
erfcx = x / Fi / SQRPI
End If End function
Several approximations are discuss here:
AMS Journal Article
Once you have determined which approximation is suitable, we can help you code it in either a worksheet function or a VBA UDF()

Excel VBA method ROUND is incorrect

Public Function foo()
Dim x As Double, y As Double, z As Double
x = 1.26
y = 3.175
z = Round(x + y, 2)
foo = z
End Function
Running Excel 2007 on Windows 7. This function returns 4.43 into a cell with =foo() which is annoying as I want 4.44. I found some documentation claiming VBA ROUND uses even rounding but here the last digit is odd. What is wrong here?
You can always use the Worksheet Round Function instead of VBA's built-in one
Public Function foo2()
Dim x As Double, y As Double, z As Double
x = 1.26
y = 3.175
z = Application.WorksheetFunction.Round(x + y, 2)
foo2 = z
End Function
foo2 will result in 4.44 (tested on my machine). I don't know if this would affect performance at all.
You will need to use decimal types to accomplish this which uses integer based arithmetic as opposed to floating point based.
Excel doesn't have a native data type for this, so you have to use a Variant and then convert to a decimal using the CDec function.
Public Function foo()
Dim x As Variant, y As Variant, z As Variant
x = CDec(1.26)
y = CDec(3.175)
z = Round(x + y, 2)
foo = z
End Function
While Excel.WorksheetFunction.Round does perform correct 4/5 rounding, it is terribly slow and, of course, requires Excel to be installed.
For fast and precise rounding of any value - up, down, 4/5, Banker's, significant digits, Base 2 or Base 10, and more - go to my project VBA.Round.

Ceiling function in Access

How to create a Ceiling Function in MS access that behaves the same as the one in Excel?
Since Int() seems to work like Floor(), you can get Ceiling like this:
-Int(-x)
This answer uses VBA for Access, and is derived from http://www.tek-tips.com/faqs.cfm?fid=5031:
Public Function Ceiling(ByVal X As Double, Optional ByVal Factor As Double = 1) As Double
' X is the value you want to round
' Factor is the optional multiple to which you want to round, defaulting to 1
Ceiling = (Int(X / Factor) - (X / Factor - Int(X / Factor) > 0)) * Factor
End Function
Note that this answer is mathematically correct for negative X. See http://en.wikipedia.org/wiki/Floor_and_ceiling_functions#Spreadsheet_software for background.
Thanks, marg, for the answer. For future reference, here is the VBA function that I wrote after importing the Microsoft Excel Object Library:
Public Function Ceiling(Value As Double, Significance As Double) As Double
Ceiling = Excel.WorksheetFunction.Ceiling(Value, Significance)
End Function
Then in my query, I was trying to calculate billable hours from actual time worked, rounding up to the next quarter hour:
SELECT Ceiling(([WorkTimes]![EndTime]-[WorkTimes]![BeginTime])*24,0.25) AS BillableTime
FROM WorkTimes;
You can add a Reference to the Microsoft Excel Object Library and use Excel.WorksheetFunction.Ceiling
While this question specifically asked for Access here is the answer for VB.NET
Public Function Ceiling(ByVal value As Double, ByVal factor As Double) As Double
Return Math.Ceiling(value / factor) * factor
End Function
And the answer in C#
public double Ceiling(double value, double factor)
{
return Math.Ceiling(value / factor) * factor;
}
I'm posting it here because I needed such a function google sent me to this question but I couldn't find an answer for .Net. I finally figured it out for myself.

Resources