【问题标题】:Print Preview issues after running large amount of VBA运行大量 VBA 后出现打印预览问题
【发布时间】:2016-05-18 13:53:36
【问题描述】:

我有一个 Excel 工作簿,其中几乎所有内容都是自动化的。它打开其他工作簿,从中复制数据,关闭它们,然后多次循环数据以生成我们打印和使用的报告。几乎每次运行所有 VBA 然后尝试打印后,打印预览都会卡住,要么找到打印机,要么加载图片中的页面大小。关闭 Excel 并重新打开文档会将打印预览恢复为正常功能。 VBA 所做的唯一与打印相关的事情就是更改打印区域。我对运行 VBA 的任何其他文档都没有这个问题。这只是一个错误还是代码中的某些东西?

这是导致打印预览无法以某种方式加载的代码。如果我跳过本节,那么它会按预期工作......我希望以某种方式让这个代码发挥作用,因为它仍然需要。

    Set wb1 = Workbooks.Open(FileName)
    Set wb2 = ThisWorkbook

    For i = LBound(sArray) To UBound(sArray) 'Loops through array, copies available data from last report
        ShtName = sArray(i, 0)
        On Error Resume Next
            wb1.Sheets(ShtName).Activate
            If Err.Number = 0 Then
                wb1.Sheets(ShtName).Activate
                Columns("A:U").Copy
                wb2.Sheets(ShtName).Activate
                Columns("BE:BV").Select
                Selection.PasteSpecial xlPasteValues
                Application.CutCopyMode = False
                lastrow = Cells(Rows.Count, "BE").End(xlUp).Row
                Range("BA2:BC2").Select
                Selection.AutoFill Destination:=Range(Cells(2, "BA"), Cells(lastrow, "BC")), Type:=xlFillDefault
            End If
        On Error GoTo 0

        DoEvents

    Next i

    wb1.Close False

    Sheet2.Activate

我尝试注释掉“On Error Resume Next”、“On Error Goto 0”、“If...”、“End If”和“DoEvents”。打印预览仍然失败,删除了那些,只是从上一张表中复制和粘贴。

【问题讨论】:

  • 如果您正在寻找解决方案,您需要提供一些附加信息。代码是什么?如果您不运行代码的打印区域部分会发生什么?它发生在每台机器上吗?不同版本的excel呢?
  • 你能把你的代码贴出来让我们看看发生了什么吗?工作簿的打开或丢失可能存在问题。您可以尝试设置 activePrinter 或 paperSize 类似 ActiveWorkbook.Sheets("Name").PageSetup.PaperSize = xlPaperLegal
  • 也许您可以在运行 VBA 之后在工作簿和工作表级别检查名称集合。如果您发现有多个 Print_Area 名称或任何其他奇怪的 Name 条目,那么这可能是您的罪魁祸首。赠品是通过重新启动 Excel 消除了问题,这表明您在此过程中迭代的工作簿中的名称正在污染您在具有打印预览问题的主工作簿中的名称集合。
  • 导致问题的行是Selection.AutoFill Destination:=Range(Cells(2, "BA"), Cells(lastrow, "BC")), Type:=xlFillDefault
  • 好的,似乎任何放入“BC”列的公式都会阻止打印预览工作,并导致我在关闭工作簿时收到消息“Microsoft Excel 已停止工作”。我尝试将该公式移至“BB”,删除代码中对该公式的所有进一步引用,但似乎没有任何效果。我也尝试将工作簿重建为新的。更糟糕的是,如果我单步执行每个子程序,则打印预览工作正常,但如果我只是不间断地运行它,那么它就不会。认为是时候放弃这个问题了……

标签: excel vba


【解决方案1】:

看来删除DoEvents 的所有实例已经解决了这个问题...

打印预览工作正常,退出工作簿时 Excel 不再崩溃。

【讨论】:

  • 唉,你发现了可怕的事情。我并不是说它是 100% 邪恶的,但在大多数情况下,它产生的问题比它解决的问题多。为了解事件点赞
【解决方案2】:

我相信您正在寻找某种类型的刷新操作,可以将预览显示与工作表上的数据重新同步。最后你可能想试试这个:

ActiveSheet.EnableCalculation = False  
ActiveSheet.EnableCalculation = True

如果这不起作用,请查看手动保存是否可以解决问题。您可以尝试在最后拨打Application.Save

