el-table打印PDF预览,表头错位的解决方案

文章目录

背景与需求

本例以vue2项目为例,vue3与react等同理。

有个项目需要打印的功能,网页使用vue2写的,主体内容为表格el-table,添加某个按钮,点击按钮时弹出PDF打印预览,示例如下:

需求分析

通常我们会使用vue-print-nb组件,通过一些配置即可实现需求,但是会出现一些奇怪的bug,比如:

  • 表头错位
  • 首页尾页多出一页
  • 边框线不显示
  • 表格的边框1px不会不显示的问题
  • 某些边框变粗了......

以上问题会在下面解决!

解决方案

方案一:vue-print-nb插件

vue-print-nb是vue项目中用的比较广泛的打印预览插件,其npm地址如下:

vue-print-nb文档(https://www.npmjs.com/package/vue-print-nb)

安装

javascript 复制代码
npm install vue-print-nb --save

引入

在main.js中引入并注册插件:

javascript 复制代码
import Print from 'vue-print-nb'
Vue.use(Print)

使用

在需要的vue组件中使用:

javascript 复制代码
<template>
  <div class="app-container">
    <el-button type="primary" size="medium" v-print="printObj">报表打印</el-button>

    <div id="printArea" ref="gatprintArea">
      打印区域,内容自定义
    </div>
    
  </div>
</template>

<script>
  export default {
    data() {
      return {
        printObj: {
          id: 'printArea', // 这里是要打印元素的ID
          popTitle: '&nbsp', // 打印的标题
        },
      };
    },
  };
</script>

通过上述代码,我们可以实现打印并预览PDF的效果,但是实际应用中会出现之前说的问题。

原图:

预览效果图:

可以看到,没有把完整的表格区域打印出来,而且表格的很多边框线没显示,我们给它添加一些样式,先让它能完整的打印出来:

javascript 复制代码
  ::v-deep table {
    table-layout: auto;
  }
  ::v-deep .el-table__header-wrapper .el-table__header {
    width: 100% !important;
  }
  ::v-deep .el-table__body-wrapper .el-table__body {
    width: 100% !important;
  }
  ::v-deep .el-table .cell.el-tooltip {
    text-overflow: clip;
    white-space: normal;
    min-width: none;
    width: auto !important;
    border: none !important;
  }

添加完样式之后,表格能完整的显示出来了,效果如下:

但是边框线还是不显示,再加一些样式如下:

javascript 复制代码
  @page{
    size:  auto;
    margin-bottom: 0; //去掉页脚
  }

  @media print{
    body {
      margin: 0;
      padding: 0;
    }
    #printArea {
      page-break-inside: avoid;
    }

    ::v-deep .el-table th.gutter {
      display: table-cell !important;
    }

    // 设置表格边框样式
    ::v-deep table {
      //table-layout: auto;
      border: 1px solid #dfe6ec !important;
      border-color: #dfe6ec !important;
      //border-collapse: collapse;
      font-size: 12px !important;
      td {
        border-right: 1px solid  #dfe6ec !important;
        border-bottom: 1px solid  #dfe6ec !important;
      }
      tbody {
        border-left: 1px solid  #dfe6ec !important;
      }
      th {
        border: 1px solid #dfe6ec !important;
        border-bottom: none !important;
        width: auto !important;
      }
      .cell {
        padding: 0 !important;
      }
    }
    ::v-deep thead tr th {
      border-right: 0 !important;
    }
   
    // 清除原来的边框样式
    ::v-deep .el-table--border::after,
    .el-table--group::after,
    .el-table::before {
      background-color: transparent;
    }
    ::v-deep .el-table th {
      border-bottom: 1px solid #dfe6ec;
      background: #F5F7FA !important;
    }
    ::v-deep {
      .el-table--border::after {
        display: none !important;
      }
      .el-table__header {
        border: 0 !important;
        .gutter {
          width: 0 !important;
        }
      }
      thead tr:nth-child(1) th:nth-child(1) {
        border-left: 0 !important;
      }
    }
  }

现在可以看到,边框线经过处理后,基本都能显示出来了,但是还有表头错位的问题没有解决,这是因为预览时,表格自动计算的宽度会存在误差,且目前无法避免(即使没有多级表头),效果如下:

既然这样会存在一点问题,那么我们只能试试第二种方案了。

方案二

html2canvas与print-js结合,其原理是先把需要打印的内容转化为图片,然后打印预览图片,这样就不会出现表头错位的问题了。

安装

javascript 复制代码
npm install --save html2canvas
npm install --save print-js

使用

示例代码如下:

