Using math functions in Sql with MS Access - sql

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.

Related

NZ function in T-SQL where ValueIfNull is NOT specified

I am working on an MS Access to SQL Server Migration project and am currently in the process of converting a complex query into T-SQL from MS Access.
Now I'm quite familiar with how Nz works in Access and how a 0 or empty string " " is returned if the valueifnull argument is not provided.
Source: https://support.office.com/en-gb/article/nz-function-8ef85549-cc9c-438b-860a-7fd9f4c69b6c
The exception to this rule is if the Nz function is used within a query expression, in which case, the returned value in the event of a null in the Variant, is an empty string.
Now, moving onto my actual problem, I am working on converting this Nz-filled query expression into T-SQL using ISNULL in T-SQL.
ISNULL requires 2 arguments. Both the Expression and the Value. The latter being an optional argument in Access' Nz, has made it a bit difficult for me to translate the expression. The Value argument also needs to match the original data type of the Variant (in SQL Server), this means that I can not just simply add an empty string " " as the second argument as Nz in Access does by default.
Take a snippet of the complex query I use in Access compared to what I've written in T-SQL:
Access
TotalWIP: IIf([PercentageDoneTotal]<0,0,IIf(nz([TotalPurchasesReceived])+
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0))+IIf((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))>0,((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))*
[PercentageDoneTotal]),0)>([Accepted Price]*[OutstandingBalance]*0.9),
([Accepted Price]*[OutstandingBalance]*0.9),nz([TotalPurchasesReceived])+
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0))+IIf((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))>0,((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))*
[PercentageDoneTotal]),0)))
T-SQL
IIf([PercentageDoneTotal]<0,0,
IIf(ISNULL([TotalPurchasesReceived],NULL)+
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0))+
IIf((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)
-(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))>0,
((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)-
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))*
[PercentageDoneTotal]),0)>([Accepted Price]*[OutstandingBalance]*0.9),
([Accepted Price]*
[OutstandingBalance]*0.9),ISNULL([TotalPurchasesReceived],NULL)+
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0))+
IIf((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)-
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))>0,
((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)-
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))*
[PercentageDoneTotal]),0))
) AS TotalWIP
Note the above NULL in the T-SQL example. This NULL is not suitable as it is messing up my calculations, I essentially need to mimic Nz without a second argument in T-SQL.
Edit:
Without putting the entire query into this question, Here is an expected result for Job Number: 294784 in both MS Access and SQL Server:
Access Results:
SQL Results:
Edit 2: have added the edited to add entire code.
As #Salman A noted, this is a great reason not to use variant. But having said that, I assume that you are looking for a numeric value, so why not use:
IIF([PercentageDoneTotal]<0,0, IIF(ISNULL([TotalPurchasesReceived],0)+
(IIF([PercentageDoneTotal]>0,ISNULL([TotalStockAllocate],0),0))

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

Two queries related in UniObjects for .NET

Context
I have a interface in VB.NET that extract the data from the UniVerse using UniObjects for .NET
Problem
From the COB file I need to get all keys where the FEC.COB field is equal to a specific date and the field SEC is equal to 04.
An expert in UniVerse Database told me that I can run the follow queries:
SELECT COB WITH FEC.COB > “31/10/2013”
SELECT.ID 1 2 04
But I don't know how can I do that with UniObjects library. Can anyone help me?
I don't use UniObjects as my shop normally gets data our of UniVerse via ODBC. Also my VB is bad, so I don't have much metacode for you, but the basic idea would be to do something like this.
1.) Create a UV Session. Hopefully you have that much worked out as I can be of next to no help there.
2.) Once the session is established Execute your query by doing something like this
session.Command.Text = "SELECT COB WITH FEC.COB > '31/10/2013'"
session.Command.Exec
(I converted your double quotes to single quotes and Universe won't mind).
3.) If you just need the IDs, you can get them by iterating through the select list that your query returns. A command line query will always return to list 0 unless you specify otherwise in your UV query. In most cases your results will be in session.SelectList(0)
Dim objSelect As object
Set objSelect = objSession.SelectList(0)
4.) It looks like the SelectList object has a ReadList method which returns a Dynamic Array Object, which you should be able to iterate through using normal array looping. Additionally you can use a while loop and next to do what you need to do.
Dim someObject as Object
someObject = objSelect.Next ' Get first ID
Do While Not objSelect.LastRecordRead
' Do something here with someObject. Maybe ToString it or something
someObject = objSelect.Next' Get next ID
Loop
Hope that is somewhat helpful.

How to allow end user write his own functions?

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.

Ascw returns "Cannot convert to 'Integer'." in Watch or Immediate

I have following sample code
Dim q As Char = "a"
Dim res As String = CStr(AscW(q))
res contains correctly "97" but when I use AscW(q) in watch or immediate it returns message: Cannot convert to 'Integer'.
Is it a bug or Visual Studio or am I doing something not correctly?
How can I see a character code in Immediate.
Note
The code presented is just an example. I found the problem when trying to see Character code in the Watch Window.
For a workaround, how about the command
? System.Text.Encoding.Unicode.GetBytes(q)
I personally believe that any acceptable VB.Net code should be acceptable in the Immediate window and really don't understand why AscW is causing errors when VB.Net offers no equivalent (e.g. in C#, but not VB.Net, you can cast a Char variable to an Integer to get the character code).
You are doing everything right (and the outputs will be OK in any case), although you are using old VB code. If you need functionalities like AscW (, Asc, ChrW, etc.), you would have to rely on this "old code" to get what you want (directly or via Microsoft.VisualBasic.Strings which, btw, does not show a different behaviour). But, in any other case, you should avoid the utilisation of this old code.
Test these two lines in the Immediate Window:
Dim res As String = CStr(5)
res = 5.ToString()
As you can see, you get an "error" (VS 2010, right-click on the line and select "QuickWatch") in the first line (old version), but not in the second one (.NET version).
Thus, the behaviour you observed can be considered as an inoffensive bug (no real effects in the execution) more or less understandable if you analyse the situation (you are asking a certain language (VB.NET) to support all its own features and the ones from an old language (VB); with the old one, some secondary functionalities might not be perfect).