浏览器打印复杂表格
一、需求
1.1、实现如图所示内容的打印
1.2、打印内容分析:
1.2.1、包括:1、页眉;2、页脚;3、表头;4、合并行;5、合并列;6、分页;
二、print.js
1、html打印
2、打印
// 打印内容--可以直接使用
/*** @des 打印的方法* @param {[String|Object]} body require true* @param {Array} styleList require false 样式* @param {String} scale require false 缩放比例* body 1:自定义字符串 可以把样式写到行内* body 2:html节点 例如:this.$refs.name.$el/this.$el* 可以所有style标签全部传入当作样式--styleList = Array.from(document.getElementsByTagName('style'))*/
export const _print = (body, styleList = [], scale = '1') => {// 把所有样式放入打印区域let styleStr = styleList.map(item => {return item.nodeType ? item.cloneNode(true).outerHTML : ''})// table字段太多是要缩放打印let width = 100 / Number(scale)body = body.nodeType ? body.outerHTML : bodylet printStr = `${styleStr.join('')}`printStr = printStr + body + ''// 打印弹窗_printMotheds(printStr)
}
// 兼容火狐 谷歌 ie
const _printMotheds = (str) => {let browser = myBrowser()if (['FF', 'SOUGOU'].includes(browser)) {printByOpenWindow(str)} else {printByIframe(str)}
}
// 打开新窗口
const printByIframe = (str) => {let iframe = document.createElement('IFRAME')iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;')document.body.appendChild(iframe)let doc = iframe.contentWindow.documentdoc.write(str)doc.close()iframe.contentWindow.onload = ()=>{iframe.contentWindow.focus()iframe.contentWindow.print() // iframe打印document.body.removeChild(iframe)}
}
// 利用iframe--避免打印影响原网页
const printByOpenWindow = (str) => {var page = window.open('', '_blank')page.document.write(str) // 写入打印页面的内容page.print() // html打印var userAgent = navigator.userAgentif ((userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1) || (userAgent.indexOf('Edge') > -1) || (userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1)) {// IE浏览器page.document.execCommand('print')} else {console.log('not IE')}page.close() // 关闭打印窗口
}
// 获取浏览器类型
const myBrowser = () => {var userAgent = navigator.userAgent // 取得浏览器的userAgent字符串var isOpera = userAgent.indexOf('Opera') > -1if (isOpera) {return 'Opera'} // 判断是否Opera浏览器if (userAgent.indexOf('Firefox') > -1) {return 'FF'} // 判断是否Firefox浏览器if (userAgent.indexOf('Chrome') > -1) {return 'Chrome'}if (userAgent.indexOf('Safari') > -1) {return 'Safari'} // 判断是否Safari浏览器if (userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 && !isOpera) {return 'IE'} // 判断是否IE浏览器if (userAgent.toLowerCase().indexOf('se 2.x') > -1) {return 'SOUGOU'}
}
二、实现需求
分析:关键是实现所要打印内容的字符串;
这里实现了:
1、根据每页要展示多少行进行分页;
2、通过css实现分页;
3、logo、页眉、页脚的处理;
4、${this.(index)}表格行数据,这里包括合并行、合并列 单独做处理
printContent() {// 数据已脱敏,请根据自己的数据来使用let content = '';const len = Math.ceil(this.data.length / 10);//根据每页打印十条数据进行分页,不足十条也占一页// style="page-break-after:always; margin: 0;font-size:10px;" 实现分页,分页时会自动带着页眉页脚与表头信息,页眉页脚这里也用表格实现,隐藏边框for (let index = 0; index < len; index += 1) {content += `单据title
页眉字段1:${this.printData.fields1 || ''} 字段2:${this.printData.fields2 || ''} 字段3:${this.printData.fields3 || ''} 字段4:${this.printData.fields4 || ''} 字段5:${this.printData.fields5 || ''} 字段6:${this.printData.fields6 || ''} 备注 表头字段1 字段2 字段3 字段4 字段5 字段6 字段7 字段8 字段9 字段10 字段11 字段12 // 动态展示表格行数据,包括合并行,合并列,每页展示10条数据${this.ListStr(index)}页脚字段1: 字段2: 字段3:${this.printData.data3} 字段4:${this.printData.data4|| ''} 字段5:${this.printData.data5|| ''} 字段6:${this.printData.data6|| ''} 字段7:${this.printData.data7|| ''} 字段8: 字段9: 字段10:
`;}// 打印弹窗_print(content);},
行数据的处理,这里我仅介绍我项目的情况,有了上边的代码要打印的内容基本已经实现了,表格的行数据怎样合并合并行、合并列要根据自己的需求具体实现,我仅介绍我项目的情况作为参考。
分析:表格前六行可能会合并列,后两行会合并列
关键点:第一页末尾数据是要实现合并列的,但是已经到了第一页的末尾,剩下还有一行或多行数据要展示在第二页,这是的合并列要再做处理。
通过 实现合并列
一开始我对数据已做了一些处理,数据格式大致如下:
data = [{rowspanLen: 2,//要合并的列数,仅在要合并的一组数据中的第一条有内容,这里是要合并2列fields1: '1',fields2: '2'},{rowspanLen: '',fields1: '1',fields2: '2'},{rowspanLen: 1,//要合并的列数,仅在要合并的一组数据中的第一条有内容,这里是要合并1列fields1: '1',fields2: '2'}
]
ListStr(index2) {let str = '';let curList = cloneDeep(this.data);curList = curList.splice(10 * index2, 10);// 从第二页开始,首行rowspanLen为空的处理// 第一页是起始页面不需要let only = 0;if (curList[0].rowspanLen === '') {let flagIndex = 0;curList.forEach((item) => {if (item.rowspanLen === '' && only === 0) {flagIndex += 1;} else {// foreach循环迭代数组元素时,没有数组元素的值// 因此,这里用only做一个标记,这里只需要执行一次// 否则同一页如果还有合并项,可能还会执行forEach循环only += 1;curList[0].rowspanLen = flagIndex;curList[0].data1= '';curList[0].data2= '';curList[0].data3 = '';curList[0].data4= '';curList[0].data5= '';curList[0].data6= '';}});// 整页rowspanLen为空的处理if (curList[0].rowspanLen === '') {curList[0].rowspanLen = curList.length;curList[0].data1 = '';curList[0].data2= '';curList[0].data3= '';curList[0].data4= '';curList[0].data5 = '';curList[0].data6 = '';}}curList.forEach((item, index) => {str += ``;// 前六列,可能会合并列的数据if (item.rowspanLen !== '') {str += `${item.data1|| ''} ${item.data2|| ''} ${item.data3|| ''} ${item.data4|| ''} ${item.data5|| ''} ${item.data6|| ''} `;}// 中间不会合并的数据str += `${item.data7 || ''} ${item.data8 || ''} ${item.data9|| ''} ${item.data10|| ''} `;// 后两行整页的列都要合并if (index === 0) {str += `${item.data11|| ''} ${item.data12|| ''} `;}str += ` `;});return str;},
三、欢迎交流指正,留言必回。