Java使用POI为Excel打水印,调整列宽并设置Excel只读(用户不可编辑)

您所在的位置:网站首页 pdf怎么修改为只读模式 Java使用POI为Excel打水印,调整列宽并设置Excel只读(用户不可编辑)

Java使用POI为Excel打水印,调整列宽并设置Excel只读(用户不可编辑)

#Java使用POI为Excel打水印,调整列宽并设置Excel只读(用户不可编辑)| 来源: 网络整理| 查看: 265

本文介绍在Java语言环境下,使用POI为Excel打水印的解决方案,具体的代码编写以及相关的注意事项。

需求描述:

要求通过系统下载的Excel都带上公司的水印,列宽调整为合适的宽度,并且设置为不可编辑,即只读。

即:

1:加水印;

2:调整列宽将单元格内容显示全;

3:设置只读;

 

解决方案思路介绍:

三点需求比较来说,以第一点比较复杂,同时网上关于POI为Excel加水印的资料非常少,而这些资料又多数是相互之间Copy得来,干货较少。

 

一:使用模版Excel的形式设置水印:

目前网上关于POI为Excel打水印,主要是通过模版的形式来实现,即先准备一份打了水印的模版Excel,说白了就是在这个模版Excel中的一个Sheet中添加一些艺术字,调整下透明度还有字体,角度等,模仿水印,然后加载该模版,再将内容输出到该模版中,以达到为Excel添加水印的目的,详细可参考下面这份博客(不追溯该博客是否是原始版本):http://jsonchar.blog.163.com/blog/static/17601614120106135519213/

 

但这种方式有如下问题:

1:通过手动添加水印,水印数量固定:通过人工在一个Sheet中添加水印,个数必然固定,当实际内容行数不定,列数不定,会导致水印不能覆盖内容;

2:当无法确定下载的Excel会有多少个Sheet的时候,无法保证输出的多个Sheet都有水印:产生这种情况是因为,这种实现方式的根本原理是读取已经存在的模版Excel内的Sheet,并将内容输出到该Sheet中,也就是说如果模版内的Sheet内有水印则输出内容有水印,如果该Sheet没有水印则输出内容没有水印。毕竟通过手工添加水印,准备模版的方式,你不能准备无限多个模版Sheet,准备一个两个也就到头了。

3:你无法通过程序拷贝模版Sheet:你可能会问了,那我准备一个模版Sheet,在其中尽量多的打上水印,麻烦一点横向纵向多大点,然后再通过程序拷贝该模版Sheet,想其中输出内容的形式不行吗?很遗憾,不行,翻查POI的API你就会发现创建Sheet的方式就那么两个,即通过workbook进行创建,虽然sheet(无论类型)的构造函数是public的,但是你无法将你构造好的sheet添加到workbook中。当然,workbook也提供了cloneSheet的api,但是如果你的模版水印是通过艺术字或者图片的形式打上去的,那么也将无法拷贝。

 

所以这种方案,适合于输出的内容Sheet页个数固定,行数可控的形式,因为只有这些固定下来了,在提供模版Excel的时候才能做出合适的模版,在固定的sheet页,大致的行上打上水印。

 

二:使用程序将水印图片动态打到Sheet上:

因为上面方案的问题,我选择通过程序将提前准备好的水印图片打印到Sheet上的方案,这种方案的主要步骤为:

1:将需要输出的内容正常输出到Excel中,输出的Excel假定将存在多个Sheet,每个Sheet中内容的行数也不一定;

2:获取workbook对象,提取其中的多个sheet;

3:调用工具类,传入workbook和每一个sheet,根据提供好的水印图片将睡衣图片打到每一个sheet上,水印图片在sheet上的位置,个数等可配置;

 

要求:

1:水印图片是png格式,无背景,且水印主体颜色要尽可能浅,且细,避免遮挡excel上的信息;

2:使用的POI的版本是3.9,pom文件配置如下:

org.apache.poi poi 3.9 org.apache.poi poi-ooxml 3.9

 

步骤1和步骤2不提供代码,网上有很多,直接贴步骤三的代码,如下:

1 import java.awt.image.BufferedImage; 2 import java.io.ByteArrayOutputStream; 3 import java.io.IOException; 4 import java.io.InputStream; 5 6 import javax.imageio.ImageIO; 7 8 import org.apache.poi.ss.usermodel.ClientAnchor; 9 import org.apache.poi.ss.usermodel.Drawing; 10 import org.apache.poi.ss.usermodel.Picture; 11 import org.apache.poi.ss.usermodel.Sheet; 12 import org.apache.poi.ss.usermodel.Workbook; 13 14 /** 15 * Excel水印工具类 16 * @author gang.wang 17 * 2017年4月23日 18 */ 19 public class ExcelWaterRemarkUtils { 20 21 /** 22 * 为Excel打上水印工具函数 23 * 请自行确保参数值,以保证水印图片之间不会覆盖。 24 * 在计算水印的位置的时候,并没有考虑到单元格合并的情况,请注意 25 * @param wb Excel Workbook 26 * @param sheet 需要打水印的Excel 27 * @param waterRemarkPath 水印地址,classPath,目前只支持png格式的图片, 28 * 因为非png格式的图片打到Excel上后可能会有图片变红的问题,且不容易做出透明效果。 29 * 同时请注意传入的地址格式,应该为类似:"\\excelTemplate\\test.png" 30 * @param startXCol 水印起始列 31 * @param startYRow 水印起始行 32 * @param betweenXCol 水印横向之间间隔多少列 33 * @param betweenYRow 水印纵向之间间隔多少行 34 * @param XCount 横向共有水印多少个 35 * @param YCount 纵向共有水印多少个 36 * @param waterRemarkWidth 水印图片宽度为多少列 37 * @param waterRemarkHeight 水印图片高度为多少行 38 * @throws IOException 39 */ 40 public static void putWaterRemarkToExcel(Workbook wb, Sheet sheet, String waterRemarkPath, int startXCol, int startYRow, 41 int betweenXCol, int betweenYRow, int XCount, int YCount, 42 int waterRemarkWidth, int waterRemarkHeight) throws IOException{ 43 44 //校验传入的水印图片格式 45 if(!waterRemarkPath.endsWith("png") && !waterRemarkPath.endsWith("PNG")){ 46 throw new RuntimeException("向Excel上面打印水印,目前支持png格式的图片。"); 47 } 48 49 //加载图片 50 ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); 51 InputStream imageIn = Thread.currentThread().getContextClassLoader().getResourceAsStream(waterRemarkPath); 52 if(null == imageIn || imageIn.available() < 1){ 53 throw new RuntimeException("向Excel上面打印水印,读取水印图片失败(1)。"); 54 } 55 BufferedImage bufferImg = ImageIO.read(imageIn); 56 if(null == bufferImg) { 57 throw new RuntimeException("向Excel上面打印水印,读取水印图片失败(2)。"); 58 } 59 ImageIO.write(bufferImg,"png",byteArrayOut); 60 61 //开始打水印 62 Drawing drawing = sheet.createDrawingPatriarch(); 63 64 //按照共需打印多少行水印进行循环 65 for(int yCount=0; yCount


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3