【实战分享】js生成word(docx)

这篇具有很好参考价值的文章主要介绍了【实战分享】js生成word(docx)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文将记录如何从纯前端实现生成带图片的表格的word文件,并下载到本地。

依赖 docx 插件

docx文档地址
github地址

npm install --save docx

这里的用例最终生成文档内容长这样
js 生成word,word,前端,javascript,react.js,js

import {Document,ImageRun,Packer,Paragraph,HeadingLevel,TextRun,SymbolRun,AlignmentType,WidthType,BorderStyle,Table,TableRow,TableCell,convertInchesToTwip,VerticalAlign,TableLayoutType
} from 'docx';
export default memo(() => {
 // 生成文档大标题
  const createHeading = (text1, text2) => {
    return new Paragraph({
      alignment: AlignmentType.CENTER,
      heading: HeadingLevel.HEADING_1,
      children: [
        new TextRun({
          text: text1,
        }),
        new TextRun({
          text: text2,
          break: 1,
        }),
      ],
    });
  };
 
  // 生成文档正文
  const createText = (text, num = 0) => {
    return new Paragraph({
      heading: HeadingLevel.HEADING_4,
      children: [
        new TextRun({
          text: text,
          break: num,
        }),
      ],
    });
  };
  // 生成tablecell标题
  const createTablecellTitle = (text, type, len) => {
    let obj = {};
    if (type == 1) {
      obj.alignment = AlignmentType.CENTER;
    } else {
      obj.indent = { start: 100 };
    }
    return new Paragraph({
      ...obj,
      heading: HeadingLevel.HEADING_5,
      children: [new TextRun({
        text: text,
      })],
    });
  };
  // 生成tablecell正文
  const createTablecellText = (text, type, len) => {
    let obj = {};
    if (type == 1) {
      obj.alignment = AlignmentType.CENTER;
    } else {
      obj.indent = { start: 100 };
    }
    return new Paragraph({
      ...obj,
      heading: HeadingLevel.HEADING_6,
      children: [new TextRun({
        text: text,
      })],
    });
  };

  // 生成tablecell图片
  const createTablecellImg = (photo, width, height, type = 0) => {
    let obj = {};
    if (type == 0) {
      obj.spacing = {
        before: 180,
      };
    }
    return new Paragraph({
      ...obj,
      alignment: AlignmentType.CENTER,
      children: [
        new ImageRun({
          data: photo,
          transformation: {
            width,
            height,
          },
        }),
      ],
    });
  };
  // 生成纯文字tablecell   colspan代表行合并数,type=0表示是标题,1是正文,,needCenter 1需要居中,2是需要自己打断换行的    len是
  const createTablecell = (text, colspan = 2, type = 0, needCenter = 0, len = 12) => {
    return new TableCell({
      verticalAlign: VerticalAlign.CENTER,
      columnSpan: colspan,
      children: [
        type == 0
          ? createTablecellTitle(text, needCenter, len)
          : createTablecellText(text, needCenter, len),
      ],
    });
  };
  // 生成空行(带border)
  const ceateTableRow = () => {
    return [
      new TableRow({
        children: [
          new TableCell({
            columnSpan: 12,
            children: [],
          }),
        ],
      }),
    ];
  };
   // 将大数组切割成固定长度的小数组,长度不够就填充空对象
  const chunk = (arr, size) => {
    var arr2 = [];
    for (var i = 0; i < arr.length; i = i + size) {
      if (arr.slice(i, i + size).length < size) {
        let arr3 = arr.slice(i, i + size);
        for (var j = 0; j < size; j++) {
          if (!arr3[j]) {
            arr3[j] = {};
          }
        }
        arr2.push(arr3);
      } else {
        arr2.push(arr.slice(i, i + size));
      }
    }
    return arr2;
  };
  /**
   * 导出秩序册word
   * @param {string} fileName 文件名,不含后缀
   */

  const exportWord = async (fileName = 'word') => {
// 数据
let data = [
  {
    team_name: "xxx", //代表队伍名称
    logo: "https://img.zcool.cn/community/011d2b599e435da801201794bfc968.jpg", //队伍LOGO
    team_photo:
      "https://img.zcool.cn/community/011d2b599e435da801201794bfc968.jpg", //队伍合照
    representative: "xxx单位", //参赛单位名称
    lead_name: ["姓名1", "姓名2"], //领队
    lead_name: ["姓名1"], //教练
    contacts_phone: "xxx", //教练
    retinues: [
      {
        role_name: "领队",
        name: "姓名1",
        photo:
          "https://img2.baidu.com/it/u=687610989,4177511047&fm=253&fmt=auto&app=138&f=PNG?w=500&h=527",
        phone: "13xxxxx111",
      },
      {
        role_name: "教练",
        name: "姓名2",
        photo:
          "https://img2.baidu.com/it/u=687610989,4177511047&fm=253&fmt=auto&app=138&f=PNG?w=500&h=527",
        phone: "130xxxxx110",
      },
    ], //随行人员 每行4个,自动换行
  },
];
// word文档共用设置
let commSetting = {
  creator: "22", //作者
  styles: {
    paragraphStyles: [
      // 文档大标题
      {
        id: "Heading1",
        name: "Heading 1",
        basedOn: "Normal",
        next: "Normal",
        quickFormat: true,
        run: {
          size: 32,
          bold: true,
          color: "000000",
        },
        paragraph: {
          spacing: {
            before: 250,
            after: 250,
          },
        },
      },
      // 文档正文
      {
        id: "Heading4",
        name: "Heading 4",
        basedOn: "Normal",
        next: "Normal",
        quickFormat: true,
        run: {
          size: 28,
          color: "000000",
        },
        paragraph: {
          spacing: {
            before: 250,
            after: 250,
          },
        },
      },
      // 表格正文标题
      {
        id: "Heading5",
        name: "Heading 5",
        basedOn: "Normal",
        next: "Normal",
        quickFormat: true,
        run: {
          size: 18,
          color: "000000",
          bold: true,
        },
        paragraph: {
          spacing: {
            before: 250,
            after: 250,
          },
        },
      },
      // 表格正文
      {
        id: "Heading6",
        name: "Heading 6",
        basedOn: "Normal",
        next: "Normal",
        quickFormat: true,
        run: {
          size: 18,
          color: "000000",
        },
        paragraph: {
          spacing: {
            before: 180,
            after: 180,
          },
        },
      },
    ],
  },
};
let document = null;
// 假设表格有12列
let colums = [];
for (let i = 0; i < 12; i++) {
  colums.push(convertInchesToTwip(0.5225));
}

// 统一处理数据 将图片转换成word插件可以执行的格式
for (let item of data) {
  item.logo = await fetch(item.logo).then((r) => r.blob());
  item.team_photo = await fetch(item.team_photo).then((r) => r.blob());
  for (let its of item.retinues) {
    const blob = await fetch(its.photo).then((r) => r.blob());
    its.photo = blob;
  }
}

document = new Document({
  ...commSetting,
  sections: [
    {
      children: [
        createHeading("这是一个假标题", "竞赛报名表"),
        ...data.map((item, index) => {
          let table = null;
          const tableCommSetting = {
            columnWidths: colums,
            layout: TableLayoutType.FIXED, //布局 TableLayoutType有两个属性,一个是FIXED 一个是AUTOFIT
            width: {
              size: convertInchesToTwip(6.27),
              type: WidthType.DXA,
            },
          };

          let retinueARR = [], //随行人员表格内容
            retinueArrOfArrays = [];
          // 生成"随行人员"图表
          if (item?.retinues?.length > 0) {
            retinueArrOfArrays = chunk(item.retinues, 4); //随行人员 每行4个,自动换行
            retinueARR = retinueArrOfArrays.map((itt, idx) => {
              return new TableRow({
                children: itt.map((it, ix) => {
                  if (JSON.stringify(it) == "{}") {
                    return new TableCell({ columnSpan: 3, children: [] });
                  } else {
                    return new TableCell({
                      columnSpan: 3,
                      width: {
                        size: convertInchesToTwip(0.5225 * 3),
                        type: WidthType.DXA,
                      },
                      children: [
                        createTablecellImg(it.photo, 90, 126),
                        createTablecellText(it.role_name, 1),
                        createTablecellText(it.name, 1),
                        createTablecellText(it.phone, 1),
                      ],
                    });
                  }
                }),
              });
            });
          } else {
            retinueARR = ceateTableRow();
          }

          table = new Table({
            ...tableCommSetting,
            rows: [
              new TableRow({
                children: [
                  createTablecell("代表队伍名称", 2, 0, 2),
                  createTablecell(item.team_name, 4, 1, 2, 16),
                  createTablecell("参赛单位名称", 2, 0, 2),
                  createTablecell(item.representative, 4, 1, 2, 16),
                ],
              }),
              new TableRow({
                children: [
                  createTablecell("队伍LOGO", 2, 0, 2),
                  new TableCell({
                    verticalAlign: VerticalAlign.CENTER,
                    columnSpan: 4,
                    children: [createTablecellImg(item.logo, 126, 40, 1)],
                  }),
                  createTablecell("队伍合照", 2, 0, 2),
                  new TableCell({
                    verticalAlign: VerticalAlign.CENTER,
                    columnSpan: 4,
                    children: [createTablecellImg(item.team_photo, 126, 60, 1)],
                  }),
                ],
              }),
              new TableRow({
                children: [
                  createTablecell("领队", 2, 0, 2),
                  createTablecell(item.lead_name.join("、"), 2, 1, 2),
                  createTablecell("教练", 2, 0, 2),
                  createTablecell(item.coach_name.join("、"), 2, 1, 2),
                  createTablecell("团队联系方式", 2, 0, 2),
                  createTablecell(item.contacts_phone, 2, 1, 2, 11),
                ],
              }),
              new TableRow({
                columnSpan: 12,
                children: [createTablecell("随行人员信息", 12, 0, 1)],
              }),
              ...retinueARR,
              // 最后一行空白行
              ceateTableRowBorderNone(),
            ],
          });

          return table;
        }),
      ],
    },
  ],
});
Packer.toBlob(document).then((blob) => {
  saveAs(blob, fileName + ".docx");
});

      
  };

return (
		<button  onClick={() => exportWord('报名表')} > 导出word文档 </button>
		)
  })

