通过VBA修改Word文档中嵌入的Excel工作簿

发布于 2024-07-12 23:40:22 字数 788 浏览 5 评论 0原文

我有一个包含两个嵌入 Excel 文件的 Word 文档(使用“插入”->“对象”->“从文件创建”添加),我希望使用 Word VBA 对其进行修改。 我已经能够打开嵌入文件进行编辑(请参阅下面的代码),但无法获取 Excel 工作簿的句柄,我可以使用它进行修改并保存嵌入文件。 有人有解决方案吗? 提前致谢。

Sub TestMacro()

    Dim lNumShapes As Long
    Dim lShapeCnt As Long
    Dim xlApp As Object
    Dim wrdActDoc As Document

    Set wrdActDoc = ActiveDocument

    For lShapeCnt = 1 To 1 'wrdActDoc.InlineShapes.Count
        If wrdActDoc.InlineShapes(lShapeCnt).Type = wdInlineShapeEmbeddedOLEObject Then
            If wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.ProgID = "Excel.Sheet.8" Then
                'This opens the embedded Excel workbook using Excel
                wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.Edit
            End If
        End If
    Next lShapeCnt

End Sub

I have a Word document with two embedded Excel files (added using Insert -> Object -> Create From File) which I wish to modify using Word VBA. I have got to the point where I am able to open the embedded files for editing (see code below), but am unable to get a handle on the Excel workbook using which I can make the modifications and save the embedded file. Does anyone have a solution for this? Thanks in advance.

Sub TestMacro()

    Dim lNumShapes As Long
    Dim lShapeCnt As Long
    Dim xlApp As Object
    Dim wrdActDoc As Document

    Set wrdActDoc = ActiveDocument

    For lShapeCnt = 1 To 1 'wrdActDoc.InlineShapes.Count
        If wrdActDoc.InlineShapes(lShapeCnt).Type = wdInlineShapeEmbeddedOLEObject Then
            If wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.ProgID = "Excel.Sheet.8" Then
                'This opens the embedded Excel workbook using Excel
                wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.Edit
            End If
        End If
    Next lShapeCnt

End Sub

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

层林尽染 2024-07-19 23:40:39

当您对 xlApp 进行分级时,您不会获取特定的工作簿。 因此,如果您引用一个数字,则您可能不在嵌入文件中。 更好地使用Activeworkbook。
对我来说,workbook(1) 是我的个人隐藏 xl 文件,其中包含我的个人宏。

我不进行测试,因为我的 .docx 中只有一种形状,但我认为数字“Excel.Sheet.8”对我来说相当 0.12。

    Sub TestMacro()
    
        Dim lNumShapes As Long
        Dim lShapeCnt As Long
        Dim xlApp As Object
        Dim wrdActDoc As Document
        
        Set wrdActDoc = ActiveDocument
        
        For lShapeCnt = 1 To 1 'wrdActDoc.InlineShapes.Count
            If wrdActDoc.InlineShapes(lShapeCnt).Type = wdInlineShapeEmbeddedOLEObject Then
                If wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.ProgID = "Excel.Sheet.8" Then
                    wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.Edit
                    Set xlApp = GetObject(, "Excel.Application")
                    xlApp.ActiveWorkbook.Worksheets(1).Range("A1") = "This is A modified"
                    'xlApp.ActiveWorkbook.Save
                    'xlApp.ActiveWorkbook.Close
                    xlApp.Quit
                End If
            End If
        Next lShapeCnt
    
    End Sub

当我退出 xlApp 时,焦点就脱离了嵌入的 xl。 没问题。

When you grad the xlApp, you don't grab a specific workbook. So if you refer to a number, you may not be on the embeded file. Better use Activeworkbook.
For me workbook(1) turns out to be my personnal hidden xl file containing my personnal macros.

