Converting ID to Name with VBA - ms-access

So in my database, I've got a junction table that lists all of the "purposes" someone has for a loan. The code worked when just showing the values (in number form), but in my second loop where I search a second table for the actual name of the purpose, I'm running into issues. It displays the correct number of purposes, but unfortunately, the text repeats the first found purpose that number of times rather than displaying all applicable purposes.
Here is the code I'm using:
Private Sub cmdMsgBox_Click()
Dim DB As Database
Dim tblOpp2LP As Recordset
Dim tblLoanPurpose As Recordset
Dim ctlFindRecord As Control
Dim lngHoldOpportunityID As Variant
Dim intRecordCount As Integer
Dim valTestBox As String
Dim valLP As String
Dim valName As String
Set DB = CurrentDb
Set tblInputOpp2LP = DB.OpenRecordset("Opp2LP")
Set tblLoanPurpose = DB.OpenRecordset("LoanPurpose")
Set ctlFindRecord = Me.ctlFindRecord
lngHoldOpportunityID = CLng(ctlFindRecord)
valTestBox = ""
On Error GoTo ErrorHandling_Err:
tblInputOpp2LP.FindFirst "[OpportunityID] = " & lngHoldOpportunityID
If tblInputOpp2LP.NoMatch Then
MsgBox "No Matching Record Found"
Exit Sub
Else
Do Until tblInputOpp2LP.EOF
If lngHoldOpportunityID = tblInputOpp2LP![OpportunityID] Then
valLP = tblInputOpp2LP![LPID]
intCounter = intCounter + 1
Do Until tblLoanPurpose.EOF
If valLP = tblLoanPurpose![LPID] Then
valName = tblLoanPurpose![Name]
End If
tblLoanPurpose.MoveNext
Loop
If valTestBox = "" Then
valTestBox = valName
Else
valTestBox = valTestBox & ", " & valName
End If
End If
tblInputOpp2LP.MoveNext
Loop
txtMsgbox = valTestBox
End If
ErrorHandling_Exit:
Exit Sub
ErrorHandling_Err:
MsgBox Err.Description & " - " & Err.Number
Resume ErrorHandling_Exit
End Sub
Thoughts? Thanks in advance!

I got it!
As it turns out, what I needed to do was add an "exit do" in the second loop.
See the below code example.
Private Sub cmdMsgBox_Click()
Dim DB As Database
Dim tblOpp2LP As Recordset
Dim tblLoanPurpose As Recordset
Dim ctlFindRecord As Control
Dim lngHoldOpportunityID As Variant
Dim intRecordCount As Integer
Dim valTestBox As String
Dim valLP As String
Dim valName As String
Set DB = CurrentDb
Set tblInputOpp2LP = DB.OpenRecordset("Opp2LP")
Set tblLoanPurpose = DB.OpenRecordset("LoanPurpose")
Set ctlFindRecord = Me.ctlFindRecord
lngHoldOpportunityID = CLng(ctlFindRecord)
valTestBox = ""
On Error GoTo ErrorHandling_Err:
tblInputOpp2LP.FindFirst "[OpportunityID] = " & lngHoldOpportunityID
If tblInputOpp2LP.NoMatch Then
MsgBox "No Matching Record Found"
Exit Sub
Else
Do Until tblInputOpp2LP.EOF
If lngHoldOpportunityID = tblInputOpp2LP![OpportunityID] Then
valLP = tblInputOpp2LP![LPID]
intCounter = intCounter + 1
Do Until tblLoanPurpose.EOF
If valLP = tblLoanPurpose![LPID] Then
valName = tblLoanPurpose![Name]
exit do
End If
tblLoanPurpose.MoveNext
Loop
If valTestBox = "" Then
valTestBox = valName
Else
valTestBox = valTestBox & ", " & valName
End If
End If
tblInputOpp2LP.MoveNext
Loop
txtMsgbox = valTestBox
End If
ErrorHandling_Exit:
Exit Sub
ErrorHandling_Err:
MsgBox Err.Description & " - " & Err.Number
Resume ErrorHandling_Exit
End Sub

