MS Access create forms for distinct field value in VBA - vba

I have a VBA script and I need to create forms based on distinct LocationIDs in a table. So for every row with LocationID = 1 create a form with the name of that location represented in the title of the form, "formLocation1". Then for each LocationID = 2, create another form with the name of that one in the title, "formLocation2", etc. What is the best way to do this using DoCmd.OpenForm"" in the VBA script?

You can try something like this.
Loop through a recordset, and create a form for each LocationID using the CreateForm() method. You can then set the Form's .Caption property to "formLocation(LocationID)".
(Change T to the name of your table).
Public Sub CreateForms()
On Error GoTo ex
Dim rs As DAO.Recordset
Set rs = CurrentDb().OpenRecordset("SELECT DISTINCT LocationID FROM T ORDER BY LocationID;", dbOpenSnapshot)
With rs
If .EOF Then GoTo out
.MoveLast
.MoveFirst
End With
Dim frm As Access.Form, i As Integer
For i = 1 To rs.RecordCount
Set frm = CreateForm()
frm.Caption = "formLocation" & rs![LocationID]
DoCmd.Close acForm, frm.Name, acSaveYes
Set frm = Nothing
rs.MoveNext
Next i
out:
On Error Resume Next
rs.Close
Set rs = Nothing
On Error GoTo 0
Exit Sub
ex:
MsgBox Err.Description, vbCritical
Resume out
End Sub

Related

How to navigate to previous records depending on textbox

I have a button on my form whenever I click on it, it creates several records including a column named: [Aantal], if aantal says 5, it will create 5 records. This column is also as a textbox named [Aantal] on the form.
After the records are created it goes to the last record as shown here:
DoCmd.GoToRecord acDataForm, "GeleidelijstForm", acLast
Is it possible to make it navigate to the first record of those 5 created?
So not the very first record in the table, but the first of those just created. For example if [Aantal] is 5, make it go back 4 records, that way it will be on the first of the 5 records it just created.
Edit:
I have something like this that goes to the latest record, now I want it to go to the first record instead:
pgn = Me.CurrentRecord
t1 = Nz(Me.Aantal, 1)
If t1 > 1 Then
t2 = pgn + t1 - 1
You can also use acPrevious and acNext instead of acLast. See: AcRecord enumeration (Access). But you must make the calculation of how many times you must move to get to the desired record yourself. Access does not know which records you've just created.
Dim t1 As Long, i As Long
t1 = Clng(Nz(Me.Aantal, 1))
DoCmd.GoToRecord acDataForm, "GeleidelijstForm", acLast
For i = 1 To t1 - 1
DoCmd.GoToRecord acDataForm, "GeleidelijstForm", acPrevious
Next i
Or you can directly jump to it with
Dim rs As DAO.Recordset
Dim t1 As Long, numRecords As Long
t1 = Clng(Nz(Me.Aantal, 1))
Set rs = Me.RecordsetClone
rs.MoveLast
numRecords = rs.RecordCount
rs.Close
DoCmd.GoToRecord acDataForm, "GeleidelijstForm", acGoTo, numRecords - t1 + 1
You can also jump to a specific record like this in case you are able to identify the record by some value
Dim rs As Object
Set rs = Me.Recordset.Clone
rs.FindFirst "[MyID] = " & theId
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
rs.Close
You can use the RecordsetClone and loop backwards a number of times. Something like:
Private Sub cmdPos_Click()
On Error GoTo E_Handle
Dim rs As DAO.Recordset
Dim lngLoop1 As Long
Dim lngCount As Long
lngCount = Me!txtPos - 1
Set rs = Me.RecordsetClone
rs.MoveLast
If lngCount > 0 Then ' if only one record added then no need to loop
For lngLoop1 = 1 To lngCount
rs.MovePrevious
Next lngLoop1
End If
Me.Bookmark = rs.Bookmark
sExit:
On Error Resume Next
Set rs = Nothing
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "cmdPos_Click", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub

Occasional Error Update or CancelUpdate without AddNew or Edit

