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
Related
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
I'm very new to programming and have been building my company's inventory database on MS Access 2016. I've been able to get by just fine with macros so far, but I'm trying to run a transaction made of append and delete queries and am struggling with the vba code.
I figured out how to run a transaction where the queries fail on error. However, the append query I'm trying to include in the transaction is drawing values from a blank form, and as far as I can figure out, that means I need to define the query parameters in the code.
So this is the code where the transaction and error handling works:
Private Sub Command0_Click()
Dim ws As DAO.Workspace, db As DAO.Database
Set ws = DBEngine.Workspaces(0)
Set db = ws.Databases(0)
Set qdf = db.QueryDefs
On Error GoTo ErrTrap
ws.BeginTrans
DoCmd.SetWarnings False
db.Execute "TESTQRY1", dbFailOnError
db.Execute "TEST2QRY", dbFailOnError
db.Execute "TESTQRY3", dbFailOnError
ws.CommitTrans
MsgBox ("You have successfully updated the data")
DoCmd.SetWarnings True
Exit Sub
ErrTrap:
ws.Rollback
MsgBox "Rollback needed because:" & vbCr & Err.Description
End Sub
And this is the code that works for actually running the query, but which doesn't have the error handling or transaction working:
Private Sub Add_Click()
Dim db As DAO.Database
Dim qry As DAO.QueryDef
Dim ws As DAO.Workspace
Set ws = DBEngine.Workspaces(0)
Set db = ws.Databases(0)
Set qry = db.QueryDefs("APPENDQRY")
qry.Parameters(0) = Forms!LotNumberFrm!txtLotNumber
qry.Parameters(1) = Forms!LotNumberFrm!txtFWNumber
qry.Parameters(2) = Forms!LotNumberFrm!txtExpDate
qry.Parameters(3) = Forms!LotNumberFrm!chkActive
qry.Execute
Exit Sub
End Sub
So basically my issue is that I need to do both of these things at the same time - run the query as part of a transaction with error handling AND define the query parameters in the code.
I've tried to slice and splice these two bits of code together a bunch of different ways without success. Any help would be much appreciated.
I don't really understand why you were unable to integrate the code from your first section into your second question, but I'll do it for you.
Private Sub Add_Click()
Dim db As DAO.Database
Dim qry As DAO.QueryDef
Dim ws As DAO.Workspace
Set ws = DBEngine.Workspaces(0)
Set db = ws.Databases(0)
Set qry = db.QueryDefs("APPENDQRY")
qry.Parameters(0) = Forms!LotNumberFrm!txtLotNumber
qry.Parameters(1) = Forms!LotNumberFrm!txtFWNumber
qry.Parameters(2) = Forms!LotNumberFrm!txtExpDate
qry.Parameters(3) = Forms!LotNumberFrm!chkActive
On Error GoTo ErrTrap
ws.BeginTrans
qry.Execute
ws.CommitTrans
Exit Sub
ErrTrap:
ws.Rollback
MsgBox "Rollback needed because:" & vbCr & Err.Description
End Sub
An alternative way to execute a single query transactionally is the following:
qry.Execute dbFailOnError
This rolls back the query on an error. No need for any workspace stuff.
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
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
I use MS Access macros and queries to build my application. I use some temporary import files, and need to either run a macro, or some VBA, to test if they exist, and then if they do, to delete them.
My table name is "TempImport1"
I've researched this via Google searches and have some VBA that might work. I have cut/pasted VBA code under a button in the past, and it worked, but not this time. How do I put the code into a module or a click sub button?
Function IsTable(sTblName As String) As Boolean
'does table exists and work ?
'note: finding the name in the TableDefs collection is not enough,
' since the backend might be invalid or missing
On Error GoTo TrapError
Dim x
x = DCount("*", sTblName)
IsTable = True
Exit Function
TrapError:
Debug.Print Now, sTblName, Err.Number, Err.Description
IsTable = False
End Function
First you should check whether the table exists and then you should try to close it, if it exists. Then you should set warnings to False, so it does not ask you whether you are sure that you want to delete the table.
In the example below, you delete Table3. The If Not IsNull is checking whether the table exists:
Option Compare Database
Option Explicit
Public Sub DeleteIfExists()
Dim tableName As String
tableName = "Table3"
If Not IsNull(DLookup("Name", "MSysObjects", "Name='" & tableName & "'")) Then
DoCmd.SetWarnings False
DoCmd.Close acTable, tableName, acSaveYes
DoCmd.DeleteObject acTable = acDefault, tableName
Debug.Print "Table" & tableName & "deleted..."
DoCmd.SetWarnings True
End If
End Sub
Pretty much the code should work.
To delete the TempImport1 table if it exists just use the below function.
Function DeleteTables()
If Not IsNull(DLookup("Name", "MSysObjects", "Name='TempImport1' AND Type = 1")) Then
DoCmd.DeleteObject acTable, "TempImport1"
End If
End Function
Once the function has been created, create a macro, add the action run code then type in DeleteTables() in to the Function Name.
You then have a macro to run to delete the table if it exists.
Checking MSysObjects (used in other answers) misreported a table as existing if it was recently deleted. I found the following test more reliable.
Option Compare Database
Option Explicit
Public Sub DeleteIfExists()
Dim tableName As String
tableName = "Table3"
On Error Resume Next
Set td = db.TableDefs(tableName)
If Err.Number <> 0 Then
DoCmd.SetWarnings False
DoCmd.Close acTable, tableName, acSaveYes
DoCmd.DeleteObject acTable = acDefault, tableName
Debug.Print "Table" & tableName & "deleted..."
DoCmd.SetWarnings True
End If
End Sub
Here is the version I created to get rid of import error tables. The Err. Number must be 0 to actually remove table. TRACE is my internal flag.
Public Function RemoveImportErrorTables(Optional strTableBaseName As String = "rngExportDaily_ImportErrors") As Integer
'Purpose:
' Remove ImportError Tables
'In:
' Tables base Name
'Out:
' number of tables flushed
'History:
' Created 2021-12-06 16:10 Anton Sachs; Last modified 2021-12-06 16:15 Anton Sachs
'
Dim intResult As Integer
Dim strTableName As String
Dim dbCur As Database
Dim tdfTableDef As TableDef
Dim intTableIndex As Integer
On Error GoTo RemoveImportErrorTables_Err
Set dbCur = CurrentDb()
For intTableIndex = 0 To 100
If intTableIndex = 0 Then
strTableName = strTableBaseName
Else
strTableName = strTableBaseName & CStr(intTableIndex)
End If
On Error Resume Next
Set tdfTableDef = dbCur.TableDefs(strTableName)
If Err.Number = 0 Then
DoCmd.SetWarnings False
DoCmd.Close acTable, strTableName, acSaveYes
DoCmd.DeleteObject acTable = acDefault, strTableName
DoCmd.SetWarnings True
intResult = intResult + 1
Else
On Error GoTo RemoveImportErrorTables_Err
Exit For
End If
Next intTableIndex
RemoveImportErrorTables_Exit:
RemoveImportErrorTables = intResult
If Not tdfTableDef Is Nothing Then
Set tdfTableDef = Nothing
End If
If Not dbCur Is Nothing Then
Set dbCur = Nothing
End If
Exit Function
RemoveImportErrorTables_Err:
If TRACE = 0 Then TRACE = GetStandard("Trace")
If TRACE <> False Then
Debug.Print "Error " & Err.Number & " " & Err.Description & " in RemoveImportErrorTables"
Err.Clear
If TRACE = CTR±Stop Then
Stop
Resume Next
End If
Else
Err.Clear
Resume Next
End If
RemoveImportErrorTables_Fail:
intResult = False
GoTo RemoveImportErrorTables_Exit
End Function