简体   繁体   English

如何在Mac OS上使用Excel VBA保存Word文档?

[英]How to save Word document using Excel VBA on Mac OS?

I am trying to run an Excel VBA subroutine to save a Word document.我正在尝试运行 Excel VBA 子例程来保存 Word 文档。

Language version: Word/Excel version 16.41语言版本:Word/Excel 16.41版
Operating system: Mac OS Mojave 10.14.6操作系统:Mac OS Mojave 10.14.6

I tried: ( https://www.reddit.com/r/vba/comments/ivwxlw/trouble_with_path_when_saving_basic_word_document/ )我试过了:( https://www.reddit.com/r/vba/comments/ivwxlw/trouble_with_path_when_saving_basic_word_document/

( https://answers.microsoft.com/en-us/msoffice/forum/all/excel-vba-macro-to-save-as-basic-word-document/df78bf58-ec21-4502-abfe-bc3df1fca7ae ) ( https://answers.microsoft.com/en-us/msoffice/forum/all/excel-vba-macro-to-save-as-basic-word-document/df78bf58-ec21-4502-abfe-bc3df1fca7ae )

I am starting from scratch on a different computer and operating system.我在不同的计算机和操作系统上从头开始。 I am now using Mac OS Majave 10.14.6 and Word/Excel version 16.41.我现在使用的是 Mac OS Majave 10.14.6 和 Word/Excel 版本 16.41。 I was able to open tools-references-and select the Word library, but now References is unhighlighted and unclickable.我能够打开工具-参考-和 select Word 库,但现在参考未突出显示且无法单击。 (it was briefly before also) (之前也有简要介绍)

I encounter:我遇到:

Run time error -2146959355 (80080005) Automation Error.运行时错误 -2146959355 (80080005) 自动化错误。

The line that needs debugging:需要调试的行:

Set wdApp = New Word.Application
Option Explicit

Sub CreateBasicWordReportEarlyBinding()

    Dim wdApp As Word.Application

    Set wdApp = New Word.Application
    With wdApp

        .Visible = True
        .Activate
        .Documents.Add
       
        With .Selection
            .ParagraphFormat.Alignment = wdAlignParagraphCenter
            .BoldRun
            .Font.Size = 18
            .TypeText "Best Movies Ever"
            .BoldRun
            .Font.Size = 12
            .TypeText vbNewLine
            .ParagraphFormat.Alignment = wdAlignParagraphLeft
            .TypeParagraph

        End With

        Range("A2", Range("A2").End(xlDown).End(xlToRight)).Copy

        .Selection.Paste

        .ActiveDocument.SaveAs2 Environ("UserProfile") & "\Desktop\MovieReport.docx"

        .ActiveDocument.Close

        .Quit

    End With

   Set wdApp = Nothing
End Sub

See freeflow 's comment, which should be posted as answer.请参阅freeflow的评论,该评论应作为答案发布。 In VBE, pick Tools > References > Microsoft Word 16.0 Object Library.在 VBE 中,选择工具 > 参考 > Microsoft Word 16.0 对象库。

There's 2 ways you can automate word from Excel:有两种方法可以让 Excel 中的 word 自动化:

  1. Early Binding: Add a reference to the microsoft word object library.早期绑定:添加对 Microsoft Word 对象库的引用。
  2. Late Binding: declare your variables as objects.后期绑定:将变量声明为对象。

In your case I would use early binding to have access to intellisense.在你的情况下,我会使用早期绑定来访问智能感知。 enter image description here在此处输入图片说明

There have been problems using COM Automation (which is what New Word.Application ", CreateObject etc are doing) on the Mac versions of Office for some years now. You may have seen similar questions elsewhere.多年来,在 Mac 版本的 Office 上使用 COM 自动化( New Word.Application “、 CreateObject等正在做的事情)一直存在问题。您可能在其他地方看到过类似的问题。

The trouble is that not everyone seems to experience these problems, which suggests that they could result from a configuration issue.问题是并不是每个人似乎都会遇到这些问题,这表明它们可能是由配置问题引起的。 The usual suspect would be "something to do with Mac OS Sandboxing".通常的怀疑是“与 Mac OS 沙盒有关”。 However, I have never seen a support document by anyone, including Microsoft, that tells you how to fix that.但是,我从未见过任何人(包括 Microsoft)的支持文档告诉您如何解决该问题。 I have done clean installs of Office on clean installs of Mac OS and encountered and reported the problems, and that's when I think the software author should really investigate the problem and provide fix or a workaround.我已经在 Mac OS 的全新安装上完成了 Office 的全新安装,并遇到并报告了问题,那时我认为软件作者应该真正调查问题并提供修复或解决方法。

Here, (same Office version, but Mac OS Catalina 10.15.6) what I find is that...在这里,(相同的 Office 版本,但 Mac OS Catalina 10.15.6)我发现......

The problems are a bit different depending on which application you are running or trying to automate.根据您正在运行或尝试自动化的应用程序,问题会有所不同。

In Excel, trying to use an early-bound object of type Word.Application always fails.在 Excel 中,尝试使用Word.Application类型的早期绑定对象总是失败。 So you cannot use所以你不能使用

Dim wdApp As New Word.Document

or或者

Dim myApp As Word.Document
Set myApp = New Word.Document

(It doesn't matter whether or not you have defined the correct reference in VBE Tools->References. If you don't, you'll see see a compile-time error anyway and VBA won't actually run the code). (您是否在 VBE Tools->References 中定义了正确的引用并不重要。如果不这样做,无论如何您都会看到编译时错误并且 VBA 不会实际运行代码)。

So you need所以你需要

Dim wdApp As Object

and to use CreateObject (if Word is not already running or when you you need a new instance of Word, on Windows at least) or GetObject (when you want to connect to a/the existing instance of Word.并使用 CreateObject(如果 Word 尚未运行,或者当您需要一个新的 Word 实例时,至少在 Windows 上)或 GetObject(当您想要连接到现有的 Word 实例时。

However, here I find that CreateObject only works sometimes, and I haven't been able to work out why.但是,在这里我发现 CreateObject 仅有时有效,我一直无法弄清楚原因。 It always starts Word if it hasn't started, but sometimes it waits for Word to start and returns a reference to the Word object and sometimes it does not.如果 Word 尚未启动,它总是会启动 Word,但有时它会等待 Word 启动并返回对 Word 对象的引用,有时则不会。 Tests are not completely conclusive, but it actually looks as if it works a maximum of "every other time you call it in an Excel session", It looks to me as if Excel retains some state information that it should not and thinks it "knows" that WOrd has started when in fact it hasn't.测试并不完全是决定性的,但实际上它看起来最多“每隔一次在 Excel 会话中调用它”,在我看来,Excel 似乎保留了一些它不应该保留的状态信息,并认为它“知道” “这个词已经开始了,但实际上还没有。

In contrast, GetObject seems to work OK.相比之下,GetObject 似乎工作正常。 Normally it returns an error if Word has not started, but returns a reference to the Word object if it has.通常,如果 Word 尚未启动,则返回错误,但如果启动,则返回对 Word 对象的引用。 So I tried to use something like this所以我尝试使用这样的东西

Dim wdApp As Object
On Error Resume Next
Set wdApp = CreateObject("Word.Application")
Err.Clear
If wdApp Is Nothing Then
  Set wdApp = GetObject(,"Word.Application")
End If

But then I still sometimes get error 429 ActiveX component can't create object in the GetObject line - in those cases it looks as if CreateObject isn't waiting for Word to start.但是有时我仍然会收到错误 429 ActiveX 组件无法在 GetObject 行中创建对象- 在这些情况下,看起来 CreateObject 没有等待 Word 启动。

So I looked at the possibility of Starting Word without using COM.所以我研究了在不使用 COM 的情况下启动 Word 的可能性。 There are a few ways you could try to do that on Mac, but the simplest is to use the MacScript function to run a bit of AppleScript to do it.有几种方法可以尝试在 Mac 上执行此操作,但最简单的方法是使用 MacScript 函数运行一些 AppleScript 来执行此操作。 It's simplest because all the code can be in the VBA Sub/Function - you don't need any external files.这是最简单的,因为所有代码都可以在 VBA 子/函数中 - 您不需要任何外部文件。

MacScript is actually deprecated because of problems with Mac OS sandboxing.由于 Mac OS 沙箱问题,MacScript 实际上已被弃用。 You are really supposed to use AppleScriptTask instead.您真的应该改用 AppleScriptTask。 But MacScript currently seems to do the job, except that it always raises a VBA error (which IMO it should not), so we have to mess around with VBA error trapping.但是 MacScript 目前似乎可以完成这项工作,只是它总是会引发 VBA 错误(IMO 不应该这样做),因此我们必须处理 VBA 错误陷阱。

Here, the following code always works.在这里,以下代码始终有效。 For now.目前。

Dim theApp As Object
On Error Resume Next
MacScript "tell application id ""com.microsoft.Word"" to activate"
Err.Clear
'On Error Goto problem ' you need to set this up
Set theApp = GetObject(,"Word.Application")
' just be careful
If theApp Is Nothing Then
  Debug.Print "theApp Is Nothing"
Else
  Debug.Print TypeName(theApp)
  ' get on with what you need to do
End If

The other thing I tried quite hard to do was see if I could then take advantage of early binding (for Intellisense etc.) by adding this code at the appropriate points:我非常努力地做的另一件事是看看我是否可以通过在适当的点添加以下代码来利用早期绑定(对于 Intellisense 等):

Dim myApp As Word.Application

Set myApp = theApp
'or
Set myApp = theApp.Application

But that never worked.但这从来没有奏效。 So I seem to be stuck with late binding.所以我似乎被后期绑定困住了。

if you find that you cannot use MacScript, you can use AppleScriptTask.如果您发现无法使用 MacScript,则可以使用 AppleScriptTask。 At its simplest you put a text file called myStartWordScript.scpt in a folder in the user's "Library", here在最简单的情况下,您将一个名为 myStartWordScript.scpt 的文本文件放在用户“库”的文件夹中,这里

~/Library/Application Scripts/com.microsoft.Excel

I used a script like this:我使用了这样的脚本:

on myStartWord(dummy as text)
    tell application id "com.microsoft.Word"
        activate
    end tell
    return "Word has started"
end myStartWord

Then you can ditch some of that error heandling stuff and use VBA code like this:然后你可以抛弃一些错误处理的东西并使用这样的 VBA 代码:

Dim theApp As Object
Debug.Print AppleScriptTask("myStartWordScript","myStartWord","")
'On Error Goto problem ' you need to set this up
Set theApp = GetObject(,"Word.Application")
' just be careful
If theApp Is Nothing Then
  Debug.Print "theApp Is Nothing"
Else
  Debug.Print TypeName(theApp)
  ' get on with what you need to do
End If

To find the proper syntax for saving to a Mac OS X folder:要找到保存到 Mac OS X 文件夹的正确语法:

  • open a file打开一个文件
  • record a macro录制宏
  • save the file (choose your folder)保存文件(选择你的文件夹)
  • stop the recording停止录音
  • edit the macro编辑宏
  • see how Word translated it in VisualBasic查看 Word 如何在 VisualBasic 中翻译它

example with Word 16 (2019):以 Word 16 (2019) 为例:

ActiveDocument.SaveAs2 FileName:= _
    "/Users/myusername/anyfolder/nameofthefile" & DocNum & ".txt" _
    , FileFormat:=wdFormatText, LockComments:=False, Password:="", _
    AddToRecentFiles:=True, WritePassword:="", ReadOnlyRecommended:=False, _
    EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData _
    :=False, SaveAsAOCELetter:=False, Encoding:=65001, InsertLineBreaks:= _
    False, AllowSubstitutions:=False, LineEnding:=wdCROnly

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM