Learning MS Access - ms-access

i am new to ms-access, and i have started to look at code that works. unfortunately it is completely uncommented.
Private Sub OKbut_Click()
Dim dt As Date
dt = Now()
Set rstOrder = New ADODB.Recordset
rstOrder.Open "tblUsers", CurrentProject.Connection, adOpenStatic, adLockOptimistic
If rstOrder.Supports(adAddNew) Then
With rstOrder
.AddNew
.Fields("title") = title
.Fields("first") = first
.Fields("last") = last
.Fields("gender") = gender
.Fields("date_submitted") = dt
.Update
End With
End If
rstOrder.Close
Set rstOrder = Nothing
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT id FROM tblUsers WHERE date_submitted=#" & dt & "#")
duser = rs.Fields("id")
rs.Close
Set rs = Nothing
Do While Not user_defined(duser)
DoCmd.OpenForm "define_user_frm", , , , , acDialog
Loop
'Forms(0).user_lst.RowSource = "select * from users where id=" & duser
Me.SetFocus
DoCmd.Close
End Sub
what does the function Now() do?
ADODB.Recordset is just a way to connect to a table?
adOpenStatic, adLockOptimistic what are these?
why are we checking this: if rstOrder.Supports(adAddNew) ?
why do we need to do this: Set rstOrder = Nothing?
what does this do:? Do While Not user_defined(duser)
DoCmd.OpenForm "define_user_frm", , , , , acDialog
Loop

Approaching existing code like this isn't the best way to learn to program. There are plenty of online tutorials that will help you get started and progress in a linear manner. The other advice I'd give is to try things out for yourself. Write a small method that contains "MsgBox Now()" and run it to see what happens. Then run it a couple of seconds later.
I can't over-recommend finding a beginners tutorial.
However that said . . .
Now - returns the computers system date and time, at the moment it's called
Yes - Among other things.
Hints to the query engine. Open Static says you don't want to see rows added after the record set is retrieved, optimistic locking tells the engine which record locking option to use (the other is pessemistic)
Checking this because you can't add records to all resordsets (e.g. complex queries joining several tables)
Not stricly necessary, but better for memory management, otherwise the recordset object (and all associated resources - memory, handles etc) wouldn't be disposed until the end of the method.
Opens an ms access form until the condition "user_defined(duser)" returns true
Hope this helps.

what does the function Now() do?
Now() returns the current system date and time
ADODB.Recordset is just a way to connect to a table?
Yes - more importantly, it is a good way to iterate through records of a dataset individually. Like a cursor in SQL Server. You could do something like
While not rstOrder.EOF
'a.k.a. while there are still records left to iterate through
'Do something
End While
adOpenStatic, adLockOptimistic what are these?
From http://www.dotnetspider.com/forum/16958-In-VB-What-difference-between-adopendynamic.aspx
adOpenForwardOnly - this is the default cursor if no other is specified. This cursor allows only forward movement through a recordset
adOpenKeyset - this cursor supports forwards as well as backwards navigation. It also allows you to update a recordset and all changes will be reflected in other users recordsets. The cursor also supports bookmarking
adOpenDynamic - this cursor supports forward and backward navigation but bookmarks may not be supported (ie Access). Any changes made to data are immediately visible with no need to resynchronise the cursor with the database
adOpenStatic - this cursor uses a static copy of data from the database and therefore no changes to the data are visible and supports forward and backward navigation
why are we checking this: if rstOrder.Supports(adAddNew) ?
It's a way of writing more robust code - i.e. before attempting to add a new record, first check whether the recordset supports the addition of new records.
why do we need to do this: Set rstOrder = Nothing?
Frees the recordset from memory. Not absolutely necessary but again, makes for more robust code.
what does this do:? Do While Not user_defined(duser) DoCmd.OpenForm "define_user_frm", , , , , acDialog Loop
Checks for existence of a user and if it doesn't exist, it opens a form called "define_user_frm" which I assume allows for creating a new user.

what does the function Now() do?
Place the cursor on the word Now in your subroutine, then press the F1 key. Is Access' help not helpful for answering your question?
I'm trying to suggest it should be quicker for you to use the built-in Help feature for a question like that, instead of posting to Stack Overflow and waiting for responses. Then you only need post the questions that Help doesn't answer adequately for you.