【讨论】:

  • 我会在星期一尝试计算设置。我知道这个问题发生在保存之前和使用另存为之后。即使显示/纸张尺寸失败,如果单击打印,文档仍将打印。
  • 不幸的是,将它添加到每张纸上并没有解决它。
【解决方案3】:

“当您选择文件 --> 打印时会自动进行打印预览。另一个选项是使用页面布局视图(状态栏右侧的图标)。要获得旧式打印预览,您需要使用 VBA。以下语句显示活动工作表的打印预览:ActiveSheet.PrintPreview"

引自 John Walkenbach 的 Microsoft Excel 2013 Power Programming with VBA,第 956-957 页。

话虽如此,我通过记录一个相对复杂的宏来测试您的问题,该宏创建一个新工作表,执行 25 个自动操作,并显示打印预览,然后在我单击 MsgBox 上的确定时关闭打印预览。我将程序迭代了 1000 次。我从来没有遇到过 PrintPreview 的问题。

【讨论】:

  • 我会考虑添加打印预览 VBA。现在通常打印的工作表是从列表中生成的,所以我使用复制的模板。它从列表中平均创建 1-12 个工作表,从旧工作簿复制数据,循环通过大约 3,000 行来填充创建的工作表,然后循环通过大约 40,000 行以向工作表添加更多信息。现在功能蔓延已经结束,它可能会从重写中受益,但我认为自己没有时间这样做......
  • 同意@tjb1,时间是一种稀有资源。在您的情况下,我会做的不是尝试整个重写,而是从保存到您的桌面(副网络服务器或其他东西)的原始代码的可测试副本开始。然后,当你有时间的时候尝试简单的改变。例如,VBA 代码 ActiveSheet.PrintPreview 依赖于较旧的、内存占用较少的打印预览,这可能足以修复故障。
【解决方案4】:

这有点像在黑暗中拍摄,但我尝试稍微清理一下您的代码。看看这是否有任何影响。

Sub Test()

Dim wb1 As Workbook, wb2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Dim isWS As Boolean

On Error GoTo sub_err

Set wb1 = Workbooks.Open(Filename)
Set wb2 = ThisWorkbook

For i = LBound(sArray) To UBound(sArray) 'Loops through array, copies available data from last report
    ShtName = sArray(i, 0)
    isWS = True
    Set ws1 = wb1.Sheets(ShtName)

    If isWS Then
        Set ws2 = wb2.Sheets(ShtName)

        ws1.Columns("A:U").Copy
        ws2.Columns("BE:BV").PasteSpecial xlPasteValues
        Application.CutCopyMode = False
        lastrow = ws2.Cells(ws2.Rows.Count, "BE").End(xlUp).Row
        ws2.Range("BA2:BC2").AutoFill Destination:=ws2.Range(ws2.Cells(2, "BA"), ws2.Cells(lastrow, "BC")), Type:=xlFillDefault
    End If
    DoEvents
Next i

wb1.Close False

ws2.Activate

sub_exit:
Exit Sub

sub_err:
If Err.Number = 9 Then
    isWS = False
    Resume Next
Else
    MsgBox "Error: " & Err.Number & vbNewLine & Err.Description
    Resume sub_exit
End If

End Sub

我所做的最重要的事情是分离了您的错误处理,这样只有当您在 wb1 中找不到工作表时它才会恢复,并且所有其他错误(无错误 9 错误)仍会显示您的错误消息。

我还确保您的所有 Range()、Cells() 和 Columns() 都引用了正确的工作表(以防 excel 变得混乱)并且我认为活动工作表是正确的工作表,但您可能想要在代码中验证这一点,以确保它在正确的工作表中执行正确的操作。

现在复制代码仅在isWS = true 时运行,并且除非抛出错误 9 代码,否则它将始终为真。我唯一不知道的是 wb2 是否总是有一个等于 ShtName 的工作表名称,但我猜它会因为它在你的 if err.number = 0 中。

我不确定这是否会为您带来任何改变,但我很想以其他方式听到您的结果。

【讨论】:

  • 我昨天通过从代码中删除所有DoEvents 来修复它。我不知道它们是否处于不良位置或问题出在哪里,但删除它们会使一切恢复正常。我确实对那段代码玩了很多,即使一起删除错误处理仍然有问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多