VBA Soccer League Schedule Emailer - excel

My code is shown below. I keep getting the error message "Compile error. Sub or Function not defined". The debug is highlight the first line in my code. Does anyone know what I am doing wrong or what this should actually read?
Sub ScheduleUpdate()
Dim recipientList() As String
Dim emailSubject As String
Dim emailBody As String
Dim lastRow As Long
Dim i As Long
' Define the email subject
emailSubject = "Soccer League Schedule Update"
' Get the last row with data in the worksheet
lastRow = ActiveSheet.Range("A1").CurrentRegion.Rows.Count
' Loop through each row in the worksheet
For i = 2 To lastRow
' Check if the game has been rescheduled
If ActiveSheet.Cells(i, 7).Value = "Rescheduled" Then
' Define the email body
emailBody = "The following game has been rescheduled: " & vbNewLine & vbNewLine & "Date: " & ActiveSheet.Cells(i, 1).Value & vbNewLine & "Time: " & ActiveSheet.Cells(i, 2).Value & vbNewLine & "Location: " & ActiveSheet.Cells(i, 3).Value & vbNewLine & "Field #: " & ActiveSheet.Cells(i, 4).Value & vbNewLine & "Home Team: " & ActiveSheet.Cells(i, 5).Value & vbNewLine & "Away Team: " & ActiveSheet.Cells(i, 6).Value
' Split the email addresses into an array
recipientList = Split(ActiveSheet.Cells(i, 8).Value, ";")
' Loop through each recipient
For j = 0 To UBound(recipientList)
' Send the email to each recipient
On Error GoTo HandleError
Try
Dim email As Object
Set email = CreateObject("Outlook.Application")
Dim mailItem As Object
Set mailItem = email.CreateItem(0)
mailItem.Subject = emailSubject
mailItem.Body = emailBody
mailItem.To = Trim(recipientList(j))
mailItem.Send
Catch ex As Exception
MsgBox "An error occurred while sending the email: " & ex.Message
End Try
On Error GoTo 0
Next j
End If
Next i
End Sub
I was expecting it to work when I typed into the excel cell "Rescheduled" that it would send out an email to the email addresses that I had listed with information about their rescheduled game.

It seems you have mixed VBA and VB.NET syntax in your code, so that is why you've got such error message. For example, in the code you have the following declaration:
' Send the email to each recipient
On Error GoTo HandleError
Without any declaration of the HandleError point in the code where the flow should switch.
At the same time the try/catch block is used which is a feature of VB.NET, but not VBA. You need to use one or the other way of handling errors in the code. Depending of your programming language you need to use the try/catch block (VB.NET) or On Error GoTo (VBA).
The On Error statement has the following structure in VBA:
Sub InitializeMatrix(Var1, Var2, Var3, Var4)
On Error GoTo ErrorHandler
. . .
Exit Sub
ErrorHandler:
. . .
Resume Next
End Sub

Related

Confirm Email Sent by Displaying Sent/Not Sent Text

