Visual basic for word and excel

This post is the second in a series about controlling other applications from Excel using VBA. In the first part we looked at the basics of how to reference other applications using Early Binding or Late Binding. In this post, we will look at how we can automate Word from Excel even though we don’t know any VBA code for Word… yet. The process we will use for this is as follows:

  1. Enable the Word Developer menu
  2. Record a Word macro
  3. Add the code to Excel VBA and amend
  4. Record macros in Excel if necessary
  5. Repeat the previous steps until macro complete

I am not an Excel VBA expert (I’m more of an Excel VBA tinkerer), and I am certainly not a Word VBA expert. The process I am about to show you may not create the most efficient code, but I know this process works, because I have used it myself to automate lots tasks using Microsoft Word.

Enable the Word Developer menu

If you have enabled the Excel Developer menu it is the same process in Word.

In Word: File -> Options -> Customize Ribbon

Then tick the Developer Ribbon option, OK.

Enable Word Developer Tab

Record a Word Macro

The key to the success of this method is taking small sections of code and building up a complex macro bit by bit. Using the Word Macro Recorder is again, similar to the Excel Macro recorder.

Click on: Developer -> Record Macro

Word VBA Record Macro

For the example in this post, we will create a macro which will open a new Word document, then copy a chart from Excel and paste it into that Word document. We will tackle this one stage at a time. Firstly, lets create the macro to open a new word document.

Click – Developer -> Record Macro. The Record Macro window will open.

Word Record Macro Window

Make a note of the “Store macro in” option, as we will need to know where to find the recorded code later. Normal.dotm is fine for now. Click OK – the Macro Recorder is now running.

Open a new Word Document – File -> New -> Blank Document

Stop the Macro from recording – Developer -> Stop Recording

Word VBA Stop Recording

We can now view the code for opening a new Word Document in the Visual Basic Editor. Click: Developer -> Visual Basic.

Word Visual Basic Editor

Find the location of your recorded code in the Visual Basic Editor. In this example: Normal -> Modules -> NewMacros.

Automate Word from Excel

Your code should look like the following. It may be slightly different, but not significantly.

Sub Macro1()
'
' Macro1 Macro
'
'
    Documents.Add Template:="Normal", NewTemplate:=False, DocumentType:=0
    Windows("Document1").Activate
    Windows("Document2").Activate
End Sub

Add the code to Excel VBA and amend

Let’s head back to the Excel VBA Editor and use the Early Binding method to control to Microsoft Word. In the Visual Basic Editor click Tools -> References select Microsoft Word x.xx Object Library. Then click OK.

VBA Word Object Library

As we are using Early Binding we need to declare the Application as a variable as follows:

Dim WordApp As Word.Application
Set WordApp = New Word.Application

Now copy and paste the code from the Word VBA Editor into the Excel VBA Editor.

The Word VBA code started with Documents.Add, all we have to do is add our application variable to the front of that line of code. Now becomes WordApp.Documents.Add . . .

Often, Selecting and Activating Objects is not required in VBA code, so I have not copied those statements into the code below.

Sub CreateWordDocument()

'Connect using Early Binding.
'Remember to set the reference to the Word Object Library
'In VBE Editor Tools -> References -> Microsoft Word x.xx Object Library
Dim WordApp As Word.Application
Set WordApp = New Word.Application

WordApp.Documents.Add Template:="Normal", NewTemplate:=False, DocumentType:=0
WordApp.Visible = True 'New Apps will be hidden by default, so make visible

Set WordApp = Nothing 'release the memory

End Sub

A point to note, when an application is opened with VBA, it is normally opened in the background. To make the Word document visible I have added the following code:

WordApp.Visible = True

Record macros in Excel (if necessary)

If we want to copy Excel content into a Word document, we will need to copy that content using Excel VBA. We can use the Macro Recorder in Excel to obtain the VBA code for copying, then we can use the Word Macro Recorder to obtain the VBA code for pasting.

Macro Recording from Excel – selecting a worksheet and copying chart

Sheets("Sheet1").Select
ActiveSheet.ChartObjects("Chart 1").Activate
ActiveChart.ChartArea.Copy

Macro Recording from Word – pasting a chart into a document

Selection.PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False

We can add both Macro recordings into our Excel macro. Remember to add WordApp. at the start of each statement of Word VBA code.

Sub CreateWordDocument()

'Connect using Early Binding.
'Remember to set the reference to the Word Object Library
'In VBE Editor Tools -> References -> Microsoft Word x.xx Object Library
Dim WordApp As Word.Application
Set WordApp = New Word.Application

WordApp.Documents.Add Template:="Normal", NewTemplate:=False, DocumentType:=0
WordApp.Visible = True 'New Apps will be hidden by default, so make visible

'code copied from Excel Macro recorder
Sheets("Sheet1").Select
Selection.ChartObjects("Chart 1").ChartArea.Copy

'code copied from Word Macro recorder with WordApp. added to the front.
WordApp.Selection.PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False

Set WordApp = Nothing 'release the memory 

End Sub

This code is not particularly efficient; it contains a few unnecessary sections code. However… it works!

Repeat the previous steps until macro complete

By repeating the same steps above; recording short actions, then transferring the code into Excel, we can slowly build up much more complex Macros. The key is to keep the actions short, if you do too many actions with the Macro Recorder, code starts to look long and scary.

If you’ve you tried to use the Macro Recorder before you will know that this is not as easy as it seems. And this simple tutorial may make you think it is easy, when it’s not. Sometimes, it can be quite frustrating trying to find out where the issues and errors are. The key to success is recording very short actions, such as those below and copying them into the Visual Basic Editor.

'Pressing the Enter Key to move to a new line in Word
WordApp.Selection.TypeParagraph

'Turn on/off Bold Text
WordApp.Selection.Font.Bold = wdToggle

'Change Font Size
WordApp.Selection.Font.Size = 16

'Type some text
WordApp.Selection.TypeText Text:="Here is some text"

You will soon build up a standard library of code that you can use to control Word for most basic tasks.

In recorded VBA code from Word, the word “Selection” in the code often refers to the document itself. It is possible to make the code a little bit more efficient by declaring the document as a variable. If we were opening a specific document, we could include this at the start, just below the declaration of the application.

'Declare a specific document as a variable
Dim WordDocument As Object
Set WordDocument = WordApp.Documents.Open(sourceFileName)

Or, if we created a new document we could include the following below the declaration of the application variable.

'Delcare a new document as a variable
Dim WordDocument As Object
Set WordDocument = WordApp.Documents.Add Template:="Normal", _
NewTemplate:=False, DocumentType:=0

If we have created the document as a variable we can then reference the specific document. This code:

WordApp.Selection.TypeParagraph

Would become this code:

WordDocument.TypeParagraph

Or this code:

WordApp.Selection.TypeText Text:="Here is some text"

Would become this code:

WordDocument.TypeText Text:="Here is some text"

This method is much better, as it doesn’t rely on the Selection of the user being in the right place.

Conclusion

We have seen in this post that it is possible to create complex Macros to automate Word from Excel using VBA. By understanding how to declare variables for the application and documents we can create much more robust macros, even without knowing a lot of VBA code.

Related Posts:

  • 5 quick ways to embed a Word document in Excel
  • Controlling Powerpoint from Excel using VBA
  • Edit links in Word using VBA
  • How to link Excel to Word

Headshot Round

About the author

Hey, I’m Mark, and I run Excel Off The Grid.

My parents tell me that at the age of 7 I declared I was going to become a qualified accountant. I was either psychic or had no imagination, as that is exactly what happened. However, it wasn’t until I was 35 that my journey really began.

In 2015, I started a new job, for which I was regularly working after 10pm. As a result, I rarely saw my children during the week. So, I started searching for the secrets to automating Excel. I discovered that by building a small number of simple tools, I could combine them together in different ways to automate nearly all my regular tasks. This meant I could work less hours (and I got pay raises!). Today, I teach these techniques to other professionals in our training program so they too can spend less time at work (and more time with their children and doing the things they love).


Do you need help adapting this post to your needs?

I’m guessing the examples in this post don’t exactly match your situation. We all use Excel differently, so it’s impossible to write a post that will meet everybody’s needs. By taking the time to understand the techniques and principles in this post (and elsewhere on this site), you should be able to adapt it to your needs.

But, if you’re still struggling you should:

  1. Read other blogs, or watch YouTube videos on the same topic. You will benefit much more by discovering your own solutions.
  2. Ask the ‘Excel Ninja’ in your office. It’s amazing what things other people know.
  3. Ask a question in a forum like Mr Excel, or the Microsoft Answers Community. Remember, the people on these forums are generally giving their time for free. So take care to craft your question, make sure it’s clear and concise.  List all the things you’ve tried, and provide screenshots, code segments and example workbooks.
  4. Use Excel Rescue, who are my consultancy partner. They help by providing solutions to smaller Excel problems.

What next?
Don’t go yet, there is plenty more to learn on Excel Off The Grid.  Check out the latest posts:

Since most users install the full Microsoft Office suite of tools, they have Word and Excel installed on the same computer. You might need to automate Word functionality along with your Excel application. You can automate Word functionality from your Excel VBA code. In this article, we’ll show you how to automate Word functionality from your Excel spreadsheets.

Initializing Word Variables

Before you can use Word in your applications, you need to add it to your references. References are used in programming languages to allow the local application to use the third-party application’s DLLs. Dynamic link libraries (DLLs) are a part of the Windows operating system and any Microsoft application to allow other developers to code for the application. In this case, you want to use Word DLLs, so you must add the reference to your Excel VB application.

In your VBE, you’ll see the Tools menu item. This menu is where you can add references. Click «Tools» and then click «References.» A dialog window opens with a list of available third-party applications. You might be surprised at how many applications you have to choose from. If it’s installed on the local desktop, then you will probably see it in the list. You can use numerous applications in your VBA code, and all you need to do is add a reference to it from this dialog window to get started.

Scroll down to the check box labeled Microsoft Word Object Library. You’ll also see a version number, but this just indicates the version for the DLLs you’ll be using.

Click «OK» and the VBE includes the reference in your project.

With the Word DLLs referenced, you can now use VB code to work with Word automation. First, just like the other code we’ve worked with, we want to create a subroutine. Let’s create a subroutine named WordDoc().

Sub WordDoc()

End Sub

With the subroutine set up, we can now create and initialize Word variables. Take a look at the following code that sets up and defines Word variables.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

End Sub

In the above code, we have two variables. You need both of them to work with Word applications. The first one initializes the Word application itself. You need an application variable to work with its DLLs. Next, we created a Word variable for the document component. You need this variable to create, edit and manipulate documents. Just remember that both of these variables are needed when you want to work with Word documents.

With the variables created, we can now assign objects to the variables. Let’s add the variable objects.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

  Set word = New Word.Application

  word.Visible = True

  Set doc = word.Documents.Add

End Sub

We added three lines of code. The first one is the instantiation of the Word application class. You know this is an instantiation line of code because it uses the «New» statement.

The next statement makes the Word application visible. When you initialize Word, you can create documents in the background without the application being visible to the user. In this example, we make it visible to the user, so it can be manipulated or edited later. After we make the Word application visible, we now want to add a document to it. In this example, we call the Documents.Add method to add a new document to the open window.

The above code initializes the Word variables, but it essentially adds a new document as well. Once we create the Word document, we can write data to it. We’ll cover opening and writing content to a Word document in the next section.

Opening and Editing Word Documents

Since we’re working with Word documents, you should allow users to open a document manually or auto-open it for them. You can open a file automatically in code, but some applications require that you show the user an open dialog window and let them choose the file that they want to use. In this section, we’ll show you both methods and then show you how to add content to the file.

We need the same variables from the previous section, so let’s copy the code from the first section to our new EditDoc subroutine.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

  Set word = New Word.Application

  word.Visible = True

End Sub

Notice that we took away the «Add» function. We don’t want to add a new document to the application. We want to open an existing document. We know that there are two ways to do this. Let’s first open it in the code without prompting the user for a name.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

  Set word = New Word.Application

  word.Visible = True

  word.documents.Open («C:\doc.docx»)

End Sub

In the above code, we use the word variable to open the document in the existing application instance. We open the doc.docx file and add it to our instance.

In many cases, you need to prompt the user to open the file on their hard drive. You don’t need to write your own open dialog window. Microsoft Windows provides you with the tools to open a dialog window. The operating system on the user’s local computer is used to draw and prompt the user. When you open a dialog window, the code’s execution stops until the user chooses a file or clicks the Cancel button.

Let’s remove the auto-open code and add the choice for the user to select a Word document from a dialog window.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

  Set word = New Word.Application

  word.Visible = True

  choice = Application.FileDialog(msoFileDialogOpen).Show

End Sub

We added the code that shows a dialog window to the user’s interface. The «Show» command actually displays it to the user. Had we not used the Show method, the user would not see the window. Since the window is an internal Windows function, we use the Application class. Whatever file the user chooses is assigned an integer value and stored in the «choice» variable.

At this point, a file was chosen but it’s not opened yet. We need to add the code to actually open the document in the current Word application instance. Let’s take a look at the code.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

  Set word = New Word.Application

  word.Visible = True

  choice = Application.FileDialog(msoFileDialogOpen).Show

  If choice <> 0 Then

    strPath = Application.FileDialog( _

        msoFileDialogOpen).SelectedItems(1)

    word.documents.Open (strPath)

End If

End Sub

We added an If statement that first identified that the user chose a file. If the user clicks «Cancel,» then this code would not run and the subroutine would end without doing anything more. If the user clicks a file, it’s given a number to identify it from the other files. The next execution falls in the If statement.

We first assign the path of the file to a string variable. This string variable contains the drive letter and the full path including the directory tree. Notice we use the static value of 1 in the SelectedItems function. This is to indicate that the first file should be retrieved. Users can also choose multiple files at a time. In this example, we only choose the first file since we only want to allow one file to open in the application.

Once the path is assigned to the string variable, we can now open it. The Open method using the word application variable is used.  Once this line of code executes, the file is opened and added to the Word application window.

Writing Data to a Word Document

The Word document is now open and activated, so now we can write information to it. Since the focus of this article is to work with Excel data, we’ll show you how to write data from an Excel spreadsheet to the Word document. We can use the existing subroutine that we’ve worked with and add some functionality to it to take data from the spreadsheet cells and send it to the word document.

First, copy the existing subroutine from the previous section.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

  Set word = New Word.Application

  word.Visible = True

  choice = Application.FileDialog(msoFileDialogOpen).Show

  If choice <> 0 Then

    strPath = Application.FileDialog( _

        msoFileDialogOpen).SelectedItems(1)

    word.documents.Open (strPath)

End If

End Sub

Now, we need to loop through each cell and add data to Word. The following code adds two variables for the loop and the loop to retrieve data.

Sub WordDoc()

  Dim word As Word.Application

  Dim doc As Word.Document

  Set word = New Word.Application

  word.Visible = True

  choice = Application.FileDialog(msoFileDialogOpen).Show

  If choice <> 0 Then

    strPath = Application.FileDialog( _

        msoFileDialogOpen).SelectedItems(1)

    word.documents.Open (strPath)

End If

Dim j As Integer

Dim input As String

For j = 1 To 5

    doc.Activate

    input = Cells(j + 1, 1)

    word.Selection.TypeText Text:= input

    word.Selection.TypeParagraph

Next j

End Sub

We created a j variable used for the loop, and the input string variable will be used to store data from the cells we capture.

Note that we first call the Activate function on the doc variable to ensure that the Word document is set to receive data. We then loop through the first 5 rows and assign the input to a property named TypeText. The TypeParagraph property adds a carriage return and line feed to the document.

Once you work with Word documents, you can offer users a way to work with Excel and then export data to Word for reports and other word processing functionality. This coding can be useful when you have users that prefer to send a backup or archive of data to Word for future reports and printouts.

Handling Errors

  When you write real-world applications, you must account for unforeseen logic or input errors. These errors cause bugs in your application. If you don’t account for these errors, your application crashes and the Excel file closes. You can imagine that users would be very frustrated with this behavior since they lose any unsaved data. Fortunately, Visual Basic has error handling functionality that lets you send a message to the user, trap the error, and avoid crashing the application. This section discusses error handling and how you can work it into your code.

The On Error Resume Next Statement

The first and most common error handling statement is the On Error Resume Next statement. This statement has two parts.

The On Error statement is used to capture the error when it occurs. If you’re familiar with other languages such as C#, you’ll recognize the try-catch statement. The On Error statement is similar to a try-catch block.

When an error occurs, the On Error statement captures the event and holds it until you tell the compiler what to do with the bug. If you don’t have this statement available, your program crashes.

You must place the On Error statement at the top of your code or where you suspect a bug or error could be thrown. Let’s take a look at some code that uses the On Error Resume Next statement.

On Error Resume Next

j = 1 / 0

If Err.Number <> 0 Then

j = 1

End If

If you recall from basic math rules, you can’t divide any number by 0. We have an On Error Resume Next statement at the top of our code, and then we attempt to divide by 0 and assign the result to a variable. We know this causes an error to our code, so the On Error statement captures it instead of allowing the program to crash. At this point, the Resume Next statement is used. The On Error statement captures the error, and any statement following it tells the compiler what to do next. The Resume Next statement tells the compiler to ignore the error and just continue to the next block of code.

In this example, we identify if an error was captured in the next statement. If the result is 0, no error was captured. In this example, we know that an error occurred, so we then assign the j variable a value of 1.

The On Error Resume Next statement is useful in short blocks of code. The statement has two issues, though. The first one is that the next line of code after any statement must identify if there was an error from the previous statement. This can make your code tedious and complicated.

The next issue is that it forces your code to ignore errors, so you never know if there are any bugs or errors. If we eliminated the If statement in the previous example, the code would execute normally and continue execution without any warning. This can create logic bugs and unintended issues with your application.

