首先需求是用户提出导出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. Spring Cloud 系列之 Consul 配置中心

    前面我们已经学习过 Spring Cloud Config 了: Spring Cloud 系列之 Config 配置中心(一) Spring Cloud 系列之 Config 配置中心(二) Spr ...

  2. 力扣题解-面试题10- II. 青蛙跳台阶问题

    题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶.求该青蛙跳上一个 n 级的台阶总共有多少种跳法. 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008, ...

  3. C# 数据操作系列 - 11 NHibernate 配置和结构介绍

    0. 前言 今天是NHibernate的第二篇内容,通过上一篇的内容,我们初步了解了NHibernate的创建和使用.这一篇,我继续探索NHibernate背后的秘密.嗯,就是这样. 1. NHibe ...

  4. 2.5 Hello golang

    编写第一个hello golang 创建空文件hello.go,尝试执行 touch hello.go go run hello.go 产生如下报错 can't load package: packa ...

  5. python3.x 基础三:文件IO

    打开文件的两种方式 1.直接打开文件并赋值给变量,打开后得到操作句柄,但不会自动关闭 file = open('文件名‘,'打开模式',’编码‘) fd = open('../config/file1 ...

  6. WXML属性一览表

    id属性 <view id="xxx"></view> class属性 <view class="xxx"></vie ...

  7. PAT-1056 Mice and Rice (分组决胜问题)

    1056. Mice and Rice Mice and Rice is the name of a programming contest in which each programmer must ...

  8. Python-pygame案例AI贪吃蛇

    # coding: utf-8 import pygame,sys,time,random from pygame.locals import * # 定义颜色变量 redColour = pygam ...

  9. 前端基础进阶(六):在chrome开发者工具中观察函数调用栈、作用域链与闭包

    在前端开发中,有一个非常重要的技能,叫做断点调试. 在chrome的开发者工具中,通过断点调试,我们能够非常方便的一步一步的观察JavaScript的执行过程,直观感知函数调用栈,作用域链,变量对象, ...

  10. 七个生产案例告诉你BATJ为何选择ElasticSearch!应用场景和优势!

    本文来源于公众号[胖滚猪学编程],转载请注明出处. 从今天开始,想和你一起死磕ElasticSearch,学习分布式搜索引擎,跟着胖滚猪就对了! 既然是ES的第一课,那么最重要的是让你爱上它!不想说那 ...