docx库Table踩坑
介绍
最近工作中遇到了需要导出word文档的需求,只是简单的将列表详情的数据导出成word中的表格。
类似于下面的效果:
| 标题 | 内容 |
|---|---|
| 标题 | 内容 |
| 标题 | 内容 |
之后找到了相关的工具库docx。
功能强大,他封装了word中的相关模块的构造方法,只需要简单的创建一个对象就可以生成word文档。
其中的一些构造方法有Document、Table、Paragraph、TextRun等。
正文
接着就正式开始嘎嘎一顿操作。
简单实现
import {
Document,
Table,
TableCell,
TableRow,
Paragraph,
VerticalAlign,
WidthType,
TableLayoutType,
} from 'docx'
export default function exportDocx(filename, value) {
const table = new Table({
rows: value.reduce((acc, item) => {
const { key, value } = item
if (Array.isArray(value)) {
acc.push(
...value.map((item, index) => {
return new TableRow({
children: [
...(index == 0 ? [
TableCell({
rowSpan: value.length,
children: [
new Paragraph({ text: key }),
],
verticalAlign: VerticalAlign.CENTER,
}),
] : []),
new TableCell({
children: [
new Paragraph({text: item }),
],
verticalAlign: VerticalAlign.CENTER,
}),
]})
})
)
} else {
acc.push(
new TableRow({
children: [
new TableCell({
children: [
new Paragraph({ text: key }),
],
verticalAlign: VerticalAlign.CENTER,
}),
new TableCell({
children: [
new Paragraph({ text: value }),
],
verticalAlign: VerticalAlign.CENTER,
}),
],
})
)
}
return acc
}, [])
})
}
简单试试:
exportDocx('example.docx', [
{
key: "title1",
value: "value1"
},
{
key: "title2",
value: [
"value2-1",
"value2-2",
"value2-3"
]
}
])
看着没啥问题,但是他没有撑满整个文档。
给Table加个宽度。
- 因为存在一个标题存在多条数据的情况,所以需要使用到
rowSpan,和htmltable同理。 verticalAlign,内容垂直对齐方式。Paragraph段落内容,可以当成文字使用。TableRow,等同于html的trTableCell,等同于html的td
添加宽度
new Table({
width: {
type: WidthType.PERCENTAGE,
size: 100
}
})
- WidthType 是一些宽度类型的枚举值
AUTO(default) | PERCENTAGE(百分比) | NIL(空) | DXA(二十分之一点) - 关于这个
DXA单位,大致看下这里。
看着没问题。 再试试多加点内容的情况👍。
exportDocx('example.docx', [
{
key: "title1",
value: "value1".repeat(50)
},
{
key: "title2",
value: [
"value2-1",
"value2-2",
"value2-3"
]
}
])
有点问题,文字多的那一栏,宽度超出了太多。
并且在钉钉里看到的预览效果是这样的。
在仓库里逛了会儿issue找到了对应的问题。
解决办法-1。
解决办法-2。
- 不再使用百分比宽度,而是使用
DXA宽度。 - 将
Table的宽度设置成0,并且规定其列数和列宽。 - 设置
Table的layout为FIXED。
new Table({
layout: TableLayoutType.FIXED,
columns: 3,
width: 0,
columnWidths: [3213, 3213, 3212] // total page width is 9638 DXA for A4 portrait
})
关于上面宽度设置成0的问题,打开word文档查看:
虽然指定宽度的按钮未被选中,但是在钉钉中依旧生效了。
将其指定为0保证完全不受影响。
设置Table的layout为FIXED,表示固定尺寸,防止单元格被压缩变形。
关于DXA的问题,个人猜测是可能百分比不被识别。
最后附上完整的例子。
结束
简单记录下此次使用docx的踩坑。