Using access to refer to objects within access - ms-access

I have a basic table in access with several populated fields. I would like to explore if there is a way, preferably through the GUI (or maybe through SQL), to add a field containing the name of the table itself. I see only the following data formats for fields: Short text, Long text, number, Date/time, Currency, Autonumber, Yes/No, OLE Object, Hyperlink, Attachment and Calculated. There is nothing pertaining to data object parameters themselves such as table, field or query names or parameters...

You can access the meta data of the database via VBA (Visual Basic for Applications) macros.
For example, this can show all table names:
Option Compare Database
Public Sub Test()
Dim database As DAO.database
Dim tableDef As DAO.tableDef
Set database = CurrentDb
For Each tableDef In database.TableDefs
MsgBox tableDef.Name
Next
End Sub

Related

VBA Alternatives to workbook.open to pull data from a single cell

I wanted to find out if anyone can recommend an alternative way to query data in an excel file from an MS Access module.
If I have a data organised in a typical "Table" format e.g rows and columns with headers, then I have been connecting to the workbook using a DAO connection as below
Dim db as DAO.Database
Dim rsUsers as DAO.Recordset
Set db = OpenDatabase("C:\SaleLog.xls", False, True, "Excel 8.0;HDR=Yes;")
Set rsUsers = db.OpenRecordset("SELECT userID FROM [Sales$]")
I find this preferable to using
Dim xlApp As Excel.Application
Set xlApp = CreateObject("Excel.Application")
xlApp.Workbooks.Open "C:\SaleLog.xls", True, False
As it does not physically open an instance of an excel session and therefore runs a bit more quickly.
The only problem is when the data is not laid out like a table (e.g if I just wanted to get the value of 1 particular cell).
Does anyone know if there is a way to check the value of a cell in VBA without using Workbook.Open?
There may be a simpler way to achieve this but I have found 3 methods which can be used to pull data into MS Access from a single cell in a closed Excel workbook relatively efficiently (Many thanks to John Muggins for his help with this).
Firstly, the workbooks.open method can be used and will run more quickly if you set the read-only parameter to true (I'm unsure if this technically 'Opens' the workbook but it definitely seems to run more quickly while read-only). This requires you to set a reference to the Excel library.
Dim xlApp As Excel.Application
Dim src As Workbook
Set xlApp = CreateObject("Excel.Application")
Set src = xlApp.Workbooks.Open "C:\SaleLog.xls", True, True
You can then get data from specific cells using normal Excel VBA syntax like so
strUser = src.Worksheets("Sales").Range("B8")
src.Close False 'false doesn't save changes
Set src = Nothing
Another method is to use the DoCmd.Transferspreadsheet method to link or import a single cell, in this case you would need to set the HasFieldNames parameter to false as shown
path = "C:\SaleLog.xls"
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, "tblTemp", path, False, "Sales!B8:B8"
This will create a table with a single field called F1. You can get the value stored in this table using a DLookup or a recordset (You may then wish to delete the temp table e.g. DoCmd.DeleteObject acTable, "tblTemp").
Lastly you can use a DAO connection as mentioned in the original question. You can specify a specific cell like so
Dim db as DAO.Database
Dim rsUsers as DAO.Recordset
Set db = OpenDatabase("C:\SaleLog.xls", False, True, "Excel 8.0;HDR=Yes;")
Set rsUsers = db.OpenRecordset("SELECT * FROM [Sales$B8:B8]")
Again this will create a recordset with a single field called F1. You can get the value of this field by using rsUsers.Fields("F1")
Each of the above methods can be (and usually are) used to pull data from an entire worksheet or range of cells but for the purpose of this question I wanted to show how they can be used to pull data from a single cell. I haven't tested them for efficiency although I doubt there is much difference in speed between them so probably best to go with the method that you find simplest.
If anyone knows how to tweak any of these methods to make them more efficient or has another approach altogether please feel free to comment or add a new answer :)

