0
votes

I am trying to run an Excel VBA subroutine to save a Word document.

Language version: Word/Excel version 16.41
Operating system: 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://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. I was able to open tools-references-and select the Word library, but now References is unhighlighted and unclickable. (it was briefly before also)

I encounter:

Run time error -2146959355 (80080005) Automation Error.

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
3
If your host application is Excel then you need to ensure that you have a reference to Word to use early bound Word objects. i.e. Tools.References and make sure that the Microsoft Word XX.X Object Library is checked. Otherwise use Get/CreateObject.freeflow

3 Answers

0
votes

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.

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". However, I have never seen a support document by anyone, including Microsoft, that tells you how to fix that. 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.

Here, (same Office version, but Mac OS Catalina 10.15.6) what I find is that...

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. 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).

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.

However, here I find that CreateObject only works sometimes, and I haven't been able to work out why. 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. 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.

In contrast, GetObject seems to work OK. Normally it returns an error if Word has not started, but returns a reference to the Word object if it has. 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.

So I looked at the possibility of Starting Word without using COM. 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. It's simplest because all the code can be in the VBA Sub/Function - you don't need any external files.

MacScript is actually deprecated because of problems with Mac OS sandboxing. You are really supposed to use AppleScriptTask instead. 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.

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:

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. At its simplest you put a text file called myStartWordScript.scpt in a folder in the user's "Library", here

~/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:

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
0
votes

See freeflow's comment, which should be posted as answer. In VBE, pick Tools > References > Microsoft Word 16.0 Object Library.

0
votes

There's 2 ways you can automate word from Excel:

  1. Early Binding: Add a reference to the microsoft word object library.
  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