I've done a fair bit of research on this topic and I've come to the conclusion that what I'm looking to do is just simply not possible. No matter what method is used from the Outlook object library; it seems that any signature that is automatically populated by functions like .display and .getInspector will always be wiped when .body, .HTMLBody, or .RTFBody are also called afterwards. I've gotten a lot of great advice such as below but it seems like any variation of .body will wipe the signature no matter how the signature is populated.
Dim OutApp As Object
Dim OutMail As Object
Dim signature As String
Set OutApp = CreateObject("Outlook.Application")
OutApp.Session.Logon
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.BodyFormat = olFormatHTML
.HTMLBody = "f"
.Display
End With
signature = OutMail.HTMLBody
I've been thinking lately, would it be possible to take the .htm signature file located in \AppData\Roaming\Microsoft\Signature and render that into the email itself by including it in .body? Does anyone know of any alternatives to using .display and .getInspector to input a signature?
Edit 2:
Dim OutApp As Object
Dim OutMail As Object
Dim signature As String
Set OutApp = CreateObject("Outlook.Application")
OutApp.Session.Logon
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
OutMail.Display
signature = OutMail.HTMLBody
With OutMail
.HTMLBody = "fdA" & signature
'.BodyFormat = olFormatHTML
End With
The body is wiped out because your code explicitly wipes it out. Or, in your particular case, Outlook never applies the signature because it sees that the HTML body was previously set.
Outlook will add the signature when you call Display or GetInspector. In your case, call Display first (at this point the signature is added), then read the HTMLBody property (it will now contain the signature). Merge it with your html body (note that two HTML strings cannot be simply concatenated, you must merge them), then set the HTMLBody property back.
Related
I'm trying to write the VBA code that will insert the default Outlook signature into an email that has been generated in Excel. There's a few people that might use the Excel template, so I need the VBA code to pick up the default signature of the user that's creating the email.
I've found various helpful things online, however I can't get it to work. I'm new to VBA so still learning.
The code below works for the email I need - expect the signature as I've removed all that code as I couldn't get it to work.
Any help would be greatly appreciated.
Sub EmailCreator()
ActiveWorkbook.Save
Dim olApp As Outlook.Application
Dim olMail As Outlook.MailItem
Dim blRunning As Boolean
blRunning = True
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If olApp Is Nothing Then
Set olApp = New Outlook.Application
blRunning = False
End If
On Error GoTo 0
strBody = "This is my message in HTML format"
Set olMail = olApp.CreateItem(olMailItem)
With olMail
.Subject = "abc"
.Attachments.Add ActiveWorkbook.FullName
.HTMLBody = strBody
.Display
End With
If Not blRunning Then olApp.Quit
Set olApp = Nothing
Set olMail = Nothing
End Sub
Firstly, Outlook will insert the default signature when you call Display if the message body has not been modified yet.
Secondly, once you call Display (and the message body gets populated with the signature), you will need to merge the two HTML strings - not just set the HTMLBody property (which would wipe out the signature), not concatenate the two HTML strings (which cannot produce a valid HTML document), but merge. The easiest would be to look for the position of the "<body" substring, scroll to the next ">" character (to take care of the body tag with attributes), then insert your HTML after that ">" character.
In windows 7 and Office 2007 I have been using a code which opens a new email in Outlook, attach a file and send it. The code it's not mine, I found it somewhere in the internet. The problem is that now I use Windows 10 and Office 2016, and using the same code produce different results as:
The original name of the file, let's say for example "Products.xlsx", is changed to "ProjectStatus.xlsx" (any file name is always changed to "ProjectStatus.xlsx")
If I open the file then Excel opens it and shows the original name of the file ("Products.xlsx")
If I send it, sometimes the recipients see the attached file as "ProjectStatus.xlsx" and sometimes see it as "Products.xlsx". But what always happens is that if they open the file, in excel is seen as "Products.xlsx"
I need the file name always be shown with the original name. How can I do this?
This is the code I use it and is executed from both access 2016 and excel 2016.
Sub MandaMailA(destinatarios As String, copia As String, subject As String, strbody As String, attachment1 As String, Optional attachment2 As String = "", Optional CO As String = "")
Dim OutApp As Object
Dim OutMail As Object
Dim SigString As String
Dim Signature As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
'Change only Mysig.htm to the name of your signature
SigString = Environ("appdata") & _
"\Microsoft\Firmas\VBA.htm"
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
On Error Resume Next
With OutMail
.To = destinatarios
.CC = copia
.BCC = CO
.subject = subject
.HTMLBody = strbody & "<br>" & Signature
.Display 'or use .Display
.Attachments.Add attachment1, olByValue, 1, "ProjectStatus"
.Attachments.Add attachment2, olByValue, 1, "ProjectStatus"
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
I notice that this code includes the word "ProjectStatus" but honestly I have not a deep knowledge of VBA.
Thanks in advance!!
A simple read of the Attachments.Add documentation is all you need, specifically the section on the optional DisplayName parameter:
This parameter applies only if the mail item is in Rich Text format
and Type is set to olByValue : the name is displayed in an Inspector
object for the attachment or when viewing the properties of the
attachment. If the mail item is in Plain Text or HTML format, then the
attachment is displayed using the file name in the Source parameter.
So if you always want to always use the original file name, simply delete the instances of , "ProjectStatus".
I've got the following VBA code to properly create an email using an email template, however I'm trying to change some text in the email body using the Substitute() function. I'm receiving an error and am unsure on how to resolve this, any help would be great!
Run-time error '1004':
Unable to get the Substitute property of the WorksheetFunction class
Here's the code attempting to create the email from my template...
Public Function GenerateEmail(fileName As String)
Application.ScreenUpdating = False
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItemFromTemplate(fileName)
With OutMail
.HTMLbody = WorksheetFunction.Substitute(OutMail.HTMLbody, "%TESTNUM%", "98541")
.Attachments.Add (Application.ActiveWorkbook.FullName)
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Function
Replace is the correct way to go here as answered by #Brax.
For anyone looking to understand the reason behind this error.
Just to explain why the 1004 happened with substitute, you need to check the parameters when using WorksheetFunction.
Here the issue is the allowed number of characters in a Excel cell. You can only put 32767 characters in the cell. Now, certainly, your HTMLBody has more characters in it, hence the error.
Sub Test()
Dim validString As String
Dim inValidString As String
validString = "a" & Space(32766)
inValidString = "b" & Space(32767)
'/ Works as the string length is valid cell length : < =32767
MsgBox WorksheetFunction.Substitute(validString, "a", "b")
'/ Fails as the string length is invalid in terms of cell length : >32767
MsgBox WorksheetFunction.Substitute(inValidString, "a", "b")
End Sub
You can just use Replace
.HTMLbody = Replace(OutMail.HTMLbody, "%TESTNUM%", "98541")
I've got an Excel spreadsheet built by someone else that sends an email to a group via a scheduled task, or at least used to. It recently stopped working. I don't have the time to rebuild his whole Rube Goldberg / Wile E. Coyote system at the moment, so I'm trying to fix it.
In one of the excel documents, this code exists
Set rng = Nothing
On Error Resume Next
Set rng = Sheets("Weight").Range("A2")
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected" & _
vbNewLine & "please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "eric.lizotte#.com"
.CC = ""
.BCC = ""
.Subject = Sheets("Weight").Range("A1")
.HTMLBody = Convert.ToString(rng)
.Send
End With
whenever I see so many "on error resume next" in something I grit my teeth.
What's happening is that it "works" but the email it sends is blank. In debug I can see that the subject content and body content both exist and have values. I rewrote it to be
OutMail.To = "eric.lizotte#.com"
OutMail.CC = ""
OutMail.BCC = ""
OutMail.Subject = Sheets("Weight").Range("A1")
OutMail.HTMLBody = Convert.ToString(rng)
OutMail.Send
and threw a debug point on the send, and checked the properties of outmail, and the subject and htmlbody have values. I can't figure out why after the send they are blank.
Given you are automating another application you probably should not rely on the default property of the range - just specify the property you want e.g. Value:
OutMail.Subject = Sheets("Weight").Range("A1").Value
OutMail.HTMLBody = rng.Value
You might also try the Text property for the HTMLBody:
OutMail.HTMLBody = rng.Text
You can then be confident that you are assigning a String to the mail properties which is what it expects.
I want to know when and possibly where my .doc file is opened. If document is copied from my PC and opened on another PC I want to email me on which PC document is opened.
Here is a potential solution, however, there are still many variables at play that can prevent an email being sent. The below VBA is inserted in the Document_Open event handler. The method is sending an email through the Outlook application so the user who opens the file would need to have that installed too.
Option Explicit
Private Sub Document_Open()
'only run when others open
If Application.userName <> "My Name" Then
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
Dim outApp As Object
Dim outMail As Object
Dim strBody As String
Dim userName As String
Set outApp = CreateObject("Outlook.Application")
Set outMail = outApp.createitem(0)
userName = Application.userName
strBody = userName & " has opened my file"
With outMail
.To = "myEmail#myDomain.com"
.CC = ""
.BCC = ""
.Subject = "My file has been opened"
.Body = strBody
'.Display
.Send
End With
Set outMail = Nothing
Set outApp = Nothing
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End If
End Sub
The above runs smoothly but I end up with a security warning on my laptop (I am not sure if this is true across everyone else's). However, hopefully this gives you a starting point for you to tinker with to get the complete results.
The only way I can think of is to write a VBA module within the word document that will fire on the onOpen event to create and send an email using the hosts default email program. Or you could attempt to send an email using CDO or maybe even sendmail within word using VBA. Note that if the person opening the document has macros disabled, the VBA module may not run.