I have been struggling with this for some time. I am trying to use Target Range
to allow my Outlook VBA code to send emails to specific individuals from a dropdown list for each row in excel. I can get the first row to work properly but after that, each row below does not function properly. It will not populate a new email for that specific row.
I have tried various ways to get the code to work but it is a no-go. Here is my code. Again I am trying to get this to work with several rows within the sheet, works for the first row and nothing after. The drop-down list corresponds to another column within my sheet so it knows where to get the email from.
My Code is as followed:
Private Sub Worksheet_Change
Application.EnableEvents = False
Dim xRgSel As Range
Dim xOutApp As Object
Dim xMailItem As Object
Dim xMailBody As String
On Error Resume Next
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set xRg = Range("G18:G500")
Set xRgSel = Intersect(Target, xRg)
ActiveWorkbook.Save
If Not xRgSel Is Nothing Then
Set xOutApp = CreateObject("Outlook.Application")
Set xMailItem = xOutApp.CreateItem(0)
xMailBody = "Cell(s) " & xRgSel.Address(False, False) & _
" in the worksheet '" & Me.Name & "' were modified on " & _
Format$(Now, "mm/dd/yyyy") & " at " & Format$(Now, "hh:mm:ss") & _
" by " & Environ$("username") & "."
With xMailItem
.To = Range("V18").Value
.Subject = "You have a new onboarding activity"
.Body = "Please complete this line item within 2 days of receiving this message. Please update spread sheet progress once you have completed the task."
.Attachments.Add (ThisWorkbook.FullName)
.Display
End With
Set xRgSel = Nothing
Set xOutApp = Nothing
Set xMailItem = Nothing
End If
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Related
I create a picture of a range and paste it into Outlook. The code works but I added a checkbox that is located in the range that I do NOT want to paste into Outlook.
I used ActiveSheet.CheckBoxes("Branch_ChkBox").Visible = False. It works sometimes and other times it doesn't. When I step through the code I get the same inconsistent results.
Public Sub ScreenShotResults4_with_Current()
Dim rng As Range
Dim olApp As Object
Dim Email As Object
Dim Sht As Excel.Worksheet
Dim wdDoc As Word.Document
Set rng = Sheets("Summary").Range("B9:N37")
rng.CopyPicture Appearance:=xlScreen, Format:=xlPicture
'Sheets("Summary").Branch_ChkBox.Visible = False
ActiveSheet.CheckBoxes("Branch_ChkBox").Visible = False
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set olApp = CreateObject("Outlook.Application")
Set Email = olApp.CreateItem(0)
Set wdDoc = Email.GetInspector.WordEditor
'strbody = "See production data for most recent 3 months. "
With Email
.To = Worksheets("Summary").Range("B21").Value
.Subject = "12 Month LO Production Lookback for " & Worksheets("Summary").Range("B21").Value & " (" & Worksheets("Summary").Range("B23").Value & "- " & Worksheets("Summary").Range("B35").Value & ")"
'.HTMLBody = "<BODY style=font-size:12.5pt;font-family:Calibri>" & "</p>" & strbody & RangetoHTML(rng) & Signature
.Display
wdDoc.Range.PasteAndFormat Type:=wdChartPicture
ActiveSheet.CheckBoxes("Branch_ChkBox").Visible = False
'if need setup inlineshapes hight & width
With wdDoc.Content
'--- paste the range image first, because it overwrites
' everything in the document
ActiveSheet.CheckBoxes("Branch_ChkBox").Visible = False
.PasteAndFormat Type:=wdChartPicture
.InlineShapes(1).Height = 350
'--- now add our greeting at the start of the email
.InsertBefore "See 12 month production data and current pipeline. " & vbCr & vbCr
'--- finally add our sign off after the image
.InsertAfter vbCr & _
"Thank you" & vbCr & vbCr
End With
.Display
End With
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set Email = Nothing
Set olApp = Nothing
ActiveSheet.CheckBoxes("Branch_ChkBox").Visible = True
End Sub
I was able to resolve by putting the same part of the code buy at the top right under the declarations
ActiveSheet.CheckBoxes("Branch_ChkBox").Visible = False
I have a spreadsheet for work that is used to monitor insurance cover for subcontractors.
I have the system set up so that when the expiry date listed in one of the columns has passed (i.e. their insurance is out of date), the cell with the renewal date turns from green to red and in turn, an adjacent cell turns from True to False. This change of True to False then triggers some more code that sends me an email to remind me that the insurance has expired.
I have the macro set up to run every time this workbook opens, however as this sheet is opened and closed multiple times per day, I'd like to make it run only when it is opened for the first time each day.
Several people will be CC'd to the email and I'd like to avoid pinging them multiple times with the same email.
I also plan to integrate it as a tab into a larger spreadsheet; I am keen to know if I'd need to change the code in any way to achieve this.
This is the code that triggers the email. It is in the "Sheet 1" window.
Dim xRg As Range
'Update by Extendoffice 2018/3/7
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Target.Cells.Count > 1 Then Exit Sub
Set xRg = Intersect(Range("H3:H7,L3:L7,P3:P7, U3:U7"), Target)
If xRg Is Nothing Then Exit Sub
If IsNumeric(Target.Value) And Target.Value = False Then
Call Mail_small_Text_Outlook
End If
End Sub
Sub Mail_small_Text_Outlook()
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Transport, " & vbNewLine & vbNewLine & _
"Our records indicate a sub-contractor's cover has expired." & vbNewLine & _
"- #Transport: Please check the Sub-Contractor Cover spreadsheet to determine the correct sub-contractor," & vbNewLine & _
"- #Operations: please suspend the relevant sub-contractor until they supply a copy of their updated cover." & vbNewLine & _
vbNewLine & vbNewLine & _
"Best regards," & vbNewLine & _
"Sub-Contractor Notification Service"
On Error Resume Next
With xOutMail
.To = "Me#WorkAddress.co.uk"
.CC = "Operations#WorkAddress.co.uk; OperationsManager#WOrkAddress.co.uk"
.BCC = ""
.Subject = "(Test) URGENT: A Sub-Contractor's Cover Has Expired"
.Body = xMailBody
.Send
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
This is the code that triggers the macro to run on opening the workbook. It is in the "This workbook" window
Private Sub Workbook_open()
Sheet1.Mail_small_Text_Outlook
End Sub
I continue my work starting from the 1st question here:
Excel VBA - Outlook Email - Body created with rows having a particular value
Now i have another problem.
I want to repeat the below MACROs on all the SHEETS of my file.
In particular, how can I repeat this function on different SHEETS by only clicking in 1 button present in all the sheets?
All the sheets have the same structure.
I mean, the table resulting in the email must be implemented by adding the datas in all the sheets.
The data should be copied starting from the 1st sheet, for ex. TEST(1) to the last sheet, TEST(9).
The email generated after this process must be ONLY one.
Determine the body range
Sub EmailRange()
Dim Initial As Range, Final As Range, nCell As Range
On Error Resume Next
Set Initial = Sheets("TEST").Application.InputBox("Range", xTitleId, "B1:K20", Type:=8)
On Error GoTo 0
For Each nCell In Initial.Resize(Initial.Rows.Count, 1)
If nCell.Offset(, -1) = "X" Then
If Not Final Is Nothing Then
Set Final = Union(Final, nCell.Resize(1, Initial.Columns.Count))
Else
Set Final = nCell.Resize(1, Initial.Columns.Count)
End If
End If
Next nCell
If Not Final Is Nothing Then
MAIL Final
Else
MsgBox "ATTENZIONE!!!" & vbNewLine & "Seleziona un range di celle valido.", vbOKOnly
End If
End Sub
Send the email with the range
Sub MAIL(Final as Range)
Dim OutApp As Object, OutMail As Object
Dim StrBodyIn As String, StrBodyEnd As String
StrBodyIn = "Bonjour," & "<br>" & " " & "<br>" & "Buongiorno," & "<br>"
StrBodyEnd = " " & "<br>" & "Cordialement" & "<br>" & " " & "<br>" & Range("M2") & "<br>"
Application.EnableEvents = False
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "email#gmail.com"
.CC = ""
.BCC = ""
.Subject = "SITUATION"
.HTMLBody = "<p style='font-family:calibri;font-size:16'>" & StrBodyIn & RangetoHTML(Final) & "<p style='font-family:calibri;font-size:16'>" & StrBodyEnd
.Display 'or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
I've tried with something like this, but it does not work:
For I = 1 To Worksheets.Count
Sheets(I).Select
***[...]CODE OF "Determine the body range"***
Next I
Sheets("TEST(I)").Select
How can I write an excel macro which will send an automatic e-mail when one of the certain range of cells' value has been changed?
The problem is the range of cells I have chosen has formula which is directly linked to other spreadsheet cells. And those cells' data has been updated by a web connection query of Excel. As shown in the picture below, the a1:b5 range has formula linked to d1:e5 range.
Here is my syntax
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngChangeCells As Range
Dim objOutlookApp As Outlook.Application
Dim objMailItem As Outlook.MailItem
Dim strMailBody As String
On Error Resume Next
Set rngChangeCells = Intersect(Target, Me.Range("a1:b5"))
On Error GoTo 0
If Not rngChangeCells Is Nothing Then
Set objOutlookApp = New Outlook.Application
Set objMailItem = objOutlookApp.CreateItem(olMailItem)
strMailBody = "Cell(s) " & rngChangeCells.Address(False, False) & _
" in the worksheet '" & Me.Name & "' were modified on " & _
Format$(Now, "mm/dd/yyyy") & " at " & Format$(Now, "hh:mm:ss") & _
" by " & Environ$("username") & "."
With objMailItem
.To = "myagmarchuluun#gmail.com"
.Subject = "It has changed"
.Body = strMailBody
.Display
End With
Set rngChangeCells = Nothing
Set objOutlookApp = Nothing
Set objMailItem = Nothing
End If
End Sub
enter image description here
Something like this.
Note: Change YourMacroName to the name of your macro in the code.
If you want the code to work for another cell or more cells you can change the range in the event.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Application.Intersect(Range("A1"), Target) Is Nothing Then
If IsNumeric(Target.Value) And Target.Value > 200 Then
Call YourMacroName
End If
End If
End Sub
Test this example macro to create/display a Outlook mail with a small text message.
You must copy this macro in a standard module and not in the worksheet module, see this page how.
Note: I use .Display in the code to display the mail, you can change that to .Send
Do not forget to change Call YourMacroName to Call Mail_small_Text_Outlook in the Change event.
Sub Mail_small_Text_Outlook()
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
'Working in Excel 2000-2016
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"Cell A1 is changed" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
With OutMail
.To = "ron#debruin.nl"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
'You can add a file like this
'.Attachments.Add ("C:\test.txt")
.Display 'or use .Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
https://www.rondebruin.nl/win/s1/outlook/bmail9.htm
What is the correct syntax for pausing a VBA until the user saves an excel attachment? In the VB below the user is prompted upon opening the workbook with a selection, if that selection is yes then another message box appears asking them to fill out a form and save. I am trying to pause the VB until save is clicked. However, I am getting many compile errors currently. The lines with a ** ** were added to try and accomplish thisThank you :).
VB
Private Sub Workbook_Open()
Dim WS As Worksheet, Rng As Range, c As Range
Dim OutApp As Object, OutMail As Object
Dim Msg As String, Addr As String, FName As String, i As Long
Dim obj As Object
**Dim MyDoc As Document**
Dim MyFileCopy As String
Dim intAnswer As Integer
'define path
MyFileCopy = "L:\NGS\HLA LAB\total quality management\QC & QA\DOSE reports\DOSE reporting form Attachment.xlsx"
'open sheet
Sheets("Email").Activate
intAnswer = MsgBox("Are there any issues to report", vbYesNoCancel)
Select Case intAnswer
Case vbYes
Range("D2").Value = "x"
MsgBox ("Please select an issue and save"), vbExclamation
'create a separate sheet2 to mail out and pause VB
Sheets(2).Copy
Set wkb = ActiveWorkbook
With wkb
**Set MyDoc = Documents.Add
MyDoc.SaveAs "MyFileCopy.xlsx"
DoEvents
Do
Loop Until MyDoc.Saved
.Close True**
End With
Case vbCancel
Application.SendKeys "%{F11}", True
Case Else
Range("C2").Value = "x"
End Select
'create connection, check condition, send email
Set OutApp = CreateObject("Outlook.Application")
Set WS = ThisWorkbook.Sheets("Email")
With WS
Set Rng = .Range("A2", .Range("A" & .Rows.Count).End(xlUp))
End With
For Each c In Rng
Msg = "For " & WS.Cells(2, 2) & Chr(14) & Chr(14)
For i = 3 To 4
If LCase(WS.Cells(2, i)) = "x" Then
Msg = Msg & " -" & WS.Cells(1, i) & Chr(14)
End If
Next
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = c
.CC = ""
.BCC = ""
.Subject = "Daily Operational Safety Briefing"
.Body = Msg
If Range("D2").Value & Chr(14) = "x" Then .Attachments.Add MyFileCopy, 1
.Send
End With
Next c
Set OutMail = Nothing
Set OutApp = Nothing
'confirm message sent, clear sheet, and delete copy
MsgBox "The data has been emailed sucessfully.", vbInformation
Range("C2:D2").ClearContents
Kill MyFileCopy
'Exit and do not save
Application.Quit
ThisWorkbook.Close SaveChanges:=False
End Sub