【问题标题】:runtime 1004 error when running vba code for second time第二次运行 vba 代码时出现运行时 1004 错误
【发布时间】:2020-05-18 22:24:29
【问题描述】:

我编写了一个小模块来保护我工作簿的所有工作表并保护某些工作表中的某些范围。

代码第一次运行顺利,但尝试第二次运行时出现运行时 1004 错误“应用程序定义或对象定义错误”

我想我可能在以下页面上找到了一些解释: http://support.microsoft.com/kb/178510 但我就是想不通..

有人可以帮我吗?

我的代码如下。

根据首先保护的工作表,可能是这一行

WS.Protection.AllowEditRanges.Add Title:=titlef _
        , Range:=WS.Range("L:R"), Password:="pw2"

或以下引发错误的行

WS.Protection.AllowEditRanges.Add Title:=titlec _
        , Range:=WS.Range("N:T"), Password:="pw3"

Sub Protect()
Dim WS As Worksheet
Dim pWord As String
pWord = "pw1"

Dim aer As AllowEditRange
For Each WS In Worksheets
    WS.Unprotect pWord
For Each aer In WS.Protection.AllowEditRanges
    aer.Delete
Next aer
Next WS

Dim counterf As Integer
Dim counterc As Integer
counterf = 1
counterc = 1
Dim titlef As String
Dim titlec As String

For Each WS In ActiveWorkbook.Worksheets
    WS.Protect Password:=pWord, AllowFormattingCells:=True, AllowFormattingColumns:=True, AllowFormattingRows:=True
    WS.EnableSelection = xlNoRestrictions
    If InStr(UCase(WS.Name), "FORM") Then
        titlef = "Volumes form faits par poste" & counterf
        WS.Unprotect pWord
        WS.Protection.AllowEditRanges.Add Title:=titlef _
        , Range:=WS.Range("L:R"), Password:="pw2"
        WS.Protect pWord
        counterf = counterf + 1
    ElseIf InStr(UCase(WS.Name), "COND") Then
        titlec = "Volumes cond faits par poste" & counterc
        WS.Unprotect pWord
        WS.Protection.AllowEditRanges.Add Title:=titlec _
        , Range:=WS.Range("N:T"), Password:="pw3"
        WS.Protect pWord
        counterc = counterc + 1
    End If
Next

End Sub

【问题讨论】:

  • 在哪一行抛出错误?
  • 放置断点,然后让我们知道错误发生在哪里
  • 你说得对,我忘了提到引发错误的行!我会在我原来的帖子中编辑它!
  • 我意识到这已经晚了两年,所以它可能完全无关紧要,但您可能会遇到问题,因为您在工作表不受保护的情况下添加了“AllowEditRange”。根据我的经验,AER 只能在工作表受到保护时添加,并且只能在工作表不受保护时删除

标签: excel vba runtime-error


【解决方案1】:

根据您发布的知识库文章,我认为问题出在Worksheets 和/或ActiveWorkbook。由于您没有专门实例化这些对象,因此 Excel 为您提供了一个副本,基本上是在填补空白。然而,这个副本仍然存在。下面的代码在顶部创建了两个变量,并在底部杀死了这些变量。然后,它不使用Worksheets,而是使用xlBook.Worksheets,而不是ActiveWorkbook.Worksheets,它使用xlApp.ActiveWorkbook.Worksheets

Sub Protect()
    'Create an actual instance of the Excel Application and Workbook
    Dim xlApp As Excel.Application 
    Dim xlBook As Excel.Workbook

    Dim WS As Worksheet
    Dim pWord As String
    pWord = "pw1"

    Dim aer As AllowEditRange
    'Use the object's Worksheets instead of the automatic variable
    For Each WS In xlBook.Worksheets
        WS.Unprotect pWord
        For Each aer In WS.Protection.AllowEditRanges
            aer.Delete
        Next aer
    Next WS

    Dim counterf As Integer
    Dim counterc As Integer
    counterf = 1
    counterc = 1
    Dim titlef As String
    Dim titlec As String

    'Once again, use the application's property
    For Each WS In xlApp.ActiveWorkbook.Worksheets
        WS.Protect Password:=pWord, AllowFormattingCells:=True, AllowFormattingColumns:=True, AllowFormattingRows:=True
        WS.EnableSelection = xlNoRestrictions
        If InStr(UCase(WS.Name), "FORM") Then
            titlef = "Volumes form faits par poste" & counterf
            WS.Unprotect pWord
            WS.Protection.AllowEditRanges.Add Title:=titlef _
            , Range:=WS.Range("L:R"), Password:="pw2"
            WS.Protect pWord
            counterf = counterf + 1
        ElseIf InStr(UCase(WS.Name), "COND") Then
            titlec = "Volumes cond faits par poste" & counterc
            WS.Unprotect pWord
            WS.Protection.AllowEditRanges.Add Title:=titlec _
            , Range:=WS.Range("N:T"), Password:="pw3"
            WS.Protect pWord
            counterc = counterc + 1
        End If
    Next

    'Clean up
    Set xlBook = Nothing
    xlApp.Quit
    Set xlApp = Nothing
End Sub

【讨论】:

  • 感谢克里斯的帮助!它现在抛出另一个错误:运行时错误 91:对象变量或块变量未在以下行为 xlBook.Worksheets 中的每个 WS 设置
  • 抱歉,这些变量也必须是Set,但我也不知道这是否能解决您的问题。
  • 嗨 Cris,我已经通过相应地设置变量来克服运行时错误 91: Set xlApp = GetObject(, "Excel.Application") Set xlBook = xlApp.ActiveWorkbook 但确实如此不能解决我的问题:s
【解决方案2】:

老问题,但我在代码中遇到了类似的问题,在我看来,为了让 AlloEditRange.Delete 函数工作,工作表本身必须处于活动状态。因此,我相信您删除所有 AllowEditRange 对象的初始嵌套 For 循环不会达到您的预期,它仅适用于活动工作表。因此,当您尝试调用 AlloEditRanges.Add 时,这会失败,因为那里已经存在一个。

我猜你需要在 for 循环中调用 Delete 之前激活每个工作表,尽管我不喜欢将其作为“解决方案”,更多的是一种解决方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多