【问题标题】:How to protect a worksheet and unprotect a list object in vba如何保护工作表和取消保护 vba 中的列表对象
【发布时间】:2020-08-16 22:59:35
【问题描述】:

我正在运行 excel 2010,并开发了一个 xlsm 以向少数用户推出

我已使用以下运行良好的例程保护工作簿

我的问题是我在工作簿中使用 listobjects 作为映射表,需要用户干预。可以操作现有的 listobject 行,但不能添加新行 - 关于如何解决这个问题的任何想法?

谢谢

Public Sub ProtectAll(ByVal wbWorkbook As Workbook)

  Dim wks As Worksheet

  For Each wks In wbWorkbook.Worksheets
                wks.Protect sPasswordToLock, True, True, False, True,     True,True, True, False, False, False, False, False, True, True, True
                wks.EnableSelection = xlNoRestrictions

  Next wks

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    虽然答案比您预期的要复杂,但可以做到这一点。 Jon van der Heyden 曾经在他的网站 (exceldesignsolutions.com) 上有一篇关于此的好文章,但我认为他已将其删除。我采用了他的一些代码,允许您将行添加到受保护工作表上的列表对象。这样做的好处是它强制用户只在列表对象正下方的行中输入数据,从而确保列表对象“增长”以包含新数据。

    简而言之,使用的方法是创建一个自定义类,该类将包含一个 listobject 和一个事件处理程序,该处理程序侦听对包含它的工作表的更改。如果更改位于列表对象正下方的行中,则撤消更改,取消保护工作表,重做更改并重新保护工作表。另外解锁列表对象正下方的行。

    这里是做什么:

    在包含列表对象的工作簿中,创建一个自定义类模块并将其命名为 cProtectedLO。粘贴以下代码:

    Option Explicit
    
    Private m_loTable As ListObject
    Private m_strPassWord As String
    Private WithEvents m_appExcel As Excel.Application
    
    Public Property Set Table(ByVal loTable As ListObject)
        Set m_loTable = loTable
    End Property
    
    Public Property Let Password(ByVal strPassword As String)
        m_strPassWord = strPassword
    End Property
    
    Private Sub Class_Initialize()
        Set m_appExcel = Excel.Application
    End Sub
    
    Private Sub m_appExcel_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    
        Dim rngTable As Excel.Range
        Dim varValue As Variant
    
        Set rngTable = m_loTable.Range
    
        If Sh Is rngTable.Parent Then
            If Not Intersect(Target.Offset(-1), rngTable) Is Nothing Then
                If Intersect(Target, rngTable) Is Nothing Then
                    varValue = Target.Value
                    Sh.Unprotect Password:=IIf(Len(m_strPassWord), m_strPassWord, Null)
                    With Application
                        .EnableEvents = False
                        .Undo
                        Target.Value = varValue
                        Sh.Cells.Locked = True
                        m_loTable.DataBodyRange.Locked = False
                        m_loTable.Range(m_loTable.Range.Rows.Count, 1).Offset(1, 0).Resize(1, m_loTable.ListColumns.Count).Locked = False
                        .EnableEvents = True
                    End With
                    Sh.Protect Password:=IIf(Len(m_strPassWord), m_strPassWord, Null)
                    Target.Offset(1).Select
                End If
            End If
        End If
    End Sub
    
    Private Sub Class_Terminate()
        Set m_loTable = Nothing
        Set m_appExcel = Nothing
    End Sub
    

    添加一个普通代码模块并将此代码粘贴到其中:

    Option Explicit
    
    Public m_colProtectedLO As Collection
    
    Public Sub EnableProtectedTables(Optional ByVal pw As Variant)
    
        Dim clsProtectedLO As cProtectedLO
        Dim wks As Worksheet, lo As ListObject
    
        Set m_colProtectedLO = New Collection
    
        For Each wks In ThisWorkbook.Worksheets
    
            For Each lo In wks.ListObjects
                Set clsProtectedLO = New cProtectedLO
    
                With clsProtectedLO
                    Set .Table = lo
    
                    If Not IsMissing(pw) Then
                        .Password = pw
                    End If
    
                End With
    
                wks.Unprotect Password:=pw
                lo.DataBodyRange.Locked = False
                lo.Range(lo.Range.Rows.Count, 1).Offset(1, 0).Resize(1, lo.ListColumns.Count).Locked = False
                wks.Protect Password:=pw
                m_colProtectedLO.Add Item:=clsProtectedLO
            Next lo
    
        Next wks
    
     End Sub
    

    在 ThisWorkbook 模块中,粘贴以下内容:

    Option Explicit
    
    Private Sub Workbook_Open()
        EnableProtectedTables
    End Sub
    
    Private Sub Workbook_BeforeClose(Cancel As Boolean)
        Set m_colProtectedLO = Nothing
    End Sub
    

    请注意,工作表受密码保护,您必须将其作为“pw”参数的值包含在对 EnableProtectedTables 的调用中,如下所示:

    EnableProtectedTables pw:="YourPasswordHere"
    

    保存工作簿,将其关闭并再次打开,您应该已准备就绪。

    【讨论】:

    • 感谢解决方案有效,我没想到会有这么多代码。 2个问题:-vba中的protect方法没有列表对象参数的任何原因。还有一个原因是为什么上面代码中的工作表更改事件在类中,而不是在 excel 中使用 worksheet_change?谢谢
    • 我不知道你第一个问题的答案。至于第二个,如果您使用 worksheet_change 事件,则必须将代码添加到包含列表对象的工作簿中的每个工作表。通过将它放在类事件中并将每个列表对象的类实例存储在全局集合中,您需要的编码要少得多,即使您不知道有多少(以及在哪里)列表对象,它也可以工作。
    • 您还可以添加新的列表对象(如果需要,在新工作表中)它仍然可以工作,但您必须再次关闭并打开工作簿。
    • 为了处理表为空的情况,可以在EnableProtectedTables过程中添加If Not lo.DataBodyRange Is Nothing Thenlo.DataBodyRange.Locked = FalseEnd If
    猜你喜欢
    • 2020-01-20
    • 1970-01-01
    • 2023-03-27
    • 2019-03-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多