I am trying to set Outlook appointments from a userform in Excel. The code works if I am referencing cells. How do I reference boxes in a userform? I also need to add to the code recipients for the meeting which I would reference from a different list worksheet.
Here is the code that references the cells in Excel which works by clicking a button in the worksheet:
Sub AddAppointments()
' Create the Outlook session
Set myOutlook = CreateObject("Outlook.Application")
' Start at row 2
r = 2
Do Until Trim(Cells(r, 1).Value) = ""
' Create the AppointmentItem
Set myApt = myOutlook.CreateItem(1)
' Set the appointment properties
myApt.Subject = Cells(r, 1).Value
myApt.Location = Cells(r, 2).Value
myApt.Start = Cells(r, 3).Value
myApt.Duration = Cells(r, 4).Value
' If Busy Status is not specified, default to 2 (Busy)
If Trim(Cells(r, 5).Value) = "" Then
myApt.BusyStatus = 2
Else
myApt.BusyStatus = Cells(r, 5).Value
End If
If Cells(r, 6).Value > 0 Then
myApt.ReminderSet = True
myApt.ReminderMinutesBeforeStart = Cells(r, 6).Value
Else
myApt.ReminderSet = False
End If
myApt.Body = Cells(r, 7).Value
myApt.Display
r = r + 1
Loop
End Sub
This is my attempt at changing the code to reference boxes in a userform:
Private Sub Cmdappointment_Click()
Dim outlookapp As Object
'the mail item is the contents inside a mail
Dim mitem As AppointmentItem
'created outlook app
Set outlookapp = CreateObject("outlook.Application")
'it will open a new application
Set outlookapp = New Outlook.Application
'Set mail item
Set mitem = outlookapp.CreateItem(olMailItem)
Do Until userform2.TextBox4.Value = ""
' Create the AppointmentItem
Set myApt = myOutlook.CreateItem(1)
' Set the appointment properties
On Error Resume Next
mitem
myApt.Subject = Me.texbox4.Value
myApt.Location = Me.texbox3.Value
myApt.Start = Me.ComboBox1.Value
myApt.Duration = Me.ComboBox2.Value
' If Busy Status is not specified, default to 2 (Busy)
If Me.ComboBox3.Value = "" Then
myApt.BusyStatus = 2
Else
myApt.BusyStatus = Me.ComboBox3.Value
End If
If Me.TextBox1.Value > 0 Then
myApt.ReminderSet = True
myApt.ReminderMinutesBeforeStart = Me.TextBox1.Value
Else
myApt.ReminderSet = False
End If
myApt.Body = Me.TextBox2.Value
myApt.Display
End With
Loop
End Sub
Sorry couldn't fit the code in the comments so here are a couple of issues...
You are creating outlookapp and using myOutlook Object.
And also you are creating two mail items mitem and myApt each respectively from outlookapp and myOutlook. Eventually using only myApt. I do not know the origins of myOutlook. But I would rewrite the code to use just one set. One set of OutLook and MailItem objects just like in your worksheet application
Set outlookapp = CreateObject("outlook.Application")
'it will open a new application
Set outlookapp = New Outlook.Application
'Set mail item
Set mitem = outlookapp.CreateItem(olMailItem)
Do Until userform2.TextBox4.Value = ""
' Create the AppointmentItem
Set myApt = myOutlook.CreateItem(1)
To add recipients do the below
myApt.Recipients.Add('j doe')
To make it a bit more safe I would add the below line as well
Dim myApt As AppointmentItem
Sub cmdappointment_Click()
' Create the Outlook session
Set myOutlook = CreateObject("Outlook.Application")
Do Until userform2.TextBox4.Value = ""
' Create the AppointmentItem
Set myApt = myOutlook.CreateItem(1)
' Set the appointment properties
myApt.Subject = userform2.TextBox4.Value
myApt.Location = userform2.TextBox3.Value
myApt.Start = userform2.ComboBox1.Value
myApt.Duration = userform2.ComboBox2.Value
' If Busy Status is not specified, default to 2 (Busy)
If userform2.ComboBox3.Value = "" Then
myApt.BusyStatus = 2
Else
myApt.BusyStatus = userform2.ComboBox3.Value
End If
If userform2.TextBox1.Value > 0 Then
myApt.ReminderSet = True
myApt.ReminderMinutesBeforeStart = userform2.TextBox1.Value
Else
myApt.ReminderSet = False
End If
myApt.Body = userform2.TextBox2.Value
myApt.Display
Exit Do
Loop
End Sub
Related
I am extremely new to VBA, I am trying to get files from a specific folder and sender and am using this code I found on YT, I added the sender section but I keep getting variable not defined:
Option Explicit
Sub getDataFromOutlookChoiceFolder()
Dim OutlookApp As Outlook.Application
Dim OutlookNamespace As Namespace
Dim Folder As MAPIFolder
Dim OutlookMail As Variant
Dim i As Long
Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")
Set Folder = OutlookNamespace.PickFolder
If Folder.Items.Count = 0 Then
MsgBox "No emails. Exiting procedure!"
Exit Sub
End If
i = 1
Dim rngName As Name
Sheet1.Cells.Clear
For Each rngName In ActiveWorkbook.Names
rngName.Delete
Next
Range("A1").Name = "email_Subject"
Range("A1") = "EmailSubject"
Range("B1").Name = "email_Date"
Range("B1") = "Email Date"
Range("C1").Name = "email_Sender"
Range("email_Sender")**.Value = InputBox("Enter Sender Addresss")**
Range("D1").Name = "email_Body"
Range("D1") = "Email Body"
Range("E1").Name = "email_Receipt_Date"
Range("email_Receipt_Date").Value = InputBox("Enter Receipt Date like 20-mar-2020")
For Each OutlookMail In Folder.Items
If OutlookMail.ReceivedTime >= Range("email_Receipt_Date").Value **And OutlookMail.Sender = Range(“email_Sender”)** Then
Range("email_Subject").Offset(i, 0).Value = OutlookMail.Subject
Range("email_Subject").Offset(i, 0).Columns.AutoFit
Range("email_Subject").Offset(i, 0).VerticalAlignment = xlTop
Range("email_Date").Offset(i, 0).Value = OutlookMail.ReceivedTime
Range("email_Date").Offset(i, 0).Columns.AutoFit
Range("email_Date").Offset(i, 0).VerticalAlignment = xlTop
Range("email_Sender").Offset(i, 0).Value = OutlookMail.SenderName
Range("email_Sender").Offset(i, 0).Columns.AutoFit
Range("email_Sender").Offset(i, 0).VerticalAlignment = xlTop
Range("email_Body").Offset(i, 0).Value = OutlookMail.Body
Range("email_Body").Offset(i, 0).Columns.AutoFit
Range("email_Body").Offset(i, 0).VerticalAlignment = xlTop
i = i + 1
End If
Next OutlookMail
Set Folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing
End Sub
Highlighted is my changes. It works fine when just trying to select from a specific inbox
...And OutlookMail.Sender = Range(“email_Sender”)
You have "smart quotes" in there. VBA does not see those as actual quotes, but just another character, so it's sort of like writing
...And OutlookMail.Sender = Range(Xemail_SenderX)
You have not declared any variable named (eg) Xemail_SenderX, which is why you get the complaint about undeclared variable.
I am trying to get the Alias ID of every received email from the sender's email address.
To get Alias you can right click on the received email, select open Outlook Properties.
I built a code that extracts email received in my inbox from a particular date specified in cell B.
I am trying to add the Alias ID in D4 onwards.
Sub GetFromOutlook()
Dim OutlookApp As Outlook.Application
Dim OutlookNamespace As Namespace
Dim Folder As MAPIFolder
Dim OutlookMail As Variant
Dim i As Integer
Dim olExchgnUser As ExchangeUser
Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")
Set Folder = OutlookNamespace.Folders("insert your own email address").Folders("inbox")
i = 1
For Each OutlookMail In Folder.Items
If OutlookMail.ReceivedTime >= Range("email_Receipt_Date").Value Then
Range("email_Subject").Offset(i, 0).Value = OutlookMail.Subject
''Alias this is where i'm attempting to get Alias as part of the loop from every Item
Dim olNameSpace As Namespace
Dim olAddrList As AddressList
Set olAddrList = OutlookNamespace.AddressLists("Global Address List")
Set olExchgnUser = olAddrEntry.GetExchangeUser
With olExchgnUser
Range("Alias_name").Offset(i, 0) = .Alias
End With
''''ENd Alias
Range("email_Subject").Offset(i, 0).Columns.AutoFit
Range("email_Subject").Offset(i, 0).VerticalAlignment = xlTop
Range("email_Date").Offset(i, 0).Value = OutlookMail.ReceivedTime
Range("email_Date").Offset(i, 0).Columns.AutoFit
Range("email_Date").Offset(i, 0).VerticalAlignment = xlTop
Range("email_Sender").Offset(i, 0).Value = OutlookMail.SenderName
Range("email_Sender").Offset(i, 0).Columns.AutoFit
Range("email_Sender").Offset(i, 0).VerticalAlignment = xlTop
Range("email_Body").Offset(i, 0).Value = OutlookMail.Body
Range("email_Body").Offset(i, 0).Columns.AutoFit
Range("email_Body").Offset(i, 0).VerticalAlignment = xlTop
i = i + 1
End If
Next OutlookMail
Set Folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing
MsgBox "operation Complete"
End Sub
Replace the lines
Set olAddrList = OutlookNamespace.AddressLists("Global Address List")
Set olExchgnUser = olAddrEntry.GetExchangeUser
with
Set olExchgnUser = OutlookMail.Sender.GetExchangeUser
(null and error handling omitted).
You really should not be looping through all messages in a folder - use Items.Find/FindNext or Items.Restrict.
I'm NO coder and have less than an elementary base of knowledge in VBA or scripting. I pieced this code together which will take an excel spreadsheet (one meeting per row) and generate a calendar invite complete with subject, Date/Time, & attendees. This appointmentItem is being generated on my calendar, but I need it to open on a shared calendar of mine. Caveats: I do not know what code is needed to do this, and I do not have the knowledge to understand the format that an outlook calendar path is in. The accounts are linked to my corporate server and we do use aliases in our global directory.
Sub AddAppointments()
Dim myoutlook As Object ' Outlook.Application
Dim r As Long
Dim myapt As Object ' Outlook.AppointmentItem
' late bound constants
Const olAppointmentItem = 1
Const olBusy = 2
Const olMeeting = 1
' Create the Outlook session
Set myoutlook = CreateObject("Outlook.Application")
' Start at row 2
r = 2
Do Until Trim$(Cells(r, 1).Value) = ""
' Create the AppointmentItem
Set myapt = myoutlook.CreateItem(olAppointmentItem)
' Set the appointment properties
With myapt
.Subject = Cells(r, 1).Value
.Location = Cells(r, 2).Value
.Start = Cells(r, 3).Value
.Duration = Cells(r, 4).Value
'.Recipients.Add Cells(r, 8).Value
' **Why Doesn't this Work?!?**
.Recipients.ResolveAll
.MeetingStatus = olMeeting
' not necessary if recipients are email addresses
.AllDayEvent = Cells(r, 31).Value
' If Busy Status is not specified, default to 2 (Busy)
If Len(Trim$(Cells(r, 5).Value)) = 0 Then
.BusyStatus = olBusy
Else
.BusyStatus = Cells(r, 5).Value
End If
If Cells(r, 6).Value > 0 Then
.ReminderSet = True
.ReminderMinutesBeforeStart = Cells(r, 6).Value
Else
.ReminderSet = False
End If
'Set body format to HTML - ** THIS DOESN'T WORK **
'.BodyFormat = olFormatHTML
'.HTMLBody = "<HTML><BODY>Enter the message text here. </BODY></HTML>"
.Body = Cells(r, 7).Value
.Save
r = r + 1
.Send
End With
Loop
End Sub
To create an appointment on a shared calendar you need to use the Add method of the Items class which comes from the shared caledar folder. The How To: Create a new Outlook Appointment item explains different ways of creating appointment items in Outlook. Note, you can use the GetSharedDefaultFolder method of the Namespace class to get a shared calendar folder.
' **Why Doesn't this Work?!?**
.Recipients.ResolveAll
It looks like you need to add any recipient to the Recipients collection first. For example:
Sub CreateAppt()
Dim myItem As Object
Dim myRequiredAttendee, myOptionalAttendee, myResourceAttendee As Outlook.Recipient
Set myItem = Application.CreateItem(olAppointmentItem)
myItem.MeetingStatus = olMeeting
myItem.Subject = "Strategy Meeting"
myItem.Location = "Conference Room B"
myItem.Start = #9/24/2014 1:30:00 PM#
myItem.Duration = 90
Set myRequiredAttendee = myItem.Recipients.Add("Nate Sun")
myRequiredAttendee.Type = olRequired
Set myOptionalAttendee = myItem.Recipients.Add("Kevin Kennedy")
myOptionalAttendee.Type = olOptional
Set myResourceAttendee = myItem.Recipients.Add("Conference Room B")
myResourceAttendee.Type = olResource
myItem.Display
End Sub
I am using VBA in Outlook to extract mail information from items in the mainfolder and subfolder. The mainfolder failed to set(capture) the subfolder properties into it and it causes the runtime error.
The runtime error differs whenever I run. For example, sometime I received -970718969 (c6240107) and another time I received -2044460793 (86240107).
When I clicked debug, it points to this line of code:
For Each itm In subFld.Items
Here is the screenshot:
Here is the full code:
Public monthValue As Integer
Public yearValue As String
'Ensure Microsoft Excel 11.0 Object Library is ticked in tools.
Sub ExportToExcel1()
Dim appExcel As Excel.Application
Dim wkb As Excel.Workbook
Dim wks As Excel.Worksheet
Dim rng As Excel.Range
Dim strSheet As String
Dim strPath As String
Dim intRowCounter As Integer
Dim msg As Outlook.MailItem
Dim nms As Outlook.NameSpace
Dim mainFld As Outlook.MAPIFolder
Dim subFld As Outlook.MAPIFolder
Dim itm As Object
Dim offsetRow As Long
Dim emailCount As Long
'Set the path of the excel file.
strSheet = "For fun.xlsx"
strPath = "C:\Users\xxxxxx\Desktop\xxxxx\"
strSheet = strPath & strSheet
Debug.Print strSheet
Set nms = Application.GetNamespace("MAPI")
Set mainFld = nms.PickFolder 'Open the box to select the file.
'Handle potential errors with Select Folder dialog box.
If mainFld Is Nothing Then
MsgBox "Thank you for using this service.", vbOKOnly, "Error"
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
ElseIf mainFld.DefaultItemType <> olMailItem Then
MsgBox "Please select the correct folder.", vbOKOnly, "Error"
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
ElseIf mainFld.Items.Count = 0 Then
MsgBox "There are no mail messages to export", vbOKOnly, "Error"
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
End If
mainForm.Show
'If user clicks cancel, it will exit sub.
If yearValue = "" Then
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
End If
'Open and activate Excel workbook.
Set appExcel = CreateObject("Excel.Application")
appExcel.Workbooks.Open (strSheet)
Set wkb = appExcel.ActiveWorkbook
Set wks = wkb.Sheets(1)
wks.Activate
appExcel.Application.Visible = True 'Show my workbook.
'Check if there are any subfolders.
If mainFld.Folders.Count = 0 Then '1
'No subfolder.
For Each itm In mainFld.Items
If itm.Class <> olMail Then '2
'do nothing
Else
Set msg = itm
'Validate the month and year for the email.
If Month(msg.ReceivedTime) = monthValue And Year(msg.ReceivedTime) = yearValue Then '3
With wks
offsetRow = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
intRowCounter = 1 + offsetRow
Set rng = wks.Cells(intRowCounter, 1)
rng.Value = msg.ReceivedTime
Set rng = wks.Cells(intRowCounter, 2)
rng.Value = msg.SentOn
Set rng = wks.Cells(intRowCounter, 3)
rng.Value = msg.Subject
emailCount = 1 + emailCount 'Track the number of email.
Else
'Do nothing
End If '3
End If '2
Next itm
Else
'With subfolder
For Each itm In mainFld.Items
If itm.Class <> olMail Then '4
'do nothing
Else
Set msg = itm
If Month(msg.ReceivedTime) = monthValue And Year(msg.ReceivedTime) = yearValue Then '5
With wks
offsetRow = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
intRowCounter = 1 + offsetRow
Set rng = wks.Cells(intRowCounter, 1)
rng.Value = msg.ReceivedTime
Set rng = wks.Cells(intRowCounter, 2)
rng.Value = msg.SentOn
Set rng = wks.Cells(intRowCounter, 3)
rng.Value = msg.Subject
emailCount = 1 + emailCount
Else
'Do nothing
End If '5
End If '4
Next itm
For Each subFld In mainFld.Folders
For Each itm In subFld.Items
If itm.Class <> olMail Then '6
'do nothing
Else
Set msg = itm
If Month(msg.ReceivedTime) = monthValue And Year(msg.ReceivedTime) = yearValue Then '7
With wks
offsetRow = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
intRowCounter = 1 + offsetRow
Set rng = wks.Cells(intRowCounter, 1)
rng.Value = msg.ReceivedTime
Set rng = wks.Cells(intRowCounter, 2)
rng.Value = msg.SentOn
Set rng = wks.Cells(intRowCounter, 3)
rng.Value = msg.Subject
emailCount = 1 + emailCount
Else
'Do nothing
End If '7
End If '6
Next itm
Next subFld
End If '1
Set appExcel = Nothing
Set wkb = Nothing
Set wks = Nothing
Set rng = Nothing
Set msg = Nothing
Set nms = Nothing
Set mainFld = Nothing
Set subFld = Nothing
Set itm = Nothing
'Inform the user that there are no email.
If emailCount = 0 Then
MsgBox "No emails associated with this date: " & MonthName(monthValue, True) & " " & yearValue, vbOKOnly, "No Emails"
End If
Exit Sub
Set appExcel = Nothing
Set wkb = Nothing
Set wks = Nothing
Set rng = Nothing
Set msg = Nothing
Set nms = Nothing
Set mainFld = Nothing
Set subFld = Nothing
Set itm = Nothing
End Sub
Do you get that error immediately or only after processing a large number of items? Most likely you are opening too many items and run out of RPC channels. Is this a cached or an online Exchange profile?
Instead of looping through all items, use the Table object (MAPITable.GetTable) - if nothing else, it will be a lot faster.
EDIT: If you are using Exchange, every store object (message, folder, store) opens an RPC channel. Exchange Server limits the number of RPC channels to 255 per client (can be changed on the server). Do not use "for each" loop (it keeps all items referenced until the loop ends) and avoid multiple dot notation (because you will have implicit variables that you cannot explicitly dereference). You will also need to release all Outlook objects as soon as you are done with them.
set fldItems = mainFld.Items
For i = 1 to fldItems.Count do
set itm = fldItems.Item(i)
'do stuff
set itm = Nothing
next
As for the Table object (introduced in Outlook 2007), see http://msdn.microsoft.com/en-us/library/office/ff860769.aspx. If you need to use this in an earlier version of Outlook, you can use the MAPITable object in Redemption (I am its author); it also has a MAPITable.ExecSQL method that takes a standard SQL query and returns the ADODB.Recordset object.
I am trying to delete future appointments in my Outlook calendar, from Access VBA, with the code below. The code works ok, BUT those Appointments have been set up using a room (resource), and deleting the appointment in MY calendar does not delete it in the resource calendar. How can I fix that ?
Sub NoFuture()
'delete any future appointment
Dim olApp As Outlook.Application
Dim olNs As Outlook.NameSpace
Dim olRecItems
Dim olFilterRecItems
Dim olItem As Outlook.AppointmentItem, strFilter As String
Set olApp = CreateObject("Outlook.Application")
Set olNs = olApp.GetNamespace("MAPI")
Set olRecItems = olNs.GetDefaultFolder(olFolderCalendar)
strFilter = "[Start] > '" & Format(Date + 1, "mm/dd/yyyy") & "'"
Set olFilterRecItems = olRecItems.Items.Restrict(strFilter)
For Each olItem In olFilterRecItems
olItem.Delete
Next olItem
Set olRecItems = Nothing
Set olNs = Nothing
Set olApp = Nothing
End Sub
Diane Poremsky has written a macro that goes through and removes cancelled appointments from the resource calender:
' A subroutine to remove cancelled appointments.
Sub RemoveCanceledAppointments()
'Form variables.
Dim OutLookResourceCalendar As Outlook.MAPIFolder, OutLookAppointmentItem As Outlook.AppointmentItem, IntegerCounter As Integer
'This sets the path to the resource calender.
Set OutLookResourceCalendar = OpenMAPIFolder("\MailboxName\Calendar")
For IntegerCounter = OutLookResourceCalendar.Items.Count To 1 Step -1
Set OutLookAppointmentItem = OutLookResourceCalendar.Items(IntegerCounter)
If Left(OutLookAppointmentItem.Subject, 9) = "Canceled:" Then
OutLookAppointmentItem.Delete
End If
Next
Set OutLookAppointmentItem = Nothing
Set OutLookResourceCalendar = Nothing
End Sub
' A function for the folder path.
Function OpenMAPIFolder(FolderPathVar)
Dim SelectedApplication, FolderNameSpace, SelectedFolder, FolderDirectoryVar, i
Set SelectedFolder = Nothing
Set SelectedApplication = CreateObject("Outlook.Application")
If Left(FolderPathVar, Len("\")) = "\" Then
FolderPathVar = Mid(FolderPathVar, Len("\") + 1)
Else
Set SelectedFolder = SelectedApplication.ActiveExplorer.CurrentFolder
End If
While FolderPathVar <> ""
' Backslash var.
i = InStr(FolderPathVar, "\")
'If a Backslash is present, acquire the directory path and the folder path...[i].
If i Then
FolderDirectoryVar = Left(FolderPathVar, i - 1)
FolderPathVar = Mid(FolderPathVar, i + Len("\"))
Else
'[i] ...or set the path to nothing.
FolderDirectoryVar = FolderPathVar
FolderPathVar = ""
End If
' Retrieves the folder name space from the Outlook namespace, unless a folder exists... [ii].
If IsNothing(SelectedFolder) Then
Set FolderNameSpace = SelectedApplication.GetNamespace("MAPI")
Set SelectedFolder = FolderNameSpace.Folders(FolderDirectoryVar)
Else
' [ii] in which case the the existing folder namespace is used.
Set SelectedFolder = SelectedFolder.Folders(FolderDirectoryVar)
End If
Wend
Set OpenMAPIFolder = SelectedFolder
End Function
' A function to check too see if there is no set namespace for the folder path.
Function IsNothing(Obj)
If TypeName(Obj) = "Nothing" Then
IsNothing = True
Else
IsNothing = False
End If
End Function
Let me know if that removes the cancelled appointments from the resource calender -
~JOL