I am using a listbox to navigate between records on a form but I occasionally get Error Update or CancelUpdate without AddNew or Edit Run-time Error 3020
on Me.Bookmark = rs.Bookmark.
I can't seems to figure out what the problem is and was wondering if someone can help me with how to fix it.
Option Compare Database
Option Explicit
Dim rs As DAO.Recordset
Private Sub listBox_AfterUpdate()
Dim rs As DAO.Recordset
If Not IsNull(ItemNo) And Not IsNull(itemName) Then
Set rs = Me.RecordsetClone
rs.FindFirst "[ItemNo] = '" & Me![listBox] & "'"
If Not rs.NoMatch Then Me.Bookmark = rs.Bookmark
Else
Exit Sub
End If
If IsNull(ItemNo) Or IsNull(itemName) Then
Exit Sub
End If
rs.Close
Set rs = Nothing
End Sub
You have probably started to edit the record in the Form. Save the pending edits before moving to another record.
If Not rs.NoMatch Then
Me.Dirty = False 'Saves any pending changes.
Me.Bookmark = rs.Bookmark 'Navigate to another record.
End If

Run time Error 3201 when reading Database and missing the last entry

I am currently struggling with this piece of Code:
While receiver = data.Fields("Contact")
If first Then
first = False
strSig = Replace(strSig, ID, data.Fields("ID") & ID)
Else
strSig = Replace(strSig, ID, ", " & data.Fields("ID") & ID)
End If
data.MoveNext
Wend
It is not reading the last database entry.
My complete code is doing the following:
Read Database
Read an HTML File
Search for multiple IDs for a person and aggregate those
Replace the IDs with a placeholder in the IDs
Send the Email
The process does work except for for the last entry. For that entry I receive a
3021 Run Time Error - No Current Record.
Here is an example of how to loop through a recordset:
Option Explicit
Sub recordsetDemo()
'can use the name of a table or of a query, or a specific SQL query:
Const rs_Source = "select * from tblYourTable"
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset(rs_Source) 'open the recordset
With rs 'refer to the RS with "." dots instead of the full name "rs."
If Not .EOF Then .MoveFirst 'move to the first record
Do While Not .EOF 'keep doing this until the end of the recordset
Debug.Print !myField1, !myField2 'do "something" here with the data.
.MoveNext 'move to the next record
Loop 'loop will end if there's no "next record"
.Close 'close the recordset
End With
Set rs = Nothing 'clear the variable
End Sub
A rough adaptation using your example:
Sub recordsetDemo()
Dim data As Recordset
Set data = CurrentDb.OpenRecordset("YourTableOrQueryName") 'open recordset
'***however you setup your "Data" recordset could replace the above code***
With data
If .EOF Then 'check if there's data
MsgBox "No Data Found!"
Exit Sub
End If
.MoveFirst 'move to the first record
Do While Not .EOF 'keep doing this until the end of the recordset
If first Then
first = False
strSig = Replace(strSig, id, !id & id)
Else
strSig = Replace(strSig, id, ", " & !id & id)
End If
.MoveNext 'move to the next record
Loop 'loop will end if there's no "next record"
.Close 'close the recordset
End With
Set rs = Nothing 'clear the variable
End Sub
That's all I can do given the information you provided.

Access loop through continuous form

