Create .docx files with Vue.js

omarmorales

Omar Saúl Morales Ibarra

Posted on July 16, 2019

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.

💖 💪 🙅 🚩
omarmorales
Omar Saúl Morales Ibarra

Posted on July 16, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related