I am trying to set up an Outlook calendar at work, from Excel data sheets.
I run a query to get data, then treat it, and fill Outlook calendar events.
The problem is, when I enter my required attendees, via my olAppointmentItem, it only notifies me and fills my calendar, not my colleagues' calendars.
I think this might come from the fact that I create it from my own Outlook account.
Here is the mapping of my Excel sheet:
Here is the code I use:
Sub RegisterAppointmentList()
' adds a list of appointments to the Calendar in Outlook
Dim olApp As Outlook.Application
Dim olAppItem As Outlook.AppointmentItem
Dim row As Long
On Error Resume Next
Worksheets("to_be_added").Activate 'worksheet with the list of my appointments to be added
Set olApp = GetObject("", "Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
On Error Resume Next
Set olApp = CreateObject("Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
MsgBox "Outlook is not available!"
Exit Sub
End If
End If
row = 2 ' first row with appointment data in the active worksheet
Dim mysub, myStart, myEnd
While Len(Cells(row, 2).text) <> 0
mysub = "Test"
myStart = DateValue("09/20/2019") + TimeValue("8:00") 'date and time
myEnd = DateValue("09/20/2019") + TimeValue("9:00") 'date and time
Set olAppItem = olApp.CreateItem(olAppointmentItem)
' set default appointment values
.Location = "Office" 'Location of my event
.Body = "Test appointment" 'title
.ReminderSet = True
.BusyStatus = olBusy 'doesn't need to set people busy
```
.RequiredAttendees = "me#company.com" 'this works just fine
.RequiredAttendees = "colleague#company.com" 'this doesn't work
```
'On Error Resume Next
.Start = myStart
.End = myEnd
.AllDayEvent = False
.Subject = mysub
'.Location = Cells(row, 9).Value
'.Body = Cells(row, 8).Value
'.ReminderSet = True
'.BusyStatus = olBusy
.Categories = "In" 'My own categories (two possibilities, In or Out)
On Error GoTo 0
.Save
End With
row = row + 1
Wend
Set olAppItem = Nothing
Set olApp = Nothing
End Sub
I think this is just a parameter that doesn't catch or something, because it works fine on my own calendar, I get reminders as well as events.
You created an appointment with a superfluous .RequiredAttendees property.
You did not attempt to .Send.
Sub RegisterAppointmentList_SendMeetingInvitation_Minimal()
' Most Excel-related code is removed
' Create a meeting from an appointment
Dim olApp As Outlook.Application
Dim olAppItem As Outlook.AppointmentItem
Dim myStart As Date
Dim myEnd As Date
On Error Resume Next
Set olApp = GetObject("", "Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
On Error Resume Next
Set olApp = CreateObject("Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
MsgBox "Outlook is not available!"
Exit Sub
End If
End If
myStart = DateValue("09/21/2019") + TimeValue("8:00") 'date and time
myEnd = DateValue("09/21/2019") + TimeValue("9:00") 'date and time
Set olAppItem = olApp.CreateItem(olAppointmentItem)
With olAppItem
' set default appointment values
.Location = "Office" 'Location of my event
.Body = "Test appointment"
.ReminderSet = True
.BusyStatus = olBusy
.RequiredAttendees = "me#company.com"
.RequiredAttendees = "colleague#company.com"
.Start = myStart
.End = myEnd
.AllDayEvent = False
.Subject = "Test"
' Change appointment to meeting
.MeetingStatus = olMeeting
.Display ' change to .Send when tested
End With
End Sub
Related
I have a worksheet set up to send email notifications when certain cells contain values, such as "75%" and "Due".
Around half the time I get
Runtime error 462
It seems this is because I have not specified elements of my code properly.
Private Sub Worksheet_Change(ByVal Target As Range)
Call Check_Project_Progress
End Sub
Private Sub Send_Email(Optional ByVal email_title As String = "")
Dim olNS As Namespace
Dim olMail As MailItem
Set olNS = GetNamespace("MAPI")
Set olMail = CreateItem(olMailItem)
With olMail
.Subject = email_title
.To = "LearnDataAnalysis#outlook.com"
.Body = "Value reads 75%"
.SendUsingAccount = olNS.Accounts.Item(1)
.Display
'.Send
End With
Set olMail = Nothing
Set olNS = Nothing
End Sub
Private Sub Send_Email2(Optional ByVal email_title As String = "")
Dim olNS As Namespace
Dim olMail As MailItem
Set olNS = GetNamespace("MAPI")
Set olMail = CreateItem(olMailItem)
With olMail
.Subject = email_title
.To = "LearnDataAnalysis#outlook.com"
.Body = "PLA determination due"
.SendUsingAccount = olNS.Accounts.Item(1)
.Display
'.Send
End With
Set olMail = Nothing
Set olNS = Nothing
End Sub
Private Sub Check_Project_Progress()
Dim LastRow As Long, RowNumber As Long
Dim ws As Worksheet
Set ws = ActiveSheet
With ws
LastRow = 500
If 4 > LastRow Then Exit Sub
For RowNumber = 4 To LastRow
If .Cells(RowNumber, "AB").Value = 0.75 And .Cells(RowNumber, "AD").Value <> "S" Then
.Cells(RowNumber, "AD").Value = "S"
.Cells(RowNumber, "AE") = "Email sent on:" & Now()
Call Send_Email(.Cells(RowNumber, "C").Value & " is approaching deadline")
End If
If 4 > LastRow Then Exit Sub
If .Cells(RowNumber, "AC").Value = "Due" And .Cells(RowNumber, "AD").Value <> "S,S" Then
.Cells(RowNumber, "AD").Value = "S,S"
.Cells(RowNumber, "AF") = "Email sent on:" & Now()
Call Send_Email2(.Cells(RowNumber, "C").Value & " has met deadline")
End If
Next RowNumber
End With
Set ws = Nothing
End Sub
Again, the error message is Runtime error 462. I have little idea what I'm doing.
You are getting that error becuase the code is not able to connect to the outlook application.
Try this. I have shown you for Send_Email. Adapt it for Send_Email2 as well.
Private Sub Send_Email(Optional ByVal email_title As String = "")
Dim olNS As Object
Dim olMail As Object
Dim OutlookApp As Object
'~~> Establish an Outlook application object
On Error Resume Next
Set OutlookApp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then
Set OutlookApp = CreateObject("Outlook.Application")
End If
Err.Clear
On Error GoTo 0
'~~> Check if we managed to connect to Outlook
If OutlookApp Is Nothing Then
MsgBox "unable to connect to outlook"
Exit Sub
End If
Set olNS = OutlookApp.GetNamespace("MAPI")
Set olMail = OutlookApp.CreateItem(0)
With olMail
.Subject = email_title
.To = "LearnDataAnalysis#outlook.com"
.Body = "Value reads 75%"
.SendUsingAccount = olNS.Accounts.Item(1)
.Display
'.Send
End With
End Sub
My code works fine in the default calendar but I am unable to get it to made an appointment in the AllPublicFolders Calendar. I am unable to call the function GetPublicFolder because I am new using VBA. Any help would be greatly appreciated.
Here is my code with "Big Store A Calendar in the all public folders:
Option Explicit
Sub RegisterAppointmentList()
' adds a list of appointments to the Calendar in Outlook
Dim olApp As Outlook.Application
Dim olAppItem As Outlook.AppointmentItem
Dim r As Long
On Error Resume Next
'Worksheets("Schedule").Activate
Worksheets("Appt").Activate
Set olApp = GetObject("", "Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
On Error Resume Next
Set olApp = CreateObject("Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
MsgBox "Outlook is not available!"
Exit Sub
End If
End If
'r = 6 ' first row with appointment data in the active worksheet
r = 2 ' first row with appointment data in the active worksheet
Dim mysub, myStart, myEnd
While Len(Cells(r, 2).Text) <> 0
mysub = Cells(r, 2) & ", " & Cells(r, 3)
myStart = DateValue(Cells(r, 5).Value) + Cells(r, 6).Value
myEnd = DateValue(Cells(r, 7).Value) + Cells(r, 8).Value
'DeleteTestAppointments mysub, myStart, myEnd
Set olAppItem = olApp.CreateItem(olAppointmentItem) ' creates a new appointment
With olAppItem
' set default appointment values
.Location = Cells(r, 2)
.Body = Cells(r, 3).Value
.ReminderSet = False
.BusyStatus = olFree
'.RequiredAttendees = "johndoe#microsoft.com"
On Error Resume Next
.Start = myStart
.End = myEnd
.Subject = Cells(r, 1)
.Location = Cells(r, 2)
.Body = Cells(r, 3).Value
'.ReminderSet = True
'.BusyStatus = olBusy
.Categories = Cells(r, 4).Value
On Error GoTo 0
.Save ' saves the new appointment to the default folder
End With
r = r + 1
Wend
Set olAppItem = Nothing
Set olApp = Nothing
' Print the Appt Sheet
Sheets("Sheet1").PrintOut
MsgBox "The Appt Sheet Printed and the Appt was entered in your default calendar on May 31st!"
End Sub
‘-------------------------I Need to get correct Public folder for the Exchange calendar -------------
‘I am using VBA for excel workbooks and need to create appointments in 2 public folder shared calendars
‘I need to get code like the code below to create appointments in the shared public calendar – ‘
‘I determine which calendar for the appointment using a workbook cell which is a list box of the 2 calendar names –
‘ Big Store A Calendar or Big Store B Calendar
' GetFolder - Gets a Public folder based on a string path - e.g.
'If Folder name in English is
'Public Folders\All Public Folders\Big Store A Calendar or
‘'Public Folders\All Public Folders\Big Store B Calendar
Public Function GetPublicFolder(strFolderPath)
Dim colFolders
Dim objFolder
Dim arrFolders
Dim i
On Error Resume Next
strFolderPath = Replace(strFolderPath, "/", "\")
arrFolders = Split(strFolderPath, "\")
Set objFolder = Application.Session.GetDefaultFolder(18) ‘This is the correct folder # for “All Public Folders”
Set objFolder = objFolder.Folders.Item(arrFolders(0))
If Not objFolder Is Nothing Then
For i = 1 To UBound(arrFolders)
Set colFolders = objFolder.Folders
Set objFolder = Nothing
Set objFolder = colFolders.Item(arrFolders(i))
If objFolder Is Nothing Then
Exit For
End If
Next
End If
Set GetPublicFolder = objFolder
Set colFolders = Nothing
' Set objApp = Nothing
Set objFolder = Nothing
End Function
Application in Set objFolder = Application.Session.GetDefaultFolder(18) is Excel. You want to use Outlook.
Sub DisplyOutlookPublicFolderFromExcel()
Dim olApp As Outlook.Application
Dim olAppItem As Outlook.AppointmentItem
Dim pubCal As Folder
Set olApp = CreateObject("Outlook.Application")
Set pubCal = GetPublicFolder(olApp, "All Public Folders\Big Store A Calendar")
pubCal.Display
Set olAppItem = Nothing
Set olApp = Nothing
Set pubCal= Nothing
End Sub
Public Function GetPublicFolder(objApp, strFolderPath)
Dim colFolders
Dim objFolder
Dim arrFolders
Dim i
On Error Resume Next
strFolderPath = Replace(strFolderPath, "/", "\")
arrFolders = Split(strFolderPath, "\")
Set objFolder = objApp.Session.GetDefaultFolder(18) 'This is the correct folder # for “All Public Folders”
Set objFolder = objFolder.Folders.Item(arrFolders(0))
If Not objFolder Is Nothing Then
For i = 1 To UBound(arrFolders)
Set colFolders = objFolder.Folders
Set objFolder = Nothing
Set objFolder = colFolders.Item(arrFolders(i))
If objFolder Is Nothing Then
Exit For
End If
Next
End If
Set GetPublicFolder = objFolder
Set colFolders = Nothing
Set objApp = Nothing
Set objFolder = Nothing
End Function
I have the following logic to send an email through outlook from excel. using a userform. The problem is having the textbox activated upon selecting the checkbox. The texbox does not activate upon checking it. I also have tried with the visible property.
The problem is the checkbox is not activating the logic that the else statement.
Private Sub CommandButton9_Click()
On Error GoTo ERRORMSG
Dim OutApp As Object
Dim OutMail As Object
Dim olInsp As Object
Dim wdDoc As Object
Dim oRng As Object
Set otlApp = CreateObject("Outlook.Application")
Set olMail = otlApp.CreateItem(olMailItem)
Set Doc = olMail.GetInspector.WordEditor
Set mainWB = ActiveWorkbook
If CheckBox1.Value = False Then
mainWB.Sheets("Mail").Range("m8").Value = ComboBox4.Value
mainWB.Sheets("Mail").Range("n8").Value = TextBox40.Value
mainWB.Sheets("Mail").Range("q8").Value = ComboBox5.Value
mainWB.Sheets("Mail").Range("r8").Value = ComboBox6.Value
mainWB.Sheets("Mail").Range("s8").Value = ComboBox7.Value
mainWB.Sheets("Mail").Range("t8").Value = TextBox44.Value
On Error Resume Next
Set OutApp = GetObject(, "Outlook.Application")
If Err <> 0 Then Set OutApp = CreateObject("Outlook.Application")
On Error GoTo 0
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = "mainWB.Sheets("Mail").Range("G12").Value"
.cc = mainWB.Sheets("Mail").Range("L12").Value
.Subject = mainWB.Sheets("Mail").Range("O15").Value
Set olInsp = .GetInspector
Set wdDoc = olInsp.WordEditor
Set oRng = wdDoc.Range
'force html format
.HTMLBody = "<HTML><body><body></HTML>"
.display
'--- start with 6 CrLf's, so we can place each table
' above all but the last used...
oRng.InsertAfter vbCrLf & vbCrLf
'--- now reselect the entire document, collapse our cursor to the end
' and back up one character (so that the table inserts before the SIXTH CrLf)
Set oRng = wdDoc.Range
oRng.collapse 0
oRng.Move 1, -1
Range("K3:T10").Select
Selection.Copy
oRng.Paste
'--- finally move the cursor all the way to the end and paste the
' second table BELOW the SIXTH CrLf
Set oRng = wdDoc.Range
oRng.collapse 0
Range("K38:T46").Select
Selection.Copy
oRng.Paste
End With
Else
Label54.enable = True
TextBox46.enable = True
mainWB.Sheets("Mail").Range("m57").Value = ComboBox4.Value
mainWB.Sheets("Mail").Range("n57").Value = TextBox40.Value
mainWB.Sheets("Mail").Range("O57").Value = TextBox46.Value
mainWB.Sheets("Mail").Range("q57").Value = ComboBox5.Value
mainWB.Sheets("Mail").Range("r57").Value = ComboBox6.Value
mainWB.Sheets("Mail").Range("s57").Value = ComboBox7.Value
mainWB.Sheets("Mail").Range("t57").Value = TextBox44.Value
On Error Resume Next
Set OutApp = GetObject(, "Outlook.Application")
If Err <> 0 Then Set OutApp = CreateObject("Outlook.Application")
On Error GoTo 0
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = "mainWB.Sheets("Mail").Range("G12").Value"
.cc = mainWB.Sheets("Mail").Range("L12").Value
.Subject = mainWB.Sheets("Mail").Range("O15").Value
Set olInsp = .GetInspector
Set wdDoc = olInsp.WordEditor
Set oRng = wdDoc.Range
'force html format
.HTMLBody = "<HTML><body><body></HTML>"
.display
'--- start with 6 CrLf's, so we can place each table
' above all but the last used...
oRng.InsertAfter vbCrLf & vbCrLf
'--- now reselect the entire document, collapse our cursor to the end
' and back up one character (so that the table inserts before the SIXTH CrLf)
Set oRng = wdDoc.Range
oRng.collapse 0
oRng.Move 1, -1
Range("K52:T59").Select
Selection.Copy
oRng.Paste
'--- finally move the cursor all the way to the end and paste the
' second table BELOW the SIXTH CrLf
Set oRng = wdDoc.Range
oRng.collapse 0
Range("K38:T46").Select
Selection.Copy
oRng.Paste
End With
End If
Exit Sub
ERRORMSG:
MsgBox "No email was sent", vbExclamation
End Sub
you must:
set both Label54 and TextBox46 Enabled property prior to executing any Userform event handling code
this you can achieve:
either with a Private Sub UserForm_Initialize() sub:
Private Sub UserForm_Initialize()
With Me
.Label54.Enabled = False
.TextBox46.Enabled = False
End With
End Sub
or in the Userform calling block of your "main" sub
Sub Main()
... code
With MyUserForm '<--| change "MyUserForm" to your actual userform name
.Label54.Enabled = False
.TextBox46.Enabled = False
... other possible code here to set some Userform members before showing it
.Show '<--| show your userform
End With
Unload MyUserForm
... more code
End SUb
set both Label54 and TextBox46 Enabled property in your CommandButton9_Click event handler accordingly to CheckBox1 value
like follows:
Option Explicit
Private Sub CommandButton9_Click()
Dim OutApp As Object
Dim mailSht As Worksheet
Dim rowOffset As Long
Set OutApp = GetApp("Outlook.Application")
If OutApp Is Nothing Then
MsgBox "Couldn't set 'Outlook.Application' object"
Exit Sub
End If
Set mailSht = ActiveWorkbook.Sheets("Mail")
rowOffset = IIf(CheckBox1, 56, 7) '<--| set a row offset (from row 1) in according to CheckBox value
Label54.Enabled = CheckBox1 '<--| enable Label54 control if CheckBox1 is checked
TextBox46.Enabled = CheckBox1 '<--| enable TextBox46 control if CheckBox1 is checked
With Me '<--| refer to this userform
'fill "Mail" sheet properly offsetted cells with ComboBoxes and TextBoxes values
FillRangeWithComboBoxValue .ComboBox4, mailSht.Range("m1").Offset(rowOffset)
mailSht.Range("n1").Offset(rowOffset).value = .TextBox40.value
FillRangeWithComboBoxValue .ComboBox5, mailSht.Range("q1").Offset(rowOffset)
FillRangeWithComboBoxValue .ComboBox6, mailSht.Range("r1").Offset(rowOffset)
FillRangeWithComboBoxValue .ComboBox7, mailSht.Range("s1").Offset(rowOffset)
mailSht.Range("t1").Offset(rowOffset).value = .TextBox44.value
End With
On Error GoTo ERRORMSG
With OutApp.CreateItem(0)
.To = mailSht.Range("G12").value
.CC = mailSht.Range("L12").value
.Subject = mailSht.Range("O15").value
'force html format
.HTMLBody = "<HTML><body><body></HTML>"
.display
With .GetInspector.WordEditor
'--- start with 6 CrLf's, so we can place each table
' above all but the last used...
.Range.InsertAfter vbCrLf & vbCrLf
'--- now reselect the entire document, collapse our cursor to the end
' and back up one character (so that the table inserts before the SIXTH CrLf)
With .Range
.collapse 0
.Move 1, -1
mailSht.Range("K3:T10").Copy
.Paste
End With
'--- finally move the cursor all the way to the end and paste the
' second table BELOW the SIXTH CrLf
With .Range
.collapse 0
mailSht.Range("K38:T46").Copy
.Paste
End With
End With
End With
Set OutApp = Nothing '<--| dispose the object variable
Exit Sub
ERRORMSG:
MsgBox "Error on email processing", vbExclamation
End Sub
Function GetApp(appName As String) As Object
On Error Resume Next
Set GetApp = GetObject(, appName)
If GetApp Is Nothing Then Set GetApp = CreateObject(appName)
End Function
Sub FillRangeWithComboBoxValue(cb As msforms.ComboBox, rng As Range)
If cb.ListIndex <> -1 Then rng.value = cb.value
End Sub
where you see I proposed some code shortening and modulizing tips to have it (hopefully) more readable and maintainable
Thanks Guys, it was a simple fix. I put the checkbox condition in the checkbox change event and it works like a gem.
Private Sub CheckBox1_Change()
I am trying to import dates in column "E" to my Outlook calendar.
I have code started, but it is only adding certain dates to my calendar and not adding what it seems to me like multiple dates for ex. The date of 6/2 is being added to my calendar with correct subject date and body, but for dates for 6/1 I have an empty slot.
Option Explicit
Public Sub CreateOutlookApptz()
Sheets("Sheet2").Select
On Error GoTo Err_Execute
Dim olApp As OUtlook.Application
Dim olAppt As OUtlook.AppointmentItem
Dim blnCreated As Boolean
Dim olNs As OUtlook.Namespace
Dim CalFolder As OUtlook.MAPIFolder
Dim subFolder As OUtlook.MAPIFolder
Dim arrCal As String
Dim i As Long
On Error Resume Next
Set olApp = OUtlook.Application
If olApp Is Nothing Then
Set olApp = OUtlook.Application
blnCreated = True
Err.Clear
Else
blnCreated = False
End If
On Error GoTo 0
Set olNs = olApp.GetNamespace("MAPI")
Set CalFolder = olNs.GetDefaultFolder(olFolderCalendar)
i = 2
Do Until Trim(Cells(i, 1).Value) = ""
Set subFolder = CalFolder
Set olAppt = subFolder.Items.Add(olAppointmentItem)
MsgBox Cells(i, 6) + Cells(i, 7)
'MsgBox subFolder, vbOKCancel, "Folder Name"
With olAppt
'Define calendar item properties
.Start = Cells(i, 6) + Cells(i, 7)
.End = Cells(i, 8) + Cells(i, 9)
.Subject = Cells(i, 2)
.Location = Cells(i, 3)
.Body = Cells(i, 4)
.BusyStatus = olBusy
.ReminderMinutesBeforeStart = Cells(i, 10)
.ReminderSet = True
.Categories = Cells(i, 5)
.Save
End With
i = i + 1
Loop
Set olAppt = Nothing
Set olApp = Nothing
Exit Sub
Err_Execute:
MsgBox "An error occurred - Exporting items to Calendar."
End Sub
Try it this way.
Private Sub Add_Appointments_To_Outlook_Calendar()
'Include Microsoft Outlook nn.nn Object Library from Tools -> References
Dim oAppt As AppointmentItem
Dim Remind_Time As Double
i = 2
Subj = ThisWorkbook.Sheets(1).Cells(i, 1)
'Loop through entire list of Reminders to be added
While Subj <> ""
Set oAppt = Outlook.Application.CreateItem(olAppointmentItem)
oAppt.Subject = Subj
oAppt.Location = ThisWorkbook.Sheets(1).Cells(i, 2)
oAppt.Start = ThisWorkbook.Sheets(1).Cells(i, 3)
Remind_Time = ThisWorkbook.Sheets(1).Cells(i, 4) * 1 * 60
oAppt.ReminderMinutesBeforeStart = Remind_Time
oAppt.AllDayEvent = True
oAppt.Save
i = i + 1
Subj = ThisWorkbook.Sheets(1).Cells(i, 1)
Wend
MsgBox "Reminder(s) Added To Outlook Calendar"
End Sub
Your setup will look something like this.
I talk about this concept, and many other similar, but different, things in my book.
https://www.amazon.com/Automating-Business-Processes-Reducing-Increasing-ebook/dp/B01DJJKVZC?ie=UTF8&keywords=ryan%20shuell&qid=1464361126&ref_=sr_1_1&sr=8-1
I have an Excel macro that I run, which takes activity names, dates and times from the spreadsheet and places them into the Outlook calendar. This works fine when Outlook is running, but when it is not, the macro does not make the appointments.
I have made an error checking piece that checks to see if a running instance of Outlook is running and if not creates one but it still only works when Outlook is running.
Any ideas why??
Sub SetAppt()
' Dim olApp As Outlook.Application
Dim olApt As AppointmentItem
Dim olApp As Object
'if an instance of outlook is not open then create an instance of the application
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If er.Number = 429 Then
Set olApp = CreateObject("Outlook.Application.14")
End If
On Error GoTo 0
Set olApp = CreateObject("Outlook.Application")
' Set olApp = New Outlook.Application
'declare an index for all the variables
Dim i As Integer
i = 2
'declare the variables that will hold the data and set their initial value
Dim occ, actName, srtTime, duration As String
occ = "A" & i
actName = "B" & i
srtTime = "F" & i
duration = "G" & i
'for holding different parts of the dates/times that will be split
Dim splitStr() As String
Dim splitDrtion() As String
'loop until there is no more items
While Range(occ).Value <> ""
'create a new appointment
Set olApt = olApp.CreateItem(olAppointmentItem)
'we must split the start time and date
splitStr = Split(Range(srtTime).Value, " ")
Dim oDate As Date
oDate = splitStr(0)
'we must also spilt the duration (number/hour)
splitDrtion = Split(Range(duration).Value, " ")
'with is used to acces the appointment items properties
With olApt
.Start = oDate + TimeValue(splitStr(1))
'if the duration is in hours then multiply number else leave it
If splitDrtion(1) = "Hour" Then
.duration = 60 * splitDrtion(0)
Else
.duration = splitDrtion(0)
End If
.Subject = Range(occ).Value
.Body = Range(actName).Value
.Save
End With
'increment i and reset all the variables with the new number
i = i + 1
occ = "A" & i
actName = "B" & i
srtTime = "F" & i
duration = "G" & i
Set olApt = Nothing
Wend
Set olApp = Nothing
End Sub
Building on Siddharth's example, here is a refactored version of your code.
Sub SetAppt()
Dim olApt As Object ' Outlook.AppointmentItem
Dim olApp As Object ' Outlook.Application
Dim i As Long
Dim apptRange As Variant
Const olAppointmentItem As Long = 1
' create outlook
Set olApp = GetOutlookApp
If olApp Is Nothing Then
MsgBox "Could not start Outlook"
Exit Sub
End If
' read appts into array
apptRange = Range(Cells(2, 1), Cells(Rows.Count, 7).End(xlUp)).value
For i = LBound(apptRange) To UBound(apptRange)
Set olApt = olApp.CreateItem(olAppointmentItem)
With olApt
.Start = apptRange(i, 6)
If InStr(apptRange(i, 7), "Hour") > 0 Then
' numeric portion cell is delimited by space
.Duration = 60 * Split(apptRange(i, 7), " ")(0)
Else
.Duration = apptRange(i, 7)
End If
.Subject = apptRange(i, 1)
.Body = apptRange(i, 2)
.Save
End With
Next i
End Sub
Function GetOutlookApp() As Object
On Error Resume Next
Set GetOutlookApp = CreateObject("Outlook.Application")
End Function
This code reads your worksheet data into an array. This avoids the time penalty that comes from the COM interaction between VBA and Excel.
We loop through the array and create a new appointment for each row.
Using the following sample data, it worked regardless of whether Outlook was open or not (Outlook being closed makes it obviously slower, however).
There is in fact no need to check if Outlook is open.
Instead of
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If er.Number = 429 Then
Set olApp = CreateObject("Outlook.Application.14")
End If
On Error GoTo 0
Set olApp = CreateObject("Outlook.Application")
Try this
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
'~~> If not found then create new instance
If Err.Number <> 0 Then
Set olApp = CreateObject("Outlook.Application")
End If
Err.Clear
On Error GoTo 0
Since I cannot test it, here is your code with the necessary updates. Please try this.
Sub SetAppt()
Dim olApt As Object, olApp As Object
Dim i As Integer
Dim occ As String, actName As String, srtTime As String, duration As String
Dim splitStr() As String, splitDrtion() As String
Dim oDate As Date
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
'~~> If not found then create new instance
If Err.Number <> 0 Then
Set olApp = CreateObject("Outlook.Application")
End If
Err.Clear
On Error GoTo 0
'declare an index for all the variables
i = 2
'declare the variables that will hold the data and set their initial value
occ = "A" & i
actName = "B" & i
srtTime = "F" & i
duration = "G" & i
'loop until there is no more items
While Range(occ).Value <> ""
'create a new appointment
Set olApt = olApp.CreateItem(1)
'we must split the start time and date
splitStr = Split(Range(srtTime).Value, " ")
oDate = splitStr(0)
'we must also spilt the duration (number/hour)
splitDrtion = Split(Range(duration).Value, " ")
'with is used to acces the appointment items properties
With olApt
.Start = oDate + TimeValue(splitStr(1))
'if the duration is in hours then multiply number else leave it
If splitDrtion(1) = "Hour" Then
.duration = 60 * splitDrtion(0)
Else
.duration = splitDrtion(0)
End If
.Subject = Range(occ).Value
.Body = Range(actName).Value
.Save
End With
'increment i and reset all the variables with the new number
i = i + 1
occ = "A" & i
actName = "B" & i
srtTime = "F" & i
duration = "G" & i
Set olApt = Nothing
Wend
Set olApp = Nothing
End Sub