首先需求是用户提出导出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. linux wc 的用法-linux 下统计行数、单词数、字符个数

    linux wc 的用法-linux 下统计行数.单词数.字符个数   wc : wc -l 统计有多少行 wc -w 统计有多少个单词 wc -c 统计有多少个字符

  2. spark机器学习从0到1特征抽取–CountVectorizer(十三)

        一.概念 CountVectorizer 旨在通过计数来将一个文档转换为向量.当不存在先验字典时,Countvectorizer作为Estimator提取词汇进行训练,并生成一个CountVe ...

  3. Django视图函数之FBV与CBV模式

    FBV模式: FBV(function base views) 就是在视图里使用函数处理请求. 一般直接用函数写的都属于是FBV模式. veiws.py from django.shortcuts i ...

  4. python3.x 基础四:生成器与迭代器

    1.预先存值到内存,调用之前已经占用了内存,不管用与不用,都占用内存 >>> a=[1,2,3,4,5] >>> type(a) <class 'list'& ...

  5. TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

    我的项目在mac上运行的很好,结果windows电脑,就一直报这个错误 解决方案: babel增加 @babel/plugin-transform-modules-commonjs 参考文章: htt ...

  6. python基本数据类型;字符串及其方法三:

    ###################判断类型################### ######################################################### ...

  7. 模板:JSP公共内容

    page页面标签指令 <%@ page %> taglib标准标签指令 <%@ taglib %> 标签内基本属性 language="设置JSP页面使用的语言&qu ...

  8. centos7 安装rpm版的mysql遇到坑——误删root用户的恢复

    在网上找了教程http://blog.csdn.net/frankcheng5143/article/details/77609093安装过程很顺利,随着修改了root的密码后不下心误删了root账号 ...

  9. rocketmq初识

    概念说明 通常一个消息队列需要掌握的知识点有Topic(主体).Producer(生产者).Consumer(消费者).Queue(队列).Delivery Semantics(消息传递范式) 蛋疼的 ...

  10. 【C++】常见易犯错误之数值类型取值溢出与截断(2)

    本节内容紧接上节,解决红色字体遗留问题.本节所有例子运行环境: win10 + VS2015 + X64 + debug 在上节例子中,查看变量 c .d .d+1 的类型. //// Console ...