以编程方式更新嵌入的Excel文件

5
我正在尝试通过编程来修改Word文档中嵌入的Excel表格。为此,我已经修改了docx文件和嵌入的Excel文件。
主文档的重要部分如下:
<w:object w:dxaOrig="8406" w:dyaOrig="2056">
  <v:shape id="_x0000_i1028" type="#_x0000_t75" 
    style="width:390.75pt;height:95.25pt" o:ole=""><v:imagedata r:id="rId14" 
    o:title=""/>
  </v:shape>
  <o:OLEObject Type="Embed" ProgID="Excel.Sheet.12" ShapeID="_x0000_i1028" 
    DrawAspect="Content" ObjectID="_1349794876" r:id="rId15" 
    UpdateMode="Always"/>
</w:object>

该文档使用OLEObject链接到嵌入的Excel文档。为了显示目的,使用了一个.wmf文件(使用v:shape元素)。我修改了Excel文档,这使得该预览过时了。
这导致文档中出现一些奇怪的行为:
- 嵌入式(Excel)表格的预览显示错误的数据 - 双击嵌入式表格会在嵌入的Excel中打开表格并显示正确的数据 - 关闭嵌入式编辑器会触发生成新的预览,显示正确的数据
当然,我希望在打开文档时表格显示正确的内容。如何触发Word丢弃图像并重新绘制预览?
对我来说,理想的解决方案是通过修改docx的内容触发预览的再生,但使用小脚本的解决方案也会有所帮助。

你是通过OpenXML、.NET、VSTO或VBA更新嵌入式电子表格吗? - Todd Main
我正在使用PHP(SimpleXML和一点DOMDocument)进行转换。电子表格的转换完美无缺,但“预览”图像是个问题。 - Scharrels
3个回答

4

这个问题没有完美的解决方案,但是大部分情况下可以强制打开/关闭OLEFormat.Object来解决。无论您是通过对象模型还是从Word外部重新激活嵌入的Excel工作表(即操作Open XML格式)进行操作,都没关系。所需步骤是从Word中打开嵌入的Excel电子表格,然后关闭该对象,以便将图像更改为嵌入式电子表格中的当前值,并创建新的图像。

如果您正在多个Word文档上执行此操作,或者只是一个文档上运行代码,那么就稍微有些不同。在前一种情况下,可以使用全局模板(例如normal.dot或自定义的一个,并放在STARTUP文件夹中),而在后一种情况下,则只需运行一个文档的代码。两种方法运行起来方式不同,但本质上都要钩取Document_Open事件,然后检查当前文档是否有OLE嵌入对象,并在有时打开和关闭它们。

不涉及钩子,就像我说的,这段代码并不漂亮。基本上因为它使用SendKeys。大多数时间,这样做会奏效。但有时候不行。这是SendKeys和其他程序在未经同意的情况下获得焦点的本质(例如即时通讯程序)。

如果Word具有焦点(这意味着您无法打开VBE并按下F5),则此代码将完成工作:

Sub UpdateEmbeddedXLSX()
Dim workbook As InlineShape
    For Each workbook In ActiveDocument.InlineShapes
        With workbook
            If .Type = wdInlineShapeEmbeddedOLEObject Then
                ''# Excel.Sheet.12 for Excel 2007
                If .OLEFormat.ClassType = "Excel.Sheet.12" Then
                    ''# Open Object as spreadsheet
                    .OLEFormat.DoVerb wdOLEVerbPrimary
                    ''# If you want, you can also do any updates here like
                    .OLEFormat.Object.ActiveSheet.Cells(2, 2).Value = ".1"
                    ''# Nasty - but it works - SendKeys
                    SendKeys "{ESC}", True
                End If
            End If
        End With
    Next
End Sub

至少,您可以将此代码放入normal.dot中,并将其分配给QAT以作为宏运行。

请注意,该代码无法绕过Excel打开、值更改和关闭的过程 - 这是使用嵌入式对象的必要步骤。使用链接而不是嵌入式对象会更加顺畅,但我知道这并不总是可行的。


我本来希望能找到一个不需要使用宏的解决方案,但最终还是采用了这个。感谢您的答案! - Scharrels

1

仅仅是为了补充一下一个旧帖子,以防有人像我一样偶然发现:

上述代码运行很好,但是我修改了它,使用书签而不是使用SendKeys。 SendKeys语句会让我的键盘NumLock出现问题,这只是该命令的怪癖之一。

我所做的是在我的Word文档模板中创建书签。 然后在我的代码中,我创建了到该书签的指针:

Dim bMark as bookmark
Set bMark as ActiveDocument.Bookmarks("NameOfBookmark")

然后我用以下代码替换了SendKeys语句:

bMark.Range.Select
Selection.EndKey

这基本上将焦点从嵌入的工作表中移出,并放在页面的书签上。然后,.EndKey语句只是简单地删除了选择。你甚至不需要它。
希望这有所帮助!

0

如果有人在这里寻找如何通过VBA宏更新嵌入在Visio文档中的Excel对象而无需双击,您只需要调用内嵌工作簿上的Save

Dim wb As Excel.Workbook
Set wb = ThisDocument.Pages("MyPageName").Shapes("NameOfWorksheetShape").Object
'Calling me updates the visible worksheets.
wb.Save

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接