首先需求是用户提出导出excel数据需使用水印备注其用途;

其实就是在导出excel的同时带有自定义文字水印的导出。

那么我们首先想到的肯定是以一个什么样的思路去解决该问题,首先查找poi导出excel有没有相关技术可以直接导出文字水印,可想而知我写了这篇博客,当然是没有一步走成的方法

那么我们开始换一种思路,大家都知道图片可以添加文字水印和图片水印,那么既然图片可以添加文字水印,可能就可以想到excel可以导出图片的功能。那么我们可以先创建一个透明色的图片,然后添加文字水印,最后添加到excel中导出,结束,那么我们直接来看实现

首先看一下如何生成有文字水印的透明色图片

/**
* 生成背景透明的 文字水印,文字位于透明区域正中央,可设置旋转角度
*
* @param width 生成图片宽度
* @param heigth 生成图片高度
* @param text 水印文字
* @param color 颜色对象
* @param font awt字体
* @param degree 水印文字旋转角度
* @param alpha 水印不透明度0f-1.0f
*/
public static BufferedImage waterMarkByText(int width, int heigth, String text, Color color,
Font font, Double degree, float alpha) {
BufferedImage buffImg = new BufferedImage(width, heigth, BufferedImage.TYPE_INT_RGB);
/**2、得到画笔对象*/
Graphics2D g2d = buffImg.createGraphics();
// ---------- 增加下面的代码使得背景透明 -----------------
buffImg = g2d.getDeviceConfiguration().createCompatibleImage(width, heigth, Transparency.TRANSLUCENT);
g2d.dispose();
g2d = buffImg.createGraphics();
// ---------- 背景透明代码结束 ----------------- // 设置对线段的锯齿状边缘处理
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// 设置水印旋转
if (null != degree) {
//注意rotate函数参数theta,为弧度制,故需用Math.toRadians转换一下
//以矩形区域中央为圆心旋转
g2d.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
}
// 设置颜色
g2d.setColor(color);
// 设置 Font
g2d.setFont(font);
//设置透明度:1.0f为透明度 ,值从0-1.0,依次变得不透明
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
//计算绘图偏移x、y,使得使得水印文字在图片中居中
//这里需要理解x、y坐标是基于Graphics2D.rotate过后的坐标系
int x = -width / 3;
int y = -heigth / 2;
// 字体长度
int markWidth = font.getSize() * getTextLength (text);
// 字体高度
int markHeight = font.getSize();
// 循环添加水印
while (x < width * 1.5) {
y = -heigth / 2;
while (y < heigth * 1.5) {
g2d.drawString (text, x, y);
y += markHeight + 200;
}
x += markWidth + 200;
}
//取绘制的字串宽度、高度中间点进行偏移,使得文字在图片坐标中居中
//释放资源
g2d.dispose();
return buffImg;

然后在原来的导出文件方法中添加用来获取已经添加文字的透明色图片

 /**
* 生成导出文件
* @param sheetName
* @param dataItems
* @param columnKeys
* @param columnNames
* @throws IOException
*/
public static void initExportFileToWb(HSSFWorkbook wb,String sheetName,List<Map<String,Object>> dataItems,List<String> columnKeys,List<String> columnNames,String waterText) throws IOException {
HSSFSheet sheet = wb.createSheet(sheetName);
// 设置安全性密码
sheet.protectSheet(UUID.randomUUID().toString());
HSSFRow row = sheet.createRow(0);
row.setHeight((short) 500);
// 学生信息excel
// 初始化头部
initHeader(wb,sheet,columnNames);
// 初始化数据
initData(sheet, dataItems, columnKeys,columnNames);
     // 根据导出列数计算图片的宽度 153和17是写定的,大家看情况
int width = columnNames.size()*153;
     // 根据导出数据计算图片的高度
int height = (dataItems.size()+2)*17;
     // 获取有文字水印的透明色图片
BufferedImage water = CommonUtils.getWaterImage(width,height,waterText);
     导入图片
putWaterRemarkToExcel(wb,sheet,water,20,40);
}

最后就是导出excel时插入图片

/**
* 为Excel打上水印工具函数
* 请自行确保参数值,以保证水印图片之间不会覆盖。
* 在计算水印的位置的时候,并没有考虑到单元格合并的情况,请注意
* @param wb Excel Workbook
* @param sheet 需要打水印的Excel
* @param waterRemarkPath 水印地址,classPath,目前只支持png格式的图片,
* 因为非png格式的图片打到Excel上后可能会有图片变红的问题,且不容易做出透明效果。
* 同时请注意传入的地址格式,应该为类似:"\\excelTemplate\\test.png"
* @param waterRemarkWidth 水印图片宽度为多少列
* @param waterRemarkHeight 水印图片高度为多少行
* @throws IOException
*/
public static void putWaterRemarkToExcel(HSSFWorkbook wb,HSSFSheet sheet, BufferedImage waterRemarkPath,
int waterRemarkWidth, int waterRemarkHeight) throws IOException{ //加载图片
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
if(null == waterRemarkPath) {
throw new RuntimeException("向Excel上面打印水印,读取水印图片失败(2)。");
}
ImageIO.write(waterRemarkPath,"png",byteArrayOut);
//开始打水印
Drawing drawing = sheet.createDrawingPatriarch();
/*
* 参数定义:
* 第一个参数是(x轴的开始节点);
* 第二个参数是(是y轴的开始节点);
* 第三个参数是(是x轴的结束节点);
* 第四个参数是(是y轴的结束节点);
* 第五个参数是(是从Excel的第几列开始插入图片,从0开始计数);
* 第六个参数是(是从excel的第几行开始插入图片,从0开始计数);
* 第七个参数是(图片宽度,共多少列);
* 第8个参数是(图片高度,共多少行);
*/
ClientAnchor anchor = drawing.createAnchor(0, 0, 255, 255, 0, 0, waterRemarkWidth, waterRemarkHeight);
Picture pic = drawing.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG));
pic.resize(); }

