vba email embed image not showing - image

I have an odd experience here. I have had loads of problems embedding a logo or image to emails using the src=cid... found out it wont show if not setting size for example.
I have an Access application to send from, but have broken it down to the code below using Excel.
BUT
It now works fine, if I display the email and then send it. Not doing anything else at all. Just display then send.
If I send directly from vba, the image will not display properly. The attachment symbol shows and Outlook itself will put the image inline, but say, gmail, wont. It's not gmails fault, as the attachmet symbol shows in Outlook. It doesn't if I display and then send.
I suspect it's still something with sizing or placing. Without the width part, Outlook will still show the image at correct place, but still show as attachment. So when you display and press send then there must me another attribute set or something. I cannot find out what!
Hope someone can help or has an idea! I'm not the strongest in HTLM, so it's probably something simple...
Thanks
John
Sub test()
Dim oApp As Outlook.Application
Dim oEmail As MailItem
Dim colAttach As Outlook.Attachments
Dim oAttach As Outlook.Attachment
'create new Outlook MailItem
Set oApp = CreateObject("Outlook.Application")
Set oEmail = oApp.CreateItem(olMailItem)
'add graphic as attachment to Outlook message
'change path to graphic as needed
Set colAttach = oEmail.Attachments
Set oAttach = colAttach.Add("C:\temp\logo.jpg")
oEmail.Close olSave
'change the src property to 'cid:your picture filename'
'it will be changed to the correct cid when its sent.
oEmail.HTMLBody = "<BODY><IMG src=""cid:logo.jpg"" width=200> </BODY>"
oEmail.Save
oEmail.To = "someemailtogoinhere#gmail.com"
oEmail.Subject = "test"
oEmail.Display
'oEmail.Send
Set oEmail = Nothing
Set colAttach = Nothing
Set oAttach = Nothing
Set oApp = Nothing
End Sub

Just to post the simple form of code that works. Big thanks to #Eugene Astafiev.
Sub test()
Dim oApp As Outlook.Application
Dim oEmail As MailItem
Dim colAttach As Outlook.Attachments
Dim oAttach As Outlook.Attachment
Dim olkPA As Outlook.PropertyAccessor
Const PR_ATTACH_CONTENT_ID = "http://schemas.microsoft.com/mapi/proptag/0x3712001F"
'create new Outlook MailItem
Set oApp = CreateObject("Outlook.Application")
Set oEmail = oApp.CreateItem(olMailItem)
'add graphic as attachment to Outlook message
'change path to graphic as needed
Set colAttach = oEmail.Attachments
Set oAttach = colAttach.Add("C:\temp\logo.jpg")
Set olkPA = oAttach.PropertyAccessor
olkPA.SetProperty PR_ATTACH_CONTENT_ID, "logo.jpg"
oEmail.Close olSave
'change the src property to 'cid:your picture filename'
'it will be changed to the correct cid when its sent.
oEmail.HTMLBody = "<BODY><IMG src=""cid:logo.jpg""> </BODY>"
oEmail.Save
oEmail.To = "someemail#gmail.com"
oEmail.Subject = "test"
oEmail.Send
Set oEmail = Nothing
Set colAttach = Nothing
Set oAttach = Nothing
Set oApp = Nothing
End Sub

You need to set PR_ATTACH_CONTENT_ID property (DASL - http://schemas.microsoft.com/mapi/proptag/0x3712001F) on the attachment using Attachment.PropertyAccessor. Be aware, the PropertyAccessor property of the Attachment class was added in Outlook 2007.
You may find the How do I embed image in Outlook Message in VBA? link helpful.

Related

Outlook add-in mailitem.display not working Visual Basic

I'm in the process of converting some outlook VBA macros to an Add-in. I am having difficulty with my macros that create emails based on a template. I decided to code a simple button to create and display a new email with the subject test.
Everything is working up to displaying the email which doesn't happen.
Private Sub ButtonGenEmail_Click(sender As Object, e As EventArgs) Handles ButtonGenEmail.Click
Me.Close()
Dim objApp As Outlook.Application
Dim objMail As Outlook.MailItem
objApp = Globals.ThisAddIn.Application
objMail = objApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem)
objMail.Subject = "test"
objMail.Save()
objMail.Display(False)
End Sub
At one point I added msgbox "Done" after objMail.Display(False) and the message never appears.
Thanks in advance
This should obviously work. I'm not so skilled in Outlook but I guess the problem here is that you run it from a form (I see the Me.Close)
Isn't then Outlook blocking to display the mail because the form is still open (I guess modal = ShowDialog())?
I think you will have to either change the form to be not modal (use Show() instead of ShowDialog()) or handle the event after the form is closed, something like
All code below written from top of my mind, so I may miss something
A method from where you initialize the form
Dim frm as new YourForm()
frm.ShowDialog()
if frm.MyState = TheyClickOnButton Then
' Run your mailItem code here
End If
in the form code
Public Enum State
Unknown = 0
TheyClickedOnButton
End Enum
Public Property MyState as State
Private Sub ButtonGenEmail_Click(sender As Object, e As EventArgs) Handles ButtonGenEmail.Click
MyState = TheyClickedOnButton
Me.Close()
End Sub