The On Error Resume Next statement should be used rarely and only when you know that resuming to the next code statement won’t cause any significant issues with your application.

The On Error Goto Statement

The alternative to the On Error Resume Next statement is to use the On Error Goto statement. Instead of ignoring an error and moving to the next line of code, the Goto statement tells the compiler to jump to a location that specifies how you want to handle the error. This statement makes it much easier to handle errors, because you know the error occurs and control the next block of code that executes.

Let’s take a look at an example using the divide-by-zero code we used in the previous section.

Sub ErrorSample()

On Error Goto ErrHandler

  j = 1 / 0

  j = 1

  MsgBox j

Exit Sub

  ErrHandler:

  MsgBox «You have an error in your code!»

End Sub

We’ve created an ErrorSample subroutine to demonstrate the way On Error Goto works. We used the same division code, which again throws an error.

Instead of moving to the next line of code, the On Error statement captures the bug and then sends the next execution directive to the label indicated in the Goto statement. In this example, we used the name ErrHandler, but you can give your labels any name. The name you choose for the Goto statement must match the name of the label.

The label code syntax is its name and then a colon. After this colon, the error handling statements are executed. We just used a message box to send a message to the user. In this example, we tell the user that there was an error in the application. Once the error handler runs, no other code in the subroutine runs.

You can test this code by executing the subroutine. Instead of assigning the j variable with the value of 1, the j variable contains no value and the message «You have an error in your code» displays. If no error occurs, the j variable is assigned the value of one and a message box displays the value of j. Of course, we purposely throw an error in this code, so the proper code will never run and the error handler always executes.

This type of error handling is the most popular in VB, so it will be a majority of your error handling code.

You can have multiple labels and error handling statements. Let’ stake a look at some code that uses two error handling blocks.

Sub ErrorSample()

On Error Goto ErrHandler

  j = 1 / 0

  j = 1

  MsgBox j

Exit Sub

  ErrHandler:

  On Error Goto ErrHandler2

  Debug.Print 1/0 ‘this also throws an error

  ErrHandler2:

  MsgBox «You have an error in your code!»

End Sub

In the code above, we use two labels. The first one catches the original error. We then have another division statement in the error handler. Since this code also throws an error, we need another error handler. This error handler then tells the user that there is a bug in the code.

When you receive an error in your code, the best way to manage it is to use the debugger to step through the code and watch the way the compiler executes each statement. As soon as an error is found, the execution flow jumps to the error handler assigned to the subroutine.

The Resume Statement

We saw the Resume Next statement in the first section, but the Resume statement doesn’t require «Next» to function. The Resume statement simply tells the compiler to resume to the next statement for execution. This statement can be controlled within your error handling blocks.

In the previous sections, we showed you error handlers that displayed a message to the user but then exited the subroutine with no follow-up statements. In many cases, once you trap the error, you want to continue with the rest of the subroutine statements.

For instance, your code could throw an error during a calculation. If the calculation fails you want to tell the user but then use an alternative value or resort to the previous value. Prematurely ending the subroutine could be an issue with some functions.

Luckily, the Visual Basic language has the Resume statement that lets you handle an error and then go back to the subroutines main statements.

Let’s take a look at an example.

Sub ErrorSample()

On Error Goto ErrHandler

  Worksheets(«NewSheet»).Activate

  Exit Sub

  ErrHandler:

  If Err.Number = 9 Then

    Worksheets.Add.Name = «NewSheet»

   Resume

    End If

End Sub

In the code above, we work with a new worksheet. We first try to activate the worksheet. If the worksheet does not exist, then the Activate function will throw an error. Without capturing the error, your program would crash and the user would be forced to re-open Excel.

Since we capture the error, the program doesn’t crash. Instead, program execution falls to the ErrHandler label. The error returned is an integer value of 9. You need to look up these values or run through your code using the debugger to identify the right integer value for different errors.

If the error is number 9, then we create a new worksheet and use the Resume statement. The Resume statement tells the error handler to return to the statement that caused the error. In this example, the Activate method for a worksheet named «NewSheet» caused the error. Code execution returns to this line of code. Now that NewSheet does indeed exist, the subroutine is able to activate the worksheet and continue functioning.

This type of error handling is the best way to handle bugs if you’re able to work with it. You won’t always be able to automatically fix the error and return to code execution, but it’s the most convenient for your users.

Error handling is an important factor for good user experiences. These handlers stop your application from crashing, and they allow your users to work with your VBA code without losing any data that they haven’t saved. It’s also a convenient way to trap bugs that would otherwise cause critical logic bugs. Every subroutine should have an error handler label assigned to it even if you don’t think it will throw an error. A common developer mistake is thinking that sections of code could never throw an error. Always write subroutines with error handlers regardless if you think they could never throw an error.

Using Excel VBA to create Microsoft Word documents

In these examples, we generate Microsoft Word Documents with various formatting features using
the Microsoft Excel VBA scripting language. These techniques can have many useful applications.
For instance if you have a list of data like a price or product list in Excel that you want to present
in a formatted Word Document, these techniques can prove useful.

In these examples, we assume the reader has at least basic knowledge of VBA, so we will not
go over basics of creating and running scripts. This code has been tested on Microsoft Word and Excel
2007. Some changes may be required for other versions of Word and Excel.

Writing to Word
Inserting a Table of Contents
Inserting Tabs
Inserting Tables
Inserting Bullet List
more on Inserting Tables
Multiple Features

Function that demonstrates VBA writing to a Microsoft Word document

The following code illustrates the use of VBA Word.Application object and related properties.
In this example, we create a new Word Document add some text.

    'In Tools > References, add reference to "Microsoft Word XX.X Object Library" before running.
	
    'Early Binding
    Dim wdApp As Word.Application
    Set wdApp = New Word.Application
    
    'Alternatively, we can use Late Binding
    'Dim wdApp As Object
    'Set wdApp = CreateObject("word.Application")
        
    With wdApp
        .Visible = True
        .Activate
        .Documents.Add
        
        With .Selection
            .ParagraphFormat.Alignment = wdAlignParagraphCenter
            .Font.Bold = True
            .Font.Name = "arial"
            .Font.Size = 14
            .TypeText ("My Heading")
            .TypeParagraph            
        End With
    End With 

