胖蔡叨叨叨
你听我说

使用docxjs实现前端的word生成

Docx 可以帮助我们实现ts/js代码生成*.docx文件的功能,它可以同时被运用于Node端和浏览器端。使用docx基本可以实现大多数Microsoft Word文档英文版的绝大数API操作,但由于Microsoft Word文档中英文版本的差异,对于中文版本的功能、属性控制还是得需要通过自定义xml的方式来实现。本篇文章简单介绍下如何使用docxjs实现word文档的生成。

2c26b65871ed768

可访问官网查看官方文档:https://docx.js.org/   。我始终坚持认为,官方文档是最能帮助开发者的。

安装

$ npm install -s docx

基本用法

import * as fs from "fs"; 
import { Document, Packer, Paragraph, TextRun } from "docx";

 // 文档类Document中包含章节数组sections,可向其中添加多个章节 
const doc = new Document({ 
      sections: [{ 
          properties: {}, 
          children: [ new Paragraph({ 
             children: [ new TextRun("Hello World"), 
                  new TextRun({ text: "Foo Bar", bold: true, }),
                  new TextRun({ text: "\tGithub is the best", bold: true, }), ], }), ], }], }); 

// 通过fs实现将docx从buffer流转化成*.docx文件

 Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); // 完成下载


通过上方的示例,可以发现docx将整个文档拆分成多个区域块,然后通过组合、包含区域块的方式实现文档的输出。下面,简单介绍下docx中常用的几个模块类。

Document

Document可以说是docx梦开始的地方。其实,我们也可以将其理解为docx文档本生。一个docx文档有且仅有一个document生成。可以通过如下方式生成一个基本的document对象。
const doc = new docx.Document();
document很重要,包含的属性有如下:
  • creator
  • description
  • title
  • subject
  • keywords
  • lastModifiedBy
  • revision
  • externalStyles
  • styles
  • numbering
  • footnotes
  • hyperlinks
  • background
  • sections
这里重点介绍externalStyles、styles。

externalStyles

这个属性对于我们的中文用户来说尤为重要,这或许也是docx作者考虑可能属性覆盖不全,所以特意留下的一个自定义属性样式的窗口。功能可以说是及其省事。我们完全可以通过解压docx文档,将其中的xml属性配置文件拿出来做些微的修改来实现我们的功能。大致就像下面这样。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:styles xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
    xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
    xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" mc:Ignorable="w14 w15">
    <w:docDefaults>
        <w:rPrDefault>
            <w:rPr>
                <w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi"/>
                <w:sz w:val="22"/>
                <w:szCs w:val="22"/>
                <w:lang w:val="en-GB" w:eastAsia="en-US" w:bidi="ar-SA"/>
            </w:rPr>
        </w:rPrDefault>
        <w:pPrDefault>
            <w:pPr>
                <w:spacing w:after="160" w:line="259" w:lineRule="auto"/>
            </w:pPr>
        </w:pPrDefault>
    </w:docDefaults>

 

    <w:style w:type="paragraph" w:default="1" w:styleId="Normal">
        <w:name w:val="Normal"/>
        <w:qFormat/>
        <w:rsid w:val="000D2D99"/>
        <w:rPr>
            <w:rFonts w:ascii="MV Boli" w:hAnsi="MV Boli"/>
            <w:color w:val="C45911" w:themeColor="accent2" w:themeShade="BF"/>
        </w:rPr>
    </w:style>

    <w:style w:type="paragraph" w:styleId="Heading1">
        <w:name w:val="heading 1"/>
        <w:basedOn w:val="Normal"/>
        <w:next w:val="Normal"/>
        <w:link w:val="Heading1Char"/>
        <w:uiPriority w:val="9"/>
        <w:qFormat/>
        <w:rsid w:val="000D2D99"/>
        <w:pPr>
            <w:keepNext/>
            <w:keepLines/>
            <w:spacing w:before="240" w:after="0"/>
            <w:outlineLvl w:val="0"/>
        </w:pPr>
        <w:rPr>
            <w:rFonts w:ascii="Impact" w:eastAsiaTheme="majorEastAsia" w:hAnsi="Impact" w:cstheme="majorBidi"/>
            <w:color w:val="538135" w:themeColor="accent6" w:themeShade="BF"/>
            <w:sz w:val="32"/>
            <w:szCs w:val="32"/>
        </w:rPr>
    </w:style>

    <w:style w:type="character" w:default="1" w:styleId="DefaultParagraphFont">
        <w:name w:val="Default Paragraph Font"/>
        <w:uiPriority w:val="1"/>
        <w:semiHidden/>
        <w:unhideWhenUsed/>
    </w:style>

    <w:style w:type="table" w:default="1" w:styleId="TableNormal">
        <w:name w:val="Normal Table"/>
        <w:uiPriority w:val="99"/>
        <w:semiHidden/>
        <w:unhideWhenUsed/>
        <w:tblPr>
            <w:tblInd w:w="0" w:type="dxa"/>
            <w:tblCellMar>
                <w:top w:w="0" w:type="dxa"/>
                <w:left w:w="108" w:type="dxa"/>
                <w:bottom w:w="0" w:type="dxa"/>
                <w:right w:w="108" w:type="dxa"/>
            </w:tblCellMar>
        </w:tblPr>
    </w:style>

    <w:style w:type="table" w:customStyle="1" w:styleId="MyCustomTableStyle">
        <w:name w:val="My Custom TableStyle"/>
        <w:uiPriority w:val="99"/>
        <w:rsid w:val="00C36BA2"/>
        <w:pPr>
            <w:spacing w:after="0" w:line="240" w:lineRule="auto"/>
        </w:pPr>
        <w:rPr>
            <w:rFonts w:ascii="Comic Sans MS" w:hAnsi="Comic Sans MS"/>
            <w:szCs w:val="20"/>
            <w:lang w:val="en-US"/>
        </w:rPr>

        <w:tcPr>
            <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
        </w:tcPr>

        <w:tblStylePr w:type="firstRow">

            <w:rPr>
                <w:b/>
                <w:bCs/>
                <w:color w:val="FFFFFF" w:themeColor="background1"/>
            </w:rPr>

            <w:tblPr/>

            <w:tcPr>
                <w:tcBorders>
                    <w:tl2br w:val="none" w:sz="0" w:space="0" w:color="auto"/>
                    <w:tr2bl w:val="none" w:sz="0" w:space="0" w:color="auto"/>
                </w:tcBorders>
                <w:shd w:val="clear" w:color="auto" w:fill="4472C4" w:themeFill="accent1"/>
            </w:tcPr>

        </w:tblStylePr>

    </w:style>

    <w:style w:type="numbering" w:default="1" w:styleId="NoList">
        <w:name w:val="No List"/>
        <w:uiPriority w:val="99"/>
        <w:semiHidden/>
        <w:unhideWhenUsed/>
    </w:style>

    <w:style w:type="paragraph" w:customStyle="1" w:styleId="CustomStyle">
        <w:name w:val="Custom Style"/>
        <w:basedOn w:val="Normal"/>
        <w:link w:val="CustomStyleChar"/>
        <w:rsid w:val="00B557A5"/>
        <w:rPr>
            <w:sz w:val="72"/>
        </w:rPr>
    </w:style>

    <w:style w:type="character" w:customStyle="1" w:styleId="CustomStyleChar">
        <w:name w:val="Custom Style Char"/>
        <w:basedOn w:val="DefaultParagraphFont"/>
        <w:link w:val="CustomStyle"/>
        <w:rsid w:val="00B557A5"/>
        <w:rPr>
            <w:rFonts w:ascii="MV Boli" w:hAnsi="MV Boli"/>
            <w:color w:val="C45911" w:themeColor="accent2" w:themeShade="BF"/>
            <w:sz w:val="72"/>
        </w:rPr>
    </w:style>

    <w:style w:type="character" w:customStyle="1" w:styleId="Heading1Char">
        <w:name w:val="Heading 1 Char"/>
        <w:basedOn w:val="DefaultParagraphFont"/>
        <w:link w:val="Heading1"/>
        <w:uiPriority w:val="9"/>
        <w:rsid w:val="000D2D99"/>
        <w:rPr>
            <w:rFonts w:ascii="Impact" w:eastAsiaTheme="majorEastAsia" w:hAnsi="Impact" w:cstheme="majorBidi"/>
            <w:color w:val="538135" w:themeColor="accent6" w:themeShade="BF"/>
            <w:sz w:val="32"/>
            <w:szCs w:val="32"/>
        </w:rPr>
    </w:style>

    <w:style w:type="paragraph" w:customStyle="1" w:styleId="MyFancyStyle">
        <w:name w:val="MyFancyStyle"/>
        <w:basedOn w:val="Normal"/>
        <w:link w:val="MyFancyStyleChar"/>
        <w:qFormat/>
        <w:rsid w:val="008802A5"/>
        <w:rPr>
            <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman"/>
            <w:color w:val="FF0000"/>
            <w:sz w:val="144"/>
        </w:rPr>

    </w:style>

    <w:style w:type="paragraph" w:customStyle="1" w:styleId="subject">
        <w:name w:val="subject"/>
        <w:basedOn w:val="Normal"/>
        <w:link w:val="subjectChar"/>
        <w:qFormat/>
        <w:rsid w:val="008802A5"/>
        <w:textAlignment w:val="center"/>
        <w:rPr>
            <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
            <w:sz w:val="24"/>
            <w:szCs w:val="24"/>
            <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
             <w:color w:val="FF0000"/>
        </w:rPr>

    </w:style>

     <w:style w:type="character" w:customStyle="1" w:styleId="subjectChar">
        <w:name w:val="subject Char"/>
        <w:basedOn w:val="DefaultParagraphFont"/>
        <w:link w:val="subject"/>
        <w:rsid w:val="008802A5"/>

        <w:rPr>
           <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312" w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
            <w:sz w:val="24"/>
            <w:szCs w:val="24"/>
            <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
             <w:color w:val="FF0000"/>

        </w:rPr>

    </w:style>

    <w:style w:type="character" w:customStyle="1" w:styleId="MyFancyStyleChar">
        <w:name w:val="MyFancyStyle Char"/>
        <w:basedOn w:val="DefaultParagraphFont"/>
        <w:link w:val="MyFancyStyle"/>
        <w:rsid w:val="008802A5"/>

        <w:rPr>
            <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman"/>
            <w:color w:val="FF0000"/>
            <w:sz w:val="144"/>
        </w:rPr>
    </w:style>

