此处是vue项目中的用法,也可以改写,不使用vue的语法,也可以实现其他框架使用
window.print()
直接调用默认打印,设置打印时样式
@media print {@page {margin: 0.5cm;}}
普通打印
打印分页表格时,可以实现各分页分别都展示表头。有高度限制,超出了就不展示表头(各浏览器不同)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>打印测试</title><script src="https://unpkg.com/vue@next"></script><style>table {font-size: 12px;width: 100%;font-size: 9pt;border-collapse: collapse;border-spacing: 0;}tr {page-break-inside: avoid;}td {border: 1px solid #ccc;text-align: center;height: 36px;}</style></head><body><div id="demo"><table><thead style="display:table-header-group;font-weight:bold"><tr><td colspan="2" align="center" style="font-weight:bold;border:3px double red">每页都有的表头</td></tr></thead><tbody><tr v-for="(item,index) in list"><td>{{item.a+index}}</td><td>{{item.b+index}}</td></tr></tbody><tfoot style="display:table-footer-group;font-weight:bold"><tr><td colspan="2" align="center" style="font-weight:bold;border:3px double blue">每页都有的表尾</td></tr></tfoot></table></div><script>const DEMO = {data() {return {list: []}},mounted() {this.list = new Array(50).fill({ a: 1, b: 10 })this.$nextTick(() => {window.print()})},methods: {}}Vue.createApp(DEMO).mount('#demo')</script></body></html>
根据表头自动计算打印分页
实现功能:动态表头,计算打印数据
注意:
- 在使用方法时,需要在打印时,将打印纸的宽高确定,在样式表设置打印的width,height
this.$uDeepClone 深克隆方法
this.$pluc cm、px转换方法
/*** 实现打印表头分页* 前提:表格结构* index 为外层循环的index* A4纸打印 21cm*29.7cm** <table>* <thead :ref="'thead' + index"></thead>* <tbody :ref="'tbody' + index">* <tr :ref="'tr' + index"></tr> //分割的数组* </tbody>* </table>** @param {Array} parentData 打印数据* @param {String} name 切分循环的数据*/export default {methods: {// 重写打印页面 根据改变打印数据 printData.tableList 实现calcPrintRender(parentData, name) {let footH = 30 //最后一行高度let pageH = this.$pluc.cm2px(29.7) - footH // 计算pxlet newPrintData = this.$uDeepClone(parentData) //重写数据newPrintData = newPrintData.map((v, i) => {v.symbol = i //添加标识位v.paging = '1/1'return v})for (let pI in parentData) {let item = parentData[pI]let detailArr = item[name]let thead = this.$refs[`thead${pI}`][0]let tbody = this.$refs[`tbody${pI}`][0]let tr = this.$refs[`tr${pI}`]if (thead && tbody && tr) {let theadH = thead.offsetHeight //头部高度let renderBody = pageH - theadHif (theadH > pageH) {continue}let tbodyH = tbody.offsetHeightconsole.log('pageH, theadH, tbodyH,renderBody', pageH, theadH, tbodyH, renderBody)// tr总高度let trTotal = tr.reduce((prev, next) => {console.log(next.offsetHeight)return prev + next.offsetHeight}, 0)// console.log(' trTotal', trTotal)if (theadH + tbodyH < pageH) {// 不做处理continue}// 获取渲染函数let sliceArr = this.deepRenderTr({ tr, renderBody, trTotal })// console.log('sliceArr', sliceArr)for (let newI in newPrintData) {let newItem = newPrintData[newI]if (newItem.symbol == pI) {let len = sliceArr.lengthif (len > 0) {let newArr = []sliceArr.forEach((v, i) => {let obj = this.$uDeepClone(item)if (i == 0) {obj[name] = detailArr.slice(0, v)} else {obj[name] = detailArr.slice(sliceArr[i - 1], v)}obj.paging = `${i + 1}/${len + 1}`newArr.push(obj)})// 推送最后一组数据let nObj = this.$uDeepClone(item)let last = sliceArr[len - 1] - detailArr.lengthnObj[name] = detailArr.slice(last)nObj.paging = `${len + 1}/${len + 1}`newArr.push(nObj)newPrintData.splice(newI, 1, ...newArr)}}}}}// console.log('new', newPrintData)return newPrintData},// 获取哪些tr需要截取deepRenderTr({ arr = [], tr, renderBody, trTotal }) {// 找到第一页 最后 tr的index 暂不考虑表头占满情况// console.log(arr, tr.length, renderBody, trTotal)let trSum = 0let firstPageIndex = nullfor (let trI in tr) {trSum += tr[trI].offsetHeightif (trSum >= renderBody) {firstPageIndex = trI - 1break}}if (firstPageIndex === null) {return arr} else {// 计算剩余高度let restH = trTotal - trSum + tr[firstPageIndex + 1].offsetHeightif (arr.length > 0) {let n = firstPageIndex + arr[arr.length - 1]arr.push(n)} else {arr.push(firstPageIndex)}if (restH < renderBody) {return arr} else {let newTr = tr.slice(firstPageIndex + 1, tr.length)let param = { arr: arr, tr: newTr, renderBody: renderBody, trTotal: restH }return this.deepRenderTr(param)}}},},}
cm与px的转换
var ratio = 0pluc()export default {px2cm: function(px) {return Math.floor((px * 10) / ratio) / 10},px2mn: function(px) {var r = ratio / 10return Math.floor(px / r)},cm2px: function(cm) {return Math.floor(cm * ratio)},mm2px: function(mm) {var r = ratio / 10return Math.floor(mm * r)},}function pluc() {'use strict'var div = document.createElement('div')div.style.width = '1cm'div.id = 'puc'document.body.appendChild(div)var w = getComputedStyle(div, null).widthratio = w.substr(0, w.length - 2)div.parentNode.removeChild(div)}