javascript 复制代码
<template>
  <div class="app-container">
    <el-button type="primary" size="medium" @click="onPrint">报表打印</el-button>

    <div id="printArea" ref="gatprintArea">
      打印区域,内容自定义
    </div>
    
  </div>
</template>

<script>

import html2canvas from "html2canvas";
import printJS from "print-js";
export default {
  
  methods: {
    
    // 方案二,这种方法不会错位
    onPrint() {
      const printContent = this.$refs.gatprintArea; //获取上面的ref对应的组件实例
 
      // 获取dom 宽度 高度
      const width = printContent.clientWidth + 2; //如果有边框可适当增加2~10之间的画布大小
      const height = printContent.clientHeight + 2;//如果有边框可适当增加2~10之间的画布大小
      // 创建一个canvas节点
      const canvas = document.createElement('canvas');

      const scale = 1; // 定义任意放大倍数,支持小数;越大,图片清晰度越高,生成图片越慢。
      canvas.width = width * scale; // 定义canvas 宽度 * 缩放
      canvas.height = height * scale; // 定义canvas高度 *缩放
      canvas.style.width = width * scale + 'px';
      canvas.style.height = height * scale + 'px';
      canvas.getContext('2d').scale(scale, scale); // 获取context,设置scale

      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 获取滚动轴滚动的长度
      const scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; // 获取水平滚动轴的长度
      
      html2canvas(printContent, {
        canvas,
        // backgroundColor: null,
        useCORS: true,
        windowHeight: document.body.scrollHeight,
        scrollX: -scrollLeft, // 解决水平偏移问题,防止打印的内容不全
        scrollY: -scrollTop
      }).then((myCanvas) => {
        const url = myCanvas.toDataURL('image/png')
        printJS({
          printable: url,
          type: 'image',
          documentTitle: '', // 标题
          style: '@page{size:auto;margin: 0.5cm 1cm 0cm 1cm;}' // 去除页眉页脚
        })
      }).catch(err => {
        console.error(err);
      })
    }
  }
};
</script>

可以从下图看到,虽然显示效果没有方案一的好,但是实现了功能,示例图如下:

如果打印的内容超过一页,会在收尾出现空白页,可添加样式如下:

javascript 复制代码
printJS({
 printable: url,
  type: 'image',
  documentTitle: '', // 标题
  style: '@page{size:auto;margin: 0.5cm 1cm 0cm 1cm;}body{margin:0}' // 去除页眉页脚
})

至此,本方案成功解决需求

方案三

看了网友的一个方案,就是把表头隐藏起来:show-header="false" ,把表头放到表格内容中,再稍微调整一下样式,这样就不会出现错位了,因为表头和内容自动分配宽度,也页面内可以正确对齐,但是打印时又计算了,其他因素影响导致错位的。

总结

方案一显示下过好,但是表头错位问题无法解决,如果不涉及el-table表头,打印预览其他内容时,本方案很推荐

如果方案一无法解决,那么就用方案二

如果表格简单,也可以用方案三

如果有更好的解决方案,欢迎评论!

相关推荐
ydjs678899-bot11 小时前
如何在Java中打印pdf静默打印和打印对话框选择
java·python·pdf
SamChan9013 小时前
PDF 翻译后 1,250 变成 1.250,是错了吗?用 Python 核对数字格式
python·pdf·ocr·数据校验·文档翻译
开开心心就好16 小时前
打印机卡住打不了?一键清理卡死打印队列
服务器·开发语言·算法·pdf·ocr·idea·visual studio code
打工仔折腾 AI1 天前
在线PDF工具隐私焦虑?把BentoPDF部署到极空间NAS本地处理
人工智能·后端·python·pdf·ai agent 实战
霸道流氓气质2 天前
AI 简历制作平台:结构化输出解析、多模板渲染与 PDF 导出的 Vue3 + Spring AI 全栈实战
人工智能·spring·pdf
开开心心_Every2 天前
黄金价格软件国内外价格实时监控超方便
运维·服务器·游戏·智能手机·pdf·lua·perl
JasonSJX2 天前
DRM-X 5.0 PDF 保护更新:Windows 与 Mac 打印保留用户水印,ZJGet iOS 版支持 PDF 阅读
macos·pdf
shmily麻瓜小菜鸡2 天前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
ComPDFKit3 天前
PDF 涂黑后还能复制?用 ComPDF 检查敏感文字是否真正删除
pdf
飞塔老梅子3 天前
21. 按页数或章节分割大PDF文件 ❀ 老梅子学AI
pdf·分割·basic·pdfsam·裁切