Microsoft Access Append VBA - vba

I am trying to automate records from a query to append to a table if the ID does not exist. While running into issues, I have even tried to use VBA from some other databases I know this is working on and put it into the targeted database. Still, I am receiving the same error. It is highlighting "dbs as Database" when the error appears.
Error- "Compile Error: User-defined type not defined"
Function HistoricTable()
Dim dbs As Database
Dim qdf As QueryDef
Set dbs = CurrentDb
dbs.Execute "insert into [Destination_Table] SELECT * FROM [Query Name] "
End Function
Thank you!

I believe it should be something like this.
INSERT INTO target [(field1[, field2[, …]])]
VALUES (value1[, value2[, …]])
See the link below for more info.
http://www.fmsinc.com/microsoftaccess/query/snytax/append-query.html

You have to add a reference to the DAO library in the VBA editor. In my old Access it's in the menu Tools > References...
You can also remove the ADODB library (the other database access technology).

Related

Using the Month function as criteria in an Access SQL query

I'm trying to extract data from an Access 2016 database using SQL and VBA. Below is the code I'm trying to use and every time I run it, I get a "No value given for one or more parameters". I've also shown what I see in the immediate window.
vsql = "SELECT [ResDate],[ResNanme],[ResStart],[ResEnd] FROM [TrainingRoom] where Month([ResDate]) = " & MonNo
Set RecSet1 = Connection.Execute(vsql, dbrows, adCmdText)
Immediate Window:
SELECT [ResDate],[ResNanme],[ResStart],[ResEnd] FROM [TrainingRoom] where(Month([ResDate])) = 11
I don't see anything wrong but I'm sure this is user error. The "MonNo" variable is declared as an integer.
Any suggestions would be greatly appreciated. Thanks for the help.....
I've never used Execute method to open ADO recordset, only Open.
Assuming Connection is a declared and set variable - but it is a reserved word and really should not use as a variable. If code is behind same db pulling data from, could just use CurrentDb with DAO recordset variable and OpenRecordset method. Example that accepts default parameters for optional arguments:
Dim RecSet1 As DAO.Recordset
Set RecSet1 = CurrentDb.OpenRecordset(vsql)

Can I run a VBA macro to run SQL queries I have saved in a MS Access database?

I spent alot of time to create 24 different separate MS Access queries that I have saved in the MS Access database. They have to be run in a specific order.
I want to run a macro that will just execute them one after another.
I know I can do this using VBA but I have copy all the SQL into VBA one at a time.
is there a way I can just have VBA run the saved queries in the MS Access database without copying them into VBA?
I am very good with SQL. 15+ years doing Oracle work, Code writing, DB Tuning, Data DBA work.
I am new to using SQL and VBA to run against MS Access DB.
To clear a few terminologies:
MS Access GUI comprises of five main object types: tables, queries, forms, macros, and modules. Technically, there is no such thing as VBA macros in MS Access. This is a terminology from MS Excel where each subroutine is defined as a macro.
In MS Access there is a physical object known as a macro which is divorced from VBA (though can call VBA code). Coded routines which includes all functions and subroutines in MS Access are encapsulated in the module (object) usually behind forms, reports, or standalone modules.
Do remember each Microsoft Office application maintains its own object library and should not be conflated with one another. VBA itself is a separate component installed by default (see Tools \ References in IDE). Any language (Java, PHP, Python, etc.) that can run COM-interfacing can connect and run each Office app's object library. VBA is simply one type that does this.
MS Access maintains stored queries (as another object) which can be actions queries (UPDATE, INSERT even CREATE TABLE or ALTER TABLE) or recordset queries (SELECT). You do not have to copy all of SQL code inside VBA to run these saved query objects. In fact, stored queries run more efficiently than string queries called in code since the MS Access engine compiles the best execution plan with stored queries.
Having said that, consider a macro calling multiple OpenQuery actions or coded subroutine inside a module calling multiple DoCmd.OpenQuery commands
Macro
OpenQuery
QueryName: myfirstActionQuery
View: Datasheet
Data Mode: Edit
OpenQuery
QueryName: mySecondActionQuery
View: Datasheet
Data Mode: Edit
OpenQuery
QueryName: myThirdActionQuery
View: Datasheet
Data Mode: Edit
...
For action queries you do not have to close the query as OpenQuery runs process without physically opening anything to screen. You may want to incorporate the SetWarnings to False action in order to avoid the message prompt of how much records will be updated or inserted which is a default setting in Access. Because this is a potentially hazardous action, click Show All Actions to see this specific action.
Module
Public Sub RunQueries()
DoCmd.SetWarnings False
DoCmd.OpenQuery "myfirstSavedQuery"
DoCmd.OpenQuery "mySecondSavedQuery"
DoCmd.OpenQuery "myThirdSavedQuery"
...
DoCmd.SetWarnings True
End Sub
Similar to macros, you do not have to close action queries and can call the DoCmd.SetWarnings to suppress the message prompts with each update, insert, or make-table action.
The alternative to turning SetWarnings off and on is #LeeMac's solution which runs queries using the DAO's Database.Execute() command. In fact, because DAO is part of the MS Access object library, the above method can be run outside VBA as mentioned above.
Python
import os
import win32com.client
access_file = r'C:\Path\To\MyDatabase.accdb'
try:
oApp = win32com.client.Dispatch("Access.Application")
oApp.OpenCurrentDatabase(access_file)
db = oApp.Currentdb()
db.Execute("myFirstSavedQuery")
db.Execute("mySecondSavedQuery")
db.Execute("myThirdSavedQuery")
...
except Exception as e:
print(e)
finally:
oApp.Quit()
db = None; oApp = None
del db; del oApp
In its very simplest form, you can define a Sub such as:
Sub ExecuteQueries()
With CurrentDb
.Execute "MyQuery1"
.Execute "MyQuery2"
'...
.Execute "MyQueryN"
End With
End Sub
Or define this as a Function in a public module if you intend to invoke this from an MS Access Macro.
Here is another method if you don't have specific naming conventions utilizing an array for the query names in execution order:
Public Sub RunMasterUpdate()
Dim qryList As Variant
Dim i As Long
qryList = Array("QueryName1", "QueryName2", "QueryName3")
For i = LBound(qryList) To UBound(qryList)
CurrentDb.Execute qryList(i)
Next
End Sub
You can do something like this to run saved queries:
Dim db As DAO.Database, qry As DAO.QueryDef
Set db = CurrentDb
Debug.Print "-- Start --"
For Each qry In db.QueryDefs
If qry.Name Like pattern Then
Debug.Print qry.Name,
qry.Execute
Debug.Print "(" & qry.RecordsAffected & ")"
End If
Next
Debug.Print "-- End --"
db.Close()
Name the queries so that the alphabetical order matches the the expected execution order, e.g., 01_deleteCustomers, 02_appendCustomers, 03_etc.
Specify a pattern string or remove the If alltogether if you want to run all the queries.
Note that in the Visual Basic editor under menu Tools > References... I have selected Microsoft DAO 3.6 Object Library. (You might have another version)

