In Outlook 2010 VBA, I want to create a task when I send an email.
I want to add to the task all the attachments from the email.
I tried .Attachments.Add (is not supported), .Attachments = item.Attachments returns property is read only.
Is it possible or how can I attach the email to the task?
Public WithEvents myOlApp As Outlook.Application
Private Sub Application_MAPILogonComplete()
End Sub
Private Sub Application_Startup()
Initialize_handler
End Sub
Public Sub Initialize_handler()
Set myOlApp = CreateObject("Outlook.Application")
End Sub
Private Sub myOlApp_ItemSend(ByVal item As Object, Cancel As Boolean)
Dim intRes As Integer
Dim strMsg As String
Dim objTask As TaskItem
Set objTask = Application.CreateItem(olTaskItem)
Dim strRecip As String
Dim att As MailItem
Dim objMail As Outlook.MailItem
strMsg = "Do you want to create a task for this message?"
intRes = MsgBox(strMsg, vbYesNo + vbExclamation, "Create Task")
If intRes = vbNo Then
Cancel = False
Else
For Each Recipient In item.Recipients
strRecip = strRecip & vbCrLf & Recipient.Address
Next Recipient
With objTask
'.Body = strRecip & vbCrLf & Item.Body
.Body = item.Body
.Subject = item.Subject
.StartDate = item.ReceivedTime
.ReminderSet = True
.ReminderTime = DateSerial(Year(Now), Month(Now), Day(Now + 1)) + #8:00:00 AM#
**.Attachments.Add (item.Attachments)**
.Save
End With
Cancel = False
End If
Set objTask = Nothing
End Sub
Attachments.Add allows to pass a string as a parameter (fully queslified attachment filename) or an Outlook item (such as MailItem). Youy are passing Attachments collection as a parameter, you cannot do that.
For each attachment, save the attachment first(Attachment.SaveAsFile), then add them to the task one at a time passing the file name as the parameter.
Here is my final code
Public WithEvents myOlApp As Outlook.Application
Private Sub Application_MAPILogonComplete()
End Sub
Private Sub Application_Startup()
Initialize_handler
End Sub
Public Sub Initialize_handler()
Set myOlApp = CreateObject("Outlook.Application")
End Sub
Private Sub myOlApp_ItemSend(ByVal item As Object, Cancel As Boolean)
Dim intRes As Integer
Dim strMsg As String
Dim objTask As TaskItem
Set objTask = Application.CreateItem(olTaskItem)
Dim strRecip As String
Dim att As MailItem
Dim objMail As Outlook.MailItem
Dim Msg As Variant
strFolderPath = "C:\temp" ' path to target folder
strMsg = "Do you want to create a task for this message?"
intRes = MsgBox(strMsg, vbYesNo + vbExclamation, "Create Task")
If intRes = vbNo Then
Cancel = False
Else
For Each Recipient In item.Recipients
strRecip = strRecip & vbCrLf & Recipient.Address
Next Recipient
item.SaveAs strFolderPath & "\" & "test" & ".msg", olMSG
'item.Save
With objTask
'.Body = strRecip & vbCrLf & Item.Body
.Body = item.Body
.Subject = item.Subject
.StartDate = item.ReceivedTime
.ReminderSet = True
.ReminderTime = DateSerial(Year(Now), Month(Now), Day(Now + 1)) + #8:00:00 AM#
.Attachments.Add item
.Save
End With
Cancel = False
End If
Set objTask = Nothing
End Sub
Related
I have a code that I was able to string together that logs my sent emails into an excel sheet so i can use that data for other analysis.
In it, I have it resolving the name into an email as outlook shortens it ("Jimenez, Ramon" = email#address.com) as outlook configured this and it works when i send an email to anyone in my company as they are in my address book.
Now, when I email anyone outside it defaults to lastName, firstName so it is not converting this and logging it.
I thought the code I have in here already does this, but I guess not. I have already come this far and I am NOT a software guru at all. Does anyone have insight on how I can also include this as well?? Please see code below:
Private WithEvents Items As Outlook.Items
Const strFile As String = "C:\Users\a0227084\Videos\work\test.xlsx"
Private Sub Application_Startup()
Dim OLApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set OLApp = Outlook.Application
Set objNS = OLApp.GetNamespace("MAPI")
' default local Inbox
Set Items = objNS.GetDefaultFolder(olFolderSentMail).Items
End Sub
Private Sub Items_ItemAdd(ByVal item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
If TypeName(item) = "MailItem" Then
Set Msg = item
' ******************
FullName = Split(Msg.To, ";")
For i = 0 To UBound(FullName)
If i = 0 Then
STRNAME = ResolveDisplayNameToSMTP(FullName(i))
Call Write_to_excel(CStr(Msg.ReceivedTime), CStr(Msg.Subject), CStr(STRNAME))
ElseIf ResolveDisplayNameToSMTP(FullName(i)) <> "" Then
STRNAME = ResolveDisplayNameToSMTP(FullName(i))
Call Write_to_excel(CStr(Msg.ReceivedTime), CStr(Msg.Subject), CStr(STRNAME))
End If
Next i
'Call Write_to_excel(CStr(Msg.ReceivedTime), CStr(Msg.Subject), CStr(STRNAME))
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
Sub tes2t()
End Sub
Function getRecepientEmailAddress(eml As Variant)
Set out = CreateObject("System.Collections.Arraylist") ' a JavaScript-y array
For Each emlAddr In eml.Recipients
If Left(emlAddr.Address, 1) = "/" Then
' it's an Exchange email address... resolve it to an SMTP email address
out.Add ResolveDisplayNameToSMTP(emlAddr)
Else
out.Add emlAddr.Address
End If
Next
getRecepientEmailAddres = Join(out.ToArray(), ";")
End Function
Function ResolveDisplayNameToSMTP(sFromName) As String
' takes a Display Name (i.e. "James Smith") and turns it into an email address (james.smith#myco.com)
' necessary because the Outlook address is a long, convoluted string when the email is going to someone in the organization.
' source: https://stackoverflow.com/questions/31161726/creating-a-check-names-button-in-excel
Dim OLApp As Object 'Outlook.Application
Dim oRecip As Object 'Outlook.Recipient
Dim oEU As Object 'Outlook.ExchangeUser
Dim oEDL As Object 'Outlook.ExchangeDistributionList
Set OLApp = CreateObject("Outlook.Application")
Set oRecip = OLApp.Session.CreateRecipient(sFromName)
oRecip.Resolve
If oRecip.Resolved Then
Select Case oRecip.AddressEntry.AddressEntryUserType
Case 0, 5 'olExchangeUserAddressEntry & olExchangeRemoteUserAddressEntry
Set oEU = oRecip.AddressEntry.GetExchangeUser
If Not (oEU Is Nothing) Then
ResolveDisplayNameToSMTP = oEU.PrimarySmtpAddress
End If
Case 10, 30 'olOutlookContactAddressEntry & 'olSmtpAddressEntry
Dim PR_SMTP_ADDRESS As String
PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
ResolveDisplayNameToSMTP = oRecip.AddressEntry.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS)
End Select
End If
End Function
Sub Write_to_excel(str1 As String, str2 As String, str3 As String)
Dim xlApp As Object
Dim sourceWB As Workbook
Dim sourceWH As Worksheet
Set xlApp = CreateObject("Excel.Application")
With xlApp
.Visible = True
.EnableEvents = False
End With
Set sourceWB = Workbooks.Open(strFile, False, False)
Set sourceWH = sourceWB.Worksheets("Sheet1")
sourceWB.Activate
With sourceWH
lastrow = .Cells(.rows.Count, "A").End(xlUp).Row
End With
sourceWH.Cells(lastrow + 1, 1) = str1
sourceWH.Cells(lastrow + 1, 2) = str2
sourceWH.Cells(lastrow + 1, 3) = str3
sourceWB.Save
sourceWB.Close
End Sub
Error message and corrected code
Regards,
Ramon
First of all, there is no need to create a new Application instance in the ResolveDisplayNameToSMTP method:
Set OLApp = CreateObject("Outlook.Application")
Instead, you can use the Application property available in the Outlook VBA editor out of the box.
Second, you need to use the following code to get the SMTP address from the AddressEntry object:
Dim PR_SMTP_ADDRESS As String
Set PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
ResolveDisplayNameToSMTP = oRecip.AddressEntry.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS)
Instead of the following line:
ResolveDisplayNameToSMTP = oRecip.AddressEntry.Address
Read more about that in the How to get the SMTP Address of the Sender of a Mail Item using Outlook Object Model? article.
Thanks in advance :), I am trying to attach the data of subform also in mail body.
Current Status: I am able to attach Main forms data and generate mail but unable to attach subform's data as it only includes the first row, Tryied doing it through Subform and query both but no success. I will prefer to do it by subform itself. Subform's Name is : "subUpdateOrder". VB Code:
Private Sub InformCustomer_Click()
On Error GoTo Err_InformCustomer_Click
Dim CustName As String ' Customer Name
Dim varTo As Variant '-- Address for SendObject
Dim stText As String '-- E-mail text
Dim DelDate As Variant '-- Rec date for e-mail text
Dim stSubject As String '-- Subject line of e-mail
Dim stOrderID As String '-- The Order ID from form
Dim detailQry As String
'Dim stHelpDesk As String '-- Person who assigned ticket
'Dim strSQL As String '-- Create SQL update statement
'Dim errLoop As Error
CstName = Me![CustName]
varTo = Me![CustEmail]
stSubject = ":: Update - Oder Status ::"
stOrderID = Me.[OdrID]
DelDate = Me.[OdrDeliveryDate]
stText = "Dear" & CstName & _
"You have been assigned a new ticket." & Chr$(13) & Chr$(13) & _
"Order Number: " & stOrderID & Chr$(13) & _
"Please refer to your order status " & Chr$(13) & _
"Exp Delevery Date: " & DelDate & Chr$(13) & Chr$(13) & _
dQuery & Chr$(13) & _
"This is an automated message. Please do not respond to this e-mail."
'Write the e-mail content for sending to assignee
DoCmd.SendObject , , acFormatTXT, varTo, , , stSubject, stText, True
Err_InformCustomer_Click:
MsgBox Err.Description
End Sub
Form Img: Form and Command1 button to run the code
It would be something like (to insert before CstName = Me![CustName]):
Dim dQuery As String
Dim rs As DAO.Recordset
Set rs = Me!NameOfYourSubformCONTROL.Form.RecordsetClone
While Not rs.EOF
dQuery = dQuery & rs![Brand Name].Value & vbTab & rs![Model Name].Value & vbTab & rs![Color].Value & vbCrLF
Wend
Set rs = Nothing
I have a Mainform with textbox and button to search subform record
it works fine when i directly open Mainform and searching desire record
but when i open my form in Navigaition form it gives me error.
Download My Access Project What i have tried.
Below is my code:
Private Sub cmdSearch_Click()
Dim MainFK As Long
MainFK = DLookup("MainformID", "Subform", "SubformID =" & Me.txtSearch)
Debug.Print MainFK
DoCmd.SearchForRecord acDataForm, "Mainform", acFirst, "MainformID=" &MainFK
End Sub
See Screen Shot:
I think DoCmd.SearchForRecord is tricky on subforms. Try this instead:
Private Sub cmdSearch_Click()
Dim MainFK As Long
Dim rs As DAO.Recordset
Dim WhereStr As String
MainFK = DLookup("MainformID", "Subform", "SubformID =" & Me.txtSearch)
WhereStr = "MainformID=" & MainFK
With Me.Form
Set rs = .RecordsetClone
rs.FindFirst WhereStr
If _
rs.NoMatch _
Then
MsgBox "Subform record not match to mainform record"
Else
.Bookmark = rs.Bookmark
End If
End With
End Sub
Here's your file back: https://drive.google.com/file/d/0B-J5B7nFljZiLVJ1dEtoTVQwcXc/view?usp=sharing
I am currently writing code using vbscript to automate sending of email.
How do I delete that very same email that I sent in the sent folder?
Below is my code:
Dim ToAddress
Dim FromAddress
Dim MessageSubject
Dim MyTime
Dim MessageBody
Dim MessageAttachment
Dim ol, ns, newMail
ToAddress = "site.net"
MessageSubject = "stuff"
MessageBody = "SEND"
MessageAttachment = "C:\Users\Bellere\Desktop\numbers.csv"
Set ol = WScript.CreateObject("Outlook.Application")
Set ns = ol.getNamespace("MAPI")
Set newMail = ol.CreateItem(olMailItem)
newMail.Subject = MessageSubject
newMail.Body = MessageBody & vbCrLf
newMail.RecipIents.Add(ToAddress)
newMail.Attachments.Add(MessageAttachment)
newMail.Send
Any help is appericated!
Thanks!
This section describes how to use the Microsoft Outlook 11.0 Object Library to Delete messages from the Outlook Inbox in Visual Basic .NET.
Dim tempApp As Outlook.Application
Dim tempSent As Outlook.MAPIFolder
Dim SentItems As Outlook.Items
Dim tempMail As Object
tempApp = CreateObject("Outlook.Application")
tempSent = tempApp.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail)
SentItems = tempSent.Items
Dim DeleteMail As Outlook.MailItem
For Each newMail In SentItems
DeleteMail.Delete()
Next
Note : The most improtant point here to performing all tasks is to add a reference to "Microsoft Outlook object library", In case of
Microsoft Outlook 2000, Add "Microsoft Outlook 9.0 object library"
Microsoft Outlook 2002, Add "Microsoft Outlook 10.0 object library"
Microsoft Outlook 2003, Add "Microsoft Outlook 11.0 object library"
Microsoft Outlook 2007, Add "Microsoft Outlook 12.0 object library"
Add this and this should do for the first occurrence of the sent item from the script
Const olMailItem = 0
Const olFolderSentMail = 5
Dim ToAddress
Dim FromAddress
Dim MessageSubject
Dim MyTime
Dim MessageBody
Dim MessageAttachment
Dim ol, ns, newMail
Dim oMail ' <- added
ToAddress = "site.net"
MessageSubject = "stuff"
MessageBody = "SEND"
MessageAttachment = "C:\Users\Bellere\Desktop\numbers.csv"
Set ol = WScript.CreateObject("Outlook.Application")
Set ns = ol.getNamespace("MAPI")
Set newMail = ol.CreateItem(olMailItem)
newMail.Subject = MessageSubject
newMail.Body = MessageBody & vbCrLf
newMail.RecipIents.Add(ToAddress)
newMail.Attachments.Add(MessageAttachment)
newMail.Send
' Search for the first occurrence of the sent item (Subject and first recipient address)
Set newMail = Nothing
For Each oMail In ns.GetDefaultFolder(olFolderSentMail).Items
If oMail.Subject = MessageSubject And oMail.Recipients(1).Address = ToAddress Then
Set newMail = oMail
Exit For
End If
Next
If Not newMail Is Nothing Then newMail.Delete
I have the following property in my clsdata class:
Public Property Get PatientCount() As Long
PatientCount = UBound(maobjPatient)
End Property
I also have this function in my class:
Private Function CountNonEmptyLines(ByVal strfile As String) As Long
Dim intFile As Integer
Dim strLine As String
Dim lngcount As Long
intFile = FreeFile
Open strfile For Input As intFile
lngcount = 0&
Do While Not EOF(intFile)
Line Input #intFile, strLine
If Len(strLine) > 0 Then
lngcount = lngcount + 1
End If
Loop
Close #intFile
CountNonEmptyLines = lngcount
End Function
the code of InputData is the following:
Public Sub InputData()
Dim blnLoaded As Boolean
Dim path As String
Dim file As String
Dim lnglines As Long
path = MyForm.TextPath
file = MyForm.TextFile
If LoadData(path, file) = False Then
MsgBox FileErrorString
Else
blnLoaded = LoadData(path, file)
End If
End Sub
and the code of LoadData is:
Private Function LoadData( _
ByVal strPath As String, _
ByVal strfile As String) _
As Boolean
Dim strPathFile As String
Dim lngRows As Long
LoadData = False
EraseData
InitialiseState
strPathFile = strPath & "\" & strfile
If Not FileExists(strPathFile) Then
Exit Function
End If
lngRows = CountNonEmptyLines(strPathFile)
If lngRows = 0 Then
Exit Function
End If
If Not LoadPatientLines(strPathFile, lngRows) Then
Exit Function
End If
mFileError = leNOERROR
LoadData = True
End Function
In my form I have a button which loads some data from a file:
Private Sub CmdLoad_Click()
Dim myData As New clsData
Call myData.InputData
End Sub
I also have a textbox:
Private Sub TextEntries_Change()
End Sub
How can I have the value of PatientCount or the lngcount from countnonemptylines function, in my textbox when I click CmdLoad, something like TextEntries.text=...?
As follow up from comments, this one works:
TextEntries.text = myData.PatientCount