Related

How to check if the table is empty in Access 2003?

I need only empty tables in access database. Additionally, it would be great if I can get empty tables from list of tables that I have (part of all tables). But listing all empty tables would work also.
You can use a small VBA function that checks this. Something like:
Function fIsTableEmpty(strTableName As String) As Boolean
On Error GoTo E_Handle
Dim db As DAO.Database
Dim rsData As DAO.Recordset
Dim strSQL As String
Set db = CurrentDb
strSQL = "SELECT COUNT(*) FROM [" & strTableName & "];"
Set rsData = db.OpenRecordset(strSQL)
fIsTableEmpty = True ' start by assuming that there are records
If Not (rsData.BOF And rsData.EOF) Then
If rsData(0) > 0 Then fIsTableEmpty = False
End If
fExit:
On Error Resume Next
rsData.Close
Set rsData = Nothing
Set db = Nothing
Exit Function
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "fIsTableEmpty", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume fExit
End Function
You can use DCount:
Public Function ListEmptyTables()
Dim Table As DAO.TableDef
For Each Table In CurrentDb.TableDefs
If Table.SourceTableName = "" Then
If DCount("*", Table.Name) = 0 Then
Debug.Print Table.Name
End If
End If
Next
End Function

MS access - Application-Defined or Object-Defined Error while sending email

I have a code that is used to send emails using outlook from access. This code is throwing "Application-Defined or objected-Defined" error when the code is reaching .Recipient.Add line. This code works totally fine in my system but not in my colleague system. I have checked libraries and everything match but still the error is coming.
Private Sub Toggle182_Click()
On Error GoTo Err_Toggle182_Click
Dim BaCode As String
Dim lst As Control
Set lst = Me.name
Dim BillingMnth As String
BillingMnth = Format(Me.Billing_Month, "mmm")
Dim oItem As Variant
Dim iCount As Integer
Dim oApp As New Outlook.Application
Dim oEmail As Outlook.MailItem
Dim fileName As String
Dim sqry As String
Dim rs As DAO.Recordset
If lst.ItemsSelected.Count <> 0 Then
For Each oItem In lst.ItemsSelected
BaCode = lst.Column(0, oItem)
fileName = "My local path"
fileName = fileName & name & BillingMnth & ".xlsx"
sqry = "Select Distribution_List from details where name='" & name & "';"
Set rs = CurrentDb.OpenRecordset(sqry)
Set oEmail = oApp.CreateItem(olMailItem)
With oEmail
rs.MoveFirst
While Not rs.EOF
.Recipients.Add rs.Fields("Distribution_List")
rs.MoveNext
Wend
.Subject = "RTB"
.HTMLBody = "<HTML><BODY>Dear User <br><br> Please find the attached file. <br><br> Kindly do let us know in case of any concerns. <br> <br><br>Kind Regards, <br>company <br> </BODY></HTML>"
.Attachments.Add fileName
.Save
.Send
End With
iCount = iCount + 1
Next oItem
MsgBox "Email successfully sent!", vbInformation, "EMAIL STATUS"
Else
MsgBox "Please slect the name"
Exit Sub
End If
Err_Toggle182_Click:
'MsgBox Err.Description
End Sub
Possible that rs.Fields("Distribution_List") is null?
Try nz(rs.Fields("Distribution_List"),"") and see if it works.

VBA Audit Trail code throwing Argument Not Optional error

