【问题标题】:CopyPicture method of range class failed - sometimes范围类的 CopyPicture 方法失败 - 有时
【发布时间】:2014-09-04 13:52:04
【问题描述】:

我有一个 VBA 代码,用于将范围复制为图片并将它们粘贴到图表中。它这样做是为了让我可以将其保存到图片中。这段代码有 70% 的成功率,当它不起作用时,它会给出错误“范围类的 CopyPicture 方法失败”。我不明白为什么它有时可以工作,有时却不能接受相同的输入。

谁能帮忙?

Public Sub ExportRange(workbookPath As String, sheetName As String, rangeString As String, savepath As String)

    Set tempWorkBook = Workbooks.Open(workbookPath)

    Dim selectRange As range
    Set selectRange = Worksheets(sheetName).range(rangeString)
    Dim numRows As Long
    numRows = selectRange.Rows.Count
    Dim numCols As Long
    numCols = selectRange.Columns.Count

    ' Transfer selection to a new sheet and autofit the columns
    selectRange.Copy
    Dim tempSheet As Worksheet
    Set tempSheet = Sheets.Add
    tempSheet.range("A1").PasteSpecial xlPasteAll

    ActiveSheet.UsedRange.Columns.AutoFit
    Set selectRange = ActiveSheet.UsedRange
    selectRange.Select
    selectRange.CopyPicture xlScreen, xlPicture

    Dim tempSheet2 As Worksheet
    Set tempSheet2 = Sheets.Add
    Dim oChtobj As Excel.ChartObject
    Set oChtobj = tempSheet2.ChartObjects.Add( _
        selectRange.Left, selectRange.Top, selectRange.Width, selectRange.Height)

    Dim oCht As Excel.Chart
    Set oCht = oChtobj.Chart
    oCht.Paste
    oCht.Export filename:=savepath
    oChtobj.Delete

    Application.DisplayAlerts = False
    tempSheet.Delete
    tempSheet2.Delete
    tempWorkBook.Close
    Application.DisplayAlerts = True

End Sub

【问题讨论】:

  • 同一图像/工作表等是否失败?还是在不同的情况下?就像您运行一个循环执行 100 次一样,它是在某些情况下运行 0 次,而在其他情况下运行 100 次,还是在两者之间运行某个数字然后因错误而停止?
  • 同一图像和工作表失败。我用 6 张图片循环运行这个 Sub,当它失败时,它可以在任何一张图片上失败,不一定总是同一张。
  • 尝试在Application.EnableEvents = FalseApplication.EnableEvents = True中包含你的主要代码逻辑
  • 刚试过,同样的问题。有时它起作用有时不起作用。如果没有,它不会每次都停在 6 张图像循环的同一部分。
  • 我用一张白纸替换了我从中复制范围的工作簿,它也会产生错误,也许更常见。会不会是代码运行的太快了,有些部分没有等待前面的代码完成?

标签: excel vba charts copy-paste


【解决方案1】:

我找到了一种方法可以强制 excel 等到剪贴板中有图片,因为有时它太快了:

Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 

'just after copypicture, add this: (in my case i added it inside pastepicture, or i'd have too much coding )
Dim T#
  Do
      Waiting (2)
Loop Until IsClipboardFormatAvailable(2) Or Timer - T > 0.3

Sub Waiting(ByVal Mili_Seconds&)
Sleep Mili_Seconds
End Sub

【讨论】:

  • 谢谢!就我而言,“applicaiton.displayalert = false”是问题所在!
  • 这并不总是有效!尤其是在 Excel 2016 中。
  • 编辑了答案并对其进行了简化。这个最终的解决方案总是有效的
【解决方案2】:

我与您遇到的问题完全相同,我认为这与我们的 VBA 代码或缺乏编程技能无关。错误太随意了。

此外,如果我在收到错误消息后单击 DEBUG 并按 F8 继续逐步执行代码,则可以跳过该错误。在有问题的行之后,我按 F5 继续以正常执行模式。

当然,以上不是解决方案,但表明我的编码没有任何问题。

好吧,我做到了,它对我有用:

在这句话之前,

rgToPic.CopyPicture Appearance:=xlScreen, Format:=xlBitmap

我加了这个:

rgToPic.Copy  'just for nothing

我再也没有在CopyPicture 方法中遇到错误。


在其他地方找这个问题发现有些用户通过在CopyPicture方法前引入这句话可以跳过错误:

    application.CutCopyMode=false