Access 2007 Error 3151 from DAO.OpenRecordSet. How to fix?

Well this is fascinating. I am using MS-Access 2007 to make a from that will allow users to enter data from lab results.
The from utilizes a VBA code call:
DAO.OpenRecordset("{Sql query}" , DB_OPEN_DYNASET, dbSeeChanges)
This call normally works just fine, but I've noticed that when this form is closed and then re-opened, a 3151 ODBC error is generated.
We are using linked tables through Access 2007 for this form, our SQL-Server 2012 version is as follows.
Microsoft SQL Server Management Studio 11.0.2100.60
Microsoft Analysis Services Client Tools 11.0.2100.60
Microsoft Data Access Components (MDAC) 6.1.7601.17514
Microsoft MSXML 3.0 6.0
Microsoft Internet Explorer 8.0.7601.17514
Microsoft .NET Framework 4.0.30319.237
Operating System 6.1.7601
The DAO.OpenRecordset call is utilized in multiple events. Here is the list.
On_Current , _AfterUpdate , Form_Unload
I have found several reported instances of similar errors on Access 2007 with linked tables to SQL-Server, but none seem to have workable solutions for this issue.
As best I can tell, the 3151 doesn't appear to be affecting the form or data in any negative way. I am able to open the form and everything is where it should be as best I can tell. There are about 20 thousand records on this table, so I may be missing something.
Does anyone have any ideas?
9/14 In response to comments I am adding some additional code.
Here is the call on Form_Unload. It contains the failing line.
Private Sub Form_Unload(Cancel As Integer)
Dim ImportID
Dim rst As DAO.Recordset
Dim db As Database
Set db = CurrentDb
Set ImportID = Me.ImportID
#This is the failing line below.
Set rst = db.OpenRecordset("SELECT [dbo_t_inspect].* FROM [dbo_t_inspect] WHERE [dbo_t_inspect].ImportID= " & ImportID & ";", DB_OPEN_DYNASET, dbSeeChanges)
Here is the call from On_Current. This On_Current call is actually made by a sub-form on the main form.
Private Sub Form_Current()
Dim rst As DAO.Recordset
Dim strImportID As String
If IsNull(Me.ImportID) Then
[Forms]![Inspection Receiving]![LabComplete].Visible = False
[Forms]![Inspection Receiving]![LabPending].Visible = True
Else
strImportID = Me.ImportID
Dim db As Database
Set db = CurrentDb
Set rst = db.OpenRecordset("SELECT [dbo_t_health].*, [dbo_t_health].ImportID FROM [dbo_t_health] WHERE ((([dbo_t_health].ImportID)=" & Me.ImportID & "));", DB_OPEN_DYNASET, dbSeeChanges)
I am not sure where DAO is defined in this solution. I cannot find it's declaration in my folder titled Microsoft Office Access Class Objects I am open to suggestions on where that might be located.
The precise error message is as follows
Failed to connect to {ODBC Connection Name} Error 3151.
I can then select the debug option and the debugger will take me to the line that tried and failed to connect the the ODBC Connection I am using.
The Error is highly reproducible. All I have to do is enable VBA Macros on the Security Alert and then open the form in question. I close out the form after it loads. Once I attempt to reopen the form, I get the error described above. The Form opens anyway after I click Ok on the error.

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.

SQL Query Run Against Excel Workbook Returns Truncated Text Field

I'm running a SQL SELECT query through an ADO connection to an Excel 2007 workbook with the following code (using a custom version of VBScript)
dim ado, rs
set ado = CreateObject("ADODB.Connection")
ado.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=workbook.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"
ado.open()
set rs = ado.execute("SELECT * FROM [sheet1$]")
which is straighforward. The problem is that any cell that has text longer than 255 characters is truncated; is there any way around this? Is there a property in the connection string that will support this or is it an option I need to change in the excel document itself? I have tried MSSQL's CAST() function but this just causes an error when executed.
Any help would be greatly appreciated.
I think you're running into a variant of a long-standing limitation in Excel's data access provider. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;189897 for an example or google for thousands more.
Instead of trying to use CAST(), have you tried to use the CONVERT() function?