I'm very rusty with VB/Access but:
1) Now returns the current date and time
2) Recordset is a set of records - from memory doesn't have to be a table, could be a query.
3) Those are flags to indicate how the table (as it is a table in this case) should be accessed can't remember static but the Lock says that we're going to use optimistic locking i.e. we will basically assume that the record won't be changed by anyone else.
4) Because you can open recordsets in a number of different ways - so it may well be the case that you have a read-only set of data. In the context of the example its notionally redundant but in terms of good practice its a reasonable bit of defensive programming.
5) Probably don't but again its sensible defensive programming and it ensures that all resources associated with the recordset are released. rstOrder is coming from somewhere external to the sub so not leaving it in an open state is sensible.
6) The loop repeats until the function user_defined(duser) returns true. duser being the - erk, that looks horrid - ID returned by the query but that doesn't look safe. DoCmd.Open form is popping up the "define_user_form" as a dialog so... if the user doesn't exist then fire up the dialog to define the user then check again that the user has been defined. That's also a bit questionable (although of course without a bit more context its hard to tell).
Basically VBA in Access is mostly VB6 but with sufficient differences to drive one slightly mad... there's a whole pile of stuff that you can assume to exist in access that you have to be rather more explicit about in VB.OLD

what does the function Now() do?
Returns a Variant (Date) specifying the current date and time according your computer's system date and time.
ADODB.Recordset is just a way to connect to a table?
The ADO Recordset object is used to hold a set of records from a database table. A Recordset object consist of records and columns (fields). It can be used to open tables, queries, custom SQL statements, etc.
adOpenStatic, adLockOptimistic what are these?
adOpenStatic: Provides a static copy of the records (you can't see additions, changes or deletions by other users), but all types of movement are enabled (e.g. .moveNext, .MoveFirst, .moveLast, etc).
adLockOptimistic: Record locking is performed only when you call the Update method.
why are we checking this: if rstOrder.Supports(adAddNew) ?
Checking whether the recordset allows new records to be added.
why do we need to do this: Set rstOrder = Nothing?
When you're completely finished with rstOrder, setting it equal to Nothing removes it from memory. You can think of it as a simple version of garbage collection.
what does this do:? Do While Not user_defined(duser) DoCmd.OpenForm
"define_user_frm", , , , , acDialog
Loop
Assuming user_defined() is a custom function, it loops through the record just added and opens a form that allows you to define the user.
Reference:
http://www.w3schools.com/ado/ado_ref_recordset.asp

what does the function Now() do? - Creates a DateTime for the current date and time the function is being run.
ADODB.Recordset is just a way to connect to a table? This is an object or saying that rstOrder is not a ABDODM.Recordset with a method to open the connection to the DB.
why do we need to do this: Set rstOrder = Nothing? - This is cleaning up the connection so that the computer does not keep the memory and for rstOrder. Other wise after running your computer might slow down or have less memory.
what does this do:? Do While Not user_defined(duser) DoCmd.OpenForm "define_user_frm", , , , , acDialog Loop - This is a loop that will be repeated and will Open an Access form as long as user_defined is not duser.

Now() just returns the current date and time
ADODB.Recordset is in this instance being used as a way to connect to a table. It is generally used to connect to an external (read SQL) dataset. And can be populated from a query or stored procedure. Similar to the access builtin Recordset
These are switches used to set certain options in the connection. I would recommend reading over the MSDN documentation.
Not every recordset supports adding records (such as that returned from a query) this simply checks that before you attempt to add a record. It is part of writing code that won't throw errors.
This is simply a way to clean up the memory. As far as I know VBA is garbage collected but if you have a large recordset this can free up some memory sooner.
I'm not sure about this here. but it looks like it's calling a user defined function and it returns false it opens a form.

Related

How to directly update a record in a database from a form number (Access 2007)

I have a job-tracking system, and there is a query that returns results of all jobs that are overdue.
I have a form that displays each of these jobs one-by-one, and has two buttons (Job has been completed, and Job not completed). Not completed simply shows the next record.
I cannot find a way to get access to the current record to update it's contents if the "Has been Completed" button is pressed, the closest I can get is the long number which represents the records position in the form.
The VBA to get the index of the record in the form is as follows.
Sub Jobcompleted(frm As Form)
Dim curr_rec_num As Long
curr_rec_num = frm.CurrentRecord
End Sub
This is my first shot at VBA, and after an hour of searching I cannot find anything to solve my problem.
Am I going about this the entirely wrong way? Working in Microsoft Access 2007
Further Info All tables are normalized
Vehicle Table: Contains vehicle_id(pk), as well as rego and model etc
Job Table: Contains job_id(pk), vehicle_id(fk) and other info about what needs to happen, as well as the next occurance date, days between each occurance of the job (all jobs repeat) and other info
Job History Table: Contains job_history_id(pk), job_id(fk), date completed and comments
When the job completed button is pressed, it should create a new entry in the job history table with the current date, any comments and the job id
This is the script I am trying to get working
Private Sub Command29_Click()
Dim strSQL1 As String
Dim strSQL2 As String
Set Rs = CurrentRs
Set db = CurrentDb
strSQL1 = "INSERT INTO completed_jobs(JOB_ID, DATE_COMPLETED, COMMENTS) VALUES " & Rs!job.ID & ", " & Date
db.Execute strSQL1, dbFailOnError
strSQL2 = "UPDATE job SET JOB_NEXT_OCCURANCE = JOB_NEXT_OCCURANCE+JOB_RECURRANCE_RATE WHERE job.ID = Rs!job.ID"
db.Execute strSQL2, dbFailOnError
End Sub
Note: Line Set Rs = CurrentRs is completely incorrect, I believe this is what I need to figure out? This is called on button-press
I am posting an image which shows the form (non-continuous).
#HansUp, I get what you are saying, but I dont quite think it's applicable (I did not provide enough information first time around for you to understand I think)
#sarh I believe this Recordset that you are talking about is what I need, however I cannot figure out how to use it, any hints?
#Matt I am 90% sure I am using a bound form (Like I said, new to Access, been looking at everything people have suggested and learning as I go). There is of course an ID for the job (Just not shown, no need to be visible), but how would I access this to perform an operation on it? SQL I can do, integrating with Access/VBA I am new at
As I understand your situation, your form is data-bound bound (you can get record index), so - your form already located on this record. If you need to update some field of underlying dataset, you can write something like
Me!SomeField = ...
DoCmd.RunCommand acCmdSaveRecord
If your form has control bound to "SomeField", then the form will be updated automatically.
If this will not help, you can look to a couple of another directions:
1) Update records using SQL code. For example, you have ID of record that should be updated in the form data set, so you can write something like:
Call CurrentDB.Execute( _
"UPDATE SomeTable SET SomeField = SomeValue WHERE SomeTableID = " & Me!SomeTableID, dbSeeChanges)
2) You can look at the Bookmark property - both Recordset and Form has this property, it describes the record position. So you can write something like this (not the best example, but can help you to get an idea):
Dim Rs as Recordset
Set Rs = Me.RecordsetClone 'make a reference copy of the form recordset
Rs.Bookmark = Me.Bookmark 'locate this recordset to the form current record
Consider a simpler approach. I doubt you need to be concerned with the form's CurrentRecord property. And I don't see why you should need a command button for "Has been Completed" and another for "Has not been Completed".
Add a "Yes/No" data type field to the table which is used by your form's record source. Set it's default value property to 0, which represents False or No. Call it "completion_status". Create a new form using that record source. Then your form can have a check box control for completion_status.
Newly added records will have False/No as completion_status --- the check box will appear unchecked. The completion_status for other records in the forms can be toggled between Yes (checked) and No (unchecked) using the check box control.