Why does my database object show no Recordsets?

Why does my database object show no Recordsets? And why does it not show a Connection? The key bit of code is:
Public Sub PrintRecords()
Dim dbCurr As DAO.Database
Set dbCurr = CurrentDb
Dim rsCourses as Recordset
Set rsCourses = CurrentDb.OpenRecordset(“Courses”)
End Sub
Here is my screenshot, where the database has tables (upper left), but the CurrentDB object has a name but no Recordsets (in the locals window below.)
For what it’s worth, this is in Access 2013, following this tutorial to manipulate the database, stopping on the error “Run-time error ‘3078’: The Microsoft Access database engine cannot find the input table or query”. But the problem seems to be deeper than that.
You have typographic quotes in there, use straight ones "".
And use your assigned database object:
Set rsCourses = dbCurr.OpenRecordset("Courses")
And please don't post only screenshots of code, copy & paste the code itself as text.

MS Access 2007: Runtime error 64224: Method 'Collect' of object 'recordset2' failed

I have been searching high and low for a workaround for this error, but since I haven't, I now turn to you for help. I am not (at all) an experienced programmer, so I hope this is not too basic a question to ask here, and that others can still benefit.
I am trying to set up a form, where I can register when one of our employees lends some stuff for a given period of time. I.e. from 21-12-2015 to 10-01-2016 employee n.n. lends a laptop. The form has two unbound textboxes TxtFraDato and TxtTilDato for the dates (from and to), and two unbound listboxes containing the name of the employee and the 'stuff' to be lend. The listboxes get their data from the tables:
Medarbejder (The employee):
- Navn: text (Primary key)
Materiale:
- Id: number (Primary key)
- ModelType: Text
I know that having a table like my Medarbejder-table is not at all pretty, and I have a fealing that this could be causing the problem, but this table is linked to a .txt-file created from a bat-file, and I have not been able to figure out, if there is another way to create such a link, that will give me a chance to give the table another primary key.
Finally, I have a button that on-click should save the record to the table "Udlaan":
Id: number (Primary key)
FraDato: date
TilDato: date
Medarbejder: text (lookup column)
Materiale: number (lookup column)
However, when I click the button, I get the runtime error 64224: Method 'Collect' of object 'recordset2' failed.
Private Sub btnSaveUdlaan_Click()
Dim db As Database
Dim rs As Recordset
Dim FraDato As Date
Dim TilDato As Date
Dim Medarbejder As String
Dim Model As Integer
Set db = CurrentDb
Set rs = db.OpenRecordset("Udlaan")
FraDato = Me.TxtFraDato.Value
TilDato = Me.TxtTilDato.Value
Medarbejder = Me.MAList.Column(0)
Model = Me.ModelList.Column(0)
AddUdlaan rs, FraDato, TilDato, Medarbejder, Model
rs.Close
db.Close
End Sub
The AddUdlaan:
Private Sub AddUdlaan(rs As Recordset, FraDato As Date, _
TilDato As Date, Medarbejder As String, Model As Integer)
' Adds a new record to a Recordset using the data passed
' by the calling procedure.
With rs
.AddNew
!FraDato = FraDato
!TilDato = TilDato
**!Medarbejder** = Medarbejder ß The debugger is pointing to this field
!Materiale = Model
.Update
End With
End Sub
Perhaps this is not at all the right way to solve by problem, so any help on this is much appreciated. But as it is, I would also be happy to lean something from the encounter with this error.
This is because the lookup field is a recordset of the recordset. Only Recordset2 can handle these.
Thus, what you should assign is the (hidden) Id of Medarbejder, in pseudo code:
!Medarbejder = <Id of recordset Medarbejder>
This can be done but - as already mentioned by #Parfait - do yourself a favour and get rid of the lookup fields. How "smart" they may seem, they will cause you nothing than trouble in the future.
As a start, change table Medarbejder to have an AutoNumber Id as the primary key.

