Making automatic email reminder using VBA - vba

I am trying to make email using Outlook to remind someone to update their CV information per 6 months (180 days).
I have 1 query and 1 table.
Duedate_7 query consists of employee information, which passed 180 days or more since the last update. Access would send email to those employees.
Highlights table consists of the ID of the employees (Number), date of the project (date) and content of the project (long text).
Option Compare Database
Option Explicit
Function Otomail()
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim emailTo As String
Dim emailSubject As String
Dim emailText As String
Dim outApp As Outlook.Application
Dim outMail As Outlook.MailItem
Dim outlookStarted As Boolean
On Error Resume Next
Set outApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
Set outApp = CreateObject("Outlook.Application")
outlookStarted = True
End If
Set db = CurrentDb
Set rs1 = db.OpenRecordset("SELECT ID, NIK, Nama, email, datemailsend FROM DueDate_7")
Do Until rs1.EOF
emailTo = rs1.Fields("email")
emailSubject = "Update CV"
emailText = "Please send the newest project highlights informations of Mr/Mrs' " & rs1.Fields("Nama").Value & " to the inside sales department for updating your CV which is scheduled once per 6 months." & vbCr & _
"Your latest project highlights update was " & vbCr & _
"This email is auto generated from Task Database. Please Do Not Reply!"
Set outMail = outApp.CreateItem(olMailItem)
outMail.To = emailTo
outMail.Subject = emailSubject
outMail.Body = emailText
outMail.Display
rs1.Edit
rs1!datemailsend = Date
rs1.Update
rs1.MoveNext
Loop
rs1.Close
Set rs1 = Nothing
Set db = Nothing
Set outMail = Nothing
Set outApp = Nothing
End Function
I want to include each of the employee's 3 latest project highlights, stored in Highlights table, in each of the email I send.

What you need to do is to use a second recordset inside the loop that you have already got that selects the information required. Something like:
If Not (rs1.BOF And rs1.EOF) Then
Do
strProject = ""
strSQL = "SELECT TOP 3 ProjectName, ProjectDate " _
& " FROM Highlights " _
& " WHERE NameID=" & rs1!NameID _
& " ORDER BY ProjectDate DESC;"
Set rsProject = db.OpenRecordset(strSQL)
If Not (rsProject.BOF And rsProject.EOF) Then
Do
strProject = strProject & rsProject!ProjectDate & vbTab & rsProject!ProjectName & vbCrLf
rsProject.MoveNext
Loop Until rsProject.EOF
End If
Set outMail = outApp.CreateItem(olMailItem)
outMail.To = rs1!email
outMail.Subject = "Update CV"
outMail.Body = emailText & strProject
outMail.Display
rs1.MoveNext
Loop Until rs1.EOF
End If
This is assuming that you have a field called NameID that identifies the person to be selected.
Regards,

Related

Microsoft Access VBA code to send email to recipients with attachment based on results of query filtered on check date

I've commented out the section to add the attachment because I know it works, but the files currently aren't present to be attached. I'm new to VBA and am missing something. My data is simply employee number, check date (send_checkdt), check number, name, etc. The query has no parameters, which is why I'm doing the select based on the form date defined in strSQL.
When I run it I immediately get an over and it exits. Previously I was only able to send the email to the first person in the query and the record didn't advance. The email part is working correctly, I'm just not processing the data correctly.as
What am I missing?
Private Sub Command1_Click()
Dim Msg As String
Dim F_attach As String
Dim O As Outlook.Application
Dim M As Outlook.MailItem
Dim DT As String
DT = Forms!Form1!frmCheckDt
Dim strSQL As String
strSQL = "SELECT * FROM qryMailList Where send_checkdt=" & DT
Dim dbs As DAO.Database
Dim Mlist As DAO.Recordset
'Dim Mfiltered As DAO.Recordset
Set dbs = CurrentDb
Set Mlist = dbs.OpenRecordset(strSQL, dbOpenDynaset)
Set O = New Outlook.Application
Set M = O.CreateItem(olMailItem)
Mlist.MoveFirst
Do Until Mlist.EOF
Msg = "Dear " & Mail_FullName & "," & vbCrLf & vbCrLf & _
"Your payroll check number " & Send_CheckNo & " was deposited on " & _
send_checkdt & " for " & Format(Send_NetPay, "Currency") & "." & vbCrLf & vbCrLf & _
"Sincerely," & vbCrLf & Send_CoName
F_attach = "f:\archives\CK" & Mail_emp & "_" & Send_CheckNo & ".pdf"
With M
.BodyFormat = olFormatPlain
.Body = Msg
.To = Mail_Email
.Subject = "Direct Deposit " & send_checkdt
' .Attachments.Add F_attach
.Display
End With
Mlist.MoveNext
Loop
DoCmd.Close
Set M = Nothing
Set O = Nothing
Set Mlist = Nothing
Set dbs = Nothing
Set qdf = Nothing
Set Mfiltered = Nothing
End Sub
I moved
set O=New Outlook.Application and
set M=O.CreateItem(olMailItem)
to be below
Do Until Mlist.EOF and it works correctly.
I also had to further identify my data fields by adding Mlist! to each. Without identifying Mlist it prodcued the correct number of emails but no data was filled in. Thank you to everyone that offered comments.