Some VBA Vocabulary

ParagraphFormat
Represents all the formatting for a paragraph.

output in MS Word:

Inserting a Table of Contents into Word Document using Excel VBA

In this example, we generate a Table of Contents into a Word Document using Excel VBA

Sub sAddTableOfContents()
    
    Dim wdApp As Word.Application
    Set wdApp = New Word.Application
	
    'Alternatively, we can use Late Binding
    'Dim wdApp As Object
    'Set wdApp = CreateObject("word.Application")
    
    Dim wdDoc As Word.Document
    Set wdDoc = wdApp.Documents.Add
    
    ' Note we define a Word.range, as the default range wouled be an Excel range!
    Dim myWordRange As Word.range
    Dim Counter As Integer
    
    wdApp.Visible = True
    wdApp.Activate
    
    'Insert Some Headers
    With wdApp
        For Counter = 1 To 5
            .Selection.TypeParagraph
            .Selection.Style = "Heading 1"
            .Selection.TypeText "A Heading Level 1"
            .Selection.TypeParagraph
            .Selection.TypeText "Some details"
        Next
    End With

    ' We want to put table of contents at the top of the page
	Set myWordRange = wdApp.ActiveDocument.range(0, 0)
    
    wdApp.ActiveDocument.TablesOfContents.Add _
     range:=myWordRange, _
     UseFields:=False, _
     UseHeadingStyles:=True, _
     LowerHeadingLevel:=3, _
     UpperHeadingLevel:=1

End Sub

Some VBA Vocabulary

ActiveDocument.TablesOfContents.Add
The TablesOfContents property to return the TablesOfContents collection.
Use the Add method to add a table of contents to a document.

Some TablesOfContents Parameters

Range The range where you want the table of contents to appear. The table of contents replaces the range, if the range isn’t collapsed.

UseHeadingStyles True to use built-in heading styles to create the table of contents. The default value is True.

UpperHeadingLevel The starting heading level for the table of contents. Corresponds to the starting value used with the o switch for a Table of Contents (TOC) field. The default value is 1.

LowerHeadingLevel The ending heading level for the table of contents. Corresponds to the ending value used with the o switch for a Table of Contents (TOC) field. The default value is 9.

output Word Table in MS Word:

Write Microsoft Word Tabs

A function that writes tabbed content to a Microsoft Word Document. Note in each iteration, we change the
value of the leader character (characters that are inserted in the otherwise blank area created by the tab).

Public Sub sWriteMicrosoftTabs()

    'In Tools > References, add reference to "Microsoft Word XX.X Object Library" before running.
    
    'Early Binding
    Dim wdApp As Word.Application
    Set wdApp = New Word.Application
    
    'Alternatively, we can use Late Binding
    'Dim wdApp As Object
    'Set wdApp = CreateObject("word.Application")
        
    With wdApp
        .Visible = True
        .Activate
        .Documents.Add
    
        For Counter = 1 To 3
            .Selection.TypeText Text:=Counter & " - Tab 1 "
            
            ' position to 2.5 inches
            .Selection.Paragraphs.TabStops.Add Position:=Application.InchesToPoints(2.5), _
                Leader:=Counter, Alignment:=wdAlignTabLeft
            
            .Selection.TypeText Text:=vbTab & " - Tab 2 "
            
            ' position to 5 inches
            .Selection.Paragraphs.TabStops.Add Position:=Application.InchesToPoints(5), _
                Leader:=Counter, Alignment:=wdAlignTabLeft
            
            .Selection.TypeText Text:=vbTab & " - Tab 3 "
                    
            .Selection.TypeParagraph
        Next Counter
        
    End With
End Sub

Some VBA Vocabulary

.TabStops.Add Use the TabStops property to return the TabStops collection. In the example above,
nprogram adds a tab stop positioned at 0, 2.5 and 5 inches.

output in MS Word:

Write Microsoft Word Tables

In this example, we generate a Microsoft Table using Excel VBA

Sub sWriteMSWordTable ()
 
    'In Tools > References, add reference to "Microsoft Word XX.X Object Library" before running.
    
    'Early Binding
    Dim wdApp As Word.Application
    Set wdApp = New Word.Application
    
    'Alternatively, we can use Late Binding
    'Dim wdApp As Object
    'Set wdApp = CreateObject("word.Application")
        
    With wdApp
        .Visible = True
        .Activate
        .Documents.Add
        
        With .Selection
        
            .Tables.Add _
                    Range:=wdApp.Selection.Range, _
                    NumRows:=1, NumColumns:=3, _
                    DefaultTableBehavior:=wdWord9TableBehavior, _
                    AutoFitBehavior:=wdAutoFitContent
            
            For counter = 1 To 12
                .TypeText Text:="Cell " & counter
                If counter <> 12 Then
                    .MoveRight Unit:=wdCell
                End If
            Next
        
        End With
        
    End With

End Sub

Some VBA vocabulary

Table.AddTable object that represents a new, blank table added to a document.

Table.Add properties

Range The range where you want the table to appear. The table replaces the range, if the range isn’t collapsed.

NumRows The number of rows you want to include in the table.

NumColumns The number of columns you want to include in the table.

DefaultTableBehavior Sets a value that specifies whether Microsoft Word automatically resizes cells in tables to fit the cells� contents (AutoFit). Can be either of the following constants: wdWord8TableBehavior (AutoFit disabled) or wdWord9TableBehavior (AutoFit enabled). The default constant is wdWord8TableBehavior.

AutoFitBehavior Sets the AutoFit rules for how Word sizes tables. Can be one of the WdAutoFitBehavior constants.

output in MS Word:

Write Microsoft Word bullet list

