首页 > 解决方案 > 从在新窗口中打开的工作簿中删除保护时出现调试错误

问题描述

我有一本从网站创建的工作簿中导入数据的工作簿。当网站创建工作簿时,它们会自动在新窗口中打开,并且工作簿的名称总是会更改。我用

ActiveWindow.ActivateNext

其中一个工作簿必须在受保护的视图中打开,所以我使用

Application.ActiveProtectedViewWindow.Edit

允许在导入前对其进行编辑

我可以逐步执行宏并且它可以工作,但是当我运行它时,我总是得到“运行时错误'91':对象变量或未设置块变量。我点击调试并播放,程序完成没有问题。

完整的代码如下所示;

Sub Data()
Dim Here As String
Dim What As String
Dim Data As String
Dim DropIt As String
Dim StartBook As String

Application.DisplayAlerts = False

StartBook = ActiveWorkbook.Name

DropIt = "Data1"
ActiveWindow.ActivateNext
Application.ActiveProtectedViewWindow.Edit 'THIS IS WHERE THE DEBUG HAPPENS

Range("A1").Select
Here = ActiveSheet.Name
BookName = ActiveWorkbook.Name

    Rows("1:3").Select
    Selection.Delete Shift:=xlUp
    Rows("2:2").Select
    Selection.Delete Shift:=xlUp
    Columns("E:E").Select
    Selection.Delete Shift:=xlToLeft
    Columns("C:C").Select
    Selection.Delete Shift:=xlToLeft
    Columns("A:A").Select
    Selection.Delete Shift:=xlToLeft
Range("A1").Select
What = Range("A1", ActiveCell.SpecialCells(xlLastCell)).Address
Data = Range("A2", ActiveCell.SpecialCells(xlLastCell)).Address

    ActiveWorkbook.Worksheets(Here).Sort.SortFields.Clear
    ActiveWorkbook.Worksheets(Here).Sort.SortFields.Add2 Key:=Range("A1") _
        , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets(Here).Sort
        .SetRange Range(What)
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With

    Range(Data).Copy

    Workbooks(StartBook).Activate
    Worksheets(DropIt).Select
    Range("a10").Select
    ActiveCell.End(xlDown).Select

    Range(Selection, ActiveCell.End(xlToRight)).Select

    ActiveCell.Offset(1, 0).Select

    ActiveCell.PasteSpecial xlPasteValues
        Application.CutCopyMode = False        

    Application.DisplayAlerts = False

        Workbooks(BookName).Close savechanges:=False
Application.DisplayAlerts = True
End Sub

我只想让代码在没有调试的情况下运行

''''

标签: excelvba

解决方案


我无法测试,但我会提出一个未经测试的建议。尝试改变:

ActiveWindow.ActivateNext
Application.ActiveProtectedViewWindow.Edit

至:

Dim someWorkbook as Workbook
Set someWorkbook = Application.ProtectedViewWindows(1).Edit

我认为您的代码还有其他潜在问题。


当您调试/手动单步执行代码时“消失”的错误通常表明您的代码期望某些东西在运行时处于活动状态,但它(无论出于何种原因)不活动(因此出现错误) - 现在你'重新逐行遍历它,对象处于活动状态,您不再收到错误。情况并非总是如此,但我认为这是一种可能性。

我不熟悉ActiveProtectedViewWindow,但我建议您ProtectedViewWindow以更健壮的方式访问/引用 (这不依赖于ProtectedViewWindow处于活动状态)。

如果您确定只有 1 个受保护的窗口,您可以尝试类似Application.ProtectedViewWindows(1).Edit. 如果您有多个ProtectedViewWindows并且您只想要一个特定的,也许您可​​以遍历所有ProtectedViewWindows并检查它们的SourcePath属性是否与您想要在其中启用编辑的受保护工作簿的路径匹配。

根据我在网上阅读的内容,ProtectedViewWindow.Edit返回一个工作簿,因此您可以在Workbook那里设置对它的引用(如我的答案开头所示)。

我没有测试过下面的,但我认为你的代码可以重写类似的东西。我建议在运行之前保存工作簿/文件的副本(或使用F8键单步执行):

Option Explicit

Sub Data()
    Dim startWorkbook As Workbook ' Do you have better name for this variable?
    Set startWorkbook = ActiveWorkbook ' Can you refer to this workbook by name, instead of assuming it will be active? Using ThisWorkbook is an option too, as long as you're storing the code in startWorkbook

    Dim unprotectedWorkbook As Workbook ' This needs a better variable name.
    Set unprotectedWorkbook = Application.ProtectedViewWindows(1).Edit ' I don't know if this will work for you (in your case), but I've taken it from Microsoft's documentation

    Dim someWorksheet As Worksheet
    someWorksheet = unprotectedWorkbook.Worksheets(1) ' If you know the worksheet's name, refer to it by name, please.

    With someWorksheet
        .Rows("1:3").Delete Shift:=xlUp
        .Rows("2:2").Delete Shift:=xlUp
        .Columns("E:E").Delete Shift:=xlToLeft
        .Columns("C:C").Delete Shift:=xlToLeft
        .Columns("A:A").Delete Shift:=xlToLeft

        ' xlCellTypeLastCell isn't always the best way to get the last cell.
        Dim someRangeIncludingHeaders As Range ' This needs a better name.
        Set someRangeIncludingHeaders = .Range("A1", .Cells.SpecialCells(xlCellTypeLastCell))

        Dim someRange As Range ' This needs a better name.
        Set someRange = .Range("A2", .Cells.SpecialCells(xlCellTypeLastCell))

        With .Sort
            .SortFields.Clear
            .Sort.SortFields.Add2 Key:=.Range("A1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
            .SetRange someRangeIncludingHeaders
            .Header = xlYes
            .MatchCase = False
            .Orientation = xlTopToBottom
            .SortMethod = xlPinYin
            .Apply
        End With
    End With

    someRange.Copy
    startWorkbook.Worksheets("Data1").Range("A10").PasteSpecial xlPasteValues
    Application.CutCopyMode = False

    unprotectedWorkbook.Close SaveChanges:=False
End Sub

我所做的主要更改是:

  • 不使用 ActiveSheet,因此代码应该运行相同(无论哪个工作表恰好处于活动状态)。
  • 对象引用适用set于工作簿、工作表、范围。
  • 我们不使用Selector Selection,而是通过地址显式引用范围。
  • With语句块主要是为了方便。.With块中以 a 开头的每个对象都是With关键字(在本例中为someWorksheet)之后的对象的成员。

推荐阅读