【讨论】:

  • 这就是我的解决方案。只需调试代码即可。我必须一直按 F8!
  • 'Application.CutCopyMode=false' 对我来说效果很好。谢谢。
  • 谢谢。我自己的解决方案是在 .CopyPicture 命令之前添加 800 ms WAIT 时间(600 ms 不起作用)。然后,我找到了这个页面。在此之前,我已经尝试了此页面上的所有方法都无济于事 - 在.CopyPicture 之前添加.Copy 命令。我仍然需要等待时间,但现在是 50 毫秒。
  • 这也是我的解决方案。花了将近 1 天后,我终于找到了这个。谢谢。
【解决方案3】:

唯一对我有用的是在 CopyPicture 方法之前添加延迟。当我输入这个时,我们正在将它调整得更短,但我知道 50 毫秒的延迟工作正常:

声明 PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

'设置你想要捕捉的范围

将 rgExp 调暗为范围:设置 rgExp = Range("B2:D6")

Sleep (50) ' 以毫秒为单位暂停以防止 CopyPicture 上出现运行时错误,您的系统可能能够使用更短的睡眠时间,或者可能需要更长的时间...

' 将范围作为图片复制到剪贴板

rgExp.CopyPicture 外观:=xlScreen,格式:=xlBitmap

【讨论】:

    【解决方案4】:

    CopyPicture 方法将结果发送到剪贴板。但是出于安全原因,Win10 禁止在屏幕锁定时访问剪贴板。因此,如果您在锁定屏幕时运行宏,CopyPicture 方法将失败,错误代码为 1004。
    Worksheet.Pictures.Paste 也会发生同样的错误。

    另一方面,简单的CopyPasteSpecial 不会弹出错误。当剪贴板不可访问时,内容不会被复制到剪贴板,但 VBA 不会抱怨。

    很遗憾,PasteSpecial 没有粘贴为图片的选项。
    唯一简单的解决方法是在运行宏时让您的计算机保持解锁状态。

    【讨论】:

    • 您的信息似乎与原发帖人中的以下内容无关:“此代码的成功率约为 70%”。
    【解决方案5】:

    对我来说,我遇到了类似的问题,我可以通过在 selectRange.CopyPicture 中的 xlScreenxlPrinter 之间进行更改来解决它

    希望对你有帮助

    【讨论】:

      【解决方案6】:

      虽然这是一篇旧帖子,但也许这会对某人有所帮助。 我很长一段时间都在为类似的问题而苦苦挣扎。 CopyPicture 失败 (在某些计算机上比其他计算机更频繁,但很难在我的笔记本电脑上复制)当我复制范围时 包含嵌入的 PNG 图片。它只在Application.Visible=0 模式下失败,Application.Visible=1 工作正常(对于我的应用程序,必须在不可见模式下运行 Excel)。最后,我发现在具有 1 个 CPU 的 VM 上运行时,我可以 100% 地重现该问题。以下解决方案很奇怪,但似乎完全解决了我的问题。

      嵌入的 PNG 是 Excel API 术语中的 Shape。在调用CopyPicture 之前,我只需要循环浏览这些形状(甚至不做任何事情):

      # 'rng' is a range that I want CopyPicture on 
      for shape in rng.Shapes: pass
      rng.CopyPicture(xlScreen, xlBitmap)
      

      我的发现有点类似于this solution, 其中CopyPicture 在图表范围内失败。在他们的情况下, 激活工作簿和范围本身有所帮助。

      假设,在缓慢或负载过重的计算机上,Excel 对页面上的复杂对象进行“延迟处理”似乎是合理的,即在以某种方式访问​​对象之前不渲染它们。一种强制渲染的方法似乎是在Visible=1 模式下运行。另一种方法是循环遍历对象。如果是这种情况,那么它是 Excel 的 CopyPicture 实现的一个错误,它不会强制复杂对象在尝试复制之前呈现。当 copy 方法发现目标范围的渲染尚未准备好时,它只是抛出一个错误,而不是强制范围渲染。好吧,至少这是我的理论。

      【讨论】:

        【解决方案7】:

        我的解决方法是将它抛出一个错误捕获 while 循环并继续重试它,直到它能够完全复制范围而没有错误消息。现在就像一个魅力。

        【讨论】:

          【解决方案8】:

          对我有用的是,在我用Application.CutCopyMode = False复制图片之前清除剪贴板

          我认为最好的做法是粘贴您需要的内容,然后直接清除剪贴板。

          【讨论】:

            【解决方案9】:

            我找到了一种简单的方法来解决这个我苦苦挣扎了几个月的问题。我知道这是一个“错误代码”,但它对我很有帮助并且非常有效。在我的情况下,详细信息被复制,但调试错误窗口正在填充。因此我跳过了调试窗口,我的生活变得更轻松了。

            修复只是在您的 VBA 中的“复制”代码前面添加以下代码。这肯定会修复这个错误。

            On Error Resume Next
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-10-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多