How to allow end user write his own functions? - vb.net

I'm modeling some financial products and each product has his own pricing formula.
In the application I would like to allow the end-user create his own product with the formula. And this formula can be used by my application to price the product.
Something like :
Formula as string = "f(x) = x * 2"
Dim Result as double = call(Formula, 1)
I know this is possible in Matlab :
f="#(x)(x*2)";
Result = feval(f,1);
I wrote a class in Matlab that implements this feature and integrated it in VB.Net project, but every function takes 4700 times the execution of the same function directly written in VB.Net which is not affordable regarding the business need.
Is that possible in .Net ?

You can look into MEF, so your end users would provide DLL modules in a certain format (see the link I mentioned), which would later be discovered in your program and executed at any given time.
Or use a math parser:
VB.Net- Evaluating Mathematical Expression in a String
Evaluate mathematical expression from a string using VB
But I feel that approach #1 would be more flexible.

Related

MS Project equivalent to "xlAnd". Enumeration for logical operators

I'm trying to write a language independent filter for MS Project in VBA. I'm using the syntax:
FilterEdit (Name, Taskfilter, Create, Fieldname, Test, Value, Operation...)
I have managed to get the Fieldnames and Tests to be language independent, but I struggle with the Operation:= expression. For an English locale one would write: Operation:="and" but that doesnt work for other locales.
Is there a way to write the logical operator (and/or) as an enumeration? (not as a string?)
For Excel one could write xlAnd, and Project has a lot of enumerations starting with Pj, ie. PjTaskStart. I also know there's a Filter.LogicalOperationType, but I haven't managed to figure out if this could work for me or not. I have also experimented with FieldConstantToFieldName, but I reckon there's no fieldname for the logical operator?
I know I could use If LocaleID = xxxx Then..., but I'd like to not assume what locales will be in use.
Edit: I solved the first part of my problem!
By leaving it blank Operation:="", Project returns "And". But I haven't figured out yet how to return "Or"...
Operation:="" works for FilterEdit, but not for SetAutoFilter.
So I ended up using the dreaded If LocaleID.
Teaching moment:
I found out most operators can be language independent, except for:
And, Or, Contains and Does Not Contain.
These needs to be translated for each locale. I'll get to those in a minute. First I'll list all the language independent operators:
< Less than <= Less than or equal to > Greater than >= Greater than or equal to = Equal to <> Not equal to
My trick for finding the translations I need for the language dependent operators is the following MS Office Support page.
Notice the category named "Filter for specific text" in the English support page. Here we can read all the "words" we need. Now go to the bottom of the web page and change the language:
This opens up a new page listing all the different languages (not locale specific). Remembering where you found the word for Contains in English, then changing the language to for instance "Magyar (Magyarorzág)", we can now see that Contains = "Tartalmazza" in Magyar.
Next step is to google "Magyar languge" and learn that this actually equals Hungarian. So now you can go to this MSDN web page to see that Hungarian = LocaleID: 1038.
Putting all this together inside VBA makes you have to write the following code:
Dim LocalContains As String
If LocaleID = 1038 Then
LocalContains = "Tartalmazza" 'Hungarian
ElseIf LocaleID = 1044 Then
LocalContains = "inneholder" 'Norwegian
Else
LocalContains = "contains" 'English
End If

Use String for IF statement conditions