I have built one database where the below audit trail code works flawlessly for both forms and sub-forms in Access 2010. But now that I am using it again in another database, I now get an error "Argument Not Optional" at the first Call. Why would this work in one database and not the other if they both have had the sub-form created the same exact way? I can not get the database to give me more information outside of the not so helpful error code. My best guess is that it has something to do with Sub TrainingEntryAuditChanges(IDField As String, UserAction As String, FormToAudit As Form) but I can't really tell. Like I said, it works in one database, but not this one for some reason. Any ideas?
Module Code:
***ABOVE CODE OMITTED INTENTIONALLY***
'Audit module code for employee training entry form's sub form
Sub TrainingEntryAuditChanges(IDField As String, UserAction As String, FormToAudit As Form)
On Error GoTo AuditChanges_Err
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim ctl As Control
Dim datTimeCheck As Date
Dim strUserID As String
Set cnn = CurrentProject.Connection
Set rst = New ADODB.Recordset
rst.Open "SELECT * FROM tblAuditTrail", cnn, adOpenDynamic, adLockOptimistic
datTimeCheck = Now()
strUserID = Forms!Login!cboUser.Column(1)
'Get computer IP address
Dim myWMI As Object, myobj As Object, itm
Set myWMI = GetObject("winmgmts:\\.\root\cimv2")
Set myobj = myWMI.ExecQuery("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled = True")
For Each itm In myobj
getMyIP = itm.IPAddress(0)
Next
'If user is editing an existing record:
Select Case UserAction
Case "EDIT"
For Each ctl In FormToAudit
If ctl.Tag = "Audit" Then
If Nz(ctl.Value) <> Nz(ctl.OldValue) Then
With rst
.AddNew
![DateTime] = datTimeCheck
![UserName] = strUserID
![UserComputer] = getMyIP
![FormName] = FormToAudit.Name
![Action] = UserAction
![RecordID] = FormToAudit.Controls(IDField).Value
![FieldName] = ctl.ControlSource
![OldValue] = ctl.OldValue
![NewValue] = ctl.Value
.Update
End With
End If
End If
Next ctl
'If a user is creating a new record:
Case Else
With rst
.AddNew
![DateTime] = datTimeCheck
![UserName] = strUserID
![UserComputer] = getMyIP
![FormName] = FormToAudit.Name
![Action] = UserAction
![RecordID] = FormToAudit.Controls(IDField).Value
.Update
End With
End Select
AuditChanges_Exit:
On Error Resume Next
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
Exit Sub
'If error then:
AuditChanges_Err:
Dim strError As String
Dim lngError As Long
Dim intErl As Integer
Dim strMsg As String
strError = Err.Description
lngError = Err.Number
intErl = Erl
strMsg = "Line : " & intErl & vbCrLf & _
"Error : (" & lngError & ")" & strError
MsgBox strMsg, vbCritical
Resume AuditChanges_Exit
End Sub
Before_Update code on subform:
Private Sub Form_BeforeUpdate(Cancel As Integer)
If Me.NewRecord Then
Call TrainingEntryAuditChanges("ID", "NEW") ***ERROR THROWN HERE***
Else
Call TrainingEntryAuditChanges("ID", "EDIT")
End If
End Sub
The Argument Not Optional is thrown when you are calling a routine with the incorrect number of arguments required for that routine.
In your code
Sub TrainingEntryAuditChanges(IDField As String, UserAction As String, FormToAudit As Form)
requires three arguments, IDField, UserAction, and FormToAudit.
However, in your Call
Call TrainingEntryAuditChanges("ID", "NEW") ***ERROR THROWN HERE***
you are only passing it two arguments: ID, NEW. You need to pass it a third argument (which looks like it will be the form). Try using me as the third argument to pass the 'current' form that is being updated and therefore calling the routine.

Compare two recordset variables gives type mismatch

