Run-time error on appending linked table in MS Access - vba

I have a database that links to an Excel spreadsheet. When adding the linked table manually, I have no problems (I just follow the little wizard and the table is created perfectly). I am trying to automate that using VBA:
Dim db as DAO.Database
Dim tdf as TableDef
Set db = CurrentDB
Set tdf = db.CreateTableDef("linked_table")
tdf.Connect = "Excel 8.0;HDR=YES;IMEX=2;DATABASE=" & Me.txtExcelFile ' references form field
db.TableDefs.Append tdf ' Here's where I get a run time error
Unfortunately I get run-time error 3264 on the last line and it says, "No field defined--cannot append TableDefs or Index." I'm not even sure why the last line is needed (it seems from the documentation I've found that it's to add the table to the TableDefs collection of the database). Any suggestions on resolving the error?

You are missing:
tdf.SourceTableName = "Sheet1$"
Or whatever range or sheet name you wish to use as the table.
So, in all, this works for me:
Dim db as DAO.Database
Dim tdf as TableDef
Set db = CurrentDB
Set tdf = db.CreateTableDef("linked_table")
tdf.SourceTableName = "Sheet1$"
tdf.Connect = "Excel 8.0;HDR=YES;IMEX=2;DATABASE=" & Me.txtExcelFile ' references form field
db.TableDefs.Append tdf
You can also link Excel using TransferSpreadsheet

Related

Clear a linked table location, but keep the link