In this example, we write with bullet list and outline numbers with Excel VBA

    'In Tools > References, add reference to "Microsoft Word XX.X Object Library" before running.
    
    'Early Binding
    Dim wdApp As Word.Application
    Set wdApp = New Word.Application
    
    'Alternatively, we can use Late Binding
    'Dim wdApp As Object
    'Set wdApp = CreateObject("word.Application")
    
    With wdApp
        .Visible = True
        .Activate
        .Documents.Add
        ' turn on bullets
        .ListGalleries(wdBulletGallery).ListTemplates(1).Name = ""
        .Selection.Range.ListFormat.ApplyListTemplate ListTemplate:=.ListGalleries(wdBulletGallery).ListTemplates(1), _
            continuepreviouslist:=False, applyto:=wdListApplyToWholeList, defaultlistbehavior:=wdWord9ListBehavior
        
        With .Selection
            .ParagraphFormat.Alignment = wdAlignParagraphLeft
            .Font.Bold = False
            .Font.Name = "Century Gothic"
            .Font.Size = 12
            .TypeText ("some details")
            .TypeParagraph
            .TypeText ("some details")
            .TypeParagraph
        End With
        
        ' turn off bullets
        .Selection.Range.ListFormat.RemoveNumbers wdBulletGallery
        
        With .Selection
            .ParagraphFormat.Alignment = wdAlignParagraphLeft
            .TypeText ("some details")
            .TypeParagraph
            .TypeText ("some details")
            .TypeParagraph
            
        End With
        
        ' turn on outline numbers
        .ListGalleries(wdOutlineNumberGallery).ListTemplates(1).Name = ""
        .Selection.Range.ListFormat.ApplyListTemplate ListTemplate:=.ListGalleries(wdOutlineNumberGallery).ListTemplates(1), _
            continuepreviouslist:=False, applyto:=wdListApplyToWholeList, defaultlistbehavior:=wdWord9ListBehavior
        
        With .Selection
            .ParagraphFormat.Alignment = wdAlignParagraphLeft
            .TypeText ("some details")
            .TypeParagraph
            .TypeText ("some details")
            
        End With
        
    End With

output in MS Word:

Another example of Writing Tables to Microsoft Word

In this example we will create a word document with 20 paragraphs. Each paragraph will have a header with a header style element

    
   'In Tools > References, add reference to "Microsoft Word XX.X Object Library" before running.
    Dim wdApp As Word.Application
    Dim wdDoc As Word.Document

    Set wdApp = New Word.Application
    wdApp.Visible = True
    
    
    Dim x As Integer
    Dim y As Integer
    
    wdApp.Visible = True
    wdApp.Activate
    wdApp.Documents.Add
            
    wdApp.ActiveDocument.Tables.Add Range:=wdApp.Selection.Range, NumRows:=2, NumColumns:= _
        2, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitFixed
                
    With wdApp.Selection.Tables(1)
        If .Style <> "Table Grid" Then
            .Style = "Table Grid"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = False
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = False
        .ApplyStyleRowBands = True
        .ApplyStyleColumnBands = False
    End With
            
    With wdApp.Selection
        
        For x = 1 To 2
            ' set style name
            .Style = "Heading 1"
            .TypeText "Subject" & x
            .TypeParagraph
            .Style = "No Spacing"
            For y = 1 To 20
                .TypeText "paragraph text "
            Next y
            .TypeParagraph
        Next x
    
        ' new paragraph
        .TypeParagraph
        
        ' toggle bold on
        .Font.Bold = wdToggle
        .TypeText Text:="show some text in bold"
        .TypeParagraph
        
        'toggle bold off
        .Font.Bold = wdToggle
        .TypeText "show some text in regular front weight"
        .TypeParagraph
        
        
    End With
        
    

Some VBA vocabulary

TypeText

Inserts specified text at the beginning of the current selection. The selection is turned into an insertion point at the end of the inserted text.
If Options.ReplaceSelection = True then the original selection will be replaced. This behaves exactly the same as typing some text at the keyboard.

TypeParagraph

Insert a new blank paragraph. The selection is turned into an insertion point after the inserted paragraph mark. If Options.ReplaceSelection = True then the original selection will be replaced. This behaves exactly the same as pressing the Enter key.

output in MS Word:

Generating a Word table with VBA
	'In Tools > References, add reference to "Microsoft Word XX.X Object Library" before running.

	Dim wdApp As Word.Application
	Dim wdDoc As Word.Document
	Dim r As Integer

	Set wdApp = CreateObject("Word.Application")
	wdApp.Visible = True

	Set wdDoc = wdApp.Documents.Add
	wdApp.Activate

	Dim wdTbl As Word.Table
	Set wdTbl = wdDoc.Tables.Add(Range:=wdDoc.Range, NumRows:=5, NumColumns:=1)

	With wdTbl

		.Borders(wdBorderTop).LineStyle = wdLineStyleSingle
		.Borders(wdBorderLeft).LineStyle = wdLineStyleSingle
		.Borders(wdBorderBottom).LineStyle = wdLineStyleSingle
		.Borders(wdBorderRight).LineStyle = wdLineStyleSingle
		.Borders(wdBorderHorizontal).LineStyle = wdLineStyleSingle
		.Borders(wdBorderVertical).LineStyle = wdLineStyleSingle
		
		For r = 1 To 5
			.Cell(r, 1).Range.Text = ActiveSheet.Cells(r, 1).Value
		Next r
	End With

	

output in MS Word:

Option Explicit
Dim wdApp As Word.Application
 
Sub extractToWord()

   'In Tools > References, add reference to "Microsoft Word 12 Object Library" before running.
   
    Dim lastCell
    Dim rng As Range
    Dim row As Range
    Dim cell As Range
    Dim arrayOfColumns
    arrayOfColumns = Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "")
    Dim thisRow As Range
    Dim thisCell As Range
    Dim myStyle As String
    
    ' get last cell in column B
    lastCell = getLastCell()
    
    Set rng = Range("B2:H" & lastCell)
    
    'iterate through rows
    For Each thisRow In rng.Rows
            
        'iterate through cells in row row
        For Each thisCell In thisRow.Cells

            If thisCell.Value = arrayOfColumns(thisCell.Column) Or thisCell.Value = "" Then
            ' do nothing
                ''frWriteLine thisCell.Value, "Normal"
                ''frWriteLine arrayOfColumns(thisCell.Column), "Normal"
                  If thisCell.Value = arrayOfColumns(thisCell.Column) Or thisCell.Value = "" Then
                  End If
                  
            Else
                myStyle = "Normal"
                Select Case thisCell.Column
                    Case 2
                        myStyle = "Heading 1"
                    Case 3
                        myStyle = "Heading 2"
                    Case 4
                        myStyle = "Heading 3"
                    Case Is > 5
                        myStyle = "Normal"
                    
                End Select
                    
                frWriteLine thisCell.Value, myStyle
            End If
        
        arrayOfColumns(thisCell.Column) = thisCell.Value
    
      Next thisCell
    Next thisRow
    