Mail format getting changed in recepient's mailbox in outlook

I have written some code in vbscript to automatically send mails to a recepient using outlook,Everything is working fine but i am having just one issue, The format what i have selected for the message body getting changed in the recepient's mail box.I used font color- blue and font face -calibri but it got changed into Times new roman without any color.
Any solution?
Set MyApp = CreateObject("Outlook.Application")
Set MyItem = MyApp.CreateItem(0) 'olMailItem
With MyItem
.To = "abc#com"
.Subject = ""
.ReadReceiptRequested = False
.HTMLBody = "<font size='3' face='Calibri' color='#151B54'>Hi,Whatever written here got changed into plain text.<font>"
.Attachments.Add "C:\Excels\"& objFso.GetFileName(objFile.path)
End With
MyItem.Display
End if
Or is there any setting that i have to change in the outlook for the sent mails?
This works perfectly fine with me:
MailItem sendMail = Globals.ThisAddIn.Application.CreateItem(OlItemType.olMailItem);
sendMail.Subject = "test";
sendMail.To = SenderName; //or email
sendMail.HTMLBody = "<font size='50' face='Verdana' color='#ff0000'>Hi,Whatever written here got changed into plain text.<font>";
sendMail.Send();
When I send this to myself I recieve a big red text in verdana
Note that this is c# so I'm not sure if it will help you
EDIT:
One more thing: font size='3' won't work with me either. Because it's too small to display decently

Changing Janus GridEx grid DatabaseName programmatically

I'm using the Janus GridEx grid control in Visual Basic 6 and I'm trying to change one of the properties (DatabaseName) programmatically before it uses the connection. The one I set in the properties window can be wrong and I'd like to set it dynamically before it's used. I've tried to set it in Form_Initialize() or Form_Load() and neither of them override the on in the properties window before it's used.
Any ideas?
Create one custom recordset and set to ADORecordset property's grid
gData.HoldFields
Set gData.ADORecordset = rstData
if you created one recordset with equal schema to database you can do
saved data
IDataRepository.Save(gData.ADORecordset)
Save skeleton
function Save (rs as adodb.recordset)
Dim cn As ADODB.Connection
Set cn = new ADODB.Connection
cn.CursorLocation = adUseClient
cn.Open Cnstr
Set rs.ActiveConnection = cn
If rs.LockType = adLockBatchOptimistic Then
rs.UpdateBatch
Else
rs.Update
End If
Set rs.ActiveConnection = Nothing
cn.Close
Set cn = Nothing
end function
for property with mask you can for example
gData.Columns("Status").ValueList.Clear
gData.Columns("Status").ValueList.Add "A", "Accepted"
gData.Columns("Status").ValueList.Add "R", "Rejected"
Interval value is preserved and user can view some more human readable

Is there an Alternative to using the LoadPicture("bmp_or_icon_file_path") to loading Images in Excel 2007 VBA

