docx库Table踩坑

docx库Table踩坑

介绍

最近工作中遇到了需要导出word文档的需求,只是简单的将列表详情的数据导出成word中的表格。
类似于下面的效果:

标题 内容
标题 内容
标题 内容

之后找到了相关的工具库docx
功能强大,他封装了word中的相关模块的构造方法,只需要简单的创建一个对象就可以生成word文档。
其中的一些构造方法有DocumentTableParagraphTextRun等。

正文

接着就正式开始嘎嘎一顿操作。

简单实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
? [
new 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
}, [])
})
}

简单试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
exportDocx('example.docx', [
{
key: "title1",
value: "value1"
},
{
key: "title2",
value: [
"value2-1",
"value2-2",
"value2-3"
]
}
])

看着没啥问题,但是他没有撑满整个文档。
Table加个宽度。

  • 因为存在一个标题存在多条数据的情况,所以需要使用到rowSpan,和htmltable同理。
  • verticalAlign,内容垂直对齐方式。
  • Paragraph段落内容,可以当成文字使用。
  • TableRow,等同于html的tr
  • TableCell,等同于html的td

添加宽度

1
2
3
4
5
6
new Table({
width: {
type: WidthType.PERCENTAGE,
size: 100
}
})
  • WidthType 是一些宽度类型的枚举值AUTO(default) | PERCENTAGE(百分比) | NIL(空) | DXA(二十分之一点)
  • 关于这个DXA单位,大致看下这里

看着没问题。 再试试多加点内容的情况👍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
exportDocx('example.docx', [
{
key: "title1",
value: "value1".repeat(50)
},
{
key: "title2",
value: [
"value2-1",
"value2-2",
"value2-3"
]
}
])

有点问题,文字多的那一栏,宽度超出了太多。
并且在钉钉里看到的预览效果是这样的。

在仓库里逛了会儿issue找到了对应的问题。
解决办法-1
解决办法-2

  • 不再使用百分比宽度,而是使用DXA宽度。
  • Table的宽度设置成0,并且规定其列数和列宽。
  • 设置TablelayoutFIXED
1
2
3
4
5
6
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保证完全不受影响。
设置TablelayoutFIXED,表示固定尺寸,防止单元格被压缩变形。
关于DXA的问题,个人猜测是可能百分比不被识别。

最后附上完整的例子。

点击查看代码

结束

简单记录下此次使用docx的踩坑。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!