I have a database that works as a user interface to a few other databases. I link the secondary databases into the "front end" with linked tables.
So I have A.accdb, B.accdb, C.accdb, which all link into UI.accdb.
When I give this to people, some only get A, some only get B, some get A and C, and so on. The databases are expected to all be in the same folder. I am able to update the links by having a macro that relinks the UI back to each using the following (with some error handling).
Dim db As DAO.Database
Dim strConnect As String, dbName As String
Dim tdf As DAO.TableDef
Set db = CurrentDb
strConnect = ";DATABASE=" & CurrentProject.Path & "\"
For Each tdf In db.TableDefs
If Len(tdf.Connect) > 0 Then
tdf.Connect = sMyConnectString & dbName
tdf.RefreshLink
End If
Next tdf
My problem is that if a user does not get B, for example, then their table links will not update location and the old file location is still saved in the link (but will not work since they don't have the file). I want to clean this up though.
Is there a way that in the error handling I can set tdf.connect to something that doesn't exist? I cannot set it to Null and I cannot seem to set it to some arbitrary string. Are there any other options to make the link not work, not show the previous location, but still exist? I want it to remain in case they get one of the other databases later.

MS Access VBA code

I am new to MS Access and would like to type EmployeeID in the text box 1 (text_in) and after the button is pressed the result query (one unique value e.g. employee first name taken from the table) is printed out in the text box2 (text_out).
So far have the following code:
Private Sub btn_get_data_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
'declaration of database on recordset objects
Dim strSQL As String
Dim a As String
a = text_in.Value
Set db = CurrentDb
Set rs = db.OpenRecordset("Employee")
strSQL = "SELECT Employee.FirstName FROM Employee WHERE Employee.EmployeeId=" & a
Set db = Nothing
Set rs = Nothing
End Sub
I have tried searching for a solution in many places but I cannot understand the structure that is used in MS access VBA to implement query from regular SQL language.
Guys, thank you very much! It took me one more hour to sucessfully implement both solutions into my database file. As I wrote I am completely new to Ms-access I am learning using some tutorials but my level is still low. Thank you very much once again.
Private Sub btn_get_data_Click()
on error goto errorCatch
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
Set db = CurrentDb
strSQL = "SELECT Employee.FirstName FROM Employee WHERE Employee.EmployeeId=" & Me.text_in.Value & ";"
Set rs = db.OpenRecordset(strSql, DbOpenDynaset)
If rs.RecordCount > 0 Then
debug.print; rs!FirstName
Me.text_out.Value = rs!FirstName
End if
Cleanup:
Set db = Nothing
Set rs = Nothing
Exit Sub
errorCatch:
debug.print; err.Number
debug.print; Err.Description
GoTo Cleanup
End Sub
I cant tell what youre after is this. You need to be better at utilizing recordsets and how to use a string value as your sql statement.
You also didnt need to create a variable to store the textbox value in- you can use it directly in your sql statement.
Also it is very important to have good error handling as hanging recordset objects can be quite a pain in the ass.
EDIT - Ill expand on other ways to use string sql statements within VBA
DoCmd.RunSQl strSql
Or
DoCmd.Execute strSql
Both of these are great for UPDATE's or INSERT's.
Then, like Gustav pointed out, you have various D functions that are basically compact queries with some limitations. However, they often save you the trouble of having to do all the typing that is involved with opening,utlizing and closing records sets. Even though the D functions seem limited, I have often nested a few to get join results out of. Just a matter of imagination.
Look at this nifty site for function details -
https://www.techonthenet.com/access/functions/index.php
You don't need a query to do this. Just set the ControlSource of text2:
=DLookup("FirstName","Employee","EmployeeId=" & [text_in] & "")

Trying to run a DELETE query using DAO in VBA

Im using Access 2013 and Excel 2013. In terms of References, I am using Microsoft Office 15.0 Access database engine Object Library.
So I am trying to run a DELETE query in VBA. Here is what I have so far
Sub UpdatePartList()
Dim ws As DAO.Workspace
Dim dbs As DAO.Database
Dim rsTable As DAO.Recordset
Dim rsQuery As DAO.Recordset
Dim rsSql As DAO.Recordset
Set ws = DBEngine.Workspaces(0)
Set dbs = ws.OpenDatabase("P:\Distribution Purchasing\Kit Bids\Kit Parts Query.accdb")
'deletes previous part numbers
Sql = "DELETE * FROM [Kit Parts]"
Set rsSql = dbs.OpenRecordset(Sql, dbOpenDynaset)
When I run a SELECT query for the same table, it works just fine. But when I try to DELETE, I get this error.
" Run-time error '3219': Invalid operation. "
DAO's OpenRecordSet is not appropriate for Delete queries, which do not return any recordset object. Use the Execute method instead:
Change
Set rsSql = dbs.OpenRecordset(Sql, dbOpenDynaset)
to
dbs.Execute(Sql)
also there's no need for * in the Delete SQL statement. Although Access will accept it, other systems probably won't.
You can modify your SQL as #Rahul suggested, plus change your last line of code to:
dbs.Execute sql

Syncing two Access databases - I can't see the data on the Master DB

I have one master db and slave dbs. I would like to sync those database, but two tables make lots of troubles.
By using an SQL Query, I get an error, because I used multi-valued fields. I cannot change the data structure and therefore I decided to "manually" loop through the recordsets and sync the tables. My code looks like this:
sub UpdateTable()...
.....
Dim rstSlave, rstMaster as DAO.Recordset
Dim fld as DAO.Field
Set dbSlave = currentDB
Set dbMaster = OpenDatabse("C:\Users\MyFile\Master_DB.accdb")
Set rstSlave = dbSlave.OpenRecordset("tbl_Candidate")
Set rstMaster = dbMaster.OpenRecordset("tbl_Candidate")
Set rstSlave = dbSlave.OpenRecordset("tbl_Candidate")
rstSlave.MoveFirst
While Not rstSlave.EOF
rstMaster.MoveFirst
Do While Not rstMaster.EOF
If rstMaster![ID] = rstSlave![ID] Then GoTo nextRecord
rstMaster.MoveNext
Loop
With rstMaster
.AddNew
For Each fld in .Fields
strFieldName = fld.Name
fld.Value = rstSlave.Fields(strFieldName).Value
Next fld
.Update
End With
nextRecord:
rstSlave.MoveNext
Wend
rstSlave.Close
rstMaster.Close
Set rstSlave = Nothing
Set rstMaster = Nothing
I cannot see the record in the master db. When debugging, I see that the ID of the record which was supposed to be transferred to the master db, already existed. Still couldn't find it in the master db when I opened the file.
Strangely it works the other way around. If I change something on the master db and sync it, I can see the changes on my slavedb.

How to view a recordset in an access table by means of vba?

With help of the embedded access vb editor i've written a small code to analyse the field values of my database, and want to finally view the recordsets in a table inside the opened access. As a newbie i can only use Debug.Print to display the field names. Could anyone of you tell me with which statements/commands i can execute my SQL String in order to view the result recordset with values?
Debug.Print FinalSQLString
Here is the basic recipe:
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT * FROM myTable")
Know that you are using Jet Data Access Objects (DAO) with Access - google that for details.
Expression (rs.BOF and rs.EOF) = True indicates there were no rows.
Use rs.MoveFirst, rs.MoveNext to go to the first and next rows. Test rs.EOF after rs.MoveNext; when True, last row was already processed.
rs(FieldName) returns the value of the column named FieldName (a string expression).
rs(1) returns the value of the second column.
When done, rs.Close.
There is no way to hand Access the RecordSet and have it displayed in a Datasheet view. Instead, you will have to create a QueryDef object and use it to perform the query and display the Datasheet view of the results:
Dim qd As QueryDef
On Error Resume Next
CurrentDb.QueryDefs.Delete "temp"
On Error GoTo 0
Set qd = db.CreateQueryDef("temp", "SELECT * FROM myTable")
DoCmd.OpenQuery "temp", acViewNormal, acEdit
As far as I know, there is no way to display a datasheet containing a VBA instance of a recordset. If the source of your recordset is strQSL, you could however create a table with your results, and open that one, or more elegantly, create queryDef and open it:
Sub ShowQd(strQdName As String, strSql As String)
'creates queryDef and display it in a datasheet'
Dim qd As DAO.QueryDef
Set qd = CurrentDb.CreateQueryDef(strQdName)
With qd
.ReturnsRecords = True
.SQL = strSql
End With
DoCmd.OpenQuery strQdName
End Sub
If you focus on displaying things, you could also put a ListBox in a form, set its Number of columns to the number of fields returned by your query (qd.Fields.Count), and set your strSql as the RowSource of the ListBox. AND... if you put all your related code in that form, you now have a form that you can import in any db to quickly display what you want :)
Good luck !