DEV Community

Iain Freestone
Iain Freestone

Posted on • Updated on • Originally published at iainfreestone.com

How to create a Word document with JavaScript

Introduction

Word documents are everywhere and are used for countless tasks so you may have a requirement to support their generation from within your web application or webpage, this could include downloading a C.V from your personal site to the generation of a report based on data from within your web application that can be printed out or emailed by your client.

Goals

Create and save a Word document using only client-side vanilla/plain JavaScript.

Prerequisites

In order to complete this example you should have some basic knowledge of HTML and JavaScript.

Step 1 - Setup project

In order to concentrate on the job in hand and to get up and running as quickly as possible we are going to use CodeSandbox and their vanilla starter project.

A new CodeSandbox project can be created by opening the following link vanilla JavaScript project.

Step 2 - Install dependencies needed to create a Word document

With the project setup we can now install the two modules/dependencies needed to successfully create and save a Word document. The first package (docx) allows you to build your Word document and the second package (file-saver) gives the ability to save the document locally.

Add the two packages using the "Add Dependency" button.

Step 3 - Add a button to create our Word document

Before we start writing the code required to generate our Word documents lets add a button to the index.html file. We can then use this button to fire off the actions needed to generate the Word document.

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app"></div>
    <button id="generate">Generate Word Document</button>
    <script src="src/index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Step 4 - Create a blank Word document

From now one we will be working solely within the index.js JavaScript file, lets start by deleting everything that is currently there as this is not need.

All we will need to create a blank word document is the Document and Packer features from the docx module and the saveAs feature from file-saver module.

import { Document, Packer } from "docx"
import { saveAs } from "file-saver"
Enter fullscreen mode Exit fullscreen mode

Next add an event listener that is listening for clicks on the button we created in Step 3.

// Listen for clicks on Generate Word Document button
document.getElementById("generate").addEventListener(
  "click",
  function(event) {
    generateWordDocument(event)
  },
  false
)
Enter fullscreen mode Exit fullscreen mode

Once the event listener is triggered we will call a function that will create a new instance of Document from the docx module and send this instance to a saveDocumentToFile function.

function generateWordDocument(event) {
  event.preventDefault()
  // Create a new instance of Document for the docx module
  let doc = new Document()
  // Call saveDocumentToFile with the document instance and a filename
  saveDocumentToFile(doc, "New Document.docx")
}
Enter fullscreen mode Exit fullscreen mode

The saveDocumentToFile function creates a new instance of Packer from the docx modules, Packers in docx are used to turn your JavaScript code into a .docx file. We then send our document instance to Packers toBlob function which in turn converts our instance of Document into a Blob object, a mimeType is added to the Blob and finally the Blob is sent to saveAs feature of the file-saver module which will create the file and prompt you to save or open.

function saveDocumentToFile(doc, fileName) {
  // Create new instance of Packer for the docx module
  const packer = new Packer()
  // Create a mime type that will associate the new file with Microsoft Word
  const mimeType =
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
  // Create a Blob containing the Document instance and the mimeType
  packer.toBlob(doc).then(blob => {
    const docblob = blob.slice(0, blob.size, mimeType)
    // Save the file using saveAs from the file-saver package
    saveAs(docblob, fileName)
  })
}
Enter fullscreen mode Exit fullscreen mode

Clicking the 'Generate Word Document' button will now create and save a blank Word document.

Step 5 - Create content of the Word document

We can now start adding some content to the Word document. We will simply add a title, subtitle, two headings and a long paragraph as this will make it easier to understand once we come to start styling the document.

function generateWordDocument(event) {
  event.preventDefault()
  let doc = new Document()
  doc.createParagraph("Title")
  doc.createParagraph("Subtitle")
  doc.createParagraph("Heading 1")
  doc.createParagraph("Heading 2")
  doc.createParagraph(
    "Aliquam gravida quam sapien, quis dapibus eros malesuada vel. Praesent tempor aliquam iaculis. Nam ut neque ex. Curabitur pretium laoreet nunc, ut ornare augue aliquet sed. Pellentesque laoreet sem risus. Cras sodales libero convallis, convallis ex sed, ultrices neque. Sed quis ullamcorper mi. Ut a leo consectetur, scelerisque nibh sit amet, egestas mauris. Donec augue sapien, vestibulum in urna et, cursus feugiat enim. Ut sit amet placerat quam, id tincidunt nulla. Cras et lorem nibh. Suspendisse posuere orci nec ligula mattis vestibulum. Suspendisse in vestibulum urna, non imperdiet enim. Vestibulum vel dolor eget neque iaculis ultrices."
  )
  saveDocumentToFile(doc, "New Document.docx")
}
Enter fullscreen mode Exit fullscreen mode

The Word document will now look something like this

Step 6 - Style the Word document

Now that we have some content we can look at styling the document.

Firstly we will create a theme object that will hold all the information about which fonts and colours we want to use.

function generateWordDocument(event) {
  event.preventDefault()
  // Create new instance of Document for the docx module
  let doc = new Document()
  doc.theme = {
    font: {
      normal: {
        family: "Calibri",
        color: "303856",
      },
      header: { family: "Calibri Light" },
    },
    title: {
      color: "4ABDAC",
    },
    headings: {
      one: {
        color: "FC4A1A",
      },
      two: {
        color: "F7B733",
      },
    },
  }
  ...
  ...
  // Call saveDocumentToFile withe the document instance and a filename
  saveDocumentToFile(doc, "New Document.docx")
}
Enter fullscreen mode Exit fullscreen mode

After creating the theme object we can start creating our styles. We will create 5 styles

  • Custom Heading 1
  • Custom Heading 2
  • Custom Title
  • Custom Subtitle
  • Custom Normal

These should tie up nicely to the content that we created in Step 5.

You can learn more about styles in Microsoft Word here

function generateWordDocument(event) {
  event.preventDefault()
  // Create new instance of Document for the docx module
  let doc = new Document()
  ...
  ...
  doc.Styles.createParagraphStyle("customHeading1", "Custom Heading 1")
    .basedOn("Heading 1")
    .next("Normal")
    .quickFormat()
    .font(doc.theme.font.header.family)
    .size(32)
    .bold()
    .color(doc.theme.headings.one.color)
    .spacing({ after: 250 })

  doc.Styles.createParagraphStyle("customHeading2", "Custom Heading 2")
    .basedOn("Heading 2")
    .next("Normal")
    .quickFormat()
    .font(doc.theme.font.header.family)
    .size(26)
    .bold()
    .color(doc.theme.headings.two.color)
    .spacing({ after: 150 })

  doc.Styles.createParagraphStyle("customTitle", "Custom Title")
    .basedOn("Title")
    .next("Normal")
    .quickFormat()
    .font(doc.theme.font.header.family)
    .size(56)
    .bold()
    .color(doc.theme.font.normal.color)
    .spacing({ after: 250 })

  doc.Styles.createParagraphStyle("customSubtitle", "Custom Subtitle")
    .basedOn("Subtitle")
    .next("Normal")
    .quickFormat()
    .font(doc.theme.font.header.family)
    .size(22)
    .color(doc.theme.font.normal.color)
    .spacing({ after: 150 })

  doc.Styles.createParagraphStyle("customNormal", "Custom Normal")
    .basedOn("Normal")
    .quickFormat()
    .font(doc.theme.font.normal.family)
    .size(20)
    .color(doc.theme.font.normal.color)
    .spacing({ after: 150 })
  ...
  ...
  // Call saveDocumentToFile withe the document instance and a filename
  saveDocumentToFile(doc, "New Document.docx")
}
Enter fullscreen mode Exit fullscreen mode

With our styles in place we can apply them to our content.

function generateWordDocument(event) {
  event.preventDefault()
  // Create new instance of Document for the docx module
  let doc = new Document()
  ...
  ...
  doc.createParagraph("Title").style("customTitle")
  doc.createParagraph("Subtitle").style("customSubtitle")
  doc.createParagraph("Heading 1").style("customHeading1")
  doc.createParagraph("Heading 2").style("customHeading2")
  doc
    .createParagraph(
      "Aliquam gravida quam sapien, quis dapibus eros malesuada vel. Praesent tempor aliquam iaculis. Nam ut neque ex. Curabitur pretium laoreet nunc, ut ornare augue aliquet sed. Pellentesque laoreet sem risus. Cras sodales libero convallis, convallis ex sed, ultrices neque. Sed quis ullamcorper mi. Ut a leo consectetur, scelerisque nibh sit amet, egestas mauris. Donec augue sapien, vestibulum in urna et, cursus feugiat enim. Ut sit amet placerat quam, id tincidunt nulla. Cras et lorem nibh. Suspendisse posuere orci nec ligula mattis vestibulum. Suspendisse in vestibulum urna, non imperdiet enim. Vestibulum vel dolor eget neque iaculis ultrices."
    )
    .style("customNormal")
  // Call saveDocumentToFile withe the document instance and a filename
  saveDocumentToFile(doc, "New Document.docx")
}
Enter fullscreen mode Exit fullscreen mode

Clicking the ‘Generate Word Document’ button now will create a Word document that look something like this

Conclusion

With the use of a couple of great packages we can easily create a nice looking Word document using solely client side JavaScript. Docx is very powerful and this article only covers the basics to get you up and running with a simple Word document.

Complete Example

A complete example of the code can be found here

Top comments (0)