文章目录

  • 前言
  • 一、导入maven依赖
  • 二、工具类
  • 三、如何使用
  • 四、总结
  • 五、参考

前言

最近要完成 Excel 导出添加水印,但是查了一圈一般导出只支持 XSSFWorkbook ,没有支持 SXSSFWorkbook 的,接下来我要完成导出 Excel SXSSFWorkbook 和 XSSFWorkbook 模式添加水印
效果图


一、导入maven依赖

     <!--POI 相关依赖 start --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.4</version></dependency><!--POI 相关依赖 end --><!--hutool 工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.5.11</version></dependency>

hutool 工具类主要是用到里面的反射工具类,大家自己写反射就可以不用这个工具包。

二、工具类

代码如下:

package 你的包;import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.*;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;/*** Excel 添加水印。支持 SXSSFWorkbook 和 XSSFWorkbook 模式** @author Kim Jong-un* @since 2022-01-17*/
public class WaterMarkUtil {/*** Excel 导出添加水印** @param workbook ExcelWorkbook*/public static void insertWaterMarkTextToXlsx(Workbook workbook) throws IOException {String sysName = "朝鲜合众国运营平台"; //系统名称String userName = "金正恩"; //导出人String date = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN); //yyyy-MM-ddString waterMarkText = sysName + "\n" + userName + "  " + date;if (workbook instanceof SXSSFWorkbook) {insertWaterMarkTextToXlsx((SXSSFWorkbook) workbook, waterMarkText);} else if (workbook instanceof XSSFWorkbook) {insertWaterMarkTextToXlsx((XSSFWorkbook) workbook, waterMarkText);}//throw new RemoteException("HSSFWorkbook 模式不支持 Excel 水印");}/*** 给 Excel 添加水印** @param workbook      SXSSFWorkbook* @param waterMarkText 水印文字内容*/public static void insertWaterMarkTextToXlsx(SXSSFWorkbook workbook, String waterMarkText) throws IOException {BufferedImage image = createWatermarkImage(waterMarkText);ByteArrayOutputStream imageOs = new ByteArrayOutputStream();ImageIO.write(image, "png", imageOs);int pictureIdx = workbook.addPicture(imageOs.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG);XSSFPictureData pictureData = (XSSFPictureData) workbook.getAllPictures().get(pictureIdx);for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表SXSSFSheet sheet = workbook.getSheetAt(i);//这里由于 SXSSFSheet 没有 getCTWorksheet() 方法,通过反射取出 _sh 属性XSSFSheet shReflect = (XSSFSheet) ReflectUtil.getFieldValue(sheet, "_sh");PackagePartName ppn = pictureData.getPackagePart().getPartName();String relType = XSSFRelation.IMAGES.getRelation();PackageRelationship pr = shReflect.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);shReflect.getCTWorksheet().addNewPicture().setId(pr.getId());}}/*** 给 Excel 添加水印** @param workbook      XSSFWorkbook* @param waterMarkText 水印文字内容*/public static void insertWaterMarkTextToXlsx(XSSFWorkbook workbook, String waterMarkText) throws IOException {BufferedImage image = createWatermarkImage(waterMarkText);ByteArrayOutputStream imageOs = new ByteArrayOutputStream();ImageIO.write(image, "png", imageOs);int pictureIdx = workbook.addPicture(imageOs.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG);XSSFPictureData pictureData = workbook.getAllPictures().get(pictureIdx);for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表XSSFSheet sheet = workbook.getSheetAt(i);PackagePartName ppn = pictureData.getPackagePart().getPartName();String relType = XSSFRelation.IMAGES.getRelation();PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);sheet.getCTWorksheet().addNewPicture().setId(pr.getId());}}/*** 创建水印图片** @param waterMark 水印文字*/public static BufferedImage createWatermarkImage(String waterMark) {String[] textArray = waterMark.split("\n");Font font = new Font("microsoft-yahei", Font.PLAIN, 32);int width = 500;int height = 400;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 背景透明 开始Graphics2D g = image.createGraphics();image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);g.dispose();// 背景透明 结束g = image.createGraphics();g.setColor(new Color(Color.lightGray.getRGB()));// 设定画笔颜色g.setFont(font);// 设置画笔字体//   g.shear(0.1, -0.26);// 设定倾斜度//        设置字体平滑g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//文字从中心开始输入,算出文字宽度,左移动一半的宽度,即居中FontMetrics fontMetrics = g.getFontMetrics(font);// 水印位置int x = width / 2;int y = height / 2;// 设置水印旋转g.rotate(Math.toRadians(-40), x, y);for (String s : textArray) {// 文字宽度int textWidth = fontMetrics.stringWidth(s);g.drawString(s, x - (textWidth / 2), y);// 画出字符串y = y + font.getSize();}g.dispose();// 释放画笔return image;}/*** 设置打印的参数** @param wb XSSFWorkbook*/public static void setPrintParams(XSSFWorkbook wb) {XSSFSheet sheet = wb.getSheetAt(0);XSSFPrintSetup printSetup = sheet.getPrintSetup();// 打印方向,true:横向,false:纵向(默认printSetup.setLandscape(true);//设置A4纸printSetup.setPaperSize(XSSFPrintSetup.A4_PAPERSIZE);// 将整个工作表打印在一页(缩放),如果行数很多的话,可能会出问题// sheet.setAutobreaks(true);//将所有的列调整为一页,行数多的话,自动分页printSetup.setScale((short) 70);//缩放的百分比,自行调整sheet.setAutobreaks(false);}
}

三、如何使用

代码如下(示例1):

 XSSFWorkbook workbook = new XSSFWorkbook();//...你的逻辑...WaterMarkUtil.insertWaterMarkTextToXlsx(workbook); //调用这段代码后水印就添加成功了

代码如下(示例2):

 SXSSFWorkbook workbook = new SXSSFWorkbook();//...你的逻辑...WaterMarkUtil.insertWaterMarkTextToXlsx(workbook); //调用这段代码后水印就添加成功了

四、总结

  1. 注意这个工具类不支持 HSSFWorkbook 导出的方式
  2. SXSSFWorkbook 模式导出为什么要用反射?
    因为 SXSSFWorkbook 通过
    SXSSFSheet sheet = workbook.getSheetAt(i);
    获取SXSSFSheetSXSSFSheet中没有XSSFSheet的方法,
    而且SXSSFSheet中的XSSFSheet是被final修饰的final XSSFSheet _sh;
    所以可以用个取到反射从SXSSFSheet中取到XSSFSheet,这样就解决了没有XSSFSheet中类中方法的问题了

    五、参考

    https://blog.csdn.net/dream_broken/article/details/115489269
    https://www.cnblogs.com/skyislimit/articles/10514719.html
    https://blog.csdn.net/qq_37258792/article/details/111302978

POI导出 Excel 加水印支持 SXSSFWorkbook 和 XSSFWorkbook 模式相关推荐

  1. POI导出EXCEL带水印 以及单元格格式设置

    客户提个需求,需要将报表导出 excel带水印 和 pdf带水印 2个版本. 做的时候连excel本身怎么带水印都不知道,更不用说用java了.后来在网上搜到了excel添加水印的2个方法. 1.艺术 ...

  2. Java使用POI为Excel打水印,调整列宽并设置Excel只读

    武林游戏 2017-05-02 11:15 本文介绍在Java语言环境下,使用POI为Excel打水印的解决方案,具体的代码编写以及相关的注意事项. 需求描述: 要求通过系统下载的Excel都带上公司 ...

  3. JAVA POI导出EXCEL设置自定义样式(线框加粗,合并指定行,合计求和,冻结行)

