Here is the complete solution code and my reasoning behind it.
There is an inate problem in setting things up to where you cannot save or close the workbook until all fields are completed -- how do you save a "clean" copy of it for distribution and use?!
I solved that issue by using the Workbook_OPEN() event to examine the cells that must be completed by the user for a specific entry and if that entry is found, it is deleted, leaving an empty cell for the user to fill with actual data. I chose "~~~" as
that specific entry.
I then elected to use the Workbook_BeforeClose() process as the point to do the testing instead of the _BeforeSave() process. This allows the user to save the workbook while working with it, but not be able to close it until all data has been entered.
An added twist was the use of merged cells for pretty much all data entry areas, and that has to be dealt with specifically when clearing the ~~~ entries from the cells, while keeping in mind that somewhere along the line, a data entry cell may not be a
merged group.
With all of that, here is the complete code for the ThisWorkbook code module that I have provided back to you in the workbook you sent to me:
Option Explicit
'these values are used by both the _Open() and _BeforeClose() processes
'we declare them here so they only need to be declared once.
Const sName = "Daily Project Safety Report"
Const toBeRemoved = "~~~" ' the dummy value to use to save seed workbook.
Dim checkWS As Worksheet
Dim whatCell_1 As String
Dim whatCell_2 As String ' for East/West testing
Dim RLC As Long ' Row Loop Counter
Private Sub Workbook_Open()
'this process looks at the cells of interest and if they
'contain ~~~ then the entry is deleted, leaving an empty cell.
'this will then allow the tests for empty cells to take
'place later while allowing you to work with the workbook
'for maintenance and you can put ~~~ into all data entry cells
'and be able to save and distribute the workbook to others for
'normal use.
'
'merged cells create special problems and we deal with them as needed
Application.ScreenUpdating = False ' to prevent screen flicker
Set checkWS = ThisWorkbook.Worksheets(sName)
On Error Resume Next ' so our merged cells tests work properly
whatCell_1 = "E3"
If Trim(checkWS.Range(whatCell_1)) = toBeRemoved Then
checkWS.Range(whatCell_1).MergeArea.ClearContents
If Err <> 0 Then
checkWS.Range(whatCell_1).ClearContents
Err.Clear
End If
End If
whatCell_1 = "F4"
If Trim(checkWS.Range(whatCell_1)) = toBeRemoved Then
checkWS.Range(whatCell_1).MergeArea.ClearContents
If Err <> 0 Then
checkWS.Range(whatCell_1).ClearContents
Err.Clear
End If
End If
whatCell_1 = "I4"
If Trim(checkWS.Range(whatCell_1)) = toBeRemoved Then
checkWS.Range(whatCell_1).MergeArea.ClearContents
If Err <> 0 Then
checkWS.Range(whatCell_1).ClearContents
Err.Clear
End If
End If
For RLC = 5 To 7
whatCell_1 = "E" & CStr(RLC)
If Trim(checkWS.Range(whatCell_1)) = toBeRemoved Then
checkWS.Range(whatCell_1).MergeArea.ClearContents
If Err <> 0 Then
checkWS.Range(whatCell_1).ClearContents
Err.Clear
End If
End If
Next ' end RLC loop
For RLC = 3 To 7
whatCell_1 = "O" & CStr(RLC)
If Trim(checkWS.Range(whatCell_1)) = toBeRemoved Then
checkWS.Range(whatCell_1).MergeArea.ClearContents
If Err <> 0 Then
checkWS.Range(whatCell_1).ClearContents
Err.Clear
End If
End If
Next ' end RLC loop
For RLC = 10 To 12
whatCell_1 = "K" & CStr(RLC)
If Trim(checkWS.Range(whatCell_1)) = toBeRemoved Then
checkWS.Range(whatCell_1).MergeArea.ClearContents
If Err <> 0 Then
checkWS.Range(whatCell_1).ClearContents
Err.Clear
End If
End If
Next ' end RLC loop
'reset error trapping - allow system to handle them again
On Error GoTo 0
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'
'if you want to make changes to the code or form and then
'be able to save the changes without having to make entries
'then make this one line of code active while doing that
'and then later make it a comment again to have the
'sheet force entries when used.
'Exit Sub
'but in order to save the workbook with empty cells for use
'you'll need to open the workbook but disable macros! then
'make sure your cells are empty as required, comment out
'the Exit Sub statement above and then save the workbook.
'
'make checkWS refer to the sheet we want to examine
Set checkWS = ThisWorkbook.Worksheets(sName)
'the Project Name entry
whatCell_1 = "E3"
If Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1)) Then
MsgBox "Please provide entry into cell " & whatCell_1
Cancel = True
Exit Sub
End If
'this is a 2-cell test I have assumed that either
'one or the other must be completed, but not both
'the East/West entries
whatCell_1 = "F4"
whatCell_2 = "I4"
If (Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1))) _
And _
(Trim(checkWS.Range(whatCell_2)) = "" Or _
IsEmpty(checkWS.Range(whatCell_2))) Then
MsgBox "You must provide an East/West entry at " _
& whatCell_1 & " or " & whatCell_2
Cancel = True
Exit Sub
End If
'the Rep's Name entry
whatCell_1 = "O4"
If Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1)) Then
MsgBox "Please provide entry into cell " & whatCell_1
Cancel = True
Exit Sub
End If
'the Project/Work Order entry
whatCell_1 = "E5"
If Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1)) Then
MsgBox "Please provide entry into cell " & whatCell_1
Cancel = True
Exit Sub
End If
'the General Contractor entry
whatCell_1 = "E6"
If Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1)) Then
MsgBox "Please provide entry into cell " & whatCell_1
Cancel = True
Exit Sub
End If
'the Safety Rep Company entry
whatCell_1 = "E7"
If Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1)) Then
MsgBox "Please provide entry into cell " & whatCell_1
Cancel = True
Exit Sub
End If
'here I show how to check a contiguous range/list of cells
'for the 4 entries in column O beginning at row 3.
For RLC = 3 To 6 ' the rows involved
whatCell_1 = "O" & CStr(RLC) ' combine "O" with the # to make an address
If Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1)) Then
MsgBox "Please provide entry into cell " & whatCell_1
Cancel = True
Exit Sub
End If
Next ' end of RLC loop
'here I show how to check a contiguous range/list of cells
'this time for the 3 Site Conditions entries
For RLC = 10 To 12 ' the rows involved
whatCell_1 = "K" & CStr(RLC) ' combine "K" with the # to make an address
If Trim(checkWS.Range(whatCell_1)) = "" Or _
IsEmpty(checkWS.Range(whatCell_1)) Then
MsgBox "Please provide entry into cell " & whatCell_1
Cancel = True
Exit Sub
End If
Next ' end of RLC loop
End Sub