>首页> IT >

【全球新要闻】怎么利用node生成word文档?使用库分享

时间:2022-07-28 19:44:13       来源:转载


【资料图】

怎么利用node生成word文档?下面本篇文章给大家介绍一下使用node生成word文档的方法,分享一个实用库,聊聊该库的使用方法,希望对大家有所帮助!

最近有项目需要用到生成word文档,平时经常用的都是通过模板生成,里面变量使用占位符替换,好处是快捷、方便、简单、不需要通过代码调word样式,确定是很多库不支持图片绘制(很多都是付费功能),找一圈,发现一个很有意思的库,正好也满足我们的需求,特此分享一下

依赖

// https://docx.js.org/#/npm i docx // https://www.npmjs.com/package/downloadnpm i download

说明,因为docx绘图只支持文件流,所以要把网络文件下载到本地转成buffer

代码

话不多说,上代码

import * as fs from "fs"import { Document, Packer, Paragraph, TextRun, ImageRun, HeadingLevel, AlignmentType, convertInchesToTwip, Table, TableRow, TableCell, WidthType, VerticalAlign, BorderStyle } from "docx"const download = require("download")// 性别enum Gender {  Male = "male",  Female = "female"}// 选手type PlayerSchema = {  name: string  gender: string  idCard?: string  birthday?: string  weight?: string  remark?: string  avatar?: string  localAvatar?: string  level: string}type GroupSchema = {  // gender: Gender  institution: string  leader: string  phone: string  coach: string  doctor: string  players: PlayerSchema[]}// 所有数据interface DataSchema  {  [key: string]: GroupSchema}// 表格无边框const noBoder = {  top: {    style: BorderStyle.NIL,    size: 0,    color: "FFFFFF"  },  bottom: {    style: BorderStyle.NIL,    size: 0,    color: "FFFFFF"  },  left: {    style: BorderStyle.NIL,    size: 0,    color: "FFFFFF"  },  right: {    style: BorderStyle.NIL,    size: 0,    color: "FFFFFF"  }}// 删除下载的照片及文件夹function delStaticFile(groupNames: string[]) {  for (let groupName of groupNames) {    if (fs.existsSync(groupName)) {      const files = fs.readdirSync(groupName)      files.map((file: string) => {        let curPath = groupName + "/" + file        // 删除选手招聘        fs.unlinkSync(curPath)      })      fs.rmdirSync(groupName)    }  }}// 生成wordasync function generate (data: DataSchema) {  const groupNames = Object.keys(data)  // 比较粗糙的控制单元格长度逻辑  const longHeaders = ["身份证号", "备注"]  // 下载远程资源到本地  for (let groupName of groupNames) {    if (!fs.existsSync(groupName)) {      fs.mkdirSync(groupName)    }    const players = data[groupName].players    for (let player of players) {      if (player.avatar) {        const avatarArr = player.avatar.split("/")        const fileName = `${groupName}/${avatarArr[avatarArr.length - 1]}`        if (!fs.existsSync(fileName)) {          await download(player.avatar, groupName)        }        // 下载后的本地的资源路径        player.localAvatar = fileName      }    }  }  // 需要多个文件合一  const sections = groupNames.map(groupName => {    const info = data[groupName]    const { institution, leader, phone, coach, doctor, players } = info    // 标头内容    // let headers = ["序号", "照片", "姓名", "性别", "出生年月", "体重", "级别", "备注"]    let headers = ["序号", "照片", "姓名", "性别", "身份证号", "级别", "备注"]    // 表格数据    let tableData: any[][] = []    tableData.push(headers)    // 填充选手信息    let index = 1    for (let player of players) {      tableData.push([        index.toString(),        player.localAvatar || "",        player.name,        player.gender === Gender.Male ? "男" : "女",        player.idCard,        // player.birthday,        // player.weight,        player.level,        player.remark,      ])      index++    }    // 表格渲染    const tableRows = tableData.map(colums => {      return new TableRow({        children: colums.map(cell => {        return new TableCell({          verticalAlign: VerticalAlign.CENTER,          width: {            // 设置宽度 dxa长度单位 https://stackoverflow.com/questions/14360183/default-wordml-unit-measurement-pixel-or-point-or-inches            size: longHeaders.some(j => cell === j) ? 3000 : 800,            type: WidthType.DXA,          },          children: cell && colums.findIndex(i => i === cell) === 1 && cell !== "照片" ?              [new Paragraph({                alignment: AlignmentType.CENTER,                children: [                  new ImageRun({                    // 将图片转化为buffer                    data: fs.readFileSync(cell),                    transformation: {                      width: 100,                      height: 129,                    },                  })                ]              })]:            [new Paragraph({              alignment: AlignmentType.CENTER,              children:[                new TextRun(cell || "")              ]            })]          })        })      })    })    // 渲染报名表格    const table = new Table({      alignment: AlignmentType.CENTER,      rows: tableRows    })    return {      properties: {},      children: [        // new Paragraph({        //   style: "wellSpaced",        //   children: [        //     new TextRun({        //       text: "附件 4",        //       color: "999999",        //     })        //   ],        // }),        // 表头信息        new Paragraph({          spacing: {            before: 400,            after: 400          },          style: "Title",          text: `自 由 搏 击 比 赛 报 名 表(${groupName === Gender.Male ? "男子" : "女子"})`,          heading: HeadingLevel.TITLE,          alignment: AlignmentType.CENTER        }),        // 队伍信息        new Table({          style: "wellSpaced",          alignment: AlignmentType.CENTER,          borders: noBoder,          rows: [            new TableRow({            children: [              new TableCell({                width: {                  size: 600,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`单位: `),                ],              }),              new TableCell({                width: {                  size: 1800,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`${institution}`)                ],              }),              new TableCell({                width: {                  size: 700,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`  领队: `),                ],              }),              new TableCell({                width: {                  size: 1200,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`${leader}`)                ],              }),              new TableCell({                width: {                  size: 1100,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`  联系电话: `),                ],              }),              new TableCell({                width: {                  size: 1400,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`${phone}`)                ],              }),              new TableCell({                width: {                  size: 700,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`  教练: `),                ],              }),              new TableCell({                width: {                  size: 1300,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`${coach}`)                ],              }),              new TableCell({                width: {                  size: 700,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`  队医: `),                ],              }),              new TableCell({                width: {                  size: 1300,                  type: WidthType.DXA,                },                borders: noBoder,                children: [                  new Paragraph(`${doctor}`)                ],              }),            ],          }),          ]        }),        // 用于段落距离(table无法设置spacing属性)        new Paragraph({          spacing: {            // 通过调整before值来调整段落渐进            before: 400,          },          text: ``,        }),        // 选手信息        table,        // 印章和时间        new Paragraph({          style: "wellSpaced",          children: [            new TextRun({              text: "\t\t\t\t报名单位章:\t\t\t\t\t\t",            }),            new TextRun({              text: "年\t\t"            }),            new TextRun({              text: "月\t\t"            }),            new TextRun({              text: "日"            })          ]        })      ]    }  })  // 创建整个文档  const doc = new Document({    styles: {      paragraphStyles: [        {          id: "Title",          name: "title",          basedOn: "Normal",          next: "Normal",          quickFormat: true,          run: {              size: 30,              bold: true,              color: "000000"          }        },        {          id: "wellSpaced",          name: "Well Spaced",          basedOn: "Normal",          quickFormat: true,          paragraph: {            indent: {              left: convertInchesToTwip(0.5),            },            spacing: {              before: 400,            },          },        },      ],    },    sections  })    // 生成word文档  Packer.toBuffer(doc).then((buffer) => {    fs.writeFileSync("enrolls.docx", buffer)  })  // 删除下载的选手照片  delStaticFile(groupNames)}const group: GroupSchema = {  institution: "江苏省南京市舜禹集团总部",  leader: "王猛(男)",  phone: "18861856665",  coach: "刘国梁(男)",  doctor: "杨永信(女)",  players: [    {      name: "莱昂纳多迪卡普里奥",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/13.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/7.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      idCard: "320888199001019878",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    },    {      name: "张三",      gender: Gender.Male,      idCard: "320888199001019878",      birthday: "1999-01-02",      weight: "60kg",      avatar: "https://multi-xm.oss-cn-hangzhou.aliyuncs.com/atms/14.png",      remark: "",      level: "60kg"    }  ]}const data: DataSchema = {  [Gender.Male]: group,  [Gender.Female]: group,}generate(data)

更多node相关知识,请访问:nodejs 教程!

以上就是怎么利用node生成word文档?使用库分享的详细内容,更多请关注php中文网其它相关文章!

关键词: 相关文章 使用方法 长度单位