I have a bound form with several subforms. some of these subforms can 0 or more records, others have 1 or more.
The form is always open in read-only and on it there are an "edit" and a "close" button.
When the user clicks on the edit button I save the content of the current record togehter with all records of the subforms so that when he/she clicks on the close button I can ask wether to save or not and, if not, discard the changes restoring from saved records.
So far this is the code of the edit button (where GclnAllCnts is a global variable of type Dictionary):
Private Sub EditLibroBtn_Click()
On Error GoTo Err_EditLibroBtn_Click
Dim lngID As Long
Dim ctlCnt As Control
Dim rs As Recordset
lngID = Me.ID
Set GclnAllCnts = New Dictionary
GclnAllCnts.Add Me.Name, Me.RecordsetClone
For Each ctlCnt In Me.Controls
If (ctlCnt.ControlType = acSubform) Then
Set rs = ctlCnt.Form.RecordsetClone
If rs.RecordCount > 0 Then
GclnAllCnts.Add ctlCnt.Name, ctlCnt.Form.RecordsetClone
Else
GclnAllCnts.Add ctlCnt.Name, Null
End If
End If
Next
DoCmd.Close acForm, Me.Name
DoCmd.OpenForm GCstMainFrmName, , , "ID = " & lngID, acFormEdit, acDialog
Exit_EditLibroBtn_Click:
Set ctlCnt = Nothing
Set rs = Nothing
Exit Sub
Err_EditLibroBtn_Click:
MsgBox err.Description & vbNewLine & "Error number: " & err.Number, vbCritical, "Errore"
Resume Exit_EditLibroBtn_Click
End Sub
And this is the code of the close button:
Private Sub ChiudiBtn_Click()
On Error GoTo Err_ChiudiBtn_Click
Dim intBoxAwr As Integer
Dim stSQL As String
Dim vKey As Variant
Dim ctlCnt As Control
Dim clnAllCnts As Dictionary
Dim bSaveNeeded As Boolean
bSaveNeeded = False
If (Me.AllowEdits And Me.ID <> "" And Not IsNull(Me.ID)) Then
Set clnAllCnts = New Dictionary
clnAllCnts.Add Me.Name, Me.RecordsetClone
For Each ctlCnt In Me.Controls
If (ctlCnt.ControlType = acSubform) Then
Set rs = ctlCnt.Form.RecordsetClone
If rs.RecordCount > 0 Then
clnAllCnts.Add ctlCnt.Name, ctlCnt.Form.RecordsetClone
Else
clnAllCnts.Add ctlCnt.Name, Null
End If
End If
Next
If clnAllCnts.Count <> GclnAllCnts.Count Then
bSaveNeeded = True
Else
For Each vKey In clnAllCnts.keys()
If Not GclnAllCnts.Exists(vKey) Then
bSaveNeeded = True
Exit For
Else
'*********** Next Gives error **********
If clnAllCnts.Item(vKey) <> GclnAllCnts.Item(vKey) Then
bSaveNeeded = True
Exit For
End If
End If
Next
End If
If bSaveNeeded Then
intBoxAwr = MsgBox("Salvare le modifiche al libro?", vbYesNo + vbQuestion, "Salvare")
If intBoxAwr = vbYes Then
'etc., omitting code
End Sub
The error I get is Type mismatch (nr. 13) and it is given by the <> comparison (I can Debug.print IsNull(clnAllCnts.Item(vKey)) and IsNull(GclnAllCnts.Item(vKey)).
How can I compare the two recordset variables?
Comparing two Recordset objects by simply saying If rst1 <> rst2 could be dicey anyway, because what does that really mean? Such an expression could very well return True every time, if rst1 and rst2 really are different objects (even if they are of the same object Type).
It appears that you are interested in whether the contents of the two Recordsets is the same. In that case, I would be inclined to serialize the recordset data and store the resulting String instead of storing the Recordset object itself.
The following VBA Function may prove helpful in that case. It loops through a recordset object and produces a JSON-like string containing the current recordset data.
(Note that the function may NOT necessarily produce valid JSON. It doesn't escape non-printing characters like vbCr and vbLf. It doesn't escape backslashes (\). It stores all values as either "string" or null. In other words, in its current form it is not designed to produce a string that could later be deserialized.)
Private Function rstSerialize(ByVal rst As DAO.Recordset)
' loop through the recordset and generate a JSON-like string
' NB: This code will NOT necessarily produce valid JSON!
'
Dim s As String, fld As DAO.Field, rowCount As Long, fldCount As Long
s = "{"
If Not (rst.BOF And rst.EOF) Then
rst.MoveFirst
rowCount = 0
Do Until rst.EOF
If rowCount > 0 Then
s = s & ", "
End If
s = s & """row"": {"
fldCount = 0
For Each fld In rst.Fields
If fldCount > 0 Then
s = s & ", "
End If
s = s & """" & fld.Name & """: " & IIf(IsNull(fld.Value), "null", """" & fld.Value & """")
fldCount = fldCount + 1
Next
s = s & "}"
rowCount = rowCount + 1
rst.MoveNext
Loop
End If
s = s & "}"
rstSerialize = s
End Function
Data Example: If the Recordset contained
DonorID Amount
------- ------
1 10
2 20
the function would return the string
{"row": {"DonorID": "1", "Amount": "10"}, "row": {"DonorID": "2", "Amount": "20"}}
Usage Example: On a form that contains a subform, a button on the main form could do the following
Private Sub Command3_Click()
Dim rst As DAO.Recordset, originalState As String
Set rst = Me.MemberDonationsSubform.Form.RecordsetClone
originalState = rstSerialize(rst)
rst.MoveFirst
rst.Edit
rst!Amount = rst!Amount + 1
rst.Update
Debug.Print "(Recordset updated.)"
If rstSerialize(rst) = originalState Then
Debug.Print "Recordset does not appear to have changed."
Else
Debug.Print "Recordset appears to have changed."
End If
End Sub
which would print the following in the VBA Immediate Window
(Recordset updated.)
Recordset appears to have changed.

Finding specific data in SQL Table

I hope someone can help me with this, I am new in SQL and this makes me confuse.
I want to find a specific/matched data in mySQL table via inputbox, This code only find data in the first row and doesn't recognize the second and the rest data in the row of my database..
here is my code..
Dim rs As New ADODB.Recordset
myConn
Dim holdstr As String
holdstr = InputBox("Enter Number")
rs.Open "SELECT * FROM lemployees ", conn
Do Until rs.EOF
If holdstr = "" Then
conn.Close
Exit Sub
End If
If holdstr = rs!ENumber Then
MsgBox "Record found!", vbInformation, "Message"
UserForm2.lblnum.Caption = rs!ENumber
UserForm2.TextBox2.Text = rs!ELName
UserForm2.TextBox3.Text = rs!EFName
UserForm2.TextBox4.Text = rs!EMName
UserForm2.boxPos = rs!EDepartment
UserForm2.TextBox6.Text = rs!EAge
UserForm2.TextBox7.Text = rs!EHourlyPaid
UserForm2.TextBox8.Text = rs!ECitizen
conn.Close
Exit Sub
Else
MsgBox "Record not found", vbInformation, "Message"
Exit Sub
End If
Loop
Thanks!
You exit the Sub inside the loop. Even if the item you are looking for is not found.
Try
Dim rs As New ADODB.Recordset
myConn
Dim holdstr As String
holdstr = InputBox("Enter Number")
If holdstr = "" Then
Exit Sub
End If
rs.Open "SELECT * FROM lemployees ", conn
Do Until rs.EOF
If holdstr = rs!ENumber Then
MsgBox "Record found!", vbInformation, "Message"
UserForm2.lblnum.Caption = rs!ENumber
UserForm2.TextBox2.Text = rs!ELName
UserForm2.TextBox3.Text = rs!EFName
UserForm2.TextBox4.Text = rs!EMName
UserForm2.boxPos = rs!EDepartment
UserForm2.TextBox6.Text = rs!EAge
UserForm2.TextBox7.Text = rs!EHourlyPaid
UserForm2.TextBox8.Text = rs!ECitizen
conn.Close
Exit Sub
End If
Loop
MsgBox "Record not found", vbInformation, "Message"
conn.Close
Exit Sub