Demo
Readme
Changelog
Releases RSS Feed
Compatibility : nodejs and browser

Summary (version 3.5.0) Buy subtemplate module

This module adds a tag to include the content of an other docx document (which can be a template itself). This allows you to define subtemplates if your templates share common parts.

This module is available as part of the docxtemplater PRO plan.

README

Subtemplate Module

This module exposes a tag to include subtemplate. The subtemplate is embeded into your document. Only the document content is embedded, footers and headers are not since they are unique for each document, so we use the headers/footers from your base template.

The styles of the resulting template should be the same as the styles from the template, which means that styles that exist in both the template and the included document will use the styles of the template itself. This means that if both your main template and your included document have Heading1, the style that will be applied to all Heading1 will be the style from the main template.

Installation:

You will need docxtemplater v3: npm install docxtemplater

Install this module with npm install --save "$url"

Usage

Your docx should contain the text: {:include subtemplate}.

In your data, the key subtemplate should be another docxtemplater instance.

You can then use the following code

const SubtemplateModule = require("docxtemplater-subtemplate-module");
const subtemplateModule = new SubtemplateModule({});

const headerZip = new JSZip(fs.readFileSync("header.docx"));
const footerZip = new JSZip(fs.readFileSync("footer.docx"));
const headerDoc = new Docxtemplater().loadZip(headerZip);
const footerDoc = new Docxtemplater().loadZip(footerZip);

const zip = new JSZip(fs.readFileSync("template.docx"));
const doc = new Docxtemplater().loadZip(zip);
doc.attachModule(subtemplateModule);
doc.setData({
    subtemplate: headerDoc,
    footer: footerDoc
});

doc.render();

In the browser

<html>
    <script src="node_modules/docxtemplater/build/docxtemplater.js"></script>
    <script src="node_modules/jszip/dist/jszip.js"></script>
    <script src="node_modules/jszip/vendor/FileSaver.js"></script>
    <script src="node_modules/jszip-utils/dist/jszip-utils.js"></script>
    <script src="build/subtemplate-module.js"></script>
    <script>
        function loadDocument(file) {
            return new Promise(function(resolve, reject) {
                JSZipUtils.getBinaryContent(file, function(error, content) {
                    if (error) {
                        return reject(errror);
                    }
                    resolve(content);
                });
            });
        }

        Promise.all([
            loadDocument("demo_template.docx"),
            loadDocument("examples/demo_header.docx"),
            loadDocument("examples/demo_footer.docx")
        ])
            .then(function(documents) {
                var doc = new docxtemplater().loadZip(new JSZip(documents[0]));
                doc.attachModule(new DocxtemplaterSubtemplateModule());
                var headerDoc = new docxtemplater().loadZip(
                    new JSZip(documents[1])
                );
                var footerDoc = new docxtemplater().loadZip(
                    new JSZip(documents[2])
                );
                doc.setData({
                    header: headerDoc,
                    footer: footerDoc
                });
                doc.render();
                var out = doc.getZip().generate({
                    type: "blob",
                    mimeType:
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                });
                saveAs(out, "generated.docx");
            })
            .catch(function(err) {
                console.log("error while loading documents");
                console.log(err);
            });
    </script>
</html>

After installing the module, you can use a working demo by running node sample.js.

Subtemplate Rendering

You can render the values in your subtemplate by using a custom parser and render the document with the current scope.

For example :

doc.setOptions({
    parser: function recursiveParser(tagString) {
        return {
            get(scope, data) {
                const isIncludeTag =
                    data &&
                    data.meta &&
                    data.meta.part &&
                    data.meta.part.module === "pro-xml-templating/include";
                let value = null;
                if (tagString === ".") {
                    value = scope;
                } else {
                    value = expressions.compile(tagString)(scope);
                }
                if (isIncludeTag && value) {
                    value.setData(scope);
                    value.render();
                }
                return value;
            }
        };
    }
});

Subsections

It is possible to include subsections, however, if you only have access to the subtemplate module, the headers will not be included.

If you have access to the subsection module, you can do the following to also include the headers of the included subsections :

const SubtemplateModule = require("docxtemplater-subtemplate-module");
const SubSectionModule = require("docxtemplater-subsection-module");
doc.attachModule(new SubtemplateModule({ subsection: new SubSectionModule() }));

When using the SubSectionModule with the SubtemplateModule, by default, the section where your tag {:include doc} is kept, meaning that it will create a new page before adding the document, and also at the end of the included document, it will include a pagebreak.

If you would prefer to not have this pagebreak, than the currentsubsection of the document is going to be replaced by the one from the subtemplate. To do this, you have two options :

var includedDoc = new Docxtemplater();
includedDoc.loadZip(new JSZip(includedContent));
includedDoc.replaceFirstSection = true;
includedDoc.replaceLastSection = true;

doc.setData({ included: includedDoc });

CHANGELOG

3.5.0

  • Add numId from styles.xml so that numbering values are better copied

  • Include w:sdt tags in addition of w:p tags

3.4.8

  • Handle numeric style ids by using name for the comparison if the id exists.

3.4.7

  • Fix Memory Leak when including document containing many images.

3.4.6

  • Bugfix : add possibility to include image that is within a table

3.4.5

  • Update browser build to use XMLSerializer instead of xmldom

  • Use requiredAPIVersion

3.4.4

  • Move docxtemplater from devDependencies to dependencies

Explanation : On some versions of npm (notably 5.8.0), when having a package containing docxtemplater-subtemplate-module, the installation will generate a tree of node_modules that puts the module on a level where it has no access to docxtemplater. By explicitly asking it as a dependency, this issue is avoided.

3.4.3

Fix bug when using equations and including templates 2 levels deep (with parent.docx /son.docx and grand-son.docx which contains an equation).

3.4.2

  • Make module compatible with docxtemplater version 3.5 and below.

Explanation : Recently, the scopemananger API (internal API) has changed, this new version of the footnotes module makes the module work with both versions newer than 3.6 and older than 3.6 of docxtemplater.

3.4.1

Add support for adding arrays of subtemplates with subsections.

When using the SubsectionModule, make it possible to replace the first section of the including document and replace the last section of the included document (this avoids additional pagebreaks).

3.4.0

Add support for adding subsections with headers by using subsection module.

3.3.0

Add possibility to add sections from subdocument if .includeSections is true

3.2.5

Add meta context argument to custom parser with information about the tag for each types of tags

3.2.4

Add support for including documents with pagebreaks

3.2.3

Fix corruption when including equations

3.2.2

Add support for including charts refering to Excel documents

3.2.1

Add support for including documents containing Excel documents (OLEObjects)

3.2.0

Add support for including documents containing comments

3.1.9

Avoid corruption when including multiple charts with subtemplates

3.1.8

Bugfix corruption when including document with chart

3.1.7

Add support for including documents containing charts

3.1.6

Remove error getElementsByTagName when word/numbering.xml doesn't exist in main document

3.1.5

Fix bug when subtemplate contains list coming from an other module (HTML)

3.1.4

Images in the subtemplate when there are already some images in the headers does not cause a corruption anymore.

3.1.3

Links in the subtemplate are now handled correctly

3.1.2

Fix corruption on some word version because of duplicate styles

3.1.1

Add support for lists in subtemplates (ordered lists and unordered lists).

3.1.0

Import styles in the case when the included document defines some styles.

3.0.1

Handle images importing

3.0.0

Initial release

Edgar Hipp

I'm the creator of docxtemplater. I work on making docxtemplater great since 2013.