I have an Excel 2007 Worksheet with many buttons and labels that act as menu options (i.e. user clicks the buttons, labels with images) and is presented with forms, or some thing else.
These images / icons for the buttons and labels are loaded in VBA by assigning the Picture property of the Control and calling LoadPicture() method with the full image file path as parameter, like So.
With SomeFormObject
.cmdOpenFile.Picture = LoadPicture("F:\projectname\images\fileopen.BMP")
End With
This method of loading images for buttons, other controls is causing 2 issues.
1) It creates a dependency on the image files and physical location for every user, so if a user does not have the drive mapped and files present, the VBA fails with runtime error of file or path not found.
2)
The app gets very slow if the images are on a shared drive (which is the case)
I want to eliminate both issues and somehow load icons, images into control internally, without any external dependencies on external image files.
What is the best way to achieve this in Excel 2007 VBA?
I could not file any Visual Basic 6.0 / Visual Studio style "Resource File Editor" / feature with which to accomplish this.
Please advice! thank you
-Shiva #
mycodetrip.com
I really hope that there is a easier way to do this, but this is the only one I found:
The Idea is:
You keep the Pictures embedded in a Sheet and every time you want to set the pictures for the Command you export them from your worksheet to a file and load them through LoadPicture. The only way to export an embedded Picture through VBA that I found is by making it a Chart first.
The following code is based on 'Export pictures from Excel' from johnske
Option Explicit
Sub setAllPictures()
setPicture "Picture 18", "CommandButtonOpen"
setPicture "Picture 3", "CommandButtonClose"
End Sub
Sub setPicture(pictureName As String, commandName As String)
Dim pictureSheet As Worksheet
Dim targetSheet As Worksheet
Dim embeddedPicture As Picture
Dim pictureChart As Chart
Dim MyPicture As String
Dim PicWidth As Long
Dim PicHeight As Long
Set pictureSheet = Sheets("NameOfYourPictureSheet") ' <- to Change '
Set targetSheet = Sheets("NameOfYourSheet") ' <- to Change '
Set embeddedPicture = pictureSheet.Shapes(pictureName).OLEFormat.Object
With embeddedPicture
MyPicture = .Name
PicHeight = .ShapeRange.Height
PicWidth = .ShapeRange.Width
End With
Charts.Add
ActiveChart.Location Where:=xlLocationAsObject, Name:=pictureSheet.Name
Set pictureChart = ActiveChart
embeddedPicture.Border.LineStyle = 0
With pictureChart.Parent
.Width = PicWidth
.Height = PicHeight
End With
With pictureSheet
.Select
.Shapes(MyPicture).Copy
With pictureChart
.ChartArea.Select
.Paste
End With
.ChartObjects(1).Chart.Export Filename:="temp.jpg", FilterName:="jpg"
End With
pictureChart.Parent.Delete
Application.ScreenUpdating = True
targetSheet.Shapes(commandName).OLEFormat.Object.Object.Picture = LoadPicture("temp.jpg")
Set pictureChart = Nothing
Set embeddedPicture = Nothing
Set targetSheet = Nothing
Set pictureSheet = Nothing
End Sub
Sub listPictures()
' Helper Function to get the Names of the Picture-Shapes '
Dim pictureSheet As Worksheet
Dim sheetShape As Shape
Set pictureSheet = Sheets("NameOfYourSheet")
For Each sheetShape In pictureSheet.Shapes
If Left(sheetShape.Name, 7) = "Picture" Then Debug.Print sheetShape.Name
Next sheetShape
Set sheetShape = Nothing
Set pictureSheet = Nothing
End Sub
To Conclude:
Loading the Images from a Mapped Networked Drive seems less messy, and there shouldn't be that much of a speed difference.
2 alternatives i can think of: form.img.picture=pastepicture , and = oleobjects("ActiveXPictureName").object.picture.

Run VBA on any PowerPoint to change the LanguageID

