SQL Query in Excel gives "undefined function name" error - sql

I wrote a SQL query in MS Access that uses the MonthName function. In access it works flawlessly. I copied the exact SQL statement into an excel module that I frequently use to query databases. When I run the query, excel keeps telling me that MonthName is an undefined function name. If I remove the MonthName portion, the query runs fine.
It seems like I'm missing a reference or something... Right now, I'm referencing Microsoft ActiveX Data Objects Library 6.0. Can anyone point me in the right direction? Thanks
strSQL = "SELECT DISTINCT Customers.CustomerName, Employees.EmployeeName, [Policy data revised].EXDT, MonthName(Month([EXDT])) AS expMonth
FROM (([Service Team table]
INNER JOIN Customers
ON [Service Team table].CustID = Customers.CustID)
INNER JOIN Employees
ON [Service Team table].EmployeeID = Employees.EmployeeID)
INNER JOIN [Policy data revised]
ON Customers.CustID = [Policy data revised].CustID
WHERE ((([Service Team table].RoleExtension)='2. Underwriting Assistant')
AND (([Policy data revised].EXDT)
BETWEEN #" & minExpDt & "# AND #" & maxExpDt & "#))
ORDER BY [Policy data revised].EXDT ASC;"

The MonthName() function is only available for queries run within an Access application session. See the "The following VBA functions won't work when called from a property sheet or used in an SQL statement" bullet point at About Microsoft Jet Expression Service sandbox mode. Within an Access application session, the db engine can use the expression service to use that sandboxed function.
Since you can't use MonthName, try this Format expression instead.
Format([EXDT], 'mmmm') AS expMonth

Strange, I just tried the following code in Excel 2010 (64-bit) and it worked for me:
Sub foo()
'' Reference: "Microsoft ActiveX Data Objects 6.0 Library"
Dim con As ADODB.Connection, rst As ADODB.Recordset
Set con = New ADODB.Connection
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Gord\Desktop\Database1.accdb;"
Set rst = New ADODB.Recordset
rst.Open "SELECT MonthName(Month([BookingStart])) FROM Payment_tbl", con, adOpenStatic, adLockOptimistic
Debug.Print rst(0).Value
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
End Sub
Edit
Further to HansUp's comment, something must have changed between Office 2007 and Office 2010. I ran another test from a 32-bit machine running Office 2010 and the above code run against an Access 2000 .mdb file worked for me using both...
Provider=Microsoft.ACE.OLEDB.12.0;
...and...
Provider=Microsoft.Jet.OLEDB.4.0;
I also checked the SandBoxMode registry value under...
HKLM\Software\Microsoft\Office\14.0\Access Connectivity Engine\Engines
...and it is 3, which is the value for "Enabled" (ref: here).

Related

Open a Table in a Form using VBA

In the "old" days, in order for me to search a "Table" for specific data in a vba statement in a "Form"/"Event" in MS Access 2003, that I chose. I would use the following code:
Set Table_ID = New ADODB.Recordset
Table_ID.CursorLocation = adUseClient
Table_ID.Open "Select * From Table_ID", _
CurrentProject.Connection, adOpenDynamic, adLockOptimistic
The above code gives me the following message when I ran it MS Access 2019:
Microsoft Visual Basic for Application Compile error: User-defined type not defined
I changed the "ADODB" with the database I'm using in MS Access 2019 as follows:
Set Table_ID = New DB002.Recordset
When I ran it again in MS Access 2019, the same message appeared.
Please advise.

MS Access crashes binding RS to a form from SQL Server stored procedure

I am just starting to move our Access DB to SQL Server and am having trouble.
I have a stored procedure that successfully returns rows to an ado recordset.
When I try to bind the rs containing the results of the stored procedure to the Access form, Access crashes without displaying any error messages. I'm on O365 32b and SQL Server 2019.
Here's the code:
Dim sSQL As String, rs As ADODB.Recordset
1 sSQL = "Exec usp_TaskStatusWidget " & Me.Tag & ",0"
2 ADOConn.ConnectionString = conADO
4 ADOConn.Open
6 Set rs = New ADODB.Recordset
7 rs.CursorLocation = adUseClient
8 rs.Open sSQL, ADOConn
10 Set Me.Recordset = rs ' Access crashes here
. . .
Any help would be greatly appreciated!
tia.
SR
Ok, are you previous using ADO, or are you just introducing this?
In most cases, you are better off to just use a view. (replace the access query with a linked view), and then continue useing client side where clauses or filters (access will ONLY pull down the rows you request). So linked views are often a better choice and much less work (in fact, even existing filter for a open report etc. will work and only critera matching the were clause records are pulled.
And in most cases, i don't introduce ADO.
So for a PT query, I often do this:
dim rs as DAO.RecordSet
with CurrentDb.queryDefs("qryPt")
.SQL = "Exec usp_TaskStatusWidget " & Me.Tag & ",0"
set rs = .OpenRecordSet
end with
So, above assumes you have a pt query called qryPt. This also means that you never deal with or worry about connection strings in code. The pt query has the connection. (and your re-link code now can re-link tables and pt queries).
I ONLY suggest the above as a FYI in case that you introducing ADO for calling store procedures, and the rest of the application was previous DAO. If the application was previous DAO, then leave it alone, and use above approach for your PT queries - even code that needs to call store procedures.
Access tends to try and parse the query text to get filters/sorts/etc to work, and if it isn't a plain syntax error but isn't Access SQL either, strange things tend to happen, mostly crashes.
Try adding a comment up front to make sure Access knows not to parse:
sSQL = "-- Access no parse pls" & vbCrLf & "Exec usp_TaskStatusWidget " & Me.Tag & ",0"
The content of the comment is not relevant, of course, its purpose is to immediately cause a syntax error when Access tries to parse it as Access SQL (which doesn't have comments)

Access VBA Module cannot get data from Form

OK, so my database was originally designed in Access 2003. On one of the machines I am using a Access 2007 Runtime as the machine does not have Office of any flavor. I am trying to find a solution using the latest version of Access in Office 365. I cannot directly access either the live version running on either Access 2003 or Access 2007 Runtime. I cannot change the versions on the other machines as these are located in a prison and have no internet. This works without issue running in 2003, only the 2007 is the issue. As I am not there and only have 365, I need a solution that will work for all versions.
The functions being used are in separate modules and are not on the actual form. The form is set to have module as that is required to access the objects. The function is to add an session for an inmate to attend the library. This must be verified to make sure there is room at the time and day of week selected, as well as individual session limits.
The issue I am dealing with is the 2007 and 365 versions are unable to get the selected data from a list box (time as a string) and option group (DayofWeek as number) to complete a SQL query instead it inserts nothing and the SQL fails claiming there is an extra ) in my code. The SQL is then used to create a DAO recordset. This is part of a verification of data to ensure limits are not reached.
I have triple checked the string sent to CO_GetSessionDetail to ensure I do not have an extra ). It thinks it does as there is nothing on the right side of my = in the string. I checked the reference to the form and the unbound fields and they all match. It compiles no problem.
THERE IS NO ISSUE IN 2003 ...
The code is posted below.
Function CO_NewCallout() As Boolean
...
' Get Session ID --------------------------------- '
With Form_f_COs_IM
iSession = CO_GetSessionDetail( _
"SessionID", _
"(((t_CO_Sess.DayOfWeek) = " & .CO_Add_DayOfWeek & ") AND " & _
"((t_CO_Sess.tSession) = '" & .CO_Add_tSession & "'))" _
)
If iSession = 0 Then
GoTo CO_NewCallout_Exit
End If
End With
...
End Function
Function CO_GetSessionDetail(stfield As String, stwhere As String) As Variant
'On Error Resume Next
' Variable Declerations -------------------------- '
Dim db As Database
Dim rst As DAO.Recordset
Dim stSQL As String
' Set Variables ---------------------------------- '
Set db = CurrentDb
If stwhere <> "" Then
stwhere = "WHERE " & stwhere
End If
stSQL = _
"SELECT * " & _
"FROM t_CO_Sess " & stwhere
Set rst = db.OpenRecordset(stSQL, dbOpenDynaset)
' Get Session ID --------------------------------- '
With rst
If Not .EOF Then
CO_GetSessionDetail = .Fields(stfield)
Else
CO_GetSessionDetail = 0
End If
End With
' Close Recordset t_CO_Sess ---------------------- '
rst.Close
Set rst = Nothing
End Function
Access 2003 - I get the unique ID of the Session
Access 2007 and 365 - cannot complete function
Let me know if more code would help.
An Access application compiled using Office 365 will not be compatible with the Access 2007 runtime or Access 2003. You must compile on a version earlier or equal to the runtime you choose. Unfortunately, it is hard to get the Access 2003 runtime because it is not freely downloadable. The 2007 runtime is freely available (which probably explains why you chose to install the later version).
Your code looks OK, and I assume it compiles and all that. Despite the fact that your 2003 database should work with the Access 2007 runtime, the fact that it doesn't says to me that you have an incompatibility you need to resolve.
Your best bet: upgrade your app to 2007 or later, ensure it works in the new version, and install the matching runtime on your client's machines.
References:
General discussion of Access version compatibility:
Access 2016/2010 Compatibility, Access 2016
Article on getting the Access 2003 Runtime:
MS Access Runtime 2003

MS Access queries with inline functions can't be exposed

I have an MS Access 2003 database that contains the following query:
SELECT Replace(Trim(TABLE_A.Field_01), "XXX", "YYY") AS FLD01 FROM TABLE_A
If I do an "Import Data" with Excel from this Access database, I can't find the name of this query that is defined in the database.
If I change the query by removing the Trim function, then I can see the query in Excel.
SELECT RTrim(LTrim(TABLE_A.Field_01)) AS FLD01 FROM TABLE_A
Has anyone had a similar experience? I think there's a limitation on what kind of function one can apply to a query in MS Access.
It looks like there is a problem with MS Jet SQL, which doesn't support the Replace() function - searching the key words "Jet Sql Replace Function" in google gives a lot of references with various issues with the same root cause, but I haven't found a decent solution yet...
Trim() function is not a part of SQL (resides in VBA.Strings library) so couldn't be called outside MS Access.
So you can use any SQL function but none of "external".
For what it's worth, the Replace() function is supported by the Access Database Engine 2010 (a.k.a. "ACE", the successor to "Jet"), available here. To verify that I created a table named [SomeTable] in an Access 2003 database file:
ID s
-- ----------------------------
1 Everybody loves tofu!
2 Nobody really liked Raymond.
...and I created a saved query named [stockReplaceQuery]:
SELECT ID, Replace([s],"tofu","bacon") AS s1
FROM SomeTable;
When I tested a Jet ODBC connection using the following VBScript
Option Explicit
Dim con, rst
Set con = CreateObject("ADODB.Connection")
con.Open "Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Users\Public\2003test.mdb;"
Set rst = CreateObject("ADODB.Recordset")
rst.Open "SELECT s1 FROM stockReplaceQuery WHERE ID = 1", con
WScript.Echo rst(0).Value
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
...I got
C:\__tmp>cscript /nologo repl.vbs
C:\__tmp\repl.vbs(6, 1) Microsoft OLE DB Provider for ODBC Drivers: [Microsoft][ODBC Microsoft Access Driver] Undefined function 'Replace' in expression.
When I tested an ACE ODBC connection by changing the con.Open line to
con.Open "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\Users\Public\2003test.mdb;"
...I got
C:\__tmp>cscript /nologo repl.vbs
Everybody loves bacon!
It might be worth a try to install the ACE engine/drivers and see if that helps any.

Multiple databases in MS Access VBA?

This Microsoft KB article details how to run a query on another database than the current one used by the Access project. However it only states how to connect to DBase, Foxpro, Paradox, BTrieve and ODBC.
I want to be able to do something like this:
UPDATE MSSQLDatabase.Table
SET MSSQLDatabase.Table.Column = AccessDatabase.Table.Column
WHERE MSSQLDatabase.Table.Column = AccessDatabase.Table.ID
INSERT INTO AccessDatabase.Table
VALUES (AccessDatabase.Table.ID)
Can you give me any pointers of where to begin? The database I want to connect to is a SQL Server 2008 Provider Native connection. I'm using Access 2007.
To do this in VBA would be perfect.
By far the easiest way to work with SQL Server in MS Access is to use linked tables. However, you can also run pass-through queries and refer to a connection in-line:
SELECT * FROM [ODBC;FILEDSN=Z:\Docs\Test.dsn;].table_1
Or
SELECT * FROM
[ODBC;DRIVER=SQL Server;SERVER=srvr;Trusted_Connection=Yes;DATABASE=Test;].table_1
Or
SELECT * FROM [ODBC;Driver={SQL Server Native Client 11.0};Server=svr;Database=test;Trusted_Connection=yes;].table_1
see also http://www.connectionstrings.com/sql-server-2008
This solution allows to catch errors:
Private Sub Command10_Click()
On Error GoTo Err1:
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
With cn
.Provider = "SQL Native Client"
.ConnectionString = "Server=myserver\myinstance;Database=mydb;Uid=myuser;Pwd=mypass;]"
.Open
End With
MsgBox "Connection successful!"
cn.Close
Exit Sub
Err1:
MsgBox Err.DESCRIPTION
End Sub
The only thing to note, is that within the Visual Basic Editor, you must first go to Tools > References, and check Microsoft ActiveX Data Objects 2.x Library.