I don't do the tests as I only have one shape in my .docx but I think the number "Excel.Sheet.8" is rather .12 for me.

    Sub TestMacro()
    
        Dim lNumShapes As Long
        Dim lShapeCnt As Long
        Dim xlApp As Object
        Dim wrdActDoc As Document
        
        Set wrdActDoc = ActiveDocument
        
        For lShapeCnt = 1 To 1 'wrdActDoc.InlineShapes.Count
            If wrdActDoc.InlineShapes(lShapeCnt).Type = wdInlineShapeEmbeddedOLEObject Then
                If wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.ProgID = "Excel.Sheet.8" Then
                    wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.Edit
                    Set xlApp = GetObject(, "Excel.Application")
                    xlApp.ActiveWorkbook.Worksheets(1).Range("A1") = "This is A modified"
                    'xlApp.ActiveWorkbook.Save
                    'xlApp.ActiveWorkbook.Close
                    xlApp.Quit
                End If
            End If
        Next lShapeCnt
    
    End Sub

When I quit xlApp, the focus gets out of the embeded xl. No problem with that.

伪心 2024-07-19 23:40:37

还有另一种简单的方法来关闭图表:只需使用查找功能来查找文档中不存在的内容。

EG

With Selection.Find
    .ClearFormatting
    .Text = "wiffleball"
    .Execute Forward:=True
End With

这将使您退出嵌入文件,关闭实例并返回到主文档,您可以从那里编写代码。

希望这有帮助,这个问题让我发疯。

Have another hackey way to get the chart to close: Simply use the find function to find something in the document that is not there.

EG

With Selection.Find
    .ClearFormatting
    .Text = "wiffleball"
    .Execute Forward:=True
End With

This will take you out of the embedded file, close the instance and back to the main document, you can just code from there.

Hope this helps, this problem was driving me crazy.

两个我 2024-07-19 23:40:34

我对自己的问题有一个解决方案。 任何进一步的意见将不胜感激 -

Sub TestMacro()

    Dim lNumShapes As Long
    Dim lShapeCnt As Long
    Dim xlApp As Object
    Dim wrdActDoc As Document

    Set wrdActDoc = ActiveDocument

    For lShapeCnt = 1 To 1 'wrdActDoc.InlineShapes.Count
        If wrdActDoc.InlineShapes(lShapeCnt).Type = wdInlineShapeEmbeddedOLEObject Then
            If wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.ProgID = "Excel.Sheet.8" Then
                wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.Edit
                Set xlApp = GetObject(, "Excel.Application")
                xlApp.Workbooks(1).Worksheets(1).Range("A1") = "This is A modified"
                xlApp.Workbooks(1).Save
                xlApp.Workbooks(1).Close
                xlApp.Quit
            End If
        End If
    Next lShapeCnt

End Sub

I have a solution to my own problem. Any further comments will be appreciated -

Sub TestMacro()

    Dim lNumShapes As Long
    Dim lShapeCnt As Long
    Dim xlApp As Object
    Dim wrdActDoc As Document

    Set wrdActDoc = ActiveDocument

    For lShapeCnt = 1 To 1 'wrdActDoc.InlineShapes.Count
        If wrdActDoc.InlineShapes(lShapeCnt).Type = wdInlineShapeEmbeddedOLEObject Then
            If wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.ProgID = "Excel.Sheet.8" Then
                wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.Edit
                Set xlApp = GetObject(, "Excel.Application")
                xlApp.Workbooks(1).Worksheets(1).Range("A1") = "This is A modified"
                xlApp.Workbooks(1).Save
                xlApp.Workbooks(1).Close
                xlApp.Quit
            End If
        End If
    Next lShapeCnt

End Sub
北渚 2024-07-19 23:40:32

哎呀,不要做你在评论中建议的事情。 您最终可能会得到多个 Excel 实例(执行代码后检查任务管理器并查看有多少个实例)。

首先,添加对 Excel 对象库的引用(项目 -> 引用并选择 Microsoft Excel 对象库)。 现在,您可以将对象声明为真正的 Excel 类型并使用早期绑定,而不是将它们声明为“对象”并使用后期绑定。 这并不是绝对必要的,但除了其他任何事情之外,这意味着您在编辑代码时可以获得智能感知。

