ASSISTANT
Based on the issue you mentioned regarding the "Invalid procedure call or argument" error, the likely culprit is the `FormatTrackerSheet` function in the `SetupModule`. Let's focus on updating that module to ensure everything works as expected. If the problem is with the formatting, it might need to be refined both in function logic and edge-case handling.
Here’s the updated code for modules that likely require adjustment:
### **SetupModule**
This module initializes the sheets and handles formatting:
```vba
Option Explicit
' Constants for sheet names and button captions
Public Const SHEET_NAME_MAIN As String = "Sheet1"
Public Const SHEET_NAME_LOG As String = "ActivityLog"
Public Const SHEET_NAME_FOLLOW_UP As String = "FollowUpMessages"
Public Const SHEET_NAME_PREFERENCES As String = "Preferences"
Public Const BTN_CAPTION_ADD As String = "Add to List"
Public Const BTN_CAPTION_DELETE As String = "Delete"
Public Const BTN_CAPTION_SEND_FOLLOW_UP As String = "Send Follow-Up"
Public Const BTN_CAPTION_CHECK_RESPONSES As String = "Check Responses"
Public Const BTN_CAPTION_SEND_FOLLOW_UP_TO_ALL As String = "Send Follow-Up To All"
Public Const BTN_CAPTION_DATA_VISUALIZATION As String = "Data Visualization"
Public Const BTN_CAPTION_IMPORT_DATA As String = "Import Data"
Public Const BTN_CAPTION_EXPORT_DATA As String = "Export Data"
Public Const BTN_CAPTION_CLOSE_TRACKER As String = "Close Tracker"
Public Const BACKUP_INTERVAL_HOURS As Integer = 1
Public Const DEFAULT_BACKUP_PATH As String = "C:\Backups\"
Public Sub InitializeFullEmailTracker()
On Error GoTo ErrorHandler
Dim wsMain As Worksheet, wsLog As Worksheet, wsFollowUp As Worksheet, wsPreferences As Worksheet
Set wsMain = EnsureSheetExists(SHEET_NAME_MAIN)
Set wsLog = EnsureSheetExists(SHEET_NAME_LOG)
Set wsFollowUp = EnsureSheetExists(SHEET_NAME_FOLLOW_UP)
Set wsPreferences = EnsureSheetExists(SHEET_NAME_PREFERENCES)
SetupHeaders wsMain
SetupInputFields wsMain
SetupButtons wsMain
SetupActivityLog wsLog
SetupFollowUpMessages wsFollowUp
SetupPreferences wsPreferences
' Format the tracker sheet
FormatTrackerSheet wsMain
' Activate the main sheet
wsMain.Activate
Exit Sub
ErrorHandler:
MsgBox "An error occurred: " & Err.Description, vbExclamation
Debug.Print "Error in InitializeFullEmailTracker: " & Err.Description
End Sub
Private Function EnsureSheetExists(sheetName As String) As Worksheet
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Sheets(sheetName)
On Error GoTo 0
If ws Is Nothing Then
Set ws = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = sheetName
End If
Set EnsureSheetExists = ws
End Function
Private Sub SetupHeaders(ws As Worksheet)
On Error GoTo ErrorHandler
With ws
' Input labels
.Cells(1, 1).Value = "Email Subject:"
.Cells(1, 2).Value = "Recipients:"
' Data table headers starting from Row 4
.Cells(4, 1).Value = "Email Subject"
.Cells(4, 2).Value = "Recipients"
.Cells(4, 3).Value = "Status"
.Cells(4, 4).Value = "Remarks"
.Cells(4, 5).Value = "Last Follow-Up Date"
.Cells(4, 6).Value = "Delete"
.Cells(4, 7).Value = "Send Follow-Up"
.Cells(4, 8).Value = "Last Response Date" ' Column H
.Cells(4, 9).Value = "Follow-Up Count" ' Column I
.Cells(4, 10).Value = "ConversationID" ' Column J (New column)
End With
Exit Sub
ErrorHandler:
MsgBox "An error occurred while setting up headers: " & Err.Description, vbExclamation
Debug.Print "Error in SetupHeaders: " & Err.Description
End Sub
Private Sub SetupInputFields(ws As Worksheet)
On Error GoTo ErrorHandler
With ws
.Cells(2, 1).Value = ""
.Cells(2, 2).Value = ""
End With
Exit Sub
ErrorHandler:
MsgBox "An error occurred while setting up input fields: " & Err.Description, vbExclamation
Debug.Print "Error in SetupInputFields: " & Err.Description
End Sub
Private Sub SetupButtons(ws As Worksheet)
On Error GoTo ErrorHandler
Dim shp As Shape
Dim rng As Range
' Add To List button
If Not ButtonExists(ws, BTN_CAPTION_ADD) Then
Set rng = ws.Range("D1:E1")
Set shp = ws.Shapes.AddShape(msoShapeRoundedRectangle, rng.Left, rng.Top, rng.Width, rng.Height)
With shp
.TextFrame.Characters.Text = BTN_CAPTION_ADD
.OnAction = "AddEmailToList"
.Name = "Button_AddToList"
.Fill.ForeColor.RGB = RGB(0, 176, 80) ' Green
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(255, 255, 255) ' White text
.Line.Visible = msoFalse
.Placement = xlMoveAndSize
.LockAspectRatio = msoTrue
End With
End If
' Check Responses button
If Not ButtonExists(ws, BTN_CAPTION_CHECK_RESPONSES) Then
Set rng = ws.Range("D2:E2")
Set shp = ws.Shapes.AddShape(msoShapeRoundedRectangle, rng.Left, rng.Top, rng.Width, rng.Height)
With shp
.TextFrame.Characters.Text = BTN_CAPTION_CHECK_RESPONSES
.OnAction = "CheckEmailResponses"
.Name = "Button_CheckResponses"
.Fill.ForeColor.RGB = RGB(0, 112, 192) ' Blue
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(255, 255, 255) ' White text
.Line.Visible = msoFalse
.Placement = xlMoveAndSize
.LockAspectRatio = msoTrue
End With
End If
' Send Follow-Up To All button
If Not ButtonExists(ws, BTN_CAPTION_SEND_FOLLOW_UP_TO_ALL) Then
Set rng = ws.Range("D3:E3")
Set shp = ws.Shapes.AddShape(msoShapeRoundedRectangle, rng.Left, rng.Top, rng.Width, rng.Height)
With shp
.TextFrame.Characters.Text = BTN_CAPTION_SEND_FOLLOW_UP_TO_ALL
.OnAction = "SendFollowUpToAll"
.Name = "Button_SendFollowUpToAll"
.Fill.ForeColor.RGB = RGB(255, 192, 0) ' Orange
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(0, 0, 0) ' Black text
.Line.Visible = msoFalse
.Placement = xlMoveAndSize
.LockAspectRatio = msoTrue
End With
End If
' Data Visualization button
If Not ButtonExists(ws, BTN_CAPTION_DATA_VISUALIZATION) Then
Set rng = ws.Range("F1:G1")
Set shp = ws.Shapes.AddShape(msoShapeRoundedRectangle, rng.Left, rng.Top, rng.Width, rng.Height)
With shp
.TextFrame.Characters.Text = BTN_CAPTION_DATA_VISUALIZATION
.OnAction = "CreateDataVisualization"
.Name = "Button_DataVisualization"
.Fill.ForeColor.RGB = RGB(112, 48, 160) ' Purple
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(255, 255, 255) ' White text
.Line.Visible = msoFalse
.Placement = xlMoveAndSize
.LockAspectRatio = msoTrue
End With
End If
' Import Data button
If Not ButtonExists(ws, BTN_CAPTION_IMPORT_DATA) Then
Set rng = ws.Range("F2:G2")
Set shp = ws.Shapes.AddShape(msoShapeRoundedRectangle, rng.Left, rng.Top, rng.Width, rng.Height)
With shp
.TextFrame.Characters.Text = BTN_CAPTION_IMPORT_DATA
.OnAction = "ImportData"
.Name = "Button_ImportData"
.Fill.ForeColor.RGB = RGB(0, 176, 240) ' Light Blue
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(0, 0, 0) ' Black text
.Line.Visible = msoFalse
.Placement = xlMoveAndSize
.LockAspectRatio = msoTrue
End With
End If
' Export Data button
If Not ButtonExists(ws, BTN_CAPTION_EXPORT_DATA) Then
Set rng = ws.Range("F3:G3")
Set shp = ws.Shapes.AddShape(msoShapeRoundedRectangle, rng.Left, rng.Top, rng.Width, rng.Height)
With shp
.TextFrame.Characters.Text = BTN_CAPTION_EXPORT_DATA
.OnAction = "ExportData"
.Name = "Button_ExportData"
.Fill.ForeColor.RGB = RGB(0, 176, 240) ' Light Blue
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(0, 0, 0) ' Black text
.Line.Visible = msoFalse
.Placement = xlMoveAndSize
.LockAspectRatio = msoTrue
End With
End If
' Close Tracker button
If Not ButtonExists(ws, BTN_CAPTION_CLOSE_TRACKER) Then
Set rng = ws.Range("F4:G4")
Set shp = ws.Shapes.AddShape(msoShapeRoundedRectangle, rng.Left, rng.Top, rng.Width, rng.Height)
With shp
.TextFrame.Characters.Text = BTN_CAPTION_CLOSE_TRACKER
.OnAction = "CloseTracker"
.Name = "Button_CloseTracker"
.Fill.ForeColor.RGB = RGB(192, 0, 0) ' Dark Red
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(255, 255, 255) ' White text
.Line.Visible = msoFalse
.Placement = xlMoveAndSize
.LockAspectRatio = msoTrue
End With
End If
Exit Sub
ErrorHandler:
MsgBox "An error occurred while setting up buttons: " & Err.Description, vbExclamation
Debug.Print "Error in SetupButtons: " & Err.Description
End Sub
Private Sub SetupActivityLog(wsLog As Worksheet)
On Error GoTo ErrorHandler
With wsLog
.Cells(1, 1).Value = "Date"
.Cells(1, 2).Value = "Action"
End With
Exit Sub
ErrorHandler:
MsgBox "An error occurred while setting up activity log: " & Err.Description, vbExclamation
Debug.Print "Error in SetupActivityLog: " & Err.Description
End Sub
Private Sub SetupFollowUpMessages(wsFollowUp As Worksheet)
On Error GoTo ErrorHandler
With wsFollowUp
.Cells(1, 1).Value = "Type"
.Cells(1, 2).Value = "Message"
.Cells(1, 3).Value = "Escalation Recipient" ' New column
.Cells(2, 1).Value = "Follow-Up Message"
.Cells(3, 1).Value = "Escalation Message"
.Cells(2, 2).Value = "This is a follow-up. Please let us know if you need any further information."
.Cells(3, 2).Value = "We have not received a response. This is an escalation email. Please respond at your earliest convenience."
.Cells(3, 3).Value = "" ' Escalation recipient email, to be filled by user
End With
Exit Sub
ErrorHandler:
MsgBox "An error occurred while setting up follow-up messages: " & Err.Description, vbExclamation
Debug.Print "Error in SetupFollowUpMessages: " & Err.Description
End Sub
Private Sub SetupPreferences(wsPreferences As Worksheet)
On Error GoTo ErrorHandler
With wsPreferences
.Cells(1, 1).Value = "Backup Path"
.Cells(1, 2).Value = DEFAULT_BACKUP_PATH
.Cells(2, 1).Value = "Backup Interval (Hours)"
.Cells(2, 2).Value = BACKUP_INTERVAL_HOURS
.Cells(3, 1).Value = "First Follow-Up Interval (Days)"
.Cells(3, 2).Value = 1
.Cells(4, 1).Value = "Escalation Interval (Days)"
.Cells(4, 2).Value = 10
.Cells(5, 1).Value = "Response Check Interval (Minutes)"
.Cells(5, 2).Value = 1 ' Default 1 minute
' You can add more settings here as needed
End With
Exit Sub
ErrorHandler:
MsgBox "An error occurred while setting up preferences: " & Err.Description, vbExclamation
Debug.Print "Error in SetupPreferences: " & Err.Description
End Sub
Private Function ButtonExists(ws As Worksheet, caption As String) As Boolean
Dim shp As Shape
ButtonExists = False
For Each shp In ws.Shapes
If shp.Type = msoShapeRectangle Or shp.Type = msoShapeRoundedRectangle Then
If shp.TextFrame.Characters.Text = caption Then
ButtonExists = True
Exit Function
End If
End If
Next shp
End Function
Public Sub FormatTrackerSheet(ws As Worksheet)
On Error GoTo ErrorHandler
Dim lastRow As Long
lastRow = GetLastDataRow(ws)
If lastRow < 4 Then
MsgBox "No data to format", vbExclamation
Exit Sub
End If
' Format Header Row (Row 4)
With ws.Range("A4:J4") ' Ensure it includes all relevant columns up to Column J
.Font.Bold = True
.Interior.Color = RGB(0, 112, 192) ' Blue color
.Font.Color = RGB(255, 255, 255) ' White text
.HorizontalAlignment = xlCenter
End With
' Auto-fit columns and check column range validity
If ws.Columns.Count >= 10 Then
ws.Columns("A:J").AutoFit ' Update columns as needed
Else
MsgBox "Error: The expected column range A:J is not fully available.", vbCritical
Exit Sub
End If
' Format Input Row
With ws.Range("A2:B2")
.Interior.Color = RGB(217, 225, 242) ' Light Blue
.Font.Color = RGB(0, 0, 0) ' Black text
End With
' Apply borders to all cells with data
If lastRow >= 5 Then
With ws.Range("A4:J" & lastRow)
.Borders.LineStyle = xlContinuous
.Borders.Weight = xlThin
End With
End If
' Clear existing conditional formatting
ws.Range("A5:J" & lastRow).FormatConditions.Delete
' Apply conditional formatting to highlight rows with responses
If lastRow >= 5 Then
Dim dataRange As Range
Set dataRange = ws.Range("A5:J" & lastRow)
With dataRange
' Highlight rows where "Remarks" is "Response Received"
.FormatConditions.Add Type:=xlExpression, Formula1:="=$D5=""Response Received"""
With .FormatConditions(.FormatConditions.Count)
.Interior.Color = RGB(198, 239, 206) ' Light Green
End With
' Highlight rows where "Status" is "Operator Replied"
.FormatConditions.Add Type:=xlExpression, Formula1:="=$C5=""Operator Replied"""
With .FormatConditions(.FormatConditions.Count)
.Interior.Color = RGB(255, 255, 204) ' Light Yellow
End With
' Highlight rows where "Status" is "You Replied"
.FormatConditions.Add Type:=xlExpression, Formula1:="=$C5=""You Replied"""
With .FormatConditions(.FormatConditions.Count)
.Interior.Color = RGB(204, 229, 255) ' Light Blue
End With
End With
End If
' Freeze panes to keep headers visible
ws.Activate
ws.Range("A5").Select
ActiveWindow.FreezePanes = True
Exit Sub
ErrorHandler:
MsgBox "An error occurred while formatting the tracker sheet: " & Err.Description, vbExclamation
Debug.Print "Error in FormatTrackerSheet: " & Err.Description
End Sub
```
### **HelperModule**
Ensure that `GetLastDataRow` is implemented as it is crucial for the context you're dealing with:
```vba
Option Explicit
Public Function GetLastDataRow(ws As Worksheet) As Long
On Error Resume Next
' Find the last row with data in column A
GetLastDataRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
' Ensure we don't count the header row (row 4) as data
If GetLastDataRow < 5 Then GetLastDataRow = 4
On Error GoTo 0
End Function
Public Function GetNextAvailableRow(ws As Worksheet) As Long
GetNextAvailableRow = GetLastDataRow(ws) + 1
If GetNextAvailableRow < 5 Then GetNextAvailableRow = 5
End Function
Public Function GetPreference(prefName As String) As Variant
Dim wsPreferences As Worksheet
Set wsPreferences = ThisWorkbook.Sheets(SHEET_NAME_PREFERENCES)
Dim lastRow As Long, i As Long
lastRow = wsPreferences.Cells(wsPreferences.Rows.Count, 1).End(xlUp).Row
For i = 1 To lastRow
If wsPreferences.Cells(i, 1).Value = prefName Then
GetPreference = wsPreferences.Cells(i, 2).Value
Exit Function
End If
Next i
' Default values if preference not found
Select Case prefName
Case "Response Check Interval (Minutes)"
GetPreference = 1
Case "First Follow-Up Interval (Days)"
GetPreference = 1
Case "Escalation Interval (Days)"
GetPreference = 10
Case Else
GetPreference = ""
End Select
End Function
```
### Changes and Checks:
1. **Last Row Logic**: Ensures logic for detecting the last row of data is correctly implemented and manipulated.
2. **Formatting and Autofit**: Ensures range availability before attempting to format or modify them (especially with Autofit).
3. **Error Messages**: Helps you track down problems by stating specific functions and error details.
Please apply these changes and test the workflow. These updates intend to address invalid range or procedure call scenarios often leading to errors. Let me know how it goes!