My goal is to know when an email has been sent.
I have msgbox code to know all email addresses have been processed.
My coding looks at cells/columns that are filled. I have a column where I list email addresses, a column for the body of the email, a column for the path to attachments, etc.
I want to add a "Status" for every email address. I want to say Sent or Not Sent (not sent would be if it was an invalid email address).
Now if an email address is invalid it debugs. I don't want to wait till it debugs to figure out it is not a valid email address. I want each row with an email address to say sent or not sent but keep sending even if it is not a valid email address.
The msgbox is great if it doesn't debug. I want to keep the msgbox.
Layout in my Excel workbook. I would like the sent and not sent to populate in the Status column.
Sub Send_Multiple_Emails()
dim sh as worksheet
set sh = thisworkbook.sheets("sheet1") '<-- rename to what the tabs name is
dim OA as Object
Dim msg As object
set OA = createobject("Outlook.Application")
Dim i as integer
dim last_row As Integer
last_row = application.worksheetfunction.counta(sh.range("B:B"))
for i = 2 To last_row
Set msg = OA.createitem(0)
msg.to = sh.Range("B" & i).Value
msg.cc = sh.Range("C" & i).Value
msg.subject = sh.range("D" & i ).Value
msg.body = sh.Range("E" & i).Value
if sh.Range("F" & i).Value <> "" Then
msg.attachments.add sh.range("F" & i).Value
msg.send
next i
msgbox "Mails Sent"
End Sub
This is a rare situation On Error Resume Next can be appropriate.
Bypass the expected error to handle it in the code.
Option Explicit
Sub RecognizeSendError()
Dim OA As Object
Dim msg As Object
Dim msgSent As Boolean
Set OA = CreateObject("Outlook.Application")
Set msg = OA.CreateItem(0)
msg.To = "NotValid"
Debug.Print "msg.To: " & msg.To
msg.Subject = "subject"
msg.Body = "body"
' use only for a specific purpose
On Error Resume Next
msg.Send
' deal with expected error
If Err <> 0 Then
'Debug.Print " Err: " & Err
msgSent = False
Else
msgSent = True
End If
' Return to normal error handling for unexpected errors
' Consider mandatory after On Error Resume Next
On Error GoTo 0
If msgSent Then
Debug.Print " Success"
Else
Debug.Print " Failure"
End If
Debug.Print "Done"
End Sub

Sending Data from Word Into Excel: Run-time error: '424' Object Required

