導出word的功能,目前看了兩個模塊:officegen 和 docxtemplater
officegen是自己繪制word格式: https://github.com/Ziv-Barber/officegen
docxtemplater以模板替換的模式 : https://docxtemplater.readthedocs.io/en/latest/installation.html
officegen操作
1. 安裝
npm install officegen
2. 使用
import * as officegen from 'officegen' import { createWriteStream } from 'fs' import { Request, Response } from 'express'; export function createWord(req: Request, res: Response) { const docx = officegen('docx') docx.on('finalize', function (written) { console.log('word創建完成.') }) docx.on('error', function (err) { console.log(err) }) // Create a new paragraph: /* addText(內容, { color: 字體顏色string, back: 后背景顏色string, bold: 加粗 boolean,默認是false underline:下划線默認false, highlight: 提亮,默認黃色, link: 添加一個鏈接 align: 位置, center/right }) */ let pObj = docx.createP() pObj.addText('Simple') pObj.addText(' with color', { color: '000088' }) pObj.addText(' and back color.', { color: '00ffff', back: '000088' }) pObj = docx.createP() pObj.addText('Since ') pObj.addText('officegen 0.2.12', { back: '00ffff', shdType: 'pct12', shdColor: 'ff0000' }) // Use pattern in the background. pObj.addText(' you can do ') pObj.addText('高亮 ', { highlight: true }) // Highlight! pObj.addText('填充!', { highlight: 'darkGreen' }) // Different highlight color. pObj = docx.createP() // 添加一個鏈接 pObj.addText('這是一個鏈接 ') pObj.addText('點我', { underline: true, color: '000088', link: 'https://github.com' }) pObj.addText('!') pObj = docx.createP() pObj.addText('加粗—+下划線', { bold: true, underline: true }) pObj = docx.createP({ align: 'center' }) pObj.addText('加邊框', { border: 'dotted', borderSize: 12, borderColor: '88CCFF' }) pObj = docx.createP() pObj.options.align = 'right' pObj.addText('Align this text to the right.') pObj = docx.createP() pObj.addText('Those two lines are in the same paragraph,') pObj.addLineBreak()// 換行 pObj.addText('but they are separated by a line break.') docx.putPageBreak()//換頁 pObj = docx.createP() pObj.addText('Fonts face only.', { font_face: 'Arial' }) pObj.addText(' 換字體並加大.', { font_face: 'Arial', font_size: 40 }) pObj = docx.createP({align: 'center'}) // pObj.options.align = 'center' pObj.addText('學生信息', { bold: true, font_face: 'Arial', font_size: 18 }) let tableStyle = { tableColWidth: 2400, tableSize: 24, tableColor: "ada", tableAlign: "center", tableVAlign: "center", tableFontFamily: "Comic Sans MS", borders: true } let table: any = [ [{ val: '姓名', opts: { align: "center", vAlign: "center", sz: '36', // cellColWidth: 42, // b: true, // shd: { // fill: "7F7F7F", // themeFill: "text1", // "themeFillTint": "80" // }, // fontFamily: "Avenir Book" } }, { val: '性別', opts: { align: "center", vAlign: "center", sz: '36', } }, { val: '年齡', opts: { align: "center", vAlign: "center", sz: '36', } }] ] let student1 = ['李四', '男', 12] let student2 = ['李四2', '男', 28] table.push(student1, student2) // 表格 docx.createTable(table, tableStyle) docx.putPageBreak() pObj = docx.createP() // 添加圖片 pObj.addImage('dd.jpg') /* 服務器生成文件 let out = createWriteStream('example.docx') out.on('error', function (err) { console.log(err) }) // Async call to generate the output file: docx.generate(out) */ // 返回給前端,前端直接下載 res.writeHead(200, { // 注意這里的type設置,導出不同文件type值不同application/vnd.openxmlformats-officedocument.wordprocessingml.document "Content-Type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 'Content-disposition': 'attachment; filename=out-' + new Date().getTime() + '.docx' }); docx.generate(res) }
docxtemplater操作,圖片替換是需要收費的
1. 安裝
npm install docxtemplater pizzip
2. 使用
var PizZip = require('pizzip'); var Docxtemplater = require('docxtemplater'); import { Request, Response } from 'express'; var fs = require('fs'); var path = require('path'); // The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors). function replaceErrors(key, value) { if (value instanceof Error) { return Object.getOwnPropertyNames(value).reduce(function (error, key) { error[key] = value[key]; return error; }, {}); } return value; } function errorHandler(error) { console.log(JSON.stringify({ error: error }, replaceErrors)); if (error.properties && error.properties.errors instanceof Array) { const errorMessages = error.properties.errors.map(function (error) { return error.properties.explanation; }).join("\n"); console.log('errorMessages', errorMessages); } throw error; } export function paddingWord(req: Request, res: Response) { console.log( path.resolve( __dirname, '../input.docx'), ) // 讀取模板 加載的docx文件為二進制 var content = fs .readFileSync(path.resolve(__dirname, '../src/input.docx'), 'binary'); var zip = new PizZip(content); var doc; try { doc = new Docxtemplater(zip); } catch (error) { // Catch compilation errors (errors caused by the compilation of the template : misplaced tags) errorHandler(error); } //set the templateVariables doc.setData({ first_name: 'John', last_name: 'Doe', phone: '0652455478', description: 'New Website。。。' }); try { doc.render() // 匹配 } catch (error) { errorHandler(error); } // 生成二進制流 var buf = doc.getZip().generate({ type: 'nodebuffer' }); res.writeHead(200, { "Content-Type": "application/vnd.openxmlformats-officedocument.presentationml.presentation", 'Content-disposition': `attachment; filename= ${new Date().getTime()}.docx` }); res.end(buf) // buf is a nodejs buffer, you can either write it to a file or do anything else with it. // fs.writeFileSync(path.resolve(__dirname, 'output.docx'), buf); }
