excel - Powerpoint VBA - 在嵌入式 Excel OLE 对象中编辑表的列名

标签 excel vba powerpoint ole

如果你运行下面的代码,你会得到一个非常有趣的结果(只运行 PowerPoint,运行前关闭所有 Excel 实例):

'Optional - Include the "Microsoft Excel 16.0 Object Library"
Option Explicit

Public Sub test()    
    Dim oslide As slide
    Set oslide = ActivePresentation.Slides.add(1, ppLayoutBlank)

    Dim oshape As Shape 
    Set oshape = oslide.Shapes.AddOLEObject(30, 30, 50, 50, "Excel.Sheet")

    oshape.OLEFormat.Object.Sheets(1).ListObjects.add(1) 'xlSrcRange
    oshape.OLEFormat.Object.Sheets(1).Cells(1, 1) = "fewewq"

    oshape.OLEFormat.Object.Close
End Sub

嵌入对象已成功创建,并且表中存在指定数据。但是,当您单击嵌入的对象时,您会收到以下错误:

enter image description here

There isn't enough memory available to read Worksheet.



无法再以任何其他方式访问此对象,并且对象的损坏性质在关闭/打开文档并重新启动时仍然存在。我已验证此问题发生在除我测试过的一个系统(PowerPoint/Excel 2016、Windows 7 X64)之外的所有系统上。

问题

所以我的问题是,其他任何人都可以复制吗?如果可以,为什么会这样?如果将“Cells(1, 1)”行更改为“Cells(2, 1)”,则没有问题,似乎编辑表头会导致某种与编辑行不同的特殊行为或其他细胞。