Generate Email and INSERT INTO on click

I want to generate an email with an MS Access form the user has filled out, as well as INSERT INTO during the same action to record the results into a table.
My table has 7 columns:
ID (autonumber)
Date Submitted (Date())
First_Name (Short Text)
Last_Name (Short Text)
Email (Short Text)
Priority (Short Text)
Error (Long Text)
The code:
Private Sub Submit_Ticket_Button_Click()
Dim oOutlook As Outlook.Application
Dim oEmailItem As MailItem
Dim rs As Recordset
Dim CustomerEmail As String
' prevent 429 error, if outlook is not open
On Error Resume Next
Err.Clear
Set oOutlook = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then
Set oOutlook = New Outlook.Application
End If
Set oEmailItem = oOutlook.CreateItem(olMailItem)
With oEmailItem
.To = "alex.e.bristow2.ctr#mail.mil"
.Subject = "A Trouble Ticket Has Been Submitted"
.Body = DoCmd.SendObject
.Display
End With
Set oEmailItem = Nothing
Set oOutlook = Nothing
End Sub
Private Sub Submit_Ticket_Button_Click1()
Dim strinsert As String
strinsert = "INSERT INTO Trouble Tickets (First_Name,Last_Name,Email,Priority,Error)" & _
"values('" & FirstName.Value & "','" & LastName.Value & "','" & Email.Value & "','" & Priority.Value & "','" & Error.Value & "');"
DoCmd.RunSQL strinsert
End Sub
I get
"compile error, Expected function or variable"
in the first Sub.
This can't be right:
.Body = DoCmd.SendObject
Body expects a string holding your message body.

"RUN-TIME error '3085' Undefined Function 'EMAIL' in expression"

I am using Access VBA code to automatically send emails through Outlook after a set amount of time.
I keep getting a run-time error 3085. I do not know what went wrong or what function it is referring to. Is it possibly a reference I am missing or did I mess up on my functions somewhere?
Option Compare Database
Sub SendMail()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim emailTo As String
Dim emailSubject As String
Dim emailText As String
Dim outApp As Outlook.Application
Dim outMail As Outlook.MailItem
Dim outlookStarted As Boolean
On Error Resume Next
Set outApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
Set outApp = CreateObject("Outlook.Application")
outlookStarted = True
End If
Set db = CurrentDb
strSQL = "SELECT DATE, COMPANY, CUSTOMER, EMAIL(DISTRIBUTOR), FUP" & _
" FROM Sample Query WHERE DATE = (Date())"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
Do Until rs.EOF
emailTo = Trim(rs.Fields("COMPANY").Value & " " & _
rs.Fields("CUSTOMER").Value) & _
" <" & rs.Fields("EMAIL(DISTRIBUTOR)").Value & ">"
emailSubject = "Proposal Follow Up"
If IsNull(rs.Fields("COMPANY").Value) Then
emailSubject = emailSubject & " for " & _
rs.Fields("COMPANY").Value & " " & rs.Fields("CUSTOMER").Value
End If
emailText = Trim("Hello " & rs.Fields("COMPANY").Value) & "!" & vbCrLf
emailText = emailText & _
"We put an order on " & rs.Fields("DATE").Value & _
" for " & rs.Fields("COMPANY").Value & _
"A follow up would be good about now"
Set outMail = outApp.CreateItem(olMailItem)
outMail.To = emailTo
outMail.Subject = emailSubject
outMail.Body = emailText
outMail.Send
rs.Edit
rs("FUP") = Now()
rs.Update
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
If outlookStarted Then
outApp.Quit
End If
Set outMail = Nothing
Set outApp = Nothing
End Sub
EMAIL(DISTRIBUTOR) needs to be surrounded by brackets to be a valid.
strSQL = "SELECT DATE, COMPANY, CUSTOMER, [EMAIL(DISTRIBUTOR)]

