0% found this document useful (0 votes)
1 views

VBA Code for Audit Schedule Booking Tool

Uploaded by

gexehon970
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

VBA Code for Audit Schedule Booking Tool

Uploaded by

gexehon970
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 6

' === CONFIGURATION CONSTANTS ===

' Change these values if your worksheet layout changes.


Public Const COL_AUDIT_NAME As Long = 1 ' Audit name in cell A1
Public Const COL_SESSION_NUMBER As Long = 1 ' Session # (Column A)
Public Const COL_AUDIT_DATE As Long = 2 ' Audit day indicator or time
range (Column B)
Public Const COL_SESSION_TIME As Long = 2 ' Time range (Column B)
Public Const COL_SUBJECT_EXTRA1 As Long = 7 ' Customer/Site (Column G)
Public Const COL_SUBJECT_EXTRA2 As Long = 3 ' Session Name (Column C)
Public Const COL_PROCESS As Long = 4 ' Process/activities description
(Column D)
Public Const COL_AUDITOR As Long = 9 ' Auditor (Column I)
Public Const COL_AUDITEE As Long = 10 ' Auditee (Column J)
Public Const COL_LOCATION As Long = 11 ' Meeting location (Column K)
Public Const START_DATA_ROW As Long = 4 ' Row where session data starts

' === MAIN SUB ===


Sub CreateOutlookMeetings()
Dim OutlookApp As Object, OutlookMeeting As Object
Dim ws As Worksheet, wb As Workbook
Dim i As Long, lastRow As Long
Dim auditDate As Date, lastAuditDate As Date
Dim timeRange As String
Dim startTime As Date, endTime As Date
Dim auditName As String
Dim lastSessionRow As Object
Dim auditDates As Object
Dim filePath As String
Dim wsIndex As Integer, wsItem As Worksheet, wsList As String
Dim sheetCounter As Integer
Dim meetingScheduled As Boolean

' --- Initialize dictionaries to track audit dates and last session row per
audit day ---
Set lastSessionRow = CreateObject("Scripting.Dictionary")
Set auditDates = CreateObject("Scripting.Dictionary")

' --- Allow the user to browse for the workbook ---
filePath = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*", ,
"Select the schedule workbook")
If filePath = "False" Then Exit Sub ' User canceled

Set wb = Workbooks.Open(filePath)

' --- Allow user to select worksheet by number ---


sheetCounter = 1
For Each wsItem In wb.Sheets
wsList = wsList & sheetCounter & ": " & wsItem.Name & vbCrLf
sheetCounter = sheetCounter + 1
Next wsItem

On Error Resume Next


wsIndex = Application.InputBox("Select a worksheet by entering its number:" &
vbCrLf & wsList, "Select Worksheet", Type:=1)
On Error GoTo 0

If wsIndex = 0 Then
MsgBox "No worksheet selected. Operation canceled.", vbExclamation
wb.Close False
Exit Sub
End If

On Error Resume Next


Set ws = wb.Sheets(wsIndex)
On Error GoTo 0

If ws Is Nothing Then
MsgBox "The selected worksheet does not exist in the workbook. Please try
again.", vbExclamation
wb.Close False
Exit Sub
End If

' --- Determine last row in the worksheet (using session number column) ---
lastRow = ws.Cells(ws.Rows.Count, COL_SESSION_NUMBER).End(xlUp).Row
If lastRow < START_DATA_ROW Then
MsgBox "The worksheet does not contain sufficient data.", vbExclamation
wb.Close False
Exit Sub
End If

' --- Initialize Outlook ---


On Error Resume Next
Set OutlookApp = GetObject(, "Outlook.Application")
If OutlookApp Is Nothing Then Set OutlookApp =
CreateObject("Outlook.Application")
If OutlookApp Is Nothing Then
MsgBox "Outlook could not be initialized.", vbExclamation
wb.Close False
Exit Sub
End If
On Error GoTo 0

' --- Retrieve audit name from cell A1 ---


auditName = Trim(ws.Cells(1, COL_AUDIT_NAME).Value)
If auditName = "" Then
MsgBox "Audit name is missing in cell A1.", vbExclamation
wb.Close False
Exit Sub
End If

' --- First pass: identify audit dates and last session row for each day ---
For i = START_DATA_ROW To lastRow
If IsEmpty(ws.Cells(i, COL_SESSION_NUMBER).Value) Or IsEmpty(ws.Cells(i,
COL_SESSION_TIME).Value) Then Exit For

' If column B holds a date, it marks a new audit day.


