当更新第一个(xlsm)而第二个(xlsx)打开时,两个工作簿都“冻结”

时间:2018-10-31 13:44:48

标签: excel vba excel-vba

问题

我有一本工作簿(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”的模块中,并在工作表“仪表板”(第1页)中具有一个按钮:

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时才成为问题。两个wb都冻结时,都看不到代码正在运行...

1)复制并删除数据连接(以免干扰),并保存并关闭工作簿

2)打开工作簿(不进行任何错误处理和应用程序声明),而无需在电子表格中进行任何更改/更新,然后打开第二个文件(slsx)-发生错误

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

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

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

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

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

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

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

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

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

2 个答案:

答案 0 :(得分:1)

如果您在这些功能的 任何 中引起错误,请设置Application.EnableEvents = True。因此...如果这些事件是由事件处理程序内部的调用触发的,则您将失去重入保护。您还可以无条件地在所有操作的顶部执行此操作:

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

cargo-cult behavior的痕迹。您应该仅在必要时执行此工作,并在必要时靠近 place 。无论您认为通过此操作获得的性能提升,都可能只是虚幻的。实际上,从性能的角度来看,反复弄乱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

答案 1 :(得分:0)

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