I keep getting error 3061 Too few parameters. Expected 1

I have tried adding brackets to my stated parameters to show that they are separate but I still get the error, I checked all the "&" but to no avail.
Here is the code. Thanks in advance.
Option Compare Database
Public Function SendMail()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim emailTo As String
Dim emailSubject As String
Dim emailText As String
Dim outApp As Outlook.Application
Dim outMail As Outlook.MailItem
Dim outlookStarted As Boolean
On Error Resume Next
Set outApp = GetObject("Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
Set outApp = CreateObject("Outlook.Application")
outlookStarted = True
End If
Set db = CurrentDb
strSQL = "SELECT DATE, COMPANY, CUSTOMER, EMAIL, FUP, [SAMPLES
REQUESTED]" & _
" FROM Sample Query WHERE DATE = Date()"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
Do Until rs.EOF
emailTo = rs.Fields("EMAIL").Value
emailSubject = "Proposal Follow Up"
If IsNull(rs.Fields("COMPANY").Value) Then
emailSubject = emailSubject & " for " & _
rs.Fields("COMPANY").Value & " " &
rs.Fields("CUSTOMER").Value
End If
emailText = Trim("Hello " & rs.Fields("COMPANY").Value) & "!" & vbCrLf
emailText = emailText & _
"Hello, " & rs.Fields("Name").Value & _
rs.Fields("CUSTOMER").Value & " ordered " & rs.Fields("SAMPLES
REQUESTED").Value & _
" on " & rs.Fields("Date").Value & " its been about a month. A
follow up would be good about now."
Set outMail = outApp.CreateItem(olMailItem)
outMail.To = emailTo
outMail.Subject = emailSubject
outMail.Body = emailText
outMail.Send
rs.Edit
rs("FUP") = Now()
rs.Update
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
If outlookStarted Then
outApp.Quit
End If
Set outMail = Nothing
Set outApp = Nothing
End Function
You miss brackets around the reserved word Date:
strSQL = "SELECT [DATE], COMPANY, CUSTOMER, EMAIL, FUP, [SAMPLES REQUESTED]" & _
" FROM [Sample Query] WHERE [DATE] = Date()"
Date is a protected word in Access. If you need to use that exact field name, put it in brackets like Gustav suggests. You can also rename the field, like TheDate or DateStart.
Here's a full list of protected words:
https://support.microsoft.com/en-us/help/286335/list-of-reserved-words-in-access-2002-and-in-later-versions-of-access

VBA Access Inserting from One DAO.Recordset into Another

Within the following code
Dim sqlStr As String
Dim OrgID As Long
Dim wrk As DAO.Workspace
Dim db As DAO.Database
Dim orgRS As DAO.Recordset
Dim staffRS As DAO.Recordset
Set wrk = DBEngine.Workspaces(0)
Set db = CurrentDb
On Error GoTo trans_Err
InsertOrganizationIntoTemp
'if staff fields are not blank Insert Staff into Temp
If (addStaffClickCheck = True) Then
staffNumber = staffNumber + 1
InsertStaffIntoTemp staffNumber
End If
wrk.BeginTrans
sqlStr = "INSERT INTO tblOrganization(OrganizationName, Affiliate, " _
& " UnionCouncil, DateJoined, OrganizationPhoneNumber, OrganizationFaxNumber, " _
& " MembershipGroup, TradeGroup, URL) " _
& " SELECT OrganizationName, Affiliate, CouncilUnion, DateJoined, OrganizationPhone, " _
& " OrganizationFax, MemberGroup, Trade, OrganizationWebsite " _
& " FROM tblTempOrganization;"
db.Execute sqlStr
OrgID = db.OpenRecordset("SELECT ##IDENTITY")(0)
sqlStr = "INSERT INTO tblAddresses(StreetName, CityName, StateName, " _
& " ZipCode, LocationID, OrganizationID) " _
& " SELECT OrganizationAddress, OrganizationCity, OrganizationState, " _
& " OrganizationZIP, OrganizationLocationType, '" & OrgID & "' " _
& " FROM tblTempOrganization;"
db.Execute sqlStr
'pull all staff and phones into two recordsets
'loop through staff and for each staff member add associated phone information
'Recordsets for temporary staff tables
Dim staffTempInfoRS As DAO.Recordset
Dim phoneTempInfoRS As DAO.Recordset
Set staffTempInfoRS = db.OpenRecordset("SELECT * FROM tblTempStaff", dbOpenDynaset)
'Recordsets for permanant staff tables
Dim StaffAddressID As Long
Dim StaffID As Long
'Check to see if the recordset actually contains rows
If Not (staffTempInfoRS.EOF And staffTempInfoRS.BOF) Then
staffTempInfoRS.MoveFirst 'Unnecessary in this case, but still a good habit
Do Until staffTempInfoRS.EOF = True
'address information
Dim staffAddressDBRS As DAO.Recordset
Set staffAddressDBRS = db.OpenRecordset("tblStaffAddresses", dbOpenDynaset)
With staffAddressDBRS
.AddNew
.Fields("StaffStreet") = staffTempInfoRS.Fields("StaffStreet")
.Fields("StaffCity") = staffTempInfoRS.Fields("StaffCity")
.Fields("StaffState") = staffTempInfoRS.Fields("StaffState")
.Fields("StaffZip") = staffTempInfoRS.Fields("StaffZip")
.Update
End With
StaffAddressID = staffAddressDBRS.LastModified
staffAddressDBRS.Close
Set staffAddressDBRS = Nothing
'staff information
Dim staffInfoDBRS As DAO.Recordset
Set staffInfoDBRS = db.OpenRecordset("tblStaff", dbOpenDynaset)
With staffInfoDBRS
.AddNew
.Fields("StaffFirstName") = staffTempInfoRS.Fields("StaffFirstName")
.Fields("StaffLastName") = staffTempInfoRS.Fields("StaffLastName")
.Fields("Email") = staffTempInfoRS.Fields("Email")
.Fields("StaffAddressID") = StaffAddressID
.Fields("OrganizationID") = OrgID
.Fields("Position") = staffTempInfoRS.Fields("StaffPosition")
.Update
End With
Dim currPos As Long
currPos = staffTempInfoRS.Fields("StaffNumber")
StaffID = staffInfoDBRS.LastModified
staffInfoDBRS.Close
Set staffInfoDBRS = Nothing
'staff phone information
Set phoneTempInfoRS = db.OpenRecordset("SELECT * FROM tblTempPhones WHERE StaffNumber = " & currPos & ";")
If Not (phoneTempInfoRS.EOF And phoneTempInfoRS.BOF) Then
phoneTempInfoRS.MoveFirst 'Unnecessary in this case, but still a good habit
Do Until phoneTempInfoRS.EOF = True
Dim phoneInfoDBRS As DAO.Recordset
Set phoneInfoDBRS = db.OpenRecordset("tblStaffPhoneNumbers", dbOpenDynaset)
With phoneInfoDBRS
.AddNew
.Fields("PhoneNumber") = phoneTempInfoRS.Fields("StaffPhoneNumber")
.Fields("PhoneTypeID") = phoneTempInfoRS.Fields("PhoneType")
.Fields("StaffID") = StaffID
.Update
End With
phoneTempInfoRS.MoveNext
Loop
Else
Resume Next
End If
MsgBox "Finished looping through phone records."
phoneTempInfoRS.Close
Set phoneTempInfoRS = Nothing
'Move to the next record. Don't ever forget to do this.
staffTempInfoRS.MoveNext
Loop
Else
MsgBox "There are no records in the staff recordset."
End If
MsgBox "Finished looping through staff records."
staffTempInfoRS.Close 'Close the recordset
Set staffTempInfoRS = Nothing 'Clean up
wrk.CommitTrans
trans_Exit:
'Clean up
wrk.Close
Set db = Nothing
Set wrk = Nothing
Exit Function
trans_Err:
'Roll back the transaction
MsgBox "Whoops! We got errors"
wrk.Rollback
Resume trans_Exit
When I step through this I get an error in this line:
.Fields("StaffStreet") = staffTempInfoRS.Fields("StaffStreet")
That says:
Item not found in collection.
However, this is the exact field name that is in the table that the recordset is set to open.
30 hours later it seems I suffered a rookie mistake and in-spite of repeated checking missed that the field names were indeed misspelled.
I also set the recordsets outside of the loops and I unset them all in the exit snippet...