vbams-word

How do I apply the Enumerations for the Word object model using the Enumerations list?


I'm new to VBA in the sense that I'm learning how to use the object model correctly, instead of just recording macros and doing a mediocre job.

I have a series of .RTF documents that are generated from an engineering program and the only file type for output is .RTF. In those RTF files are images that I need to resize before incorporating them into a report. I have a macro that resizes all of the images, and I want to save the document in a new format. For now, I'm using the Application.Dialogs(wdDialogFileSaveAs).Show statement to open a file dialog so that I can change the file format to .docx.

Obviously, this would be better if I can automate this, because I have more than a couple of files. But, there's no point in automating it until I can figure out how to use the wdFormatDocumentDefault enumeration.

I did some searching and I can't get the example enums that I found to work as described.

So my basic question is, what is the syntax to make these enumerations work? Do I need to use ActiveDocument.SaveAs2? If I do that, do I have to specify the file name? Can I just keep the same file name, but change the file type so that the .RTF file becomes a .docx file?

I modified this from another post on the Stack, but I'm getting a syntax error.

Original:

docx.SaveAs2(fileName, MSWord.WdSaveFormat.wdFormatDocumentDefault)

Modified:

ActiveDocument.SaveAs2(ActiveDocument.Name, MSWord.WdSaveFormat.wdFormatDocumentDefault)

I don't understand why the modified code doesn't work.

EDIT:

I figured out that I need to specify the enumerations like this:

ActiveDocument.SaveAs2 FileFormat:=wdFormatDocumentDefault

So, at least the code runs, but it doesn't actually save the file as a .docx file type.

I was partially referencing other tips and trying things out on my own. I removed the .RTF file extension from the file name, and then added the FileFormat enum.

Working solution is this:

ActiveDocument.SaveAs2 _
    FileName:=Left(ActiveDocument.Name, Len(ActiveDocument.Name) - 4), _
    FileFormat:=wdFormatDocumentDefault

Suggested improvements are welcome.


Solution

  • There are several different things going on in your experimental code.

    In here

    docx.SaveAs2(fileName, MSWord.WdSaveFormat.wdFormatDocumentDefault)
    
    1. At some point before executing this line, you need to have set the variable docx to the Document object you want to save (e.g. ActiveDocument or ThisDocument), e.g. using

      Set docx = ActiveDocument

    2. If you want to use the "fully qualified" name for wdFormatDocumentDefault, you need Word.WdSaveFormat.wdFormatDocumentDefault (i.e. Word rather than MSWord). That was probably what caused a syntax error in your first two examples.

    3. I don't think The wdFormatDocumentDefault option does what the documentation says it does. Hence the post by @taller. In any case, however you specify one of the standard Word zipped formats .docx, .docm, .dotx, .dotm, Word should save the document with the internal format that corresponds to the chosen exteension/format. ISTR this is regarded as a security feature.

    To expand on some of these things...

    Displaying the Immediate Window (View->Immediate WIndow) in the VB Editor makes it easy to check some things by entering them in the Window and taking advantage of VBE's Intellisense to pop up available options.

    e.g. if you enter

    ?MSWord.
    

    you won't see any suggestions, which is a clue that MSWord has no special meaning, whereas entering

    ?Word.
    

    should bring up a list of all the things you could put after the dot.

    The ? in that command is essentially the same as using Debug.Print in a SUb/Function in a code module.

    Typically, the examples of VBA code you'll find on the Internet do not use the fully qualified enum names. Since Word recognises all the wd enum names without qualification anyway, a lot of the time people leave them unqualified. You have to be more careful when using these constants in, say, VBA code to be run from Excel. In that case you either have to make a reference to the WOrd object, or use the actual value of the constant (16 in the case of wdFormatDocumentDefault), or make your own definition and use that. In code written in a more modern programming environment, say .NET, you are much more likely to see the fully qualified name. In any case, it is advisable in VBA to put the directive

    Option Explicit
    

    at the top of every Module, because the compiler then detects undeclared and variables and constant names (e.g. it will detect some misspellings).

    The syntax you worked out here:

    ActiveDocument.SaveAs2 FileFormat:=wdFormatDocumentDefault
    

    is fine, but is one of several ways you could have specified that. e.g. You could have used positional parameters like this

    ActiveDocument.SaveAs2 , wdFormatDocumentDefault
    

    NB, you can tell that the FileName parameter is optional by opening View->Object Browser, searching for WOrd's .SaveAs2 method, and looking at the Method signature, which shows

    SaveAs2([FileName],[SaveFormat],...,)
    

    The [] mean the parameter is syntactically optional. You may find there are cases where at runtime you have to provide a value. The fact that no data type is given means the parameter is a Variant, which usually means that you can pass several different types of thing to the Method.