I'm hoping someone can help answer my question, perhaps with an idea of where to go or whether what I'm trying to do is not possible with the way I want to do it.
I've been asked to write a set of rules based on the data held by our ERP form components or variables.
Unfortunately, these components and variables cannot be accessed or used outside of the ERP, so I can't use SQL to query the values and then build some kind of SQL query.
They'd like the ability to put statements like these:
C(MyComponentName) = C(MyOtherComponentName)
V(MyVariableName) > 16
(C(MyComponentName) = "") AND V(MyVariableName) <> "")
((C(MyComponentName) = "") OR C(MyOtherComponentName) = "") AND V(MyVariableName) <> "")
This should be turned into some kind of query which gets the value of MyComponentName and MyOtherComponentName and (in this case) compares them for equality.
They don't necessarily want to just compare for equality, but to be able to determine whether a component / variable value is greaterthan or lessthan etc.
Basically it's a free-form statement that gets converted into something similar to an IF statement.
I've tried this:
Sub TestCondition()
Dim Condition as string = String.Format("{0} = {1}", _
Component("MyComponent").Value, Component("MyOtherComponent").Value)
If (Condition) Then
' Do Something
Else
' Do Something Else
End If
End Sub
Obviously, this does not work and I honestly didn't think it would be so simple.
Ignoring the fact that I'd have to parse the line, extract the required operators, the values from components or variables (denoted by a C or V) - how can I do this?
I've looked at Expression Trees but these were confusing, especially as I'd never heard of them, let alone used them. (Is it possible to create an expression tree for dynamic if statements? - This link provided some detail on expression trees in C#)
I know an easier way to solve this might be to simply populate the form with a multitude of drop-down lists, so users pick what they want from lists or fill in a text box for a specific search criteria.
This wouldn't be a simple matter as the ERP doesn't allow you to dynamically create controls on its forms. You have to drag each component manually and would be next to useless as we'd potentially want at least 1 rule for every form we have (100+).
I'm either looking for someone to say you cannot do this the way you want to do it (with a suitable reason or suggestion as to how I could do it) that I can take to my manager or some hints, perhaps a link or 2 pointing me in the right direction.
If (Condition) Then
This is not possible. There is no way to treat data stored in a string as code. While the above statement is valid, it won't and can't function the way you want it to. Instead, Condition will be evaluated as what it is: a string. (Anything that doesn't boil down to 0 is treated as True; see this question.)
What you are attempting borders on allowing the user to type code dynamically to get a result. I won't say this is impossible per se in VB.Net, but it is incredibly ambitious.
Instead, I would suggest clearly defining what your application can and can't do. Enumerate the operators your code will allow and build code to support each directly. For example:
Public Function TestCondition(value1 As Object, value2 As Object, op as string) As Boolean
Select Case op
Case "="
Return value1 = value2
Case "<"
Return value1 < value2
Case ">"
Return value1 > value2
Case Else
'Error handling
End Select
End Function
Obviously you would need to tailor the above to the types of variables you will be handling and your other specific needs, but this approach should give you a workable solution.
For my particular requirements, using the NCalc library has enabled me to do most of what I was looking to do. Easy to work with and the documentation is quite extensive - lots of examples too.

VB 2010, Complex numbers

Hi does anybody know if is possible to utilise formulas containing complex numbers within basic programming. Part of the formula im trying to implement is i(e^2-e^2-2), e represents exponential and i the imaginary number. Any help appreciated.
Add a reference to the System.Numerics library to your project (Go to MyProject->References->Add->Assemblies->Search the list for System.Numerics). You can also import the namespace in your source by using Imports System.Numerics.
In this library you can find functions to compute complex numbers.
You define a complex number for example with the line
Dim MyComplex as New Complex(Realpart, ImaginaryPart)
To compute the exponential you would use
Dim Exped as Complex = Complex.Exp(MyComplex)
and so on. There are functions for most operations and the complex numbers support general operators like +, -, *, / as well.
For your specific problem you would just use
Dim result as New Complex(0, Math.Exp(2)-Math.Exp(2)-2)
This works because i*x is a complex number with a real part of zero and an imaginary part of x. I'm not judging how much sense your definition makes :-)

Using math functions in Sql with MS Access

I designed a query in SQL View using MS Access:
select floor(num1) from t1;
When I run it, I get "undefined function floor".
I get similar errors for Ceil, Mod,Power, Sign, Sqrt, Trunc, and initcap functions.
Does the Access database engine's SQL syntax have equivalent functions?
Replace Floor() with Int(). I learned this by searching in the Access help files, in this case, hitting F1 while in the query designer, and searching for "functions." That took me to a help topic comparing VBA and T-SQL functions.
You should probably have a look at the Access database engine SQL Reference. I can't find a good online reference for functions that are supported through the Jet/ACE and Access expression services. For some unknown reason, the Access Help has not included Jet/ACE expressions since Jet 3.0 and this aged resource was finally removed from MSDN a year or two ago :(
Keep in mind that the Jet/ACE expression service for use outside Access supports a much smaller subset of functions that is possible using the Access Expression Service when running your SQL inside Access 2007. Broadly speaking, the VBA5 functions (as distinct from methods) that involve simple data types (as distinct from, say, arrays or objects) are supported outside of the Access user interface; for an approximate list of function names see the 'Use Sandbox mode operations with Jet 4.0 Service Pack 3 and later' section of this MSDN article.
Also, the functions reference in the VBE help should be a starting place.
The help files are not perfect, but a little searching ought to get you what you need.
Public Function Floor(ByVal x As Double) As Double
'Be Because VBA does not have a Floor function.
'Works for positive numbers
'Turns 3.9 -> 3
'Note: Round(3.9) = 4
Dim s As String, dPos As Integer
s = CStr(x)
dPos = InStr(s, ".")
Floor = CLng(Left(s, dPos - 1))
End Function
As mentioned, Floor isn't available in access, you should use int() as an alternative. If you insist on using Floor, you could always create a vba module function in your mdb file similar to below but that is probably overkill.
Public Function floor(dblIn As Double, dec As Integer) As Double
decPosition = InStr(Str(dblIn), ".")
x = Left(dblIn, decPosition + dec - 1)
floor = x
End Function
Similar to the other math operations you described above you may create additional functions to create this set of functionality.

Using statement with more than one system resource

I have used the using statement in both C# and VB. I agree with all the critics regarding nesting using statements (C# seems well done, VB not so much)
So with that in mind I was interested in improving my VB using statements by "using" more than one system resource within the same block:
Example:
Using objBitmap As New Bitmap(100,100)
Using objGraphics as Graphics = Graphics.From(objBitmap)
End Using
End Using
Could be written like this:
Using objBitmap As New Bitmap(100,100), objGraphics as Gaphics = Graphics.FromImage(objbitmap)
End Using
So my question is what is the better method?
My gut tells me that if the resources are related/dependent then using more than one resource in a using statement is logical.
My primary language is C#, and there most people prefer "stacked" usings when you have many of them in the same scope:
using (X)
using (Y)
using (Z)
{
// ...
}
The problem with the single using statement that VB.NET has is that it seems cluttered and it would be likely to fall of the edge of the screen. So at least from that perspective, multiple usings look better in VB.NET.
Maybe if you combine the second syntax with line continuations, it would look better:
Using objBitmap As New Bitmap(100,100), _
objGraphics as Graphics = Graphics.FromImage(objbitmap)
' ...
End Using
That gets you closer to what I would consider better readability.
They are both the same, you should choose the one that you find to be the most readable as they are identical at the IL level.
I personally like the way that C# handles this by allowing this syntax:
using (Foo foo = new Foo())
using (Bar bar = new Bar())
{
// ....
}
However I find the VB.NET equivalent of this form (your second example) to be less readable than the nested Using statements from your first example. But this is just my opinion. Choose the style that best suits the readability of the code in question as that is the most important thing considering that the output is identical.