Home » excel » excel – vba insert validation list – error 1004 when worksheet locked?

excel – vba insert validation list – error 1004 when worksheet locked?

Posted by: admin April 23, 2020 Leave a comment


I have the following vba code which works fine, however it doesn’t work when I lock/protect my worksheet, even though I have unticked ‘locked’ for the relevant cells within the cell format options.

can someone help me understand why I am getting a error 1004 application defined or object defined error when the worksheet is locked? thanks

Private Sub Worksheet_Change(ByVal Target As Range)
    Application.ScreenUpdating = False
        Application.DisplayAlerts = False
    If Range("B10").Value <> "" Then
    Dim MyList(9) As String
    MyList(0) = "60 Days EOM"
    MyList(1) = "60 Days DOI"
    MyList(2) = "45 Days EOM"
    MyList(3) = "45 Days DOI"
    MyList(4) = "30 Days EOM"
    MyList(5) = "30 Days DOI"
    MyList(6) = "14 Days DOI"
    MyList(7) = "10 Days EOM"
    MyList(8) = "7 Days DOI"
    MyList(9) = "Immediate Payment"
    With Range("N38").Validation
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
             Operator:=xlBetween, Formula1:=Join(MyList, ",")
    End With
    If Intersect(Target, Target.Worksheet.Range("N38")) Is Nothing Then
    Range("N38").Value = "60 Days EOM"
    End If
    Range("N38").Value = ""
        End If
        End Sub
How to&Answers:

The answer is that even though you unlocked the cells, Data Validation is still off limits. You have to unprotect the sheet before you apply data validation.


I don’t think you can set validation when protection is enabled.

What I do is remove protection at start of procedure and add it back in at the end, remembering error handling which should set the protection back on in the case of failure.

I often create a class which applies protection.

Say a class called cProtect

Option Explicit

Private Sub Class_Initialize()
End Sub

Private Sub Class_Terminate()
End Sub

And in my procedure I start with:

Dim protect as cProtect
Set protect = new cProtect

This causes the protection to be removed via the class initialize method, and then when the instance goes out of scope for any reason (procedure ends, errors), the terminate fires and protection gets applied back on it.