研究
  • 真的没有写过这个,大部分的东西都没有
    与此特定问题有关。
  • This post声称这是字体过多的问题
    已安装(> 600)。我对此进行了测试,我只安装了 241 个...
  • 有很多没有答案的帖子(thisthis
    this , 和 this ) 不分配去那里。
  • some posts完全不相关的,又不是
    分配去那里。
  • 我在 MS Word 中测试了相同的代码,似乎工作正常,问题似乎
    隔离到 PowerPoint
  • 我试过用代码(损坏的对象)做一个版本,另一个手工做(工作对象),保存它们并比较二进制输出(of only the embedded objects)。这听起来很酷,但它并没有让我有更深入的了解。我无法使用 Excel 单独打开嵌入的对象,因为这些对象似乎存储在 proprietary format 中。 .二进制的中心区域看起来不同,但我不确定如何或为什么。到目前为止,我还没有找到一种将其解码为人类可读信息的方法。
  • After a significant delay and with proper attribution ,我已将其交叉发布到 the Microsoft forums .也许有人在那里有一些见识。我会积极维护这两个职位。如果我 100% 确信这是一个错误,我什至可以考虑 opening an issue here .
  • 您可以通过不关闭 OLEObject 来完全避免此问题,这会导致 2010 年出现问题,尤其是在与关联的图表行为结合使用时,您会显示孤立的 excel 窗口。不是很好的用户体验。我想我可以在后台打开一个隐藏的 excel 窗口,然后在我完成嵌入式工作时终止...
  • 我正在运行版本:Microsoft Office 365 ProPlus:版本 1705(构建 8201.3103 即点即用),但我也看到了 Microsoft Office Standard 2010 版本 14.0.7015.1000(32 位)上的问题。表格的问题似乎在所有其他版本的 Office 上都是相同的,但我想知道这是否会影响 2010 年前的 Office 版本?

  • 更新 1

    我用图表尝试了同样的事情:
    'Include the "Microsoft Excel 16.0 Object Library"
    Option Explicit
    
    Sub test()
        Dim sld As slide
        Dim shp As Shape
        Dim pptWorkbook As Workbook
    
        Set sld = ActivePresentation.Slides.Add(1, ppLayoutBlank)
        Set shp = sld.Shapes.AddChart
        Set pptWorkbook = shp.Chart.ChartData.Workbook
        pptWorkbook.Close SaveChanges:=True
    
        Set pptWorkbook = shp.Chart.ChartData.Workbook
        pptWorkbook.Sheets(1).Cells(1, 2) = "fewewq"
    
        Application.ActivePresentation.Save
        pptWorkbook.Close SaveChanges:=True
    End Sub
    

    如果更改标题行值,则无法再访问嵌入对象(“Cells(1, 2)”),如果更改另一个值(“Cells(2, 1)”),它运行正常。我认为这是同样的问题,运行此代码后我无法打开图表数据。如果我尝试以编程方式访问它,我会收到以下错误:

    Run-time error '-2147467259 (80004005)':

    Method 'Workbook' of object 'ChartData' failed



    虽然只是 2016 年的一个问题,但我在 2010 年尝试了一些稍微不同的东西,但没有发现任何问题。

    更新 2

    我终于弄清楚了为什么我不能在另一个系统上重现这个问题。只有在进行更改后关闭所有 excel 实例时才会出现此问题。这意味着如果您在运行此代码时打开了一个单独的(不相关的)excel 窗口,您将不会看到该问题。

    仅当 PowerPoint 单独运行且未打开任何其他 Excel 电子表格时,才能重现此问题。

    最佳答案

    我可以在 Windows10-64/Excel2013-64 上始终如一地重现您的问题。这是一个错误,我们只能尝试检查到底出了什么问题。

    通过 VBA 更改表的标题时,ListColumn固执地拒绝更新它的名字。无论您是更改标题单元格还是明确更改 ListColumn 的名称,都会发生这种情况!它仅在您编辑工作簿并手动更改单元格时才会更新,但不会从 VBA 更新:

    Public Sub Test()
        Dim oslide As Slide
        Set oslide = ActivePresentation.Slides.Add(1, ppLayoutBlank)
    
        Dim oshape As Shape
        Set oshape = oslide.Shapes.AddOLEObject(30, 30, 250, 250, "Excel.Sheet")
    
        With oshape.OLEFormat.Object
          .Sheets(1).ListObjects.Add 1, .Sheets(1).Range("B2:D5") ' <-- put it anywhere
    
    
          .Sheets(1).ListObjects(1).ListColumns(1).Name = "fewewq" ' <-- whether like this
          '.Sheets(1).Range("B2").Value = "fewewq"                 ' <-- or like this
    
          Debug.Print .Sheets(1).ListObjects(1).ListColumns(1).Range.Cells(1).Value 'fewewq
    
          Debug.Print .Sheets(1).ListObjects(1).ListColumns(1).Name
          ''''''''''''''' Still prints Column1 ! ''''''''''''''''''
    
          .Close
        End With
    End Sub
    

    结果很明显:ListObject表已损坏,因为它在内部保存了在标题中找不到的列名(即 Column1 )(标题为 fewewq )。这会导致观察到的错误,不幸的是,显示的错误消息并不总是准确的。

    当 Excel 实例已在运行时,行为会发生变化,ListColumn姓名 更新。似乎在编辑表头时更新表内部数据的“组件”在 PowerPoint VBA 中编辑时“未加载”。仅当:
  • 您在 PPT 中就地编辑工作簿,手工
  • 您有一个 Excel 实例正在运行

  • 共同的因素是加载了一些编辑器组件,并且该编辑器是在编辑表头时更新内部表数据的编辑器。

    您在答案中找到的好的解决方法是在操作之前打开 xlApp,然后在之后关闭它,这与这些观察结果一致。

    重要的是,Chart 发生的“其他”问题对象(在 更新 1 中)确实与您正确假设的问题相同(“我认为这是相同的问题”)。创建的图表链接到 ListObject工作表中的表格,并且该表格的标题位于第一行。因此,当您更改标题中的单元格时,ListColumn 的名称不更新,导致同样的损坏问题。

    更新:另一个轻量级的解决方法

    在评论提出了与打开先前 Excel 应用程序的解决方法相关的问题后,我试图找到一个“更轻松”的解决方法并找到了一个。

    确信问题是由于未能更新 ListColumn在表中的名称中,我找到了一种“强制它”更新其名称的方法。解决方法包括两个步骤:

    将表格的范围向右扩展一列,然后立即将其缩小回原始范围。

    这个操作只是强制表重新计算它的列名,就是这样!现在表的列名是正确的,问题就消失了。
    Public Sub Workaround()
      Dim oslide As Slide: Set oslide = ActivePresentation.Slides.Add(1, ppLayoutBlank)
      Dim oshape As Shape: Set oshape = oslide.Shapes.AddOLEObject(30, 30, 250, 250, "Excel.Sheet")
    
      With oshape.OLEFormat.Object.Sheets(1)
        .ListObjects.Add 1 ' xlRange
        .Range("A1").Value = "fewewq"
    
       ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
       ' Expand the table one column to the right than shrink it back
       '
        With .ListObjects(1)
          .Resize .Range.Resize(, .Range.Columns.Count + 1)
          .Resize .Range.Resize(, .Range.Columns.Count - 1)
        End With
       '
       ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      End With
    
      With oshape.OLEFormat.Object
        Debug.Print .Sheets(1).ListObjects(1).ListColumns(1).Range.Cells(1).Value ' fewewq
        Debug.Print .Sheets(1).ListObjects(1).ListColumns(1).Name ' Now prints fewewq !
        .Close
      End With
    End Sub
    

    完成此操作后,您可以验证嵌入的工作表是否可编辑,您可以关闭然后打开演示文稿,您不会发现任何问题。我希望这有帮助 :)

    关于excel - Powerpoint VBA - 在嵌入式 Excel OLE 对象中编辑表的列名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44640458/

    相关文章:

    excel - 显示货币的 VBA 文本框

    vba - 将单行复制到另一个工作表 VBA EXCEL

    python-pptx:有什么办法使文本垂直?

    Excel VBA 在 Firefox/Chrome 的新选项卡中打开网站

    vba - 如何将地址的范围引用拆分为一维数组的元素

    vba - 删除 Word VBA 中的最后一部分而不覆盖前一个标题

    c# - 在通过 COM 互操作从 C# 读取单元格值期间忽略 excel vba 错误

    VBA输入框不会关闭

    r - 用于将 R 图添加到演示文稿的官员包函数

    c# - 是否可以用新数据更新 PowerPoint 幻灯片(在 C# 中)?