Store records in an instance of a class to make available anywhere in project throughout the life of the program

I have a form with a combo box that I populate with records from a access db (I use linked tables). What I'd like to do is store the records in an instance of a class throughout the life of the program rather than querying the table each time the user selects the combo box. Right now I'm calling a funtion from a private sub, the function returns the DAO recordset data which is what I want but the question I have is, how do I pass the data from the function recordset to a public DAO.Recordset, assuming if this was possible it would hold the recordset data throughout the life of the running program. When I run the code and it finishes Public Rs() in the Watch output window says; Recordset(0 to -1) and No Variables, I'm not sure how to correct this.
Here's my code:
Private Sub cmdGetRecordset_Click()
Dim strDescription As String
Dim strModel As String
Dim rst As DAO.Recordset
Set rst = getdevices()
Do While Not rst.EOF
strDescripton = rst!DESC
strModel = rst!MODEL
Debug.Print strDescription & " " & strModel
rst.MoveNext
Loop
'rst.Close'
'Set rst = Nothing'
End Sub
''''''
Option Compare Database
Public Rs() As DAO.Recordset
Function getdevices() As DAO.Recordset
Dim Rs As Object
Dim CurDatabase As Object
connectDatabase
Set CurDatabase = CurrentDb
Set Rs = CurDatabase.OpenRecordset("SELECT * FROM tblCDA")
Set getdevices = Rs
closeDatabase
End Function
I don't fully understand your goal to be honest. Depending what you're trying to do there are a number of ways to tackle the issue.
1) Are you just pre-populating controls when the form loads?
Either run a series of queries in the Form_Load event each time the form is loaded and pass the results to each combobox as it's source OR create a temporary table with the values when the database is opened and query the temp table.
2) Are you trying to capture a persistent state of what the user selected when moving between forms or reports?
Use a temp table or dynamic array to capture the user selections (values of the comboboxes) and query the table or iterate through the array when referencing a value somewhere else.
3)Are you trying to dynamically change combobox values based on user selections?
Sadly I think having to requery the source data is the only option here. You could get all of the data from various tables and store it in memory using arrays and then iterate through the arrays as needed to change the combobox values but that would be a substantial memory footprint depending on the data.

Preventing MSAccess linked tables from having a dbo_ prefix?

Is there a way to prevent MSAccess from concatenating 'dbo_' as the prefix to tables linked from a SQL Server db?
No. Microsoft Access' native naming convention process will force the name <schema>_<ObjectName> as your default table name. There are no controls or settings which will allow you to change that, except in code. It's rather complex and goes beyond the scope of this question, but if you do the linking in code (which I do) then you can store the TableAlias and create the linked table name that way.
You can write your table definition in the code to attach the table as below where
strTableAlias is your display name in Access
strTableName is your table name with schema <schema>.<ObjectName>.
Dim td As DAO.TableDef
set td = CurrentDb.CreateTableDef(strTableAlias, dbAttachSavePassword, _
strTableName, strConnectionStr)
CurrentDb.TableDefs.Append td
If you don't do the linking in code as mentioned by Johnny you can rename the links with this VBA code:
Public Sub Remove_DBO_Prefix()
Dim obj As AccessObject
Dim dbs As Object
Set dbs = Application.CurrentData
'Search for open AccessObject objects in AllTables collection.
For Each obj In dbs.AllTables
'If found, remove prefix
If Left(obj.Name, 4) = "dbo_" Then
DoCmd.Rename Mid(obj.Name, 5), acTable, obj.Name
End If
Next obj
End Sub
Courtesy https://www.microsoftaccessexpert.com/Microsoft-Access-Code-RemoveDBOPrefix.aspx
If you're doing this with the idea of using queries that you generate in Access outside of Access remember that Access creates it's own sql dialect so you may need to convert double quotes to single and # to ' among other things.