user10391869
user10391869

Reputation: 241

how can I export react to word document

I have a React app and I want to export some html content to word document and download it. for example:

<div> Hello World!!!</div>
<input type="button" onClick={exportToWord()}/>

I search for a function that will handle a word document with the text Hello world!!!.

Upvotes: 6

Views: 21099

Answers (4)

Jasper
Jasper

Reputation: 160

I faced the same problem recently: I wanted to export some JSX pages in my React App to a Word document, and spent a long time looking up various solutions online for it.

Demo: button on the lower right

Published as an NPM package here

In the end, I did it by tweaking a jQuery plugin called jQuery-Word-Export. This has been tested on Microsoft Word for Mac.

As explained in the ReadMe, the basic idea behind the plugin is this:

“This plugin takes advantage of the fact that MS Word can interpret HTML as a document. Specifically, this plugin leverages the MHTML archive format in order to embed images directly into the file, so they can be viewed offline.”

For a more in-depth discussion, see here. In short, the user gets a "Single File Web Page", which they can open and edit with Microsoft Word (as though it is an ordinary .doc or .docx file).

In terms of implementation, I first collected all the pages I wanted to convert to Word with React.forwardRef,

export const ComponentToPrint = 
React.forwardRef((props, ref) => {
  return (
    <div ref={ref}>
      <NoticeOfMotion />
      <br className="pagebreak"></br>
      <AffidavitOfApplicant />
      <br className="pagebreak"></br>
      <AffidavitOfIdentity />
      <br className="pagebreak"></br>
      <CoverLetters />
    </div>
  );
});

I then tweaked the jQuery plugin and replaced jQuery specific syntax with ordinary Javascript,

import { TailwindStyles } from "../helper/TailwindStyles.html";
import { saveAs } from "file-saver";

export function exportHTML(sourceRef) {
  const sourceHTML = sourceRef.current.innerHTML;

  var statiC = {
    mhtml: {
      top:
      /* eslint-disable */
        "Mime-Version: 1.0\nContent-Base: " +
        location.href +
        '\nContent-Type: Multipart/related; boundary="NEXT.ITEM-BOUNDARY";type="text/html"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset="utf-8"\nContent-Location: ' +
        location.href +
        "\n\n<!DOCTYPE html>\n<html>\n_html_</html>",
      head: '<head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n<style>\n_styles_\n</style>\n</head>\n',
      body: "<body>_body_</body>",
    },
  };

  // Clone selected element before manipulating it
  var markup = sourceHTML


  // Prepare bottom of mhtml file with image data
  var mhtmlBottom = "\n";
  mhtmlBottom += "--NEXT.ITEM-BOUNDARY--";

  var styles = TailwindStyles;

  // Aggregate parts of the file together
  var fileContent =
    statiC.mhtml.top.replace(
      "_html_",
      statiC.mhtml.head.replace("_styles_", styles) +
        statiC.mhtml.body.replace("_body_", markup),
    ) + mhtmlBottom;

  // Create a Blob with the file contents
  var blob = new Blob([fileContent], {
    type: "application/msword;charset=utf-8",
  });
  saveAs(blob, `Barrister Admission Bundle(beta).doc`);
}

Finally I wired them up in my "Enter Information" page like so,

<div className="hidden">
<ComponentToPrint ref={sourceRef} id="source-html" />
</div>
<div>
  <button
    onClick={() => exportHTML(sourceRef)}>
      Download as Word.doc file
  </button>
</div>

The result is that if you click the button on the lower right here, you should get a file with a .doc prefix, which Microsoft Word for Mac should open by default with Word. You can also edit it and save it as though it is an ordinary Word document.

For completeness, the solutions proposed by the others above didn't work for me.

redocx is solving the problem I want to solve. But when I run the demo on the machine, I get this warning,

"Word found unreadable content in HelloWorld.docx. Do you want to recover the contents of this document? If you trust the source of this document, click Yes."

I also cannot edit and save the Word document without altering the format.

As for docx, that tool seems to be solving a different problem. You need to write the React components following some specific rules in order for the formatting to work on Word.

But I take it the nub of this question is how to convert export HTML+CSS (i.e. not specifically written for docx npm package or other tools) as a (reasonably styled) Word document.

The tutorial in https://www.codexworld.com/export-html-to-word-doc-docx-using-javascript/ is trying to solve the right problem. But for Microsoft Word for Mac it did not succeed in producing a document that can be edited with Word and then successfully saved. An error message appears and the user needs to save in an alternative format.

A further alternative tool that I initially investigated is pandoc-server. An impressive demo is here.

But according to its docs, pandoc-server needs to work in a server, where I need to use the executable of pandoc-server (which should be a binary file) as a CGI (common gateway interface) file.

This is quite involved, especially if it is originally not intended to set up a server for the task.

Upvotes: 0

Lojith Vinsuka
Lojith Vinsuka

Reputation: 1051

Check this out https://www.codexworld.com/export-html-to-word-doc-docx-using-javascript/

 function Export2Word(filename = "") {
    var preHtml =
      "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head><meta charset='utf-8'><title>Export HTML To Doc</title></head><body>";
    var postHtml = "</body></html>";

    var html = preHtml + dom + postHtml;

    var blob = new Blob(["\ufeff", html], {
      type: "application/msword",
    });

    // Specify link url
    var url =
      "data:application/vnd.ms-word;charset=utf-8," + encodeURIComponent(html);

    // Specify file name
    filename = filename ? filename + ".doc" : "document.doc";

    // Create download link element
    var downloadLink = document.createElement("a");

    document.body.appendChild(downloadLink);

    // Create a link to the file
    downloadLink.href = url;

    // Setting the file name
    downloadLink.download = filename;

    //triggering the function
    downloadLink.click();

    document.body.removeChild(downloadLink);
}

Upvotes: 0

aryehrein
aryehrein

Reputation: 29

You can use docx npm package

Here is a button onClick callback example:

async function exportToWord() {
    const doc = new Document({
        sections: [{
            properties: {},
            children: [
                new Paragraph({
                    children: [
                        new TextRun("Hello World")
                    ],
                 }),
            ],
         }]
    });
    const buffer = await Packer.toBuffer(doc);
    const blob = new Blob([buffer], {type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"});
    const link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = 'my.docx';
    link.click();
}

Upvotes: 2

ArunPratap
ArunPratap

Reputation: 5020

you can use redocx library for word documents with React you can install redocx by NPM

npm i redocx

this simple example will render Hello World in word doc

import React from 'react'
import { render, Document, Text } from 'redocx'

class App extends React.Component {
  render() {
    return (
      <Document>
        <Text>Hello World</Text>
      </Document>
    )
  }
}

render(<App />, `${__dirname}/example.docx`)

for Demo you can clone this repo and run locally

git clone https://github.com/nitin42/redocx.git
cd redocx
npm install
npm run example

you can find all documentation here redocx docs

Upvotes: 4

Related Questions