VBA: Faster Recordset connection

I have the following code to access a recordset from SQL Server 2008.
Dim cnn As Object
Dim rs As Object
Dim strSQL As String
Set cnn = CreateObject("ADODB.Connection") 'ADO Connection
cnn.ConnectionString = "DRIVER=SQL Server;SERVER=" & dbServer & ";" & _
"Trusted_Connection=Yes;DATABASE=" & dbDatabase
cnn.Open
strSQL = "Select * from mytable"
Set rs = CreateObject("ADODB.Recordset")
rs.Open strSQL, cnn, adOpenKeyset, adLockOptimistic
On rs.Open it takes from one second to three seconds. Is there a faster way to access the recordset?
The variables dbServer and dbDatabase are defined in a module as a constant string.
Assuming mytable is a base table rather than a VIEW, the SQL is as trivial as is possible i.e. there is no scope for optimization.
If you are bringing the entire table contents over to do further RBAR ("row by agonizing row" = pejorative) processing in VBA code then consider rewriting your procedural logic as a "set-based" paradigm using more complex SQL e.g. adding a WHERE clause would be a good start.
If you do need to bring the entire table contents over and the table is relatively large then it will take a relatively long time. Again, there is no scope in your code for optimization.
You are currently performing a synchronous fetch, meaning execution of your VBA code will wait at the rs.Open line until the fetch is complete. The effect for your users will be that the application appears frozen, possibly crashed.
An alternative approach is to use an asynchronous fetch. Relocate your code class module, declare the recordset as WIthEvents (needs to be relocated to module level) and specify the adAsyncFetch option on the recordset before opening it (you may need to alter your approach slightly to accommodate this). This will cause execution to continue past the rs.Open as soon as the request has been sent (so you will need to relocate any code that closes the connection/recordset to a separate sub procedure). You can then use the FetchProgress and FetchComplete events to give feedback to your end users in the application. For more details, see this MSDN article.
I've never been able to get any meaningful 'percent completed' style progress out of the Access engine/provider. But you can at least show a marquee style progress bar to users to reassure them that data is being fetched. They will be able to still interact with the UI (e.g. click on controls) and be reassured that the application has not crashed.
You have 2 operations:
open connection
open recordset using that connection
Where is the delay?
You could add line for Debug.Print Now() immediately before the two open statements, and another after the recordset open.
If opening the connection is the bottleneck, see whether using the native client provider speeds things up. www.connectionstrings.com: SQL Server Native Client 10.0 OLE DB Provider
If opening the recordset is the bottleneck, you have several options. If you don't actually need a dynamic/editable recordset, use adOpenStatic instead of adOpenKeyset. You could try CommandTypeEnum adCmdTable to open the table instead of using a SELECT statement which returns everything. Or with the SELECT statement, include an explicit field list instead of "*" ... because "*" requires an extra trip to the server to figure out which fields it represents. (Although that's probably not a big bottleneck.) And you could also try a WHERE clause to select a single record based on a primary key value.