在执行 .OleFormat.Edit 之前,您正在做正确的事情。 (我个人会使用 .OleFormat.Activate 但由于我从未尝试过使用 .Edit 我不能说它有什么不同)。

完成 .Activate(或者可能是 .Edit)后,您就可以访问 OleFormat.Object 成员。 由于嵌入的对象是 Excel 图表,因此“对象”将是 Excel 工作簿,因此您可以执行以下操作:

Dim oOleFormat as OleFormat
Set oOleFormat = ...

oOleFormat.Activate

Dim oWorkbook As Excel.Workbook
Set oWorkbook = oOleFormat.Object

' Do stuff with the workbook
oWorkbook.Charts(1).ChartArea.Font.Bold = True

请注意,您不需要关闭 Excel,实际上您也不能 - Word“拥有”用于编辑的实例-就地,并将决定何时关闭它。 这实际上是一个问题,因为没有明显的方法来强制停用嵌入对象,因此在执行上面的代码后图表将保持打开状态。

不过,有一种 hack-y 方法可以让图表关闭。 如果您添加告诉 Word 将其激活为其他内容,它会首先取消激活它。 因此,如果您告诉它将其激活为无意义的东西,您将获得正确的结果,因为它会停用它,然后无法重新激活它。 因此,添加以下行:

oOleFormat.ActivateAs "This.Class.Does.Not.Exist"

请注意,这将引发错误,因此您需要使用 On Error Resume Next 暂时禁用错误处理。 因此,我通常创建一个 Deactivate 方法,以避免中断主方法中的错误处理。 如:

Private Sub DeactivateOleObject(ByRef oOleFormat as OleFormat)
    On Error Resume Next
    oOleFormat.ActivateAs "This.Class.Does.Not.Exist"
End Sub

希望这有帮助。
加里

Yikes, don't do what you're suggesting in your comment. You'll probably end up with multiple instances of Excel (check Task Manager and see how many there are after executing your code).

Firstly, add a reference to the Excel object library (Project->References & choose Microsoft Excel Object Library). Now you can declare your objects as bona-fide Excel types and use early binding rather than declaring them as "Object" and using late binding. This isn't strictly necessary, but apart from anything else it means you get Intellisense when editing your code.

You're doing the right thing right up until you do .OleFormat.Edit. (I would personally use .OleFormat.Activate but since I've never tried using .Edit I couldn't say that it makes a difference).

Having done .Activate (or, presumably, .Edit), you can then access the OleFormat.Object member. Since the embedded Object is an Excel chart, the "Object" will be the Excel Workbook, so you can do this:

Dim oOleFormat as OleFormat
Set oOleFormat = ...

oOleFormat.Activate

Dim oWorkbook As Excel.Workbook
Set oWorkbook = oOleFormat.Object

' Do stuff with the workbook
oWorkbook.Charts(1).ChartArea.Font.Bold = True

Note that you do NOT need to close Excel, and indeed you cannot - Word "owns" the instance used for an edit-in-place, and will decide when to close it. This is actually something of a problem, since there's no obvious way to force the embedded object to be de-activated, so the chart would stay open after you execute the code above.

There is a hack-y way to get the chart to close, though. If you add tell Word to activate it as something else, it'll de-activate it first. So, if you tell it to activate it as something non-sensical, you'll achieve the right result because it'll de-activate it and then fail to re-activate it. So, add the following line:

oOleFormat.ActivateAs "This.Class.Does.Not.Exist"

Note that this will raise an error, so you'll need to temporarily disable error handling using On Error Resume Next. For that reason, I normally create a Deactivate method, to avoid disrupting the error handling in my main method. As in:

Private Sub DeactivateOleObject(ByRef oOleFormat as OleFormat)
    On Error Resume Next
    oOleFormat.ActivateAs "This.Class.Does.Not.Exist"
End Sub

Hope this helps.
Gary

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文