【问题标题】:How to fix Excel 2016 Object Required Error that worked in Excel 2010如何修复在 Excel 2010 中工作的 Excel 2016 对象所需错误
【发布时间】:2019-02-15 23:19:23
【问题描述】:

我最近从 2010 年迁移到 Excel 2016,我从同事那里继承的一张工作表已停止工作。我正在学习 VBA,但如果我在运行以下代码时遇到运行时错误,我将不胜感激。

我相信它是由声明变量的方式造成的(或者在这种情况下似乎不是)。该函数采用覆盖图表的范围。然后它将图表导出为 .png 图像。我不明白的另一件事是为什么它在 Excel 2010 中运行良好但在 2016 中运行良好?

错误 424 - 需要对象:

The line the error occurs:

 With .Pictures(1)

代码:

Sub createPNG(sheetName As String, rangeName As String, fileName As String)

  Dim vFilePath As Variant
  Dim rSelection As Range
  Dim sDefaultName As String

  Sheets(sheetName).Range(rangeName).Select

  Set rSelection = Selection

  vFilePath = "Z:\marginsOutput\Charts\" & fileName & ".png"
  '-- copy selected range as picture (not as bitmap)
  rSelection.CopyPicture Appearance:=xlScreen, Format:=xlPicture

  '--Create an empty chart, slightly larger than exact size of range copied
  With Sheets(sheetName).ChartObjects.Add( _
      Left:=rSelection.Left, Top:=rSelection.Top, _
      Width:=rSelection.Width + 2, Height:=rSelection.Height + 2)

  With .Chart
  ' clean up chart
  .ChartArea.Format.Line.Visible = msoFalse

  ' paste and position picture
  .Paste
  With .Pictures(1)
    .Left = .Left + 2
    .Top = .Top + 2
  End With

  ' export
  .Export CStr(vFilePath)
End With

' remove no-longer-needed chart
.Delete
  End With

End Sub

【问题讨论】:

  • 哪行代码中断了?您可以通过点击运行时错误弹出窗口中的调试按钮来判断。
  • 嗨,David,这是 With .Pictures(1) 行
  • 查看With 语句的嵌套。由于三重嵌套,您的对象无效。您应该将 Sheets(SheetName).Pictures(1) 作为您的对象。
  • 我什至不确定您是否需要最后一个 With 语句中的代码?尝试注释掉给你错误的行 + 以下 3 行,看看你是否仍然得到想要的结果。
  • 谢谢大家,实际上注释掉代码块会导致函数导出空白图像。 @Darrell,修改该行会给我一个“无法获取 Worksheet 类的图片属性”错误

标签: excel vba


【解决方案1】:

如果您在将图片粘贴到其Chart 之前只选择ChartObject,它就可以工作。
这是很少的情况之一,.Select 有帮助 - 否则请参阅 How to avoid using Select in Excel VBA

With Sheets(sheetName).ChartObjects.Add( _
    Left:=rSelection.Left, Top:=rSelection.Top, _
    Width:=rSelection.Width + 2, Height:=rSelection.Height + 2)
    .Select
    With .Chart
        ' ...
    End With
End With

...而且在调试过程中,真的很烦人:
如果您通过 (F8) 逐步运行代码,它可以在没有 ChartObject.Select 的情况下运行,但如果您正常运行它或通过 (F5) 运行它,则会出现错误,
图片(1) = 错误 424(没有这样的对象)
Shapes(1) = 错误 -2147024809(数字 1 不存在)

【讨论】:

  • 真的没必要选择图表。您只需要给 VBA 一个完成粘贴的机会,就像 Max 的回答或我的回答一样。
  • @Jon,感谢您的评论并指出进一步的解决方案。所以我把我的回答从“必要”弱化为“有帮助”:)
  • F8 与 F5 的行为有助于表明这是某种计时错误。 F8 使 VBA 有机会在尝试执行下一个语句之前启动和完成每个语句。这就是循环和DoEvents 组合的帮助。我认为选择对象也可能会迫使 VBA 更加专注于对象。 (我发现将 VBA 拟人化很有帮助,并将其视为一个脾气暴躁的小孩。)
【解决方案2】:

我有时在 VBA 中发现 .paste 似乎在第一次时不起作用,尤其是如果该项目已经在剪贴板中!在尝试选择图片之前,我添加了几行以检查是否存在图片!如果没有找到,它将再次尝试 .paste。您应该为此添加一些控件以阻止它在粘贴错误时循环!

尝试下面的编辑;

Sub createPNG(sheetName As String, rangeName As String, fileName As String)

  Dim vFilePath As Variant
  Dim rSelection As Range
  Dim sDefaultName As String

  Sheets(sheetName).Range(rangeName).Select

  Set rSelection = Selection

  vFilePath = "Z:\marginsOutput\Charts\" & fileName & ".png"

  '-- copy selected range as picture (not as bitmap)
  rSelection.CopyPicture Appearance:=xlScreen, Format:=xlPicture

  '--Create an empty chart, slightly larger than exact size of range copied
  With Sheets(sheetName).chartobjects.Add( _
      Left:=rSelection.Left, Top:=rSelection.Top, _
      Width:=rSelection.Width + 2, Height:=rSelection.Height + 2)

  With .Chart
  ' clean up chart
  .ChartArea.Format.Line.Visible = msoFalse

  ' paste and position picture
  .Paste
  If .Pictures.Count = 0 Then
        .Paste
  End If
  With .Pictures(1)
    .Left = .Left + 2
    .Top = .Top + 2
  End With

  ' export
  .Export CStr(vFilePath)
End With

' remove no-longer-needed chart
.Delete
  End With

End Sub

【讨论】:

  • 嗨,Max,感谢您的回复。当我运行它时,它最终仍然会到达 .Pictures(1) 行并引发错误。但是,每次都满足 If .Pictures.Count = 0 条件,所以看起来确实是问题所在
【解决方案3】:

与 Max 一样,我发现 Excel 中许多对各种对象(形状、图表、图片、工作表、工作簿等)进行操作的命令比以前花费的时间更长,而且 VBA 不会等待它们完成在尝试执行下一个命令之前。因此,当它尝试对尚未真正粘贴的图片执行某些操作时会失败。

此问题的一个迹象是代码在使用 F8 键单步执行 VB 编辑器时运行没有错误,但在使用 F5 键运行时全速运行失败。

类似于 Max,我想出了一个小循环来观察这个:

With .chart
  Do Until .Pictures.Count = 1
    DoEvents
    .Paste
  Loop
End With

另一种方法是将实际的粘贴放在一个单独的函数中,您可以从该部分代码调用该函数,并传入正在粘贴的图片和接收它的图表。调用堆栈中不同项目之间的障碍似乎鼓励 VBA 在继续下一步之前完成它正在做的事情。

我应该注意,我必须对我的商业 Excel VBA 加载项的许多部分执行此操作,该加载项广泛适用于图表,并且我上面粘贴的代码是直接从该加载项中提取的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    • 2013-10-03
    • 2013-01-14
    • 1970-01-01
    相关资源
    最近更新 更多