How to replace a special character in email body with a value in each row using Excel with VBA to multiple recipients - email

I am creating an Excel UserForm that creates a separate email for up to 500 recipients.
There are 4 columns on the worksheet: Name(Column A), Email(Column B), Value 1(Column C).
The code uses the For and Next loop style, where r is declared as an Integer (r = 2 To 500) and with the MailItem Object, .To =Cells(r,2).
The issue I have is attempting to incorporate values from a range (Column C) that replace special characters placed in the text box used to create the body of the email.
So if I were to type, Hello, There were ^&^ transactions that failed yesterday. and hit a command button used for "Send", it would send an email to the each email address listed in Column B and replace ^&^ with the value in Column C to each individual email address (each row).
Below is the VBA code as an example. There are a lot of other declared variables that I did not mention of course to keep this inquiry as short as possible.
Dim Signature As String, EmailSensitivity As String, EmailImportance As String
Dim Greeting As String, Punctuation As String, Security As String
Sub SendButton1_Click()
If SubjectText = vbNullString Then
If EmailBody1 = vbNullString Then
MsgBox "Form Incomplete:" & vbCrLf & vbCrLf & _
"No Subject or Email Text.", vbOKOnly
Exit Sub
End If
End If
If SubjectText = vbNullString Then
MsgBox "Form Incomplete:" & vbCrLf & vbCrLf & _
"Please enter Subject.", vbOKOnly
Exit Sub
End If
If EmailBody1 = vbNullString Then
MsgBox "Form Incomplete:" & vbCrLf & vbCrLf & _
"Please enter Email Text."
Exit Sub
End If
If SignatureText1 = vbNullString Then
Continue = MsgBox("Your email contains no signature." & vbCrLf & vbCrLf & _
"Are you sure you wish to proceed?", vbYesNo)
If Continue = vbNo Then
Exit Sub
End If
End If
Dim OutApp As Object, OutMail As Object
Dim r As Integer
Application.ScreenUpdating = False
For r = 2 To 501
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
On Error Resume Next
With OutMail
.Subject = Security & SubjectText.Value
.Body = EmailBody1.Value & vbCrLf & vbCrLf & _
SignatureText1.Value
.To = Cells(r, 2)
.Attachements.Add AttachmentText1.Value
.Importance = EmailImportance
.Sensitivity = EmailSensitivity
.Send
End With
Next r
Set OutApp = Nothing
Application.ScreenUpdating = True
Sheet1.Range("A2:B501").Clear
Continue = MsgBox("You have successfully generated a mass email!" & vbCrLf & vbCrLf & _
"Would you like to generate another email?", vbYesNo)
If Continue = vbNo Then
Application.Quit
End If
End Sub
I am still an amateur, so I'm working on cleaning a lot of unnecessary code, but this inquiry is mainly on replacing the special character with the value listed in each row.
This is my first time actually posting an inquiry on a forum, so please let me know if I am not following the correct procedure as your help is much appreciated.

It might be as simple as this, using the Replace function:
...
With OutMail
.Subject = Security & SubjectText.Value
.Body = Replace(EmailBody1.Value,"^&^",Cells(r, 3)) & _
vbCrLf & vbCrLf & SignatureText1.Value
...
Unrelated to this, but importat: On Error Resume Next means the sending (and any operation after that) will silently fail. This will make future debugging more difficult, frustrating and expensive. You should at least log relevant details about what error occured, and for what row in the sheet. And be sure to re-enable error-checking with on error goto 0 or similar after the part of your program that might fail unexpectedly.

Related

Add a new line in message body using the following vbscript