I am trying to send data to Excel from Word after an email is sent. I have the email and the rest of it working. Now, I am trying to get the part with Excel working.
Private Sub btnGenerateEmail_Click()
'Instatiate Application Objects (using late binding)
Dim App As Object
Dim Msg As Object
Const olMailItem As Long = 0
'Declare Form Variables
Dim EmplName As String: EmplName = Me.frmEmployeeName
Dim IncidentDesc As String: IncidentDesc = Me.frmIncidentDescription
Dim EmplTrain As String: EmplTrain = Me.frmEmployeeTraining
Dim FaceOnRack As String: FaceOnRack = Me.frmFaceOnRack
Dim DrawingProb As String: DrawingProb = Me.frmDrawingProblem
Dim JobNum As String: JobNum = Me.frmJobNumber
Dim DrwNum As String: DrwNum = Me.frmDrawingNumber
Dim FaceDesc As String: FaceDesc = Me.frmFaceDescription
Dim Qty As String: Qty = Me.frmQty
Dim StockOrNon As String: StockOrNon = Me.frmStockOrNon
Dim FaceReplace As String: FaceReplace = Me.frmFaceReplace
'Set Application Objects (using late binding)
Set App = CreateObject("Outlook.Application")
Set Msg = App.CreateItem(olMailItem)
'Data validation
If IsNull(EmplName) Or EmplName = "" Then
MsgBox ("Please enter the employee's name."), vbCritical
Exit Sub
End If
If IsNull(IncidentDesc) Or IncidentDesc = "" Then
MsgBox ("Please describe how the face was broken."), vbCritical
Exit Sub
End If
If IsNull(EmplTrain) Or EmplTrain = "" Then
MsgBox ("Does the employee need more training to avoid these kind of incidents in the future?"), vbCritical
Exit Sub
End If
If IsNull(FaceOnRack) Or FaceOnRack = "" Then
MsgBox ("Was the already broken when on rack?"), vbCritical
Exit Sub
End If
If IsNull(DrawingProb) Or DrawingProb = "" Then
MsgBox ("Was the face scrapped because of an issue with the drawing/art?"), vbCritical
Exit Sub
End If
If IsNull(JobNum) Or JobNum = "" Then
MsgBox ("Please enter the job number or traveler number."), vbCritical
Exit Sub
End If
If IsNull(DrwNum) Or DrwNum = "" Then
MsgBox ("Please enter the drawing number."), vbCritical
Exit Sub
End If
If IsNull(FaceDesc) Or FaceDesc = "" Then
MsgBox ("Please enter a description of the face being scrapped."), vbCritical
Exit Sub
End If
If IsNull(Qty) Or Qty = "" Then
MsgBox ("Please enter the quantity being scrapped."), vbCritical
Exit Sub
End If
If IsNull(StockOrNon) Or StockOrNon = "" Then
MsgBox ("Is the face stock or non-stock?"), vbCritical
Exit Sub
End If
If IsNull(FaceReplace) Or FaceReplace = "" Then
MsgBox ("Does this face need to be replaced?"), vbCritical
Exit Sub
End If
'Compose HTML Message Body
Dim HTMLContent As String
HTMLContent = "<p style='font-family:Calibri; font-size:14px;'>This email is an autogenerated scrap face incident report.</p>" _
& "<table style='font-family:Calibri; font-size:14px;' width='75%' border='1' bordercolor='black' cellpadding='5'>" _
& "<tr><td width='65%'>Employee Name</td><td>" & EmplName & "</td></tr>" _
& "<tr><td>How was the face broken?</td><td>" & IncidentDesc & "</td></tr>" _
& "<tr><td>Does employee in question need more training to prevent future incidents?</td><td>" & EmplTrain & "</td></tr>" _
& "<tr><td>Was the face found on the rack already broken?</td><td>" & FaceOnRack & "</td></tr>" _
& "<tr><td>Was the face scrapped because of an issue with the drawing/art?</td><td>" & DrawingProb & "</td></tr>" _
& "<tr><td>Job/Traveler Number:</td><td>" & JobNum & "</td></tr>" _
& "<tr><td>Drawing Number:</td><td>" & DrwNum & "</td></tr>" _
& "<tr><td>Face Description:</td><td>" & FaceDesc & "</td></tr>" _
& "<tr><td>Quantity</td><td>" & Qty & "</td></tr>" _
& "<tr><td>Stock or Non-Stock</td><td>" & StockOrNon & "</td></tr>" _
& "<tr><td>Does this face need to be replaced?</td><td>" & FaceReplace & "</td></tr>" _
& "</table>"
'Construct the email, pass parameter values, & send the email
With Msg
.To = "test#test.com"
.Subject = "Scrap Face Incident Report"
.HTMLBody = HTMLContent
.Display
'.Send
End With
'MAY NEED WORK
'Make sure the generated email is the active window
App.ActiveWindow.WindowState = olMaximized
'Application.Windows("Scrap Face Incident Report - Message (HTML)").Activate
'Create entry in scrap report
Dim ScrapReportFile As String
ScrapReportFile = "\\jacksonville-dc\common\SOP's for JV\WIP\Jonathan\JG - How to Replace Scrapped Faces\Scrap List (Faces).xlsx"
'File exists
If Dir(ScrapReportFile) <> "" Then
Dim ObjExcel As Object, ObjWb As Object, ObjWorksheet As Object
Set ObjExcel = CreateObject("EXCEL.APPLICATION")
Set ObjWb = ObjExcel.Workbooks.Open(ScrapReportFile)
ObjExcel.Visible = True
With ObjWb.Worksheets(3)
Dim lastrow As Long: lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
MsgBox (lastrow)
End With
'ObjWb.Worksheets(1).Range("A1") = "SOP Title: " & SOPTitle
'ObjWb.Worksheets(1).Range("F1") = "Date: " & Format(Now, "MM/dd/yyyy")
'ObjWb.Save
'ObjWb.Close
End If
'File does not exist; throw error
End Sub
On this section of code:
With ObjWb.Worksheets(3)
Dim lastrow As Long: lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
MsgBox (lastrow)
End With
I am trying to send the data gathered from the form and create a new row at the bottom of the sheet and then insert the data into specified columns. When I am doing the .Cells(.Rows.Count...etc I am getting an error.
Run-time error: '424' Object Required
Word doesn't know what xlUp is, because that is from the Excel object model.
Add the following line:
Const xlUp as Long = -4162
as per the documentation of xlUps corresponding value.

Send only those emails that have attachments by way of a VBA code

I've just started working on macros and have made a pretty decent progress so far.
However, I'm stuck in a place and can't find an answer to it.
I'm using a macro to send emails to specific recipients via outlook. I'm sending multiple excel & pdf attachments in each email.
The code works fantastic! I, nonetheless, need to add a condition wherein an email that doesn't have any EXCEL attachments isn't sent and the outlook create mail item for this specific case only closes automatically.
The rest of the macro should continue for other clients with the excel attachments.
Hoping for someone to help me on this. Following is the code that I'm currently using.
Sub SendEmailWithReview_R()
Dim OutApp As Object
Dim OutMail As Object
Dim X As Long
Lastrow = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row
For X = 10 To Lastrow
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olmailitem)
With OutMail
.To = Cells(X, 4)
.CC = Cells(X, 6)
.Subject = Cells(X, 8)
.Body = Cells(1, 8)
strlocation = "C:\Users\HKhan\Desktop\Final Macro\" & Cells(X, 1) & "-OICR.xlsx"
On Error Resume Next
.Attachments.Add (strlocation)
On Error Resume Next
strlocation = "C:\Users\HKhan\Desktop\Final Macro\" & Cells(X, 1) & "-OICLR.xlsx"
On Error Resume Next
.Attachments.Add (strlocation)
On Error Resume Next
strlocation = "C:\Users\HKhan\Desktop\Final Macro\" & "OIC - Bank Details" & ".pdf"
On Error Resume Next
.Attachments.Add (strlocation)
On Error Resume Next
strlocation = "C:\Users\HKhan\Desktop\Final Macro\" & "OICL - Bank Details" & ".pdf"
On Error Resume Next
.Attachments.Add (strlocation)
On Error Resume Next
.Display
'send
End With
Next X
End Sub
So instead of waiting for errors or trying to suppress them better check if the file exists. Therefore you can use a function like this, which returns true if a file exists:
Public Function FileExists(FilePath As String) As Boolean
Dim Path As String
On Error Resume Next
Path = Dir(FilePath)
On Error GoTo 0
If Path <> vbNullString Then FileExists = True
End Function
For adding attachments I recommend to use an array for the file names, so you can easily loop through and attach the files if they exist. Everytime we add an attachment we increase the AttachedFilesCount too.
This way you don't use On Error Resume Next wrong and you don't run into debug issues because of that. So you have a clean solution.
With OutMail
.To = Cells(X, 4)
.CC = Cells(X, 6)
.Subject = Cells(X, 8)
.Body = Cells(1, 8)
Dim FileLocations As Variant
FileLocations = Array("C:\Users\HKhan\Desktop\Final Macro\" & Cells(X, 1) & "-OICR.xlsx", _
"C:\Users\HKhan\Desktop\Final Macro\" & Cells(X, 1) & "-OICLR.xlsx", _
"C:\Users\HKhan\Desktop\Final Macro\" & "OIC - Bank Details" & ".pdf", _
"C:\Users\HKhan\Desktop\Final Macro\" & "OICL - Bank Details" & ".pdf")
Dim AttachedFilesCount As Long
Dim FileLocation As Variant
For Each FileLocation In FileLocations
If FileExists(FileLocation) Then
.Attachments.Add (FileLocation)
AttachedFilesCount = AttachedFilesCount + 1
End If
Next FileLocation
If AttachedFilesCount > 0 Then
.Display 'display or send email
Else
.Close 'close it if no attachments
End If
End With
If you now still need additional error handling on adding the attachments (personally I don't think you need it necessarily) you can implement it like this:
On Error Resume Next 'turn error reporting off
.Attachments.Add (FileLocation) 'the line where an error might possibly occur.
If Err.Number <> 0 Then 'throw a msgbox if there is an error
MsgBox "Could not attach file """ & FileLocation & """ to the email." & vbCrLf & Err.Description, vbExclamation, "Error " & Err.Number, Err.HelpFile, Err.HelpContext
End If
On Error Goto 0 'turn error reporting on again!
To add condition to check if OutMail has Excel attachment, simply replace the following
.Display
'send
With these codes
Dim Atmt As Object
For Each Atmt In OutMail.Attachments
Dim sFileType As String
sFileType = LCase$(Right$(Atmt.fileName, 4)) ' Last 4 Char in Filename
Debug.Print Atmt.fileName
Select Case sFileType
Case ".xls", "xlsx"
.Display
'.send
End Select
Next

Macro send notification when release date is not valid anymore

Next is some macro which compare cell D with current date and if it is in past it send notification to email defined in cell L. The problem here is that the macro need to be run manually by pressing Alt+F8, so the question is how to make the macro automatically run when it noticed that updated cell D value is in past, so there is no need all the time to run the macro manually.
Thanks in advance
Sub SendMail()
Dim OutApp As Object
Dim OutMail As Object
Dim RelDate As Range
Dim lastRow As Long
Dim dateCell, dateCell1 As Date
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
OutApp.Session.Logon
lastRow = Range("A" & Rows.Count).End(xlUp).Row
On Error GoTo cleanup
For Each RelDate In Range("D2:D" & lastRow)
If RelDate = "" Then GoTo 1
dateCell = RelDate.Value
dateCell1 = Cells(RelDate.Row, "C").Value
If dateCell < Date Then ' this if cell value is smalle than today then it will send notification
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = Cells(RelDate.Row, "L").Value
.Subject = "Release Date Changed" ' Change your massage subject here
'Change body of the massage here
.Body = "Dear " & Cells(RelDate.Row, "E").Value _
& vbNewLine & vbNewLine & _
"The release date of " & Cells(RelDate.Row, "A").Value & _
" is changed to " & dateCell _
& vbNewLine & vbNewLine _
& vbNewLine & vbNewLine & _
"Regards," & vbNewLine & _
"Your Name"
.send
End With
On Error GoTo 0
Set OutMail = Nothing
End If
' Cells(RelDate.Row, "C").Value = dateCell
' RelDate.ClearContents
1: Next RelDate
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
Use this code in worksheet_change event. It will compare the date in all the changed cells in column "D" and if condition is true, it will call the sendmail procedure. Please adjust your sendmail code accordingly.
This code also works if you copy paste multiple rows of data.
Hope that help!. :-)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim to_email As String
Dim subject As String
Dim body As String
For Each cell In Target.Cells
On Error Resume Next
If cell.Column = 4 And cell < Date Then
On Error GoTo errhandler
to_email = ActiveSheet.Cells(cell.Row, "L").Value
subject = "Release Date Changed"
body = "Dear " & ActiveSheet.Cells(cell.Row, "E").Value _
& vbNewLine & vbNewLine & _
"The release date of " & ActiveSheet.Cells(cell.Row, "A").Value & _
" is changed to " & ActiveSheet.Cells(cell.Row, 4) _
& vbNewLine & vbNewLine _
& vbNewLine & vbNewLine & _
"Regards," & vbNewLine & _
"Your Name"
sendmail to_email, subject, body
End If
Next cell
Exit Sub
errhandler:
Err.Raise Err.Number, Err.Source, Err.Description
End Sub
Sub sendmail(to_email As String, subject As String, body As String)
adjust your code accordingly
End Sub

Formatting email body from Excel contents

I have a worksheet with given data,
I need to email the data using Microsoft Outlook in the required format for a specific date.
Say the date is 05 Jan 2015.
This is how the email should look,
The code is written in the modules of the Excel 2007 workbook,
Public Function FormatEmail(Sourceworksheet As Worksheet, Recipients As Range, CoBDate As Date)
Dim OutApp As Object
Dim OutMail As Object
Dim rows As Range
On Error GoTo FormatEmail_Error
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
For Each rows In Recipients.Cells.SpecialCells(xlCellTypeConstants)
If rows.value Like "?*#?*.?*" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = rows.value
.Subject = "Reminder"
.Body = "Hi All, " & vbNewLine & _
vbNewLine
.display
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next rows
On Error GoTo 0
Exit Function
FormatEmail_Error:
Set OutApp = Nothing
Application.ScreenUpdating = True
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatEmail of Module modOutlook"
End Function
If you want to create nicely formatted Outlook emails then you need to generate emails with formatting. Pure text-based-emails are evidently not sufficient and hence you must be looking for HTML formatted emails. If that's the case you probably aim to dynamically create HTML code with your VBA to mimic the nice visual representation of Excel.
Under the following link http://www.quackit.com/html/online-html-editor/ you'll find an online HTML editor which allows you to prepare a nicely formatted email and then shows you the HTML code which is necessary to get this formatting. Afterwards you just need to set in VBA the email body to this HTML code using
.HTMLBody = "your HTML code here"
instead of
.Body = "pure text email without formatting"
If that is not sufficient and you want to copy / paste parts of your Excel into that email then you'll have to copy parts of your Excel, save them as a picture, and then add the picture to your email (once again using HTML). If this is what you want then you'll find the solution here:
Using VBA Code how to export excel worksheets as image in Excel 2003?
Here is the answer for that serves the purpose. The html body is build using string builder concept and the email is formed as required(Altered the sub of email from the post). This is working fine.
Public Function FormatEmail(Sourceworksheet As Worksheet, CoBDate As Date, FinalRatioLCR As Variant, FinalRatioAUD As Variant)
Dim OutApp As Object
Dim OutMail As Object
Dim eMsg As String
Dim ToRecipients As String
On Error GoTo FormatEmail_Error
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
Dim Matrix2_1, Matrix2_2, Matrix2_3, Matrix3_1 As String
Dim FinanceAllCurrency, AllCurrencyT1, AllCurrencyT0, AllCurrencyAUD As Double
'FinanceAllCurrency = FinalRatioLCR
AllCurrencyT1 = 10.12
AllCurrencyT0 = 20.154
'AllCurrencyAUD = FinalRatioAUD
Matrix2_1 = "<td>" & FinalRatioLCR & "</td>"
Matrix2_2 = "<td>" & AllCurrencyT1 & "</td>"
Matrix2_3 = "<td>" & AllCurrencyT0 & "</td>"
Matrix3_1 = "<td>" & FinalRatioAUD & "</td>"
eMsg = "<head><style>table, th, td {border: 1px solid black; border-collapse:" & _
"collapse;}</style></head><body>" & _
"<table style=""width:50%""><tr>" & _
"<th bgcolor=""#D8D8D8"">LCR</th><th bgcolor=""#D8D8D8"">Finance</th>" & _
"<th bgcolor=""#D8D8D8"">Desk T+1</th><th bgcolor=""#D8D8D8"">Desk T+0</th></tr><tr>" & _
"<td>All Currency</td>" & Matrix2_1 & Matrix2_2 & _
Matrix2_3 & _
"</tr><tr><td>AUD Only</td>" & Matrix3_1 & "<td>-</td>" & _
"<td> - </td></tr></Table></body>"
ToRecipients = GetToRecipients
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = ToRecipients
.Subject = " Report -" & CoBDate
.HTMLBody = "Hi All, " & "<br></br><br></br><br></br><br></br>" & _
eMsg
.display
End With
On Error GoTo 0
Set OutMail = Nothing
On Error GoTo 0
Exit Function
FormatEmail_Error:
Set OutApp = Nothing
Application.ScreenUpdating = True
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatEmail of Module modOutlook"
End Function
Recipients adress is dynamically retrieved from a range.
Private Function GetToRecipients() As String
Dim rngRows As Range
Dim returnName As String
For Each rngRows In shMapping.Range(MAPPING_EMAIL_RECIPIENTS).rows
If Len(returnName) = 0 Then
returnName = rngRows.Cells(, 2).value2
ElseIf Len(rngRows.Cells(, 2).value2) > 0 Or rngRows.Cells(, 2).value2 Like "?*#?*.?*" Then
returnName = returnName & ";" & rngRows.Cells(, 2).value2
End If
Next
GetToRecipients = returnName
End Function

Resources