I am attempting to add a VBA to a command button to look at a text box and if not null, then look at a combo box. If that combo box is null, have a pop up message box. Since it is a continuous form and there are several records showing, it works fine on the first record, however it does not for the following records. I believe this is because I need to loop through each record. Below is the VBA code I have so far. I would greatly appreciate any help regarding the loop, as I am new to VBA.
If Not IsNull(Me.Text33.Value) Then
If IsNull(Me.Combo24.Value) Then
MsgBox "You must state if the rationale is aligned with procedures for each disputed subcategory."
Else
'do nothing
End If
End If
DoCmd.Save
DoCmd.Close
Thank you in advance,
Susan
Since this is a continuous form, you can Clone the Form's recordset and loop in each record.
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
rs.MoveLast
rs.MoveFirst
Dim idx As Integer
For idx = 1 To rs.RecordCount
If Not IsNull(rs![TextBoxFieldName]) Then If IsNull(rs![ComboBoxFieldName]) Then MsgBox "..."
rs.MoveNext
Next idx
Set rs = Nothing
With DoCmd
.Save
.Close
End With
Note in case this is intended for validation purposes, the DoCmd actions will always execute regardless of the message-box error/warning.
You can change that by adding an Exit Sub after showing the message box.
Edit:
Sub Example()
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
rs.MoveLast
rs.MoveFirst
Dim idx As Integer
For idx = 1 To rs.RecordCount
Select Case True
Case Not IsNull(rs![ComboFieldName]) And IsNull(rs![TextBoxFieldName]):
MsgBox "You must enter dispute comments for each disputed subcategory."
GoTo Leave
Case IsNull(rs![ComboFieldName]) And Not IsNull(rs![TextBoxFieldName]):
MsgBox "You must state if the rationale is aligned with procedures for each disputed subcategory."
GoTo Leave
Case Else:
'do nothing
End Select
rs.MoveNext
Next idx
Set rs = Nothing
With DoCmd
.Save
.Close
End With
Exit Sub
Leave:
Set rs = Nothing
End Sub

MS Access logging users entrance and exit times across network

Hey guys I need some help. I was tasked with a business intelligence project where the initial step is logging users’ entrance and exit dates and times. So I have three modules:
modCaptureIns and modCaptureOuts; Also, I have modCaptureIns' function RecordIns() running on the AutoExec macro and modCaptureOuts running on when a hidden form named frmCaptureOuts is closed (upon user closing database).
Here is the problem: When a single user opens and closes the database entrance and exit times are logged in tblInsNOuts. As soon as you have more than one user, the second user is changing the SessId variable to a different number, and then the exit times are not recorded. Please give me a hand. Any help will be much appreciated.
CF
`Option Compare Database
Option Explicit
Public SessID As Integer
Public Function RecordIns()
On Error GoTo ErrorHandler
Dim db As Database
Dim rs As Recordset
DoCmd.SetWarnings False
SessID = DFirst("[MaxOfSessionID]", "[qryMaxOfSessionID]") + 1
Set db = CurrentDb
Set rs = db.OpenRecordset("tblInsNOuts")
rs.AddNew
rs.Fields("SessionID") = SessID
rs.Fields("WinID") = GetUser()
rs.Fields("EntryStamp") = Now()
rs.Update
DoCmd.SetWarnings True
rs.Close
Set rs = Nothing
db.Close
ExitSub:
Exit Function
ErrorHandler:
MsgBox "Error " & Err.Number & ": " & Err.Description
Resume ExitSub
End Function
Option Compare Database
Option Explicit
Public Function ExitStamp()
On Error GoTo ErrorHandler
Dim db As Database
Dim rs As Recordset
Dim fldEnumerator As Object
Dim fldColumns As Object
Set db = CurrentDb
Set rs = db.OpenRecordset("tblInsNOuts")
Set fldColumns = rs.Fields
DoCmd.SetWarnings False
While Not rs.EOF
For Each fldEnumerator In rs.Fields
If fldEnumerator.Name = "SessionID" Then
If fldEnumerator.Value = SessID Then
rs.Edit
rs.Fields("ExitStamp") = Now()
rs.Update
End If
End If
Next
rs.MoveNext
Wend
DoCmd.SetWarnings True
rs.Close
Set rs = Nothing
db.Close
ExitSub:
Exit Function
ErrorHandler:
MsgBox "Error " & Err.Number & ": " & Err.Description
Resume ExitSub
End Function
Option Compare Database
Private Sub Form_Close()
Call ExitStamp
End Sub
`
I went a step further with this. I was able to open another Windows image and therefore a second snapshot of the DB. When I opened both snapshots at the same time it logs the entry times for both, but when close the first one it drops the value of SessID. I realized the snapshot which remains open could no longer access the value of SessID because it's now null. Still need some help guys