MS ACCESS---Refresh all via VBA

How do I refresh all via vba?
I want to refresh all open forms...
The reason #CodeSlave's answer probably didn't do what you needed, is that the VBA method you need is requery, not refresh. Refresh will display changes made to existing records, but only requery will display newly added records.
Here is a more concise version of the code (put this in a Module, so that you can call it from any form):
Public Sub RequeryOpenForms()
Dim f as Form
For Each f In Access.Forms
f.Requery
Next
End Sub
NOTE: Unfortunately, requery has the side-effect of losing the currently selected record. This can be particularly frustrating for a use if there are a long list of records, since they may have to scroll down a long way to find the record that they were previously looking at.
What about something like this?
Sub AllForms()
Dim obj As AccessObject
dim dbs As Object
Dim i As Integer
dim intFormCount as Integer
Set dbs = Application.CurrentProject
intFormCount = dbs.AllForms.Count - 1
For i = 0 To intFormCount
If dbs.AllForms(i).isloaded = True Then
dbs.AllForms(i).refresh
End If
Next
End Sub
In a comment above you say:
I'd like the new record just added to
the table to be available in that form
when I go back to it
You might want to examine the Activate event. But it bothers me to requery the form unless you know for a fact that records have been added. I expect that if I needed to do this (I've never done so, actually -- my users know about Shift-F9 where it's relevant, but most of them never need it), I'd use the OnActivate event and check the current count of records and only requery the form if the count doesn't match the current recordset.
But again, I consider it a fairly exotic thing to do. In general, it's probably an architectural error to have too many forms sitting around with an open recordset that you depart from and then come back to. They should probably be entirely closed instead of being left open when you're away from them. This reduces the number of table handles, as well as the number of locks held on the back end database, both of which can be problems if not properly managed.

How to populate a ComboBox with a Recordset using VBA