完成后查看导出excel结果

最后既然是水印,当然该文件不可操作,可通过设置查看密码进行限制,限制如图

// 设置安全性密码,随机的谁也不知道
sheet.protectSheet(UUID.randomUUID().toString());

完美解决!第一次写博客有问题大家多多指教,谢谢!

完成该需求参考了:

https://www.cnblogs.com/wanggangblog/p/6767481.html

https://www.cnblogs.com/wzluo09/p/9669989.html

java解决poi导出excel文字水印,导出excel不可操作问题的更多相关文章

  1. Java集成POI进行Excele的导入导出,以及报错: java.lang.AbstractMethodError..........

    报错信息如下 java.lang.AbstractMethodError: org.apache.poi.xssf.usermodel.XSSFCell.setCellType(Lorg/apache ...

  2. Java使用POI的SXSSFWorkbook与HSSFWorkbook导出复杂表头

    一.HSSFWorkbook与SXSSFWorkbook的区别: HSSFWorkbook是对Excel2003以前的版本进行操作的,即后缀名为.xls SXSSFWorkbook时对Excel200 ...

  3. Java使用poi从数据库读取数据生成Excel表格

    想要使用POI操作以xsl结尾的Excel,首先要下载poi相关的jar包,用到的jar有: poi-3.9.jar poi-ooxml-3.9.jar poi-ooxml-schemas-3.9.j ...

  4. Java导出数据行写入到Excel表格:基于Apache POI

    Java导出数据行写入到Excel表格:基于Apache POI import java.io.File; import java.io.FileOutputStream; import org.ap ...

  5. Java利用POI导入导出Excel中的数据

         首先谈一下今天发生的一件开心的事,本着一颗android的心我被分配到了PB组,身在曹营心在汉啊!好吧,今天要记录和分享的是Java利用POI导入导出Excel中的数据.下面POI包的下载地 ...

  6. JAVA通过poi对Excel数据在(jsp+ssh)环境下导入导出

    POI的下载与安装  请到网站http://www.apache.org/dyn/closer.cgi/poi/右击超链接2.5.1.zip下载压缩包poi-bin-2.5.1-final-20040 ...

  7. 解决poi导出Excel异常org.openxmlformats.schemas.spreadshe

    JAVA报表 POI未捕获到 servlet OUTEXCEL 的其中一个服务方法中抛出的异常.抛出的异常:java.lang.NoClassDefFoundError: org.openxmlfor ...

  8. java实现excel的导入导出(poi详解)

    经过两天的研究,现在对excel导出有点心得了.我们使用的excel导出的jar包是poi这个阿帕奇公司的一个项目,后来被扩充了.是比较好用的excel导出工具. 下面来认识一下这个它吧. 我们知道要 ...

  9. java实现excel的导入导出(poi详解)[转]

    java实现excel的导入导出(poi详解) 博客分类: java技术 excel导出poijava  经过两天的研究,现在对excel导出有点心得了.我们使用的excel导出的jar包是poi这个 ...

随机推荐

  1. HTTP Status完整枚举

    HTTP Status完整枚举 public enum HttpStatus { // 1xx Informational    1xx信息类的 继续    CONTINUE(100, "C ...

  2. 2018-06-28 jq CSS处理

    CSS处理 1.CSS样式 css() -> 获取jq对象的css样式 css({'':"'}) ->设置jq对象的css样式 相当于js对象的style()方法 2.位置 of ...

  3. 黑马程序员_毕向东_Java基础视频教程——switch语句练习(随笔)

    switch(练习) /* if和 switch 语句很像. 具体什么场景下使用什么语句呢? 如果判断的具体数值不多且符合byte.short.int.char.String类型,虽然两个语句都可以使 ...

  4. 接口testing简介

    一.基础介绍 1.什么是接口 我们常说的接口一般指2种1)API:应用程序编程接口 2)GUI:图形用户界面(接口) 这里我们主要说API——接口测试   2.接口测试的目的 测试接口的正确性和稳定性 ...

  5. com.zx.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization. 报错问题

    数据库连接问题 需要处理的地方有3处 1.url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncodi ...

  6. python3.x 基础一

    1.python 格式化print #/usr/bin/env python #-*- coding: utf-8 -*- #Author:jenvid.yang # 连接符号+,可以连接多个变量或者 ...

  7. BZOJ1059 二分匹配

    1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4810  Solved: 2297[Submit][Stat ...

  8. poj3177 无向连通图加多少条边变成边双连通图

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15752   Accepted: 6609 ...

  9. Python的自定义属性访问跟描述器以及ORM模型的简单介绍

    一 . 自定义属性访问 1.__getattr__ 作用:当我们访问属性的时候,如果属性不存在(出现AttrError),该方法会被触发. 2.__getattribute__ 作用:访问属性的时候, ...

  10. JavaScript的流程控制语句以及函数

    一.流程控制 1. 作用:控制代码的执行顺序 2. 分类 2.1顺序结构:从上到下依次执行代码语句 2.2选择结构: 1. if语句 简单if结构 if(条件表达式){ 表达式成立时执行的代码段 } ...