Danny Brown

A Blog on Code and Occasionally Other Things

Populating Merge Fields in a Word Document Using Python

Danny BrownDecember 26, 2018

Last time, we covered adding merge fields to a Word document and using Python to get the names of all merge fields across multiple documents. If you need a refresher, check it out. Otherwise, let’s get to it.

Setting Up

We previously wrote a function that returns a list of all the merge fields from all .docx documents in the current directory. Let’s adjust this function slightly to instead allow the user to indicate which document to populate with data. Don’t forget to pip install docx-mailmerge if you didn’t do that last time.

import mailmerge

def get_merge_fields_from_a_specific_document():
    doc_name = raw_input("Populate which document? ")
    with mailmerge.MailMerge(doc_name+".docx") as document:
        results = list(document.get_merge_fields())
    results.insert(0, doc_name)
    return results

This function could be improved by printing the available .docx files in the directory (maybe [f for f in os.listdir('.') if os.path.isfile(f) and ".docx" in f]?) or adding error handling, but right now we’re just setting up, so let’s keep it simple. The line results.insert(0, doc_name) puts the name of the user-selected document as the first item in the returned list. We’re going to need this info later.

We’ll use the same documents we used last time:

doc1.docx

doc2.docx

This means that the user can input either “doc1” or “doc2” in the above function without throwing an error. doc1 thus returns ['doc1', 'CityStateZip', 'Name', 'Address'] and doc2 returns ['doc2', 'PurchasePrice', 'ShipDate', 'InvoiceNumber'].

Populating Our Document

So now what? We need to get the data we want to put into the document from the user, then actually merge that data into the document. One function can handle all of this:

import os

def generate_document(merge_fields):
    # Get absolute path of document we are generating
    file_dir = os.path.dirname(__file__) # get path to current directory
    doc_name = merge_fields.pop(0) # pop off name of document from list
    file_name = doc_name + ".docx" # add .docx extension to document name
    absolute_path = os.path.join(file_dir, file_name) # boom, absolute path
    
    # Get the data that we are going to be merging from the user
    # Put data in a dictionary for merging
    merge_data = {} # create an empty dictionary to hold the merge data
    for item in merge_fields:
        merge_data[item] = raw_input("What is the %s? " % item)
        # For each merge field, add it as a key and get value from user

    # Merge our data into the document
    document = mailmerge.MailMerge(absolute_path) # create a mailmerge object
    document.merge(**merge_data) # use the merge function with ** and our dict
    output_path = os.path.join(file_dir, "GeneratedDocument.docx")
    document.write(output_path) # write the document to the path we specified

See how easy it is? Note that we need our data to be in a dictionary, then the money line is document.merge(**merge_data), which does all the work for us of inserting the data from our dictionary into the document. We need to use the document.write() to actually save our new document as well.

That’s it! Building out what we’ve done in the last two posts, it should be easy to write a simple script to accept user input and output it into a merged .docx file. If you have any questions, feel free to post below.

Posted In code | Python

Post navigation

PreviousCollecting Merge Field Names from Multiple Word Documents Using Python
NextImplementing Search Functionality into a Django Site

Danny Brown

A Dev Blog with Some Tangents

About

Categories

  • code
    • APIs
    • Bash
    • CSS
    • Django
    • HTML
    • JavaScript
    • Python
    • S3
    • Selenium
    • Serverless
    • TypeScript
  • games
  • music
    • concert reviews
    • synthesizers
  • opinion
  • sports
  • tech
    • Bitbucket
    • Git
    • GitHub
    • MS Teams
    • WordPress
  • theater

Recent Posts

  • Open Pull Requests from the Terminal (One of My Favorite Dotfiles Scripts)
  • Dotfiles Script for a New TypeScript/Node Project
  • So I Told You to Go See a Broadway Play? Tips for Theater in New York
  • Build a Simple Microsoft Teams Bot Easily, No SDK Required
  • Creating a GUI for Conway’s Game of Life Using Pygame and Numpy

External Links

  • GitHub
  • LinkedIn

Recent Posts

  • Open Pull Requests from the Terminal (One of My Favorite Dotfiles Scripts)
  • Dotfiles Script for a New TypeScript/Node Project
  • So I Told You to Go See a Broadway Play? Tips for Theater in New York
  • Build a Simple Microsoft Teams Bot Easily, No SDK Required
  • Creating a GUI for Conway’s Game of Life Using Pygame and Numpy

Categories

  • code
    • APIs
    • Bash
    • CSS
    • Django
    • HTML
    • JavaScript
    • Python
    • S3
    • Selenium
    • Serverless
    • TypeScript
  • games
  • music
    • concert reviews
    • synthesizers
  • opinion
  • sports
  • tech
    • Bitbucket
    • Git
    • GitHub
    • MS Teams
    • WordPress
  • theater
Copyright © 2025. Danny Brown
Powered By WordPress and Meritorious