There is some literature available at expert's exchange and at teck republic about using the combobox.recordset property to populate a combobox in an Access form.
These controls are usually populated with a "SELECT *" string in the 'rowsource' properties of the control, referencing a table or query available on the client's side of the app. When I need to display server's side data in a combobox, I create a temporary local table and import requested records. This is time consuming, specially with large tables.
Being able to use a recordset to populate a combobox control would allow the user to directly display data from the server's side.
Inspired by the 2 previous examples, I wrote some code as follow:
Dim rsPersonne as ADODB.recordset
Set rsPersonne = New ADODB.Recordset
Set rsPersonne.ActiveConnection = connexionActive
rsPersonne.CursorType = adOpenDynamic
rsPersonne.LockType = adLockPessimistic
rsPersonne.CursorLocation = adUseClient
rsPersonne.Open "SELECT id_Personne, nomPersonne FROM Tbl_Personne"
fc().Controls("id_Personne").Recordset = rsPersonne
Where:
connexionActive: is my permanent ADO connection to my database server
fc(): is my current/active form
controls("id_Personne"): is the
combobox control to populate with
company's staff list
Access version in 2003
Unfortunately, it doesn't work!
In debug mode, I am able to check that the recordset is properly created, with requested columns and data, and properly associated to the combobox control. Unfortunately, when I display the form, I keep getting an empty combobox, with no records in it! Any help is highly appreciated.
EDIT:
This recordset property is indeed available for the specific combobox object, not for the standard control object, and I was very surprised to discover it a few days ago.
I have already tried to use combobox's callback function, or to populate a list with the "addItem" method of the combobox,. All of these are time consuming.
To set a control that accepts a rowsource to a recordset you do the following:
Set recordset = currentDb.OpenRecordset("SELECT * FROM TABLE", dbOpenSnapshot)
Set control.recordset = recordset
Works with DAO Recordsets for sure, I haven't tried ADO recordsets because I don't have any real reason to use them.
When done this way, a simple requery will not work to refresh the data, you must do a repeat of the set statement.
As was said, you have to get the RowSourceType to "Table/Query" (or "Table/RequĂȘte" if in french) in order to show query results in the combobox.
Your memory problems arise from opening the recordset (rsPersonne) without closing it. You should close them when closing/unloading the form (but then again you would have scope problems since the recordset is declared in the function and not in the form).
You could also try to create and save a query with Access's built-in query creator and plug that same query in the RowSource of your combobox. That way the query is validated and compiled within Access.
I found the trick ... the "rowSourceType" property of the combobox control has to be set to "Table/Query". Display is now ok, but I have now another issue with memory. Since I use these ADO recordsets on my forms, memory usage of Access is increasing each time I browse a form. Memory is not freed either by stopping the browsing or closing the form, making MS Access unstable and regularly freezing. I will open a question if I cannot solve this issue
good method with using the Recordset property, thanks for that hint!
Patrick, the method you shown on your page has a big disadvantage (I tried that too on my own): The value list can only be 32 KB, if you exceed this limit the function will throw an error.
The callback method has the big disadvantage that it is very slow and it is called once for every entry which makes it unuseable for a longer list.
Using the recordset method works very well. I needed this because my SQL string was longer than 32 KB (lot of index values for WHERE ID IN(x,x,x,x,x...)).
Here's a simple function which uses this idea to set a recordset to the combobox:
' Fills a combobox with the result of a recordset.
'
' Works with any length of recordset results (up to 10000 in ADP)
' Useful if strSQL is longer than 32767 characters
'
' Author: Christian Coppes
' Date: 16.09.2009
'
Public Sub fnADOComboboxSetRS(cmb As ComboBox, strSQL As String)
Dim rs As ADODB.Recordset
Dim lngCount As Long
On Error GoTo fnADOComboboxSetRS_Error
Set rs = fnADOSelectCommon(strSQL, adLockReadOnly, adOpenForwardOnly)
If Not rs Is Nothing Then
If Not (rs.EOF And rs.BOF) Then
Set cmb.Recordset = rs
' enforces the combobox to load completely
lngCount = cmb.ListCount
End If
End If
fnADOComboboxSetRS_Exit:
If Not rs Is Nothing Then
If rs.State = adStateOpen Then rs.Close
Set rs = Nothing
End If
Exit Sub
fnADOComboboxSetRS_Error:
Select Case Err
Case Else
fnErr "modODBC->fnADOComboboxSetRS", True
Resume fnADOComboboxSetRS_Exit
End Select
End Sub
(The function fnADOSelectCommon opens an ADO recordset and gives it back. The function fnErr shows a message box with the error, if there was one.)
As this function closes the opened recordset there should be no problem with the memory. I tested it and didn't saw any increasing of memory which wasn't released after closing the form with the comboboxes.
In the Unload Event of the form you can additionaly use a "Set rs=Me.Comboboxname.Recordset" and then close it. This should not be necessary regarding memory, but it may be better to free up open connections (if used with a backend database server).
Cheers,
Christian
A combo box control does not have a recordset property. It does have a RowSource property but Access is expecting a SQL string in there.
You can change the RowSourceType to the name of a user defined "callback" function. Access help will give you more information including sample code by positioning yourself on the RowSourceType and pressing F1. I use this type of function when I want to give the users a list of available reports, drive letters, or other data that is not available via a SQL query.
I don't understand what you mean by your third paragraph with respect to using data directly from the server side. Or rather I don't understand what the problem is with using standard queries.
In MS Access, it's ok, but in VB, you may use something like this using adodc (Jet 4.0):
Private sub Form1_Load()
with Adodc1
.commandtype = adcmdtext
.recordsource = "Select * from courses"
.refresh
while not .recordset.eof
combo1.additem = .recordset.coursecode
.recordset.movenext
wend
end with
End Sub