    前面部分是当时查询的记录: 实现Excel文件单元格合并.冻结和文件导出 Workbook wb = new HSSFWorkbook();Sheet sheet = wb.createSheet(& ...

  4. poi导出excel,给excel加背景色。兼容office和wps

    最近一段时间在研究poi导出excel的时候给excel加一些样式,像居中,设置字体之类的在网上搜的方法都是可以表现出来的,但是在设置背景色的时候遇到了一些问题,使用 cellStyle.setFil ...

  5. Java利用注解实现配置动态公式并结合POI导出Excel

    利用注解实现动态配置公式并结合POI导出Excel 实现思想 创建导出对象 创建使用注解类 创建封装导出对象属性类 创建测试类 创建ExcelUtil类 实现效果 实现思想 实施顾问提出导出Excel ...

  6. excel加水印,由于excel没有加水印功能,实际上操作是将图片丢进去

    目录 1.依赖 2.controller层代码 3.工具类 1.依赖 <!--excel poi--><dependency><groupId>org.apache ...

  7. POI导出Excel遇到数据量大该如何解决

    最近在使用Java POI导出Excel,使用的是XSSFWorkbook ,遇到数据量超过10w的话程序会爆内存溢出的错误,将XSSFWorkbook 换成SXSSFWorkbook 即可 SXSS ...

  8. POI导出Excel (满满的干货啊)

    已经实现的POI导出Excel 步骤一:导入依赖 <dependency><groupId>org.apache.poi</groupId><artifact ...

  9. JAVA导出Excel通用工具类——第一篇:详细介绍POI 导出excel的多种复杂情况,包括动态设置筛选、动态合并横向(纵向)单元格等多种复杂情况——保姆级别,真的不能再详细了,代码拿来即用)

    JAVA导出Excel通用工具--第一篇:详细介绍POI 导出excel的多种复杂情况,包括动态设置筛选.动态合并横向(纵向)单元格等多种复杂情况--保姆级别,真的不能再详细了,封装通用工具类,代码拿 ...

  10. Java POI 导出EXCEL经典实现 Java导出Excel弹出下载框

    原文转载:http://blog.csdn.net/evangel_z/article/details/7332535 目录(?)[+] 在web开发中,有一个经典的功能,就是数据的导入导出.特别是数 ...

最新文章

  1. java生成验证码登录,生成验证码
  2. 安装orb_slam 的坑解决方法
  3. Python基础教程:迭代器
  4. 微软亚洲研究院的“人立方”搜索
  5. PL/SQL Developer使用技巧总结
  6. ruby on rails ajax select
  7. libcap-ng库旨在使具有posix功能的编程比传统的libcap库容易得多
  8. python中or的用法_解析python中and与or用法
  9. 【已解决】Could not get lock /var/lib/dpkg/lock-frontend
  10. Oracle 新建用户、赋予权限
  11. JAVA中如何产生透明的VolatileImage
  12. 电子仿真软件MultiSIM
  13. udp 消息转发 服务器,UDP消息发送
  14. 图纸管理协同办公软件推荐
  15. 计算机专业考信息安全研究生,我是计算机科学与技术专业的学生,想考信息安全的研究生,我们本专业涉及的知识主要是计算机的组成原理,...
  16. kalibr源码解析之fov模型重投影误差计算
  17. 解读神经网络十大误解,再也不会弄错它的工作原理
  18. MYSQL数据库学习总结
  19. 全志h2参数_全志h3芯片性能及参数评测
  20. 记录一下获取的动态ip与路由器ip不符所以要纠错的日常

热门文章

  1. 4G远程小车1-树莓派读取WTGPS+BD模块
  2. 新手SEO优化原创与伪原创
  3. 中兴网信发布“广义智慧城市顶层设计框架”
  4. android9手机电池管家,腾讯电池管家APP
  5. 【腾讯地图】纯手写微信定位考勤小程序,内附完整源码!
  6. Action语义学综述
  7. Java实现极光推送
  8. 联想IBM笔记本驱动
  9. 冒泡排序 java代码实现
  10. 大神级ppt作品欣赏_【重磅源文件来了】课程更新2019苹果宣传片PPT福利来袭