End Sub

Public Function getLastCell() As Integer

    Dim lastRowNumber As Long
    Dim lastRowString As String
    Dim lastRowAddress As String
         
    With ActiveSheet
        getLastCell = .Cells(.Rows.Count, 2).End(xlUp).row
    End With
    
End Function

Public Function frWriteLine(someData As Variant, myStyle As String)
    
    If wdApp Is Nothing Then
        
        Set wdApp = New Word.Application
        With wdApp
            .Visible = True
            .Activate
            .Documents.Add
        End With
            
    End If
    
    With wdApp
        
        With .Selection
            .ParagraphFormat.Alignment = wdAlignParagraphCenter
            .Style = myStyle
            .TypeText (someData)
            .TypeParagraph
        End With
    End With
    
End Function

output in MS Word:

In this article, we will see how to access the various word objects using VBA in Excel and insert data from Excel to Word. This has many practical applications such as when you have to fill out a form multiple times with data from Excel or when you have to create a Word document with the same structure but different data each time and so on.

Before we go through individual controls, first let us have a look at how to access a Word document in Excel.

Step 1: Get the name and path of the Word Document that you need to modify. We will use the GetOpenFilename command for that.

fileName = Application.GetOpenFilename(, , "Select the word Document")

Step 2: Check to see if Word is already running on the system.

Set oApp = GetObject(, "Word.Application")

If Word is not running already, then start it

If Err.Number &amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;gt; 0 Then
    Set oApp = CreateObject("Word.Application")
End If


Step 3:
Assign the selected Word file to a Word object so that we can access it.

Set oDoc = oApp.Documents.Open(fileName)
oApp.Visible = True

Now that we know how to access to the Word document, let us see how to access the various controls in Word. In each of the below examples, we will need to add the above code.

Example 1: Bookmarks

In this example, we will see how to insert data from Excel after a bookmark in Word. Let us assume you have a bookmark named “Table1” in Word, where you be inserting a table from Excel. So, for simplicity, we will name that range in Excel as “Table1”.

Step 1: Access the bookmark

Set oBkMrk = oApp.ActiveDocument.Bookmarks("Table1")

Step 2: Get the location where you want to insert the data

Set objRange = oBkMrk.Range.Characters.last ‘Position of the last character of the bookmark
objRange.Start = objRange.Start + 1 ‘We need to start pasting from the next character


Step 3:
Copy the table and paste it at that location

Range(“Table1”).Copy
objRange.PasteExcelTable False, False, False

The PasteExcelTable method takes 3 arguments: LinkedToExcel, WordFormatting, RTF. We have set them all to False. Once you run the code, the Word Document will look like this

Example 2: Text boxes

In Word, the only way to assign a name to a shape is by using VBA (in contrast to Excel where this can be done using the formula bar). Secondly, Word does not force shapes to have unique names. So, accessing a text box by its name is not a very good option. The approach we will follow is referring to shapes by their index position.

Note: We are referring to text box created using drawing controls (Insert tab)
In this example we will loop through all the text boxes in Word and modify their text.

Step 1: So, first loop through all the shapes in the Word document using the .Shapes collection
Step 2: Check if the shape is a textbox
Step 3: Manipulate the .TextFrame.TextRange.Text property, to copy text from Excel.

Dim str As String
Dim i As Integer
i = 1
For Each shp In oDoc.Shapes
    If shp.Type = msoTextBox Then
        str = ThisWorkbook.Sheets("Sheet1").Cells(i, 1).Value
        shp.TextFrame.TextRange.Text = str
        i = i + 1
    End If
Next

Here the excel values we are using are in column A, and i is used as the counter to directly access column A rows from the Excel. This is how the output will look:

Example 3: Content control Text box from Developer tab

For this we will be using the Title property of a textbox to access it. The title can be set using the properties option of a textbox from the Developer Tab. The code is very similar to that in example 2

    For Each cc In oDoc.ContentControls
        If cc.Title = "Text1" Then
            cc.Range.Text = "Hello World!"
            Exit For
        End If
    Next cc

For multiple textboxes, you can match the title of the text box to the corresponding range in Excel and easily loop through.

Example 4: Headers and Footers

This code will add Headers and Footers on all the pages of Section 1 of the Word Document. The text can easily be taken from an Excel file.

With oDoc.Sections(1)
    .Headers.Item(1).Range.Text = "Header text"
    .Footers.Item(1).Range.Text = "Footer text"
End With

Here is how the header and footer will look like.


And here’s all the above code put together for easy reference:

Sub copyToWord()

Dim oApp        As Object 'Word.Application
Dim oDoc        As Object 'Word.Document
Dim sDocName    As String
Dim path        As String
Dim fileName    As String
Dim noOfFields  As Integer
Dim varName     As String
Dim wb

fileName = Application.GetOpenFilename(, , "Select the word Document")
Set wb = ThisWorkbook

On Error Resume Next
    Set oApp = GetObject(, "Word.Application") 'See if word is already running
    If Err.Number &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; 0 Then     'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If

On Error GoTo Error_Handler_Exit
    Set oDoc = oApp.Documents.Open(fileName)
    oApp.Visible = True

'Bookmarks
Set oBkMrk = oApp.ActiveDocument.Bookmarks("Table1")

Set objRange = oBkMrk.Range.Characters.last
objRange.Start = objRange.Start + 1

Range("Table1").Copy
objRange.PasteExcelTable False, False, False

'Textbox
Dim str As String
Dim i
i = 1

For Each shp In oDoc.Shapes
    If shp.Type = msoTextBox Then
        str = ThisWorkbook.Sheets("Sheet1").Cells(i, 1).Value
        shp.TextFrame.TextRange.Text = str
        i = i + 1
    End If
Next

'Textbox Content Control
    For Each cc In oDoc.ContentControls
        If cc.Title = "Text1" Then
            cc.Range.Text = "Hello World!"
            Exit For
        End If
    Next cc

'Headers and Footers
With oDoc.Sections(1)
    .Headers.Item(1).Range.Text = "Header goes here"
    .Footers.Item(1).Range.Text = "Footer goes here"
End With

oDoc.Save

Error_Handler_Exit:
    On Error Resume Next
    Set oDoc = Nothing
    Set oApp = Nothing
    Exit Sub

Error_Handler:
    MsgBox "The following error has occured." &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; vbCrLf &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; vbCrLf &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; _
           "Error Number: " &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; Err.Number &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; vbCrLf &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; _
           "Error Source: UpdateDoc" &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; vbCrLf &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; _
           "Error Description: " &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; Err.Description, _
           vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit

End Sub

Sub ExcelRangeToWord()

‘PURPOSE: Copy/Paste An Excel Table Into a New Word Document
‘NOTE: Must have Word Object Library Active in Order to Run _
  (VBE > Tools > References > Microsoft Word 12.0 Object Library)

‘SOURCE: www.TheSpreadsheetGuru.com

Dim tbl As Excel.Range
Dim WordApp As Word.Application
Dim myDoc As Word.Document
Dim WordTable As Word.Table

‘Optimize Code
  Application.ScreenUpdating = False
  Application.EnableEvents = False

‘Copy Range from Excel
  Set tbl = ThisWorkbook.Worksheets(Sheet1.Name).ListObjects(«Table1»).Range

‘Create an Instance of MS Word
  On Error Resume Next

        ‘Is MS Word already opened?
      Set WordApp = GetObject(class:=»Word.Application»)

        ‘Clear the error between errors
      Err.Clear

    ‘If MS Word is not already open then open MS Word
      If WordApp Is Nothing Then Set WordApp = CreateObject(class:=»Word.Application»)

        ‘Handle if the Word Application is not found
      If Err.Number = 429 Then
        MsgBox «Microsoft Word could not be found, aborting.»
        GoTo EndRoutine
      End If

  On Error GoTo 0

  ‘Make MS Word Visible and Active
  WordApp.Visible = True
  WordApp.Activate

    ‘Create a New Document
  Set myDoc = WordApp.Documents.Add

  ‘Copy Excel Table Range
  tbl.Copy

‘Paste Table into MS Word
  myDoc.Paragraphs(1).Range.PasteExcelTable _
    LinkedToExcel:=False, _
    WordFormatting:=False, _
    RTF:=False

‘Autofit Table so it fits inside Word Document
  Set WordTable = myDoc.Tables(1)
  WordTable.AutoFitBehavior (wdAutoFitWindow)

   EndRoutine:
‘Optimize Code
  Application.ScreenUpdating = True
  Application.EnableEvents = True

‘Clear The Clipboard
  Application.CutCopyMode = False

End Sub

In this part of the code we are determining if Microsoft Word is open or not.  If Word is already open, we can set a variable equal to the entire program by using GetObject.  If MS Word is not currently running we can use CreateObject to run an instance of Word and then set a variable equal to that specific instance of MS Word.

When using CreateObject, the target application will start running but it is not visible on screen.  Therefore we need to turn the Visible setting on (equal to true).  Also, VBA with Word is a little bit different than with Excel in that it is much more dependent on its window showing on screen.  Therefore a second command must be written to Activate Microsoft Word.

Copy From Excel, Paste Onto Document

Now that you have a new document created, you can command Excel to paste your table into MS Word.  Near the beginning of the code, there was a line that allowed you to specify the exact table you wanted to copy.  The variable tbl was used to remember this table range and to allow you to reference the range later on in the code.  

Guru Tip: It is a good idea to place code that may need to be manually changed at some point in the future near the beginning of the subroutine.  This prevents you from having to scroll through your code and pinpoint the exact place where you spelled out which range you wanted to copy or which worksheet you wanted to pull data from.  This can save you a bunch of time and prevent confusion!

Word has a special method called PasteExcelTable, which (as you can guess) allows you paste in an Excel table.  There are three variables you can tweak to get you table looking and functioning just the way you want.

  • LinkedToExcel True links the pasted table to the original Excel file so that changes made to the Excel file are reflected in Microsoft Word.

  • WordFormatting True formats the table using the formatting in the Word document.  False formats the table according to the original Excel file.

  • RTF True pastes the Excel table using Rich Text Format (RTF).  False pastes the Excel table as HTML.

Now for the last step!  Depending on how large your table is, it may be spilling outside of your document page.  In order to prevent this from happening you can go ahead and use AutoFitBehavior to resize the table to fit perfectly inside your Word document.

About The Author

Hey there! I’m Chris and I run TheSpreadsheetGuru website in my spare time. By day, I’m actually a finance professional who relies on Microsoft Excel quite heavily in the corporate world. I love taking the things I learn in the “real world” and sharing them with everyone here on this site so that you too can become a spreadsheet guru at your company.

Through my years in the corporate world, I’ve been able to pick up on opportunities to make working with Excel better and have built a variety of Excel add-ins, from inserting tickmark symbols to automating copy/pasting from Excel to PowerPoint. If you’d like to keep up to date with the latest Excel news and directly get emailed the most meaningful Excel tips I’ve learned over the years, you can sign up for my free newsletters. I hope I was able to provide you with some value today and I hope to see you back here soon!

— Chris
Founder, TheSpreadsheetGuru.com

Понравилась статья? Поделить с друзьями:
  • Visual basic for excel range
  • Visual basic excel все команды
  • Visual basic excel время
  • Visual basic excel адрес ячейки
  • Visual basic excel while not