</w:styles>
import * as fs from "fs"; 
import { Document, Packer, Paragraph, TextRun } from "docx";
import  { xmlStyles } from './xmlStyles';

 // 文档类Document中包含章节数组sections,可向其中添加多个章节 
const doc = new Document({ 
      externalStyles:xmlStyles,
      sections: [{ 
          properties: {}, 
          children: [ new Paragraph({ 
             children: [ new TextRun("Hello World"), 
                  new TextRun({ text: "Foo Bar", bold: true, }),
                  new TextRun({ text: "\tGithub is the best", bold: true, }), ], }), ], }], }); 

// 通过fs实现将docx从buffer流转化成*.docx文件

 Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); // 完成下载


styles

styles也属于样式自定义的一种方式,但这里的方式定义方式是局限于当前docx提供的属性,我们可以在docx的section、Paragraph、Text、Header等中使用。
import * as fs from "fs"; 
import { Document, Packer, Paragraph, TextRun } from "docx";


/**  * 获取自定义段落格式  */ 

function getParagraphStyles() {   
  return [ {        
     id: 'tips', // 温馨提示      
     name: 'tips',           
     basedOn: "Normal",          
     next: "Normal",            
     quickFormat: true,            
     paragraph: {
                 border: {
                     top: borderStyle,
                     left: borderStyle,
                     right: borderStyle, 
                    bottom: borderStyle
                 }
             }
         }, 
 {
             id: 'section', // 题型段落
             name: 'section',
             basedOn: "Normal",
             next: "Normal", 
            quickFormat: true,
             paragraph: { 
                indent: indent,
                spacing: {
                    before: '2pc'
                 }, 
            }
         },
     ]
 }

 // 文档类Document中包含章节数组sections,可向其中添加多个章节 
const doc = new Document({ 
      sections: [{ 
          properties: {}, 
          children: [ new Paragraph({ 
             children: [ new TextRun("Hello World"), 
                  new TextRun({ text: "Foo Bar", bold: true, }),
                  new TextRun({ text: "\tGithub is the best", bold: true, }), ], }), ], }], }); 

// 通过fs实现将docx从buffer流转化成*.docx文件

 Packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer); }); // 完成下载


赞(0) 打赏
转载请附上原文出处链接:胖蔡叨叨叨 » 使用docxjs实现前端的word生成
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