如有不满足需求的地方,还是可以上它的官方文档看看,地址再贴一次

希望对大家有所帮助,毕竟我肝文档肝了一天,希望给大家节约一点时间文章来源地址https://www.toymoban.com/news/detail-598803.html

到了这里,关于【实战分享】js生成word(docx)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端html-docx实现html转word,预览并导出文件

    使用工具:html-docx 优势:图片、图表能直接预览并转为base64导出,省去后端难以实现图表的生成后插入的麻烦 劣势:适合一些简单的word模板导出(比如只有标题正文简单的表格图表图片的文档),复杂的可以直接忽略。比如:纸张大小、纸张方向、css大部分样式等等(经本

    2024年02月16日
    浏览(38)
  • 【前端】html2canvas生成图片空白排查data:;(js vue react uniapp)

    因为要做一个分享图,就用到了html2canvas,一开始是好好的,今天随便测了下,发现图片显示不出来了。打印了下,生成的图片链接变成了 data:; 。后面一步一步地排查,发现是页面内容太多了,删减一点内容就能显示出来。然后我又去认真看了下html2canvas的各个参数,发现可

    2024年02月03日
    浏览(48)
  • Node.js 使用 officecrypto-tool 读取加密的 Excel (xls, xlsx) 和 Word( docx)文档

    Node.js 使用 officecrypto-tool 读取加密的 Excel (xls, xlsx) 和 Word( docx)文档, 还支持 xlsx 和 docx 文件的加密(具体使用看文档)。暂时不支持doc文件的解密 传送门:officecrypto-tool 读取加密的 Excel 示例 读取加密的 Word 示例 使用:mammoth officecrypto-tool 使用其他的word读取库也是一样的道理

    2024年02月10日
    浏览(33)
  • vue实战--vue+elementUI实现多文件上传+预览(word/PDF/图片/docx/doc/xlxs/txt)

        最近在做vue2.0+element UI的项目中遇到了一个需求:需求是多个文件上传的同时实现文件的在线预览功能。需求图如下:     看到这个需求的时候,小栗脑袋一炸。并不知道该如何下手,之前的实践项目中也并没有遇到相似的功能。因此也废了一番功夫想要实现这样一个

    2024年01月23日
    浏览(53)
  • JavaScript 框架比较:Angular、React、Vue.js

    在 Web 开发领域,JavaScript 提供大量技术栈可供选择。其中最典型的三套组合,分别是 MERN、MEAN 和 MEVN。这些首字母相同的选项各自代表不同的技术加工具组合。为了在这些技术栈中做出明智选择,让我们先从核心组件聊起,再对各自前端框架(React、Angular 和 Vue)进行简化比

    2024年01月20日
    浏览(47)
  • vue 生成word表格文档 前端库介绍

             在Vue中生成Word表格文档,你可以使用一些前端库来帮助你完成这项任务。以下是几个流行的库及其简要介绍:         1. **docxtemplater**:    - **介绍**: docxtemplater是一个基于JavaScript的库,它可以处理docx和pptx模板,允许你通过JSON数据来填充模板。它支持条件、

    2024年02月21日
    浏览(36)
  • 从javascript到vue再到react:前端开发框架的演变

    目录 JavaScript: 动态语言的基础 JavaScript:Web开发的起点 Vue.js: 渐进式框架的兴起 Vue.js:简洁、高效的前端框架 React.js: 声明式UI的革新 React.js:强大、灵活的前端框架 演变之路与未来展望 演变过程 当提到前端开发中的框架时,JavaScript、Vue.js和React.js是三个最常见的名词。它

    2024年02月07日
    浏览(41)
  • JavaScript框架 Angular、React、Vue.js 的全栈解决方案比较

    在 Web 开发领域,JavaScript 提供大量技术栈可供选择。其中最典型的三套组合,分别是 MERN、MEAN 和 MEVN。前端框架(React、Angular 和 Vue)进行简化比较。 MERN 技术栈包含四大具体组件: MongoDB:一款强大的 NoSQL 数据库,以灵活的 JSON 格式存储数据。 Express.js:一套极简但强大的

    2024年02月03日
    浏览(45)
  • 2023年最佳JavaScript框架:React、Vue、Angular和Node.js的比较

    🎉欢迎来到Java学习路线专栏~探索2023年最佳JavaScript框架:React、Vue、Angular和Node.js的比较 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:Java学习路线 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 🍹文章作者技术和水

    2024年02月11日
    浏览(39)
  • python-docx操作word

    在Python中操作Word文档通常涉及到读取、创建和编辑文档。这可以通过使用第三方库如 python-docx 来实现。以下是一个详细的指南,介绍如何使用 python-docx 来进行常见的Word文档操作。 安装 python-docx 首先,你需要安装 python-docx 库。可以使用pip来安装: 创建新的Word文档 使用 p

    2024年02月04日
    浏览(31)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包