If IsDate(ws.Cells(i, COL_AUDIT_DATE).Value) Then
auditDate = ws.Cells(i, COL_AUDIT_DATE).Value
lastSessionRow(auditDate) = i
If Not auditDates.Exists(auditDate) Then auditDates.Add auditDate, True
ElseIf ws.Cells(i, COL_SESSION_NUMBER).Value > 0 Then
lastSessionRow(auditDate) = i ' Update last session row for this day
End If
Next i

' --- Get the last audit day ---


If auditDates.Count = 0 Then
MsgBox "No audit dates found in the worksheet.", vbExclamation
wb.Close False
Exit Sub
End If
lastAuditDate = auditDates.Keys()(auditDates.Count - 1)

' --- Main loop: Create session meetings and schedule wrap-up meetings ---
meetingScheduled = False
For i = START_DATA_ROW To lastRow
If IsEmpty(ws.Cells(i, COL_SESSION_NUMBER).Value) Or IsEmpty(ws.Cells(i,
COL_SESSION_TIME).Value) Then Exit For

If IsDate(ws.Cells(i, COL_AUDIT_DATE).Value) Then


auditDate = ws.Cells(i, COL_AUDIT_DATE).Value
meetingScheduled = False
ElseIf ws.Cells(i, COL_SESSION_NUMBER).Value > 0 Then
CreateSessionMeeting OutlookApp, ws, i, auditName, auditDate
End If

If lastSessionRow.Exists(auditDate) And lastSessionRow(auditDate) = i And


auditDate <> lastAuditDate And Not meetingScheduled Then
CreateWrapUpMeeting OutlookApp, ws, i, auditName, auditDate, lastRow
meetingScheduled = True

' --- Pause for user confirmation before proceeding ---