I have created a txt file to support the message body of the vbscript but it only reads the last line of the messagebody.txt
WScript.Sleep 100
Set WshShell=WScript.CreateObject("WScript.Shell")
Set objShell=WScript.CreateObject("WScript.Shell")
set objOutlook=CreateObject("Outlook.Application")
Set objMail=CreateObject("CDO.Message")
Set objMail=objOutlook.CreateItem(0)
strDesktop = WshShell.SpecialFolders("Desktop")
Set objFileToReadTo = CreateObject("Scripting.FileSystemObject").OpenTextFile(strDesktop + "\\send email with attachment\List_To.txt",1)
Set objFileToReadCC = CreateObject("Scripting.FileSystemObject").OpenTextFile(strDesktop + "\\send email with attachment\List_CC.txt",1)
Set objFileToReadSubject = CreateObject("Scripting.FileSystemObject").OpenTextFile(strDesktop + "\\send email with attachment\List_Subject.txt",1)
Set objFileToReadBody = CreateObject("Scripting.FileSystemObject").OpenTextFile(strDesktop + "\\send email with attachment\Email Body.txt",1)
Set objFileToReadAttachments = CreateObject("Scripting.FileSystemObject").OpenTextFile(strDesktop + "\\send email with attachment\List_Attachments_withFileExtension.txt",1)
Dim strLineTo
Dim strLineCC
Dim strLineSubject
Dim strLineBody
Dim strLineAttachments
objMail.Display
WScript.Sleep 10
do while not objFileToReadTo.AtEndOfStream
strLineTo = objFileToReadTo.ReadLine()
objMail.To=strLineTo
loop
objFileToReadTo.Close
WScript.Sleep 10
do while not objFileToReadCC.AtEndOfStream
strLineCC = objFileToReadCC.ReadLine()
objMail.cc = strLineCC
loop
objFileToReadCC.Close
'41
WScript.Sleep 10
do while not objFileToReadSubject.AtEndOfStream
strLineSubject = objFileToReadSubject.ReadLine()
objMail.Subject = strLineSubject
loop
objFileToReadSubject.Close
'48
WScript.Sleep 10
do while not objFileToReadBody.AtEndOfStream
strLineBody = objFileToReadBody.ReadLine()
objMail.Body = strLineBody & vbCRLF
loop
objFileToReadBody.Close
'55
WScript.Sleep 10
do while not objFileToReadAttachments.AtEndOfStream
strLineAttachments = objFileToReadAttachments.ReadLine()
objMail.Attachments.Add(strLineAttachments)
loop
objFileToReadAttachments.Close
'62
'objShell.Sendkeys "%s"
WScript.Sleep 40
'objShell.SendKeys "{TAB}"
'objShell.SendKeys "{UP}"
'objShell.SendKeys "{Enter}"
'set MyEmail=nothing
'objOutlook.Quit
'Set objMail = Nothing
'Set objOutlook = Nothing
and here is my messagebody.txt
Hi,
Testing vbscript
Regards,
abcd
It only reads the last ABCD and displays the same on the oulook window.
How do I make the scipt understand multiple lines?
I really don't know why you have used different text files for storing ToList, CCList, body etc. but if you are sure about using this approach, I won't change it.
I am just pointing out why you are not getting the full text in the email body. Replace the following code:
do while not objFileToReadBody.AtEndOfStream
strLineBody = objFileToReadBody.ReadLine() 'Here you are just overwriting the value contained in strLineBody in each loop iteration. Hence, in the end, only last line is left in this variable
objMail.Body = strLineBody & vbCRLF
loop
WITH
objMail.Body = objFileToReadBody.readAll
In the loop you replace the Body with each line you read, when you should be appending to it. Switch this line;
objMail.Body = strLineBody & vbCRLF
to be;
objMail.Body = objMail.Body & strLineBody & vbNewLine
If you forgo the loop and use ReadAll (as #Gurman has suggested), bear in mind that while this will be fine for minimal text, larger text files will make the process less efficient then looping through each line as you have started to do already.

Why does it take so long to copy MailItems in Outlook?

I want to copy MailItems from one Outlook folder to another.
When I run the following code it takes a long time like i.e. 5 seconds per MailItem even if the MailItems are only mails with few lines < 5kB.
I do this in the folders of an IMAP EMail account.
Sometimes I also get an error that an item can not be moved but only be copied.
What do I do wrong? This should be simple.
Currently the code creates first a copy of the mail in the original folder and then I move this copy. I would prefer to create a copy directly in the destination folder.
If I do this manually by dragging and dropping the mails (holding Ctrl to make a copy) this works fast like maybe 1s for 3 mails.
Sub CopyMailsToOtherFolder()
On Error GoTo CopyMailsToOtherFolder_Err
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Dim TestFolder As Outlook.Folder
Dim OutFolder As Outlook.Folder
Dim objItem As Object 'Note that myItem is declared as type Object so that it can represent all types of Outlook items including meeting request and task request items.
Dim MsgOrg As Outlook.MailItem
Dim MsgCopy As Outlook.MailItem
Dim lngI As Long
Set TestFolder = objNS.Folders("Edgar").Folders("Inbox")
Set OutFolder = objNS.Folders("Edgar").Folders("Inbox").Folders("TestOut")
Debug.Print "Start: " & Time()
'For lngI = 1 To TestFolder.Items.Count
For lngI = 1 To 3
Set objItem = TestFolder.Items(lngI)
If TypeName(objItem) = "MailItem" Then
Set MsgOrg = objItem
Debug.Print " Org: " & MsgOrg.Subject
Set MsgCopy = MsgOrg.Copy 'Creates copy in original folder
MsgCopy.Move OutFolder
End If
Next
Debug.Print "Done"
CopyMailsToOtherFolder_Exit:
Debug.Print "Exit: " & Time()
Exit Sub
CopyMailsToOtherFolder_Err:
Debug.Print "Error " & Err.Number & " - " & Err.Description
Resume CopyMailsToOtherFolder_Exit
End Sub

VBscript - Body of text file into Email

i m using the following script to send a few emails during the day, it takes one or more parameters (there are a few versions) and is called by a .bat file. The script is :
Const schema = "http://schemas.microsoft.com/cdo/configuration/"
Const cdoBasic = 2
Const cdoSendUsingPort = 2
Dim oMsg, oConf
Dim sDateTimeStamp
Set args = WScript.Arguments
arg1 = args(0)
' E-mail properties
Set oMsg = CreateObject("CDO.Message")
oMsg.From = "myemail#gmail.com" ' or "Sender Name <from#gmail.com>"
oMsg.To = "otheremail#gmail.com" ' or "Recipient Name <to#gmail.com>"
oMsg.Subject = "System Message"
oMsg.BodyPart.Charset = "Windows-1253"
oMsg.Textbody = "Attached files." & vbcrlf & _
"This on a new line" & vbcrlf & _
"This on yet another"
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Const FileToBeUsed = "DIRTEST.TXT"
Dim fso, f, g
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(FileToBeUsed, ForReading)
g = f.ReadAll
f.Close
Set f = Nothing
Set fso = Nothing
' GMail SMTP server configuration and authentication info
Set oConf = oMsg.Configuration
oConf.Fields(schema & "smtpserver") = "gmail.com" 'server address
oConf.Fields(schema & "smtpserverport") = 587 'port number
oConf.Fields(schema & "sendusing") = cdoSendUsingPort
oConf.Fields(schema & "smtpauthenticate") = cdoBasic 'authentication type
oConf.Fields(schema & "smtpusessl") = False 'use SSL encryption
oConf.Fields(schema & "sendusername") = "mymy#gmail.com" 'sender username
oConf.Fields(schema & "sendpassword") = "XXXXXX" 'sender password
oConf.Fields.Update()
'base64
' send message
oMsg.Send()
' Return status message
If Err Then
resultMessage = "ERROR " & Err.Number & ": " & Err.Description
Err.Clear()
Else
resultMessage = "Success Notification Message sent succesfully."
End If
Wscript.echo(resultMessage)
Right now the text body is set to :
Attached Files
This is a new line
This is yet another
I would like to interject a directory listing between line 1 and 2, either directly or by saving the directory listing in a text file, then putting the contents of said file in the email body, like so :
Attached Files
06/10/2016 <TIME> 13.000 Name1.txt
06/10/2016 <TIME> 300.000 Name2.pdf
06/10/2016 <TIME> 150.000 Name3.pdf
06/10/2016 <TIME> 5.000.000 Name4.pdf
This is a new line
This is yet another
EDIT : The above code succesfully appends the dir list to the mail subject, but also appends a batch of gibberish characters at the top.
The script is self explanatory
Edit: Formated size. Also note it give the size of folders. This can be slow, you may want to omit for folders. For instance the first time you run above code (on c:\ folder) windows has to read every folder into memory. That takes a while. Second time you run it all folders will be in the disk cache and it will be super fast.
Edit2 The VBS help file has recently been taken down at MS web site. It is available on my skydrive at https://1drv.ms/f/s!AvqkaKIXzvDieQFjUcKneSZhDjw It's called script56.chm.
Set fso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set fldr = fso.GetFolder("c:\")
Set Fls = fldr.files
Set Fldrs = fldr.subfolders
For Each thing in Fls
A= A & vbtab & thing.name & vbtab & thing.attributes & vbtab & FormatNumber(thing.size, 0) & vbtab & Thing.DateLastModified & vbcrlf
Next
For Each thing in Fldrs
A= A & vbtab & thing.name & vbtab & thing.attributes & vbtab & FormatNumber(thing.size, 0) & vbtab & Thing.DateLastModified & vbcrlf
Next
msgbox a
msgbox a

vbscript with outdated MS Access and Outlook

I have a VBscript that I wrote for someone that access their Microsoft Access Database and sends an email, via Outlook, to people in the database if they fit a certain criteria. I have the script run every day via Task Manager. The important part of the script is to run completely in the background
I developed this script on Windows 7 with the 2013 version of Access and Outlook, but when I went to set up the code on the person's computer, they had an out-dated version of Microsoft Office (I'm pretty sure it's 2010 or 2007, but I'm not familiar with any Office products earlier than 2013). Everything worked fine on Windows 7 with Office 2013
When I ran the script I came across two errors:
Outlook prompted the user saying that a script is trying to automatically send an email and to allow it to do so.
The email wasn't went strait to the outbox and wouldn't send (although I'm pretty sure that's because I didn't set up the Outlook account right)
How can I fix this?
Here is the code:
Dim connStr, objConn, getNames
connStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\source\to\database.accdb"
Set objConn = CreateObject("ADODB.Connection")
objConn.open connStr
Set rs = objConn.execute("SELECT Fname, Email, VolunteerDate, ID, VolunteerTime FROM people")
DO WHILE NOT rs.EOF
getNames = getNames + rs.Fields(1) & ","
Dim diff
diff = DateDiff("d",Date,rs.Fields(2))
Select Case diff
Case 0
Call sendTodayEmail(rs.Fields(1),rs.Fields(2),rs.Fields(0), rs.Fields(4))
Case 7
Call sendWeekEmail(rs.Fields(1),rs.Fields(2),rs.Fields(0), rs.Fields(4))
Case else
End Select
rs.MoveNext
Loop
Sub sendTodayEmail(a,b,c,d)
dim objOutlk
dim objMail
dim strMsg
const olMailItem = 0
set objOutlk = createobject("Outlook.Application")
set objMail = objOutlk.createitem(olMailItem)
objMail.To = a
objMail.subject = "Automatic Email"
strMsg = "Hello " & c & ", this is a reminder that you are scheduled to help today at " & d
objMail.body = strMsg
objMail.Send
End Sub
Sub sendWeekEmail(a,b,c,d)
dim objOutlk
dim objMail
dim strMsg
const olMailItem = 0
set objOutlk = createobject("Outlook.Application")
set objMail = objOutlk.createitem(olMailItem)
objMail.To = a
objMail.subject = "Automatic Email"
strMsg = "Hello " & c & ", this is a reminder that you are scheduled to help one week from today at " & d & "." & vbCrLf & "Scheduled date: " & b & vbCrLf & "Scheduled time: " & d
objMail.body = strMsg
objMail.Send
End Sub
Set objConn = Nothing
Newer versions of Outlook will not display security prompts if an up-to-date version of an anti-virus app is installed.
Otherwise your options are either Extended MAPI (C++ or Delphi only), Redemption (any language - I am its author) or products like ClickYes.
See http://www.outlookcode.com/article.aspx?id=52 for more details.

VBScript Outlook encounters encrypted email producing error 'Entrust Entelligence Security Provider'

I have an HTA and using VBScript to loop through Outlook email folders and get folder size. The HTA is run on a shared drive by staff, it is not an administrator tool. On occasion, my company will send encrypted emails. When the VBS hits one of these emails, the following happens:
1) VBS pauses.
2) Outlook displays the 'Entrust Entelligence Security Provider' error and asks the user to click 'OK'.
3) Once OK is clicked, the VBS continues.
The Outlook message does not bring focus to Outlook, so it is possible the user will not notice the message and continue to wait for the VBS to finish.
Is there any way of avoiding this message?
Here is my code:
public TotalSize
Sub OutlookDetail
TotalSize = 0
msgbox "Depending on the size of your Outlook account, this process may take up to 60 seconds" & vbcrlf & vbcrlf & _
"If you have encrypted emails, Outlook will make a sound and give you the 'Entrust Entelligence Security Provider' message. Click 'OK' to proceed."
Const olFolderInbox = 6
Set objOutlook = CreateObject("Outlook.Application")
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderInbox)
Set colItems = objFolder.Items
For Each objItem in colItems
'THE OUTLOOK ERROR MAY OCCUR HERE
TotalSize = TotalSize + objItem.Size
Next
Set objInbox = objNamespace.GetDefaultFolder(olFolderInbox)
GetSubfolders(objInbox)
msgbox "The size of Inbox and all Subfolders: " & Round((TotalSize / 1048576),2) & " MB"
End Sub
Sub GetSubfolders(objParentFolder)
Set colFolders = objParentFolder.Folders
For Each objFolder in colFolders
Set objSubfolder = objParentFolder.Folders(objFolder.Name)
intSize = 0
Set colItems = objSubfolder.Items
For Each objItem in colItems
'THE OUTLOOK ERROR MAY ALSO OCCUR HERE
intSize = intSize + objItem.size
next
TotalSize = TotalSize + intSize
GetSubfolders objSubfolder
Next
End Sub