Is there a way to execute VBA code when specific tables and fields in a Microsoft Access database are updated?

I have a program that uses a Microsoft Access database for its back-end. I need to have some VBA code (that calls a web service) execute whenever specific tables/fields are updated by the program. I see this working just like a trigger in SQL Server.
Is it possible to monitor for and act upon changes like this in Access?
Update
The program in question does not run inside of Access (i.e. not a VBA app), it simply uses an MDB file as its back-end storage. Unfortunately I don't have access to the program's code as it is a closed third party application.
This question is old, but the answers are no longer correct. Access 2010 added data macro events that can be run when data is inserted, updated or deleted. The following events are available while using either the table datasheet view or table design view (events are attached directly to table and not through the form macro button):
After Delete Macro Event
After Insert Macro Event
After Update Macro Event
Before Change Macro Event
Before Delete Macro Event
More information is located here:
https://msdn.microsoft.com/en-us/library/office/dn124692.aspx
https://support.office.com/en-us/article/Create-a-data-macro-b1b94bca-4f17-47ad-a66d-f296ef834200
Access the GUI environment vs Jet the database format are separate things.
If you are using an Access database as a backend - it's just the JET functionality you can work with. Access the GUI (which includes VBA) runs on the client machine and there is no automated trigger functionality.
If your program is the only program using the Access file, then it should know when a table is being updated and execute some code in place of a trigger.
Otherwise, you need another application/service running all the time that is checking the access file tables for updates (maybe you have some update_date type of field on your tables?).
When an Access database file gets written to, it's date/time stamp changes. I suppose you could try using a file monitor to detect changes to the file, and then examine the file to see what has changed.
It would help if the Access database has LastModified date/time columns in the tables.
If you are using Jet (i.e. the data is stored in an MDB file back end) then the only places you can run code would be in the After Update Event in a Form. The problem here of course is if the data is changed without using the form then the event will not fire.
If you are using MS Access 2003 then to run a Web Service you can download the Microsoft Office 2003 Web Services Toolkit Click Here to download
If you are stuck in VBA it gets a little rough. One way to go would be to have a form with timer in it (you could have it open invisibly. The timer could check the table, say once a minute (or whatever interval seems suitable) for changes in record count, and verify the table still exists. (code below)
But personally this isn't what I would recommend that you do. Access is notorious for corruption. When used as a simple back end you are fairly safe most of the time, but to have it running a monitor, means the file is always open. This is basically playing Russian Roulette with your database. At minimum I would link to your database from another Access file and monitor the linked tables, that way if your monitor crashes, you don't take the production DB with you. Finally, make sure that you don't query too often, as I'd hate to see you be the sole cause of the website timing out:)
Option Explicit
Private m_lngLstRcrdCnt_c As Long
Private Sub Form_Open(Cancel As Integer)
Const lngOneMinute_c As Long = 60000
Me.TimerInterval = lngOneMinute_c
End Sub
Private Sub Form_Timer()
Const strTblName_c As String = "Foo"
Const strKey_c As String = "MyField1"
Dim rs As DAO.Recordset
Dim lngRcrdCnt As Long
If TableExists(strTblName_c) Then
Set rs = CurrentDb.OpenRecordset("SELECT Count(" & strKey_c & ") FROM " & strTblName_c & ";", dbOpenSnapshot)
If Not rs.EOF Then lngRcrdCnt = Nz(rs.Fields(0&).Value, 0&)
rs.Close
If lngRcrdCnt <> m_lngLstRcrdCnt_c Then
m_lngLstRcrdCnt_c = lngRcrdCnt
'Number of records changed, do something.
End If
Else
'Table is deleted, do something.
m_lngLstRcrdCnt_c = -1
End If
End Sub
Private Function TableExists(ByVal name As String) As Boolean
Dim tdf As DAO.TableDef
On Error Resume Next
Set tdf = CurrentDb.TableDefs(name)
If LenB(tdf.name) Then 'Cheap way to catch broken links.
Set SafeGetTable = tdf
End If
End Function