Dim response As VbMsgBoxResult
response = MsgBox("Do you want to continue scheduling for the next
audit day?", vbYesNo + vbQuestion, "Continue?")
If response = vbNo Then Exit For
End If
Next i

' --- Clean up ---


wb.Close False
Set OutlookApp = Nothing
MsgBox "Meetings created successfully!", vbInformation
End Sub

' === SUB: Create Session Meeting ===


Sub CreateSessionMeeting(OutlookApp As Object, ws As Worksheet, i As Long,
auditName As String, auditDate As Date)
Dim timeRange As String
Dim startTime As Date, endTime As Date
Dim timeParts() As String

timeRange = Trim(ws.Cells(i, COL_SESSION_TIME).Value)


If InStr(timeRange, "-") > 0 Then
timeParts = Split(timeRange, "-")
On Error Resume Next
startTime = CDate(auditDate & " " & Trim(timeParts(0)))
endTime = CDate(auditDate & " " & Trim(timeParts(1)))
On Error GoTo 0

If startTime > 0 And endTime > 0 Then


Dim OutlookMeeting As Object
Set OutlookMeeting = OutlookApp.CreateItem(1)
With OutlookMeeting
.Subject = "Session " & ws.Cells(i, COL_SESSION_NUMBER).Value & " _
" & _
auditName & " _ " & ws.Cells(i,
COL_SUBJECT_EXTRA1).Value & " _ " & ws.Cells(i, COL_SUBJECT_EXTRA2).Value
.Start = startTime
.End = endTime
.location = ws.Cells(i, COL_LOCATION).Value
.Body = "Dear all," & vbCrLf & vbCrLf & _
"I would like to book your calendar for the " & auditName &
" of " & _
ws.Cells(i, COL_SUBJECT_EXTRA2).Value & " as follows:" &
vbCrLf & vbCrLf & _
"Auditor: " & vbCrLf & ws.Cells(i, COL_AUDITOR).Value &
vbCrLf & vbCrLf & _
"Auditee: " & vbCrLf & ws.Cells(i, COL_AUDITEE).Value &
vbCrLf & vbCrLf & _
"Detail Process/Activities (but not limited to):" & vbCrLf
& ws.Cells(i, COL_PROCESS).Value & vbCrLf & vbCrLf & _
"Audit Location: " & ws.Cells(i, COL_LOCATION).Value &
vbCrLf & vbCrLf & _
"Audit method (MS Teams/On-site) should be aligned between
auditor & auditee." & vbCrLf & vbCrLf & _
"Please forward this invitation to related people if
needed." & vbCrLf & vbCrLf & _
"Thank you!"
.MeetingStatus = 1

' --- Add Recipients ---


Dim recipientList() As String, recipient As Variant
Dim uniqueRecipients As Collection
Set uniqueRecipients = New Collection

recipientList = ParseRecipients(ws.Cells(i, COL_AUDITOR).Value &


";" & ws.Cells(i, COL_AUDITEE).Value)
On Error Resume Next
For Each recipient In recipientList
recipient = CleanRecipient(Trim(recipient))
If recipient <> "" Then
uniqueRecipients.Add recipient, recipient ' Duplicates are
skipped
End If
Next
On Error GoTo 0

For Each recipient In uniqueRecipients


.recipients.Add recipient
Next
.recipients.ResolveAll
.recipients.ResolveAll
.Display
End With
Set OutlookMeeting = Nothing
End If
End If
End Sub

' === SUB: Create Wrap-Up Meeting ===


Sub CreateWrapUpMeeting(OutlookApp As Object, ws As Worksheet, i As Long, auditName
As String, auditDate As Date, lastRow As Long)
Dim timeRange As String
Dim wrapUpStartTime As Date, wrapUpEndTime As Date
Dim timeParts() As String

' Assumes wrap-up time is in the row immediately after the last session.
timeRange = Trim(ws.Cells(i + 1, COL_SESSION_TIME).Value)
If InStr(timeRange, "-") > 0 Then
timeParts = Split(timeRange, "-")
On Error Resume Next
wrapUpStartTime = CDate(auditDate & " " & Trim(timeParts(0)))
wrapUpEndTime = CDate(auditDate & " " & Trim(timeParts(1)))
On Error GoTo 0

If wrapUpStartTime > 0 And wrapUpEndTime > 0 Then


Dim OutlookMeeting As Object
Set OutlookMeeting = OutlookApp.CreateItem(1)
With OutlookMeeting
.Subject = "Daily Wrap-Up Meeting - " & auditName & " " & auditDate
.Start = wrapUpStartTime
.End = wrapUpEndTime
.location = "TBD"
.Body = "Dear team," & vbCrLf & vbCrLf & vbCrLf & _
"This is the wrap-up meeting for " & auditName & " on " &
auditDate & "." & vbCrLf & vbCrLf & _
"Agenda: Summary of the day's findings and discussion
points."
.MeetingStatus = 1

Dim recipientListDay As Collection, recipient As Variant


Set recipientListDay = GetRecipientsForDay(ws, auditDate, lastRow)
For Each recipient In recipientListDay
.recipients.Add recipient
Next
.recipients.ResolveAll
.recipients.ResolveAll
.Display
End With
Set OutlookMeeting = Nothing
End If
End If
End Sub

' === HELPER FUNCTION: Parse Recipients ===


Function ParseRecipients(recipientString As String) As String()
Dim temp As String, cleanedString As String
Dim separators As String, recipientArray() As String
separators = ",;" & vbLf & vbCr ' Define all possible delimiters
cleanedString = recipientString

Dim i As Integer
For i = 1 To Len(separators)
temp = Mid(separators, i, 1)
cleanedString = Replace(cleanedString, temp, ";")
Next i

recipientArray = Split(cleanedString, ";")


ParseRecipients = recipientArray
End Function

' === HELPER FUNCTION: Clean Recipient String ===


Function CleanRecipient(recipient As String) As String
Dim position As Long
position = InStr(recipient, ":")
If position = 0 Then position = InStr(recipient, "-")
If position > 0 Then
recipient = Mid(recipient, position + 1)
End If
CleanRecipient = Trim(recipient)
End Function

' === HELPER FUNCTION: Get Recipients for a Given Audit Day ===
Function GetRecipientsForDay(ws As Worksheet, auditDate As Date, lastRow As Long)
As Collection
Dim recipientList As New Collection
Dim i As Long, timeRange As String
Dim currentAuditDate As Date
Dim timeParts() As String

For i = START_DATA_ROW To lastRow


' If this row has a date in the audit date column, update our
currentAuditDate
If IsDate(ws.Cells(i, COL_AUDIT_DATE).Value) Then
currentAuditDate = ws.Cells(i, COL_AUDIT_DATE).Value
End If

' Now, if the currentAuditDate matches the auditDate we're looking for,
' and the row is a session row (indicated by a session number in the
session number column),
' then we process it.
If currentAuditDate = auditDate And ws.Cells(i, COL_SESSION_NUMBER).Value >
0 Then
timeRange = Trim(ws.Cells(i, COL_SESSION_TIME).Value)
If InStr(timeRange, "-") > 0 Then
timeParts = Split(timeRange, "-")
' We can skip validating times here if it's not needed for
collecting recipients
Dim recipients As String
recipients = Trim(ws.Cells(i, COL_AUDITOR).Value) & ";" &
Trim(ws.Cells(i, COL_AUDITEE).Value)
Dim recipientArray() As String, recipient As Variant
recipientArray = ParseRecipients(recipients)
For Each recipient In recipientArray
If Trim(recipient) <> "" Then
On Error Resume Next
recipientList.Add CleanRecipient(Trim(recipient)),
CleanRecipient(Trim(recipient))
On Error GoTo 0
End If
Next recipient
End If
End If
Next i
Set GetRecipientsForDay = recipientList
End Function

You might also like