乐于分享
好东西不私藏

docx 纯 JS 也能编辑 Word 文档了,无需依赖 Office

docx 纯 JS 也能编辑 Word 文档了,无需依赖 Office

生成 Word 文档时,你是不是遇到过:

  • • Office 依赖:必须安装 Microsoft Word 才能生成文档
  • • 手动操作繁琐:手动创建文档、格式化内容效率低下
  • • 模板限制:Word 模板不够灵活,难以动态生成
  • • 跨平台困难:Windows Office 文档在其他平台兼容性差
  • • 批量生成困难:无法自动化批量生成文档

docx 来了:纯 JavaScript/TypeScript 库,无需 Office 即可创建和修改 .docx 文档,支持完整的 Word 功能,让文档生成变得超级简单!

docx 是什么?

✅ 纯 JS 实现:无需安装 Microsoft Word
✅ 完整功能:段落、表格、图片、页眉页脚、编号、样式、图表
✅ Node.js + 浏览器:两端都能运行
✅ TypeScript 原生:完美的类型定义
✅ 零依赖:不依赖任何 Office 组件
✅ 流式输出:支持大文件生成
✅ 样式丰富:支持字体、颜色、对齐、缩进等
✅ 图表支持:内置图表生成功能

快速上手

1️⃣ 安装

npm install docx
# 或

pnpm add docx

2️⃣ 创建简单文档

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

const
 doc = new Document({
  sections
: [
    {
      children
: [
        new
 Paragraph({
          children
: [new TextRun("Hello docx!")],
        }),
      ],
    },
  ],
});

Packer
.toBuffer(doc).then((buffer) => {
  // 保存到文件(Node.js)

  require
("fs").writeFileSync("hello.docx", buffer);
});

3️⃣ 浏览器中使用

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

const
 doc = new Document({
  sections
: [
    {
      children
: [new Paragraph("Hello from browser!")],
    },
  ],
});

Packer
.toBlob(doc).then((blob) => {
  const
 url = URL.createObjectURL(blob);
  const
 link = document.createElement("a");
  link.href = url;
  link.download = "hello.docx";
  link.click();
});

核心功能

段落与文本

import { Paragraph, TextRun, HeadingLevel } from "docx";

const
 title = new Paragraph({
  heading
: HeadingLevel.HEADING_1,
  children
: [new TextRun("文档标题")],
});

const
 paragraph = new Paragraph({
  children
: [
    new
 TextRun({
      text
: "加粗文本",
      bold
: true,
    }),
    new
 TextRun({
      text
: "斜体文本",
      italics
: true,
    }),
    new
 TextRun({
      text
: "带颜色文本",
      color
: "#FF0000",
      size
: 24,
    }),
  ],
});

表格

import { Table, TableRow, TableCell, WidthType } from "docx";

const
 table = new Table({
  rows
: [
    new
 TableRow({
      children
: [
        new
 TableCell({
          width
: { size: 2000, type: WidthType.DXA },
          children
: [new Paragraph("姓名")],
        }),
        new
 TableCell({
          width
: { size: 3000, type: WidthType.DXA },
          children
: [new Paragraph("邮箱")],
        }),
      ],
    }),
    new
 TableRow({
      children
: [
        new
 TableCell({ children: [new Paragraph("张三")] }),
        new
 TableCell({ children: [new Paragraph("zhangsan@example.com")] }),
      ],
    }),
  ],
});

图片

import { ImageRun } from "docx";
import
 fs from "fs";

const
 imageBuffer = fs.readFileSync("image.png");

const
 paragraph = new Paragraph({
  children
: [
    new
 ImageRun({
      data
: imageBuffer,
      transformation
: {
        width
: 200,
        height
: 200,
      },
    }),
  ],
});

页眉页脚

import { Header, Footer, Paragraph } from "docx";

const
 header = new Header({
  children
: [
    new
 Paragraph({
      children
: [new TextRun("文档页眉")],
    }),
  ],
});

const
 footer = new Footer({
  children
: [
    new
 Paragraph({
      children
: [new TextRun("第 1 页")],
    }),
  ],
});

const
 section = {
  headers
: { default: header },
  footers
: { default: footer },
  children
: [],
};

样式

import { Document, Paragraph, TextStyle } from "docx";

const
 doc = new Document({
  styles
: {
    paragraphStyles
: [
      {
        id
: "customHeading",
        name
: "自定义标题",
        basedOn
: "Heading1",
        next
: "Normal",
        quickFormat
: true,
        run
: {
          color
: "#1a5276",
          bold
: true,
          size
: 32,
        },
      },
    ],
  },
});

const
 paragraph = new Paragraph({
  style
: "customHeading",
  children
: [new TextRun("自定义样式标题")],
});

列表

import { Paragraph, Numbering, NumberFormat } from "docx";

const
 numbering = new Numbering({
  config
: [
    {
      id
: "1",
      levels
: [
        {
          level
: 0,
          format
: NumberFormat.DECIMAL,
          text
: "%1.",
          alignment
: "start",
        },
      ],
    },
  ],
});

const
 doc = new Document({
  numbering,
  sections
: [
    {
      children
: [
        new
 Paragraph({
          numbering
: { reference: "1", level: 0 },
          children
: [new TextRun("列表项 1")],
        }),
        new
 Paragraph({
          numbering
: { reference: "1", level: 0 },
          children
: [new TextRun("列表项 2")],
        }),
      ],
    },
  ],
});

docx vs python-docx vs Office Interop vs LibreOffice

功能
docx
python-docx
Office Interop
LibreOffice
无 Office 依赖
✅ 纯 JS
✅ 纯 Python
❌ 需要 Office
❌ 需要安装
Node.js 支持
✅ 原生
❌ 无
⚠️ 需适配
❌ 无
浏览器支持
✅ 原生
❌ 无
❌ 无
❌ 无
TypeScript 支持
✅ 完美
❌ 无
❌ 无
❌ 无
图表支持
✅ 内置
⚠️ 有限
✅ 完整
⚠️ 有限
样式丰富度
✅ 丰富
✅ 丰富
✅ 完整
✅ 丰富
学习曲线
✅ 平缓
✅ 平缓
⚠️ 较陡
⚠️ 中等
跨平台
✅ 全平台
✅ 全平台
❌ Windows
✅ 全平台

最佳实践

模块化设计:将文档生成逻辑拆分为多个函数
流式输出:处理大文档时使用流式生成
样式复用:定义全局样式,避免重复代码
类型安全:使用 TypeScript,利用类型检查
测试验证:生成后验证文档能正常打开
性能优化:避免不必要的 DOM 操作

总结

docx 是 JavaScript 生成 Word 文档的最佳选择!

它纯 JS 实现,无需 Office 依赖,支持完整的 Word 功能,Node.js 和浏览器都能运行。不管是报表生成、发票模板还是文档自动化,docx 都能轻松应对。如果你正在寻找一个简单、高效的 Word 文档生成方案,docx 是你的最佳选择!