I'm trying to create a toolbar with a button that will change the LanguageID for all shapes and text boxes in a PowerPoint document to EnglishUS. This is to fix a problem where if someone spell-checks a document using another language (in this instance, French), that language is embedded into the .ppt file itself. When another user tries to spell-check the same area using another language, say English, the words the spell checker suggests are in the original language. For instance, it tried to correct the word 'specified' to 'specifie', a French word. From what I've read, the only way to fix this language issue is with a VBscript, and the only way to run a VBscript in Powerpoint without embedding it into a .ppt and loading that file every time is by creating an add-in with a toolbar button to run the macro, also using VBS. Below is the code which I've taken from various sources, and when I tried to put it together, it didn't work (although it did compile). If someone could take a look, I'm sure its a simple syntax error or something like that, it would be a HUGE help. Thanks in advance!!
By the way if anyone knows an easier way to run a macro in PPT without having to open a certain PPT every time, I'm ALL ears.
and now, the script:
Sub Auto_Open()
Dim oToolbar As CommandBar
Dim oButton As CommandBarButton
Dim MyToolbar As String
''# Give the toolbar a name
MyToolbar = "Fix Language"
On Error Resume Next
''# so that it doesn't stop on the next line if the toolbar's already there
''# Create the toolbar; PowerPoint will error if it already exists
Set oToolbar = CommandBars.Add(Name:=MyToolbar, _
Position:=msoBarFloating, Temporary:=True)
If Err.Number <> 0 Then
''# The toolbar's already there, so we have nothing to do
Exit Sub
End If
On Error GoTo ErrorHandler
''# Now add a button to the new toolbar
Set oButton = oToolbar.Controls.Add(Type:=msoControlButton)
''# And set some of the button's properties
With oButton
.DescriptionText = "Fix Language for Spell Check"
''# Tooltip text when mouse if placed over button
.Caption = "Click to Run Script"
''# Text if Text in Icon is chosen
.OnAction = "Button1"
''# Runs the Sub Button1() code when clicked
.Style = msoButtonIcon
''# Button displays as icon, not text or both
.FaceId = 59
End With
''# Repeat the above for as many more buttons as you need to add
''# Be sure to change the .OnAction property at least for each new button
''# You can set the toolbar position and visibility here if you like
''# By default, it'll be visible when created
oToolbar.Top = 150
oToolbar.Left = 150
oToolbar.Visible = True
NormalExit:
Exit Sub ''# so it doesn't go on to run the errorhandler code
ErrorHandler:
''# Just in case there is an error
MsgBox Err.Number & vbCrLf & Err.Description
Resume NormalExit:
End Sub
Sub Button1()
''# This is the code to replace the LanguageID throughout the ppt
Option Explicit
Public Sub ChangeSpellCheckingLanguage()
Dim j As Integer, k As Integer, scount As Integer, fcount As Integer
scount = ActivePresentation.Slides.Count
For j = 1 To scount
fcount = ActivePresentation.Slides(j).Shapes.Count
For k = 1 To fcount
If ActivePresentation.Slides(j).Shapes(k).HasTextFrame Then
ActivePresentation.Slides(j).Shapes(k) _
.TextFrame.TextRange.LanguageID = msoLanguageIDEnglishUS
End If
Next k
Next j
End Sub
End Sub
The answer is quite obvious if it is not clear yet.
As you can see the sub Button1() encapsulates another sub. Thus, I advise you to remove the call ChangeSpellingCheckingLanguage and the last End sub, then your code will work.
This may be an incredibly late answer, but I just solved this problem using VBScript (which can be run outside of powerpoint). The script as written will change the language of each powerpoint file in a given directory (and subdirectories) to English. Here's the script:
Option Explicit
'microsoft office constants
Const msoTrue = -1
Const msoFalse = 0
Const msoLanguageIDEnglishUS = 1033
Const msoGroup = 6
'starting folder (current folder)
Const START_FOLDER = ".\"
'valid powerpoint file extensions
Dim FILE_EXTENSIONS : FILE_EXTENSIONS = Array("pptx", "pptm", "ppt", "potx", "potm", "pot")
'desired language for all Text
Dim DESIRED_LANGUAGE : DESIRED_LANGUAGE = msoLanguageIDEnglishUS
'VBScript file system objects for starting folder
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objStartingFolder : Set objStartingFolder = objFSO.GetFolder(START_FOLDER)
IterateContainingItems objStartingFolder
'recursive subroutine to iterate each file in specified folder and all subfolders
Sub IterateContainingItems(objCurrentFolder)
Dim colFiles : Set colFiles = objCurrentFolder.Files
Dim objCurrentFile
For Each objCurrentFile in colFiles
ReportInfo(objCurrentFile)
Next
Dim colFolders : Set colFolders = objCurrentFolder.SubFolders
Dim objNextFolder
For Each objNextFolder in colFolders
IterateContainingItems objNextFolder
Next
End Sub
'subroutine executed for every file iterated by IterateContainingItems subroutine
Sub ReportInfo(objCurrentFile)
Dim strPathToFile
strPathToFile = objFSO.GetAbsolutePathName(objCurrentFile.Path)
If isPowerpointFile(strPathToFile) Then
Dim objPowerpointApp, objPresentations, objPresentation, objSlides, intSlideCount
set objPowerpointApp = CreateObject("Powerpoint.Application")
set objPresentations = objPowerpointApp.Presentations
Set objPresentation = objPresentations.Open(strPathToFile, msoFalse, msoFalse, msoFalse)
Set objSlides = objPresentation.Slides
intSlideCount = objSlides.Count
ResetLanguage objPresentation
objPresentation.Save
objPresentation.Close
objPowerpointApp.Quit
End If
End Sub
'check if given filepath specifies a powerpoint file as described by the "constant" extension array
Function isPowerpointFile(strFilePath)
Dim strExtension, found, i
strExtension = objFSO.GetExtensionName(strFilePath)
found = false
for i = 0 to ubound(FILE_EXTENSIONS)
if FILE_EXTENSIONS(i) = strExtension then
found = true
exit for
end if
next
isPowerpointFile = found
End Function
'finds every shape in the entire document and attempts to reset its LanguageID
Sub ResetLanguage(objCurrentPresentation)
Dim objShape
'change shapes from presentation-wide masters
If objCurrentPresentation.HasHandoutMaster Then
For Each objShape in objCurrentPresentation.HandoutMaster.Shapes
ChangeLanguage objShape
Next
End If
If objCurrentPresentation.HasNotesMaster Then
For Each objShape in objCurrentPresentation.NotesMaster.Shapes
ChangeLanguage objShape
Next
End If
If objCurrentPresentation.HasTitleMaster = msoTrue Then
For Each objShape in objCurrentPresentation.TitleMaster.Shapes
ChangeLanguage objShape
Next
End If
'change shapes from each design's master
Dim tempDesign
For Each tempDesign in objCurrentPresentation.Designs
For Each objShape in tempDesign.SlideMaster.Shapes
ChangeLanguage objShape
Next
Next
'change shapes from each slide
Dim tempSlide
For Each tempSlide in objCurrentPresentation.Slides
For Each objShape in tempSlide.Shapes
ChangeLanguage objShape
Next
If tempSlide.hasNotesPage Then
For Each objShape in tempSlide.NotesPage.Shapes
ChangeLanguage objShape
Next
End If
Next
End Sub
'if the given shape contains a text element, it checks and corrects the LanguageID
'if the given shape is a group, it iterates through each element in the group
Sub ChangeLanguage(objShape)
If objShape.Type = msoGroup Then
Dim objShapeGroup : Set objShapeGroup = objShape.GroupItems
Dim objShapeChild
For Each objShapeChild in objShapeGroup
ChangeLanguage objShapeChild
Next
Else
If objShape.HasTextFrame Then
Dim intOrigLanguage : intOrigLanguage = objShape.TextFrame.TextRange.LanguageID
If Not intOrigLanguage = DESIRED_LANGUAGE Then
If objShape.TextFrame.TextRange.Length = 0 Then
objShape.TextFrame.TextRange.Text = "[PLACEHOLDER_TEXT_TO_DELETE]"
End If
objShape.TextFrame.TextRange.LanguageID = DESIRED_LANGUAGE
If objShape.TextFrame.TextRange.Text = "[PLACEHOLDER_TEXT_TO_DELETE]" Then
objShape.TextFrame.TextRange.Text = ""
End If
End If
End If
End If
End Sub
To run it, just copy and paste the code into a text editor and save it as "script_name.vbs" in the directory with your powerpoint files. Run it by double clicking the script and waiting.
To load a macro every time PowerPoint is opened, you will want to create a PowerPoint AddIn. Microsoft has provided step-by-step guide for Office XP. For Office 2007 and newer, AFAIK the following steps will do that:
Save file as *.ppam into the directory it suggests (%APPDATA%\Microsoft\AddIns)
Open the Settings (click the office button in the top left corner and select "PowerPoint Options"), select the "Add-Ins" page, choose "PowerPoint Add-Ins" in the drop-down behind "Manage" and click the "Go" button. A dialog opens. Selecting "Add New" brings up a file picker dialog. You should be able to select the file there.
You can also use the Office Custom UI Editor to create ribbons.
However, I have already created such a Language Fixer Add-In for current versions of PowerPoint, and I have put it up for free download for personal use: PowerPoint Language Fixer by Jan Schejbal

Resources