【问题标题】:Both workbook "freezes" when updating the first (xlsm) while the second (xlsx) is open更新第一个(xlsm)而第二个(xlsx)打开时,两个工作簿都“冻结”
【发布时间】:2018-10-31 13:44:48
【问题描述】:

问题

我有一个工作簿 (A),其中包括一些宏以及链接到另一个 Excel 文件(数据源)。如果我只打开这个单独的工作簿,则工作簿可以完美运行并且没有问题。如果我打开另一个随机 xlsx 文件,起初一切看起来都很好。但是,一旦我在工作簿 A 中进行任何更新(例如,在空单元格中按 F2 然后输入),两个工作簿似乎都冻结了。我仍然可以在正常过程中关闭工作簿,并且工作簿 A 中的宏按钮工作正常(并将触发宏),但我无法更改 wb A 中的选项卡,并且第二个工作簿中的选项卡消失了。我可以看到光标,但目标单元格周围的绿色 Excel 边框/框在两个工作簿中都消失了。我也无法更新工作簿中的任何单元格...

我的尝试

我试过了;

  • 删除所有数据源连接

  • 删除所有宏(一个接一个,但是wb A中没有任何宏仍然存在问题...)

  • 检查宏,看看它们是否会导致任何错误(据我所知,它们没有)

  • 另外两个 xlsm 文件(与 wb A 无关)不会导致此类错误

  • 我尝试使用 application.ScreenUpdating = False、.EnableEvents = False、.Calculation = xlCalculationManual,并在最后将它们设置回原始值。

代码

-Range("B4") 是一个没有空格的下拉列表。以下宏位于 Sheet1 中:

Sub Worksheet_Change(ByVal Target As Range)

    On Error GoTo ApplicationON:
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    If Intersect(Target, Range("B4")) Is Nothing Then Exit Sub
       Call conditionalFormatting.conditionalFormatting

ApplicationON:
    On Error Resume Next
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True

End Sub

-以下宏位于一个名为“conditionalFormatting”的模块中:

Sub conditionalFormatting()

    On Error GoTo ApplicationON:
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    Dim DASHBOARD   As Worksheet
    Dim rng1        As Range
    Dim rng2        As Range
    Dim cel         As Range
    Dim col1        As Integer
    Dim col2        As Integer

    Set DASHBOARD = Sheets("DASHBOARD")
    Set rng1 = Range("R15:R45")
    Set rng2 = Range("R15:Z45")
    col1 = 18
    col2 = 26

    With rng2
        .Cells.Font.Bold = False
        .Cells.Font.Italic = False
        .Cells.Font.Size = 11
    End With

    For Each cel In rng1
        Select Case cel.Value

        Case _
        "Case1", _
        "Case2"
            Range(Cells(cel.Row, col1), Cells(cel.Row, col2)).Font.Bold = True

        Case _
        "Case3", _
        "Case4"
           Range(Cells(cel.Row, col1), Cells(cel.Row, col2)).Font.Size = 8

        Case _
        "Case5", _
        "Case6"
           Range(Cells(cel.Row, col1), Cells(cel.Row, col2)).Font.Italic = True

       End Select
    Next  

ApplicationON:
    On Error Resume Next
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True 

End Sub

-以下宏位于名为“ExportToPDF”的模块中,并且在工作表“DASHBOARD”(sheet1)中有一个按钮:

Sub ExportToPDF()

    On Error GoTo ApplicationON:
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    Dim pt As Range

    dateStamp = Format(Now(), "yyyymmdd\_hhmm")
    workbookPath = ActiveWorkbook.Path & "\"
    workbookName = ActiveWorkbook.Name
    file_Name = dateStamp & "_" & Sheets("DASHBOARD").Range("A1") & ".pdf"
    filePath = workbookPath & file_Name

    With Worksheets("DASHBOARD").PageSetup
    .PrintArea = "A6:O42"
    .Orientation = xlLandscape
    End With

    Set pt = 
  Worksheets("DASHBOARD").Range(Worksheets("DASHBOARD").PageSetup.PrintArea)

    pt.ExportAsFixedFormat _
        Type:=xlTypePDF, _
        Filename:=filePath, _
        Quality:=xlQualityStandard, _
        IncludeDocProperties:=True, _
        IgnorePrintAreas:=False, _
        OpenAfterPublish:=True

    MsgBox "PDF file has been created: " _
          & filePath

ApplicationON:
    On Error Resume Next
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True 

End Sub

经过一些额外的测试

它似乎与循环和模块 Workbook_change + 我的下拉列表有关,其中不包含任何空白值。但仍然奇怪的是,它在没有打开任何其他 wb 的情况下完美运行,但只有在打开额外的 wb 时才会出现问题。当两个 wbs 都冻结时,也看不到代码正在运行...

1) 复制并删除数据连接(因此不会干扰),然后保存和关闭工作簿

2) 打开工作簿(没有任何错误处理和应用程序语句)而不在电子表格中进行任何更改/更新,并打开第二个文件 (slsx) - 发生错误

3) 打开工作簿(没有任何错误处理和应用程序语句)并在随机空单元格中写入“=1+1”,然后打开第二个文件 (slsx) - 发生错误

4) 打开工作簿(没有任何错误处理和应用程序语句)并更改下拉列表一次(调用 worksheet_change 宏),然后打开第二个文件 (slsx) - 发生错误

5) 打开工作簿(以发布的原始状态)而不在电子表格中进行任何更改/更新,并打开第二个文件 (slsx) - 发生错误

6) 打开工作簿(以发布的原始状态)并在随机空单元格中写入“=1+1”,然后打开第二个文件 (slsx) - 不会发生错误

7) 打开工作簿(以发布的原始状态)并更改下拉列表一次(调用 worksheet_change 宏),然后打开第二个文件 (slsx) - 发生错误

8) 如果我在下拉列表中插入一个空白值(工作簿处于发布的原始状态)并选择空白值,然后打开第二个文件 (slsx) - 不会发生错误

9) 在下拉列表中选择一个值 - 发生错误

8) 删除 ExportToPDF 和 conditionalFormatting-modules,并包括对 Worksheet_change 模块的建议调整(即从 sheet1 中删除代码并将其插入到模块中)。

  • 8.1 只打开第二个文件而不更改 xlsm,并且在下拉列表中有值 - 发生错误
  • 8.2 在随机空单元格中输入 1+1 - 出现错误
  • 8.3 将下拉列表更改一次(更改为另一个值) - 发生错误
  • 8.4 将下拉列表更改为空白 - 不会发生错误

【问题讨论】:

  • 虽然我没有看到它,但它可能会导致一个无限循环,其中 Range("B2") 被 VBA 更改(可能通过公式间接)它再次调用 Worksheet_Change() 事件,触发相同的更改,触发相同的 Worksheet_Change()。为确保在您的 Worksheet_Change() 事件中不会发生这种情况,请关闭 EnableEvents,例如:Application.EnableEvents = False,然后在最后将其重新打开。
  • 当工作簿冻结时,它看起来是否正在运行 vba(在 vba 编辑器窗口标题中带有“正在运行...”?如果是这样,您可以尝试使用 Ctrl + Pause 中断执行/休息?
  • 在您的 worksheet_change 中,如果相交条件为 false,则您不会恢复 application.screenupdating 计算并启用事件。我实际上只会在 if 语句中将它们设置为 false、manual、false。
  • 另外,你真的需要捕捉'worksheet_change'中的错误吗?您在 conditionalFormatting.conditionalFormatting 中捕捉到它。如果发生错误,您可能希望了解它并且您正在抑制它
  • 我再说一遍,你的set pt 不正确

标签: excel vba


【解决方案1】:

如果您在这些函数中的任何中导致错误,则设置Application.EnableEvents = True。所以......如果这些是由来自事件处理程序内部的调用触发的,那么您将失去重新进入保护。您也无条件地在所有事情的顶部这样做:

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False

这有点像cargo-cult behavior。您应该只在必要的地方执行这项工作,并且靠近必要的地方。无论您认为这样做会获得什么性能提升,都可能只是虚幻的。事实上,从性能的角度来看,反复弄乱Application 状态可能弊大于利。

解决方案是不要依赖 Excel 来防止重新进入您的事件处理程序 - 手动执行:

Private reentryFlag As Boolean    'Module level

Sub Worksheet_Change(ByVal Target As Range)
    If reentryFlag Then Exit Sub
    reentryFlag = True

    On Error GoTo Handler
    If Intersect(Target, Range("B4")) Is Nothing Then Exit Sub

    conditionalFormatting.conditionalFormatting
Handler:
    reentryFlag = False
End Sub

【讨论】:

  • 感谢您的回复。显然我还没有理解应用程序更改的使用,我将重做我的代码。但是让我烦恼的是,即使进行了这些更改(或者实际上删除了所有模块并清除了所有宏),错误仍然会发生......我知道如果没有电子表格就很难解决问题,但是 Excel 文件是否可以“损坏” “没有给出任何错误并表现出我所描述的方式?如果这很重要,我正在使用 win7(是的......)。
  • “一个 Excel 文件可以被“破坏”而不给出任何错误吗?”....我想说不,但我的经验不允许我 :-)
  • @Jeff 如果在没有代码的情况下发生错误,我不确定我是否理解了这个问题。
【解决方案2】:

Excel 文件似乎有一个神秘的错误。我重建了仪表板,它按预期工作。为了安全起见,我跳过了链接到过滤器的“Workbook_change”代码,而是使用了一个简单的按钮来执行代码。感谢大家的意见。

【讨论】:

    猜你喜欢
    • 2020-07-17
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多