概述
文章描述如何在 Node
.js 里把之前通过H5页面展示的内容(文本,表格,图表),放到 Word
文件里,并提供用户下载。大概的思路框架如下图,分三个部分:
- 业务程序,负责处理组装数据
- officegen,生成
Word
文件 - 文件处理,提供下载接口
officegen原理说明
1.拆解.docx
文件
docx、pptx、xlsx这些格式遵循着ECMA-376标准规范,也就是Office Open XML格式标准。
ECMA-376标准对于打包方式描述的中指出,Office Open XML是由一堆相关文件包,这个包是一个ZIP」,也就可以理解成.docx、.pptx或者.xlsx 其实就是把.zip换了个写法。
把一个.docx文档后缀名改为.zip并进行解压,查看包结构。如下,有一些描述文件,核心内容存在document.xml中
2.office Open xml
docx官方API地址:officeopenxml.com/WPtableProp… 打开的我们导出的文件,左图红框内的红色文字,在document.xml中的表示方式为右图所示
3. officegen 介绍
officegen为 Microsoft Office 2007 及更高版本创建 Office Open XML
文件(Word、Excel 和 Powerpoint)。本文只介绍Word
文件的生成。
document 元素是Word
主要内容部分的根元素,而段落是文档中内容的主要块级容器,我们的数据内容,均以段落为基本元素,从上到下来生成。如下代码开始生成文档:
var pageStyle = {
type:'docx',
font_face:"仿宋",
font_size: 12,
author:"name",
creator:"name",
pageMargins:{ // 页边距 A4 PageSize width: 11906,height:16838
top: 1000,
right: 1000,
bottom: 1000,
left: 1000
}
}
var officegen = require('officegen');
var docx = officegen(pageStyle)
使用示例
段落
在元素插入需要有个段落作为父容器,可整体设置布局样式
var paragraphStyle = { // 段落设置
align :'right', // 对齐
inentLeft:640, // 整段缩进
indentFirstLine:640 // 首行缩进
spacing:{ // 段落间距
after: 640, // 段后
before: 640 // 段前
line: 640 // 行间距
},
}
var pObj = docx.createP(paragraphStyle)
officegen官方不支持段落边框的设置,做了下扩展,参考源码:github
pObj = docx.createP({
border:{
bottom:{
color: '000088',
val: 'dashed',
space: "8",
sz : '4'
},
left:{},
right:{},
top:{}
}})
文本
可设置字体样式,多次addText时,可设置不同字体样式。
```
var textStyle = {
font_face:"黑体",
font_size: 16,
bold: true,
italic:true,
border: 'dotted', // 边框
borderSize: 12,
borderColor: '88CCFF'
}
var text = '添加的本文'
pObj.addText(text, textStyle)
```
图片
pObj = docx.createP()
var imageStryle = {cx:500,cy:250} // 宽度,高度
pObj.addImage(path.resolve(__dirname,'../images_for_examples/image2.jpg'))
图表:
图表H5端渲染用的是 Highcharts
,服务端生成图片采用Highcharts
服务端导出的工具 highcharts-export-server
,并和前端渲染共用一套数据。highcharts-export-server把相关图表数据导出生成图片文件后,再通过addImage插入Word文件
表格
表格整体风格布局类似段落,列的配置信息需要个性化的在columns中,数据是结构和行列保持一致的二维数组,每个单元格样式可单独设置。
跨列:在数据单元格中配置opts: { gridSpan: 2 }
跨行:在数据单元格中配置opts: { vMerge: 'restart' }, opts: { vMerge: 'continue' }
var tableData = [ // 以行为单位的数组
[ //第一行
{ val: "I have two spans.", opts: { gridSpan: 2 } }, // 第一列,跨列 gridSpan
{ val: "3",opts:{ vMerge: "restart" } }, // 第二列,跨行 本行开始
],
[ //第二行
4,
"watch out for the baobabs!",
{ opts: { vMerge: "continue" } } ] // 第三列,被跨行 跳过
];
var tableStyle = {
borders: true,
borderSize: 1,
columns:[ // 单列样式配置
{width: 1000},
{width: 1000},
{width: 1000},
]
}
pObj = docx.createTable(tableData, tableStyle)
以上配置渲染效果:
在首行有多个单元格跨列时,列计算会有问题:解决方式是在tableStyle中声明列个数,如上columns属性
遇到的问题
-
WPS 或者 Word一方打不开,一般解决方式是打开对应document.xml看看数据差别
-
addHorizontalLine 产生的线条在 Word 打开时是个矩形框,后来改为扩展paragraph的
boder
属性