DEV Community

Cover image for Create .docx files with Vue.js
Omar Saúl Morales Ibarra
Omar Saúl Morales Ibarra

Posted on • Edited on

Create .docx files with Vue.js

Recently I've been working in a web based aplication (front-end using Vue.js) which final result is a detailed report. Everything was great, but when I share the final result with the owners of the aplication they thought that it would be awesome if they were able to download all this information into a .docx document with some kind of format. I had never done anything like this before, but I thought it should not be so difficult. So I started digging into the web looking for some javascript tool that could help me solve this requirement, so I found docx, a great tool to easily generate .docx files with JS/TS with a solid API.
You are able to use docx with any Javascript library (React.js, Angular, Vue.js), but this time I want to share my experience using it with Vue.js so if someone is in the same situation that I was can use this post as reference. Without more to say, let's start!

First you have to install docx and FileSaver.js (solution to saving files on the client-side) in your component. I used npm but you can use yarn or whatever you want.

  npm install --save docx file-saver
Enter fullscreen mode Exit fullscreen mode

Then import the packages to your component like this:

  <script>
  import { WidthType, BorderStyle, Document, Paragraph, Packer, TextRun } 
  from "docx";
  import { saveAs } from 'file-saver';
  export default {
    components: {
      Document, Paragraph, Packer, TextRun, saveAs, BorderStyle, WidthType
    },
    data: () => ({

    }),
    methods: {

    },
    created(){

    }
  }
 </script>
Enter fullscreen mode Exit fullscreen mode

After that, you create a method so when the user click a button the .docx file is automatically generated.

  <template>
  <div class="btn btn-link float-right" @click="exportDocx">
    <i class="far fa-file-word"></i>
    Generate .docx file
  </div>

  </template>
  <script>
  import { WidthType, BorderStyle, Document, Paragraph, Packer, TextRun } 
  from "docx";
  import { saveAs } from 'file-saver';
  export default {
    components: {
      Document, Paragraph, Packer, TextRun, saveAs, BorderStyle, WidthType
    },
    data: () => ({
      state: {
        name: 'San Luis Potosi'
      } 
    }),
    methods: {
      // Create a new Document an save it in a variable
      let doc = new Document();

      // Add paragraph in the document
      let title = new Paragraph(`Detailed Report for ${this.state.name}`).title().center();

      // To export into a .docx file
      let packer = new Packer();

      packer.toBlob(doc).then(blob => {
        saveAs(blob, "detailed_report.docx");

         // using sweet alert for notification
         toast({
          type: 'success',
          title: 'Document created!'
         })
      });

    },
    created(){

    }
  }
 </script>
Enter fullscreen mode Exit fullscreen mode

docx allows you to add text, images, tables, bullet points, numbering and more...
In my case I used text for titles, headings and content; added a base64 image; bullet points to organize data and tables, so I'll give you an example of how to create a document with this resources and if you need something a little more complex you can always check the documentation for more info.

  <template>
  <div class="btn btn-link float-right" @click="exportDocx">
    <i class="far fa-file-word"></i>
    Generate .docx file
  </div>

  </template>
  <script>
  import { WidthType, BorderStyle, Document, Paragraph, Packer, TextRun } 
  from "docx";
  import { saveAs } from 'file-saver';
  export default {
    components: {
      Document, Paragraph, Packer, TextRun, saveAs, BorderStyle, WidthType
    },
    data: () => ({
      state: {
        name: 'San Luis Potosi',
        map: 'data:image/png;base64',
        municipalities: [
          {name:'San Luis Potosi', population: 824000}, 
          {name:'Rio Verde', population: 160000},
          {name:'Cd Valles', population: 176000},
          {name:'Matehuala', population:82726}
        ],
        tourist_attractions: [
          'Tamtoc', 'Sótano de las Golondrinas', 'Cascada de Tamul' 
        ]
      }
    }),
    methods: {
      // Create a new Document an save it in a variable
      let doc = new Document();

      // Add paragraph in the document
      doc.addParagraph(new Paragraph(`Detailed Report for ${this.state.name}`).title().center());

      // Add heading for map
      doc.addParagraph(new Paragraph(`State Map`).heading1().thematicBreak().center());

      // Add map image
      doc.createImage(this.state.map, 600, 250, {});

      // Add heading for attractions
      doc.addParagraph(new Paragraph(`Tourist Attractions`).heading1().thematicBreak().center());

      // Bullet points
      for (let attraction of this.state.tourist_attractions) {
        doc.addParagraph(new Paragraph(attraction).bullet());
      }

      // Add heading for municipalities
      doc.addParagraph(new Paragraph(`Municipalities`).heading1().thematicBreak().center());

      // Create table
      let municipalities_table = doc.createTable({
        rows: this.state.municipalities.length+1,
        columns: 2,
        width: 100,
        widthUnitType: WidthType.AUTO,
        columnWidths: [2934, 2934],
      });
      municipalities_table.getCell(0, 0).addParagraph(new Paragraph("Name"));
      municipalities_table.getCell(0, 1).addParagraph(new Paragraph("Population"));

      for (let [index, municipality] of this.state.municipalities.entries()) {
        municipalities_table.getCell(index+1, 0).addParagraph(new Paragraph(municipality.name));
        municipalities_table.getCell(index+1, 1).addParagraph(new Paragraph(municipality.population));
      }

      // To export into a .docx file
      let packer = new Packer();

      packer.toBlob(doc).then(blob => {
        saveAs(blob, "detailed_report.docx");

         // using sweet alert for notification
         toast({
          type: 'success',
          title: 'Document created!'
         })
      });

    },
    created(){

    }
  }
 </script>
Enter fullscreen mode Exit fullscreen mode

And that's it, a simple yet powerful component to create .docx files when a user clicks a button.

Really hope this post is usefull, if so, please share and tell me if you know another way to do this, till the next post.

Top comments (3)

Collapse
 
jonathanwexler profile image
Jonathan Wexler

I'm working on getting something similar working. As it stands, the post you published above does not have working code. Do you have a codepen or link to github with working code? Are you able to run the code above successfully?

Collapse
 
omarmorales profile image
Omar Saúl Morales Ibarra

The project where I use this code is private, but I'll take some time to create a pen and update this post. Greetings

Collapse
 
juanzeta33 profile image
Juan Antonio Zamora Arosemena

Hi, Excelent post, I use it and work fine!
I have an extra question I cant found in the documentation.

There is a way to create legal size docx with this dependencie?

Thanks!