上篇 这么优秀的Excel工具类,你难道不用?介绍了Java使用poi操作excel表格的导入和修改,在日常开发中经常也会遇到在页面上点击按钮将数据库中的数据导出到excel表中;

今天我就遇到这么一个需求:根据条件将查询到的数据导出到Excel表格中要支持xls/xlsx两种不同类型的excel文件,携带水印效果,并且每个人导出时水印要不同。

(听听听听,这说的是人话吗… )

在了解Excel的水印其实就是插入艺术字再修改字体的颜色、字体、透明度就变成了所谓的水印效果了(一顿操作后我发现其实就类似插入一张透明文字图片);

思路:

根据对Excel的了解及上网查阅了几篇文章后,整理出了思路。

在对Excel完成数据的写入后,可以生成一张类似的透明文字图片,再将该图片插入到Excel表格中,就形成了水印的效果;

来人,上代码!!!

接口请求控制层:

@RestController
@RequestMapping("v1/perFee")
public class PerFeeController {​@GetMapping("/expirApplyedList")public void expirApplyedList(HttpServletResponse response,@RequestParam(required = false) Integer status, @RequestParam(required = false) String name,@RequestParam(required = false) String idNumber, @RequestParam(required = false) String phone ,@RequestParam(required = false) String exhId,@RequestParam(required = true) String filePath) {​PerFee perFee=new PerFee();perFee.setStatus(status);perFee.setName(name);perFee.setPhone(phone);perFee.setIdNumber(idNumber);perFee.setExhId(exhId);
​List<PerFee> perFeeList=perFeeService.applyedList(perFee);
​//excel标题String[] title = {"报销编号","报销人", "实际报销金额","状态"};
​//excel文件名String fileName = "报销费用审核_" + System.currentTimeMillis() + "." + filePath;//sheet名String sheetName = "报销费用审核";
​String [][] content = new String[perFeeList.size()][title.length];for (int i = 0,size=perFeeList.size();i < size; i++) {//content[i] = new Stri ng[title.length];PerFee obj = perFeeList.get(i);content[i][0] = String.valueOf(i+1);content[i][1] = obj.getName();content[i][2] = obj.getAccount();Integer status1 = obj.getStatus();String stat = "";if (status1 == 1) {stat = "财务审核中";}else if (status1 == 2) {stat = "已通过审核";}content[i][3] = stat;}
​//创建HSSFWorkbookWorkbook wb = ExcelUtils.expirWorkbook(sheetName, title, content, createWorkbook(filePath));
​//响应到客户端OutputStream os = null;try {try {fileName = new String(fileName.getBytes(), "ISO8859-1");} catch (UnsupportedEncodingException e) {e.printStackTrace();}response.setContentType("application/octet-stream;charset=ISO8859-1");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);response.addHeader("Pargam", "no-cache");response.addHeader("Cache-Control", "no-cache");
​os = response.getOutputStream();wb.write(os);os.flush();} catch (Exception ex) {ex.printStackTrace();}finally {if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}}}
​/*** 根据文件格式创建Workbook* @param filePath* @return*/private static Workbook createWorkbook(String filePath) {Workbook wb = null;try {//如果文件后缀名为xlsif ("xls".equals(filePath)) {wb = new HSSFWorkbook();}//如果文件后缀名为xlsxelse if ("xlsx".equals(filePath)) {wb = new XSSFWorkbook();} else {wb = null;}}catch (Exception e) {e.printStackTrace();}return wb;}
​
}

ExcelUtils工具类:

public class ExcelUtils{​/*** 导出Excel* @param sheetName sheet名称* @param title 标题(列头)* @param values 内容* @param wb Workbook对象  工作簿* @return*/public static Workbook expirWorkbook(String sheetName, String []title, String [][]values, Workbook wb){​// 第一步,在workbook中添加一个sheet,对应Excel文件中的sheetSheet sheet = wb.createSheet(sheetName);//设置列宽sheet.setColumnWidth(2,256*19+184);sheet.setColumnWidth(3,256*12+184);//sheet.setColumnWidth(4,256*20+184);
​//设置工作簿保护模式,只读不可修改。使用UUID获取随机值作为密码sheet.protectSheet(UUID.randomUUID().toString());
​// 第二步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制Row row = sheet.createRow(0);
​// 第三步,创建单元格,并设置值表头 设置表头居中CellStyle style = wb.createCellStyle();//style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式
​//声明列对象Cell cell = null;
​//创建标题for(int i=0;i<title.length;i++){cell = row.createCell(i);cell.setCellValue(title[i]);cell.setCellStyle(style);}
​//创建内容for(int i=0;i<values.length;i++){row = sheet.createRow(i + 1);for(int j=0;j<values[i].length;j++){//将内容按顺序赋给对应的列对象row.createCell(j).setCellValue(values[i][j]);}}
​//给Excel设置水印painWaterMark(wb,sheet,"I Love You");
​return wb;}
​/*** 给Excel添加水印* @param wb 工作簿* @param sheet  sheet页* @param content 水印内容*/private static void painWaterMark(Workbook wb,Sheet sheet,String content) {String imgFileName = "waterMark_photo_"+content+".png";//创建水印图片  (默认保存到classes目录下)createWaterMark(content,imgFileName);
​//将图片写入到excel中try {​//也可以动态获取sheet中的行和列,根据行和列适当的放置水印图片//获取excel实际所占行//int row = sheet.getFirstRowNum() + sheet.getLastRowNum();//获取excel实际所占列//int cell = sheet.getRow(sheet.getFirstRowNum()).getLastCellNum() + 1;
​putWaterRemarkToExcel(wb, sheet, imgFileName, 0, 0, 5, 5,2, 10, 2, 2);} catch (IOException e) {e.printStackTrace();}}
​/*** 创建水印图片* 注意:生成的图片会默认保存到classes目录下,可以根据自己的业务进行更改* @param content* @param fileName* @return* @throws IOException*/private static String createWaterMark(String content, String fileName) {//生成水印图片的宽度Integer width = 300;//水印图片的高度Integer height = 150;// 获取bufferedImage对象BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);String fontType = "宋体";Integer fontStyle = java.awt.Font.PLAIN;Integer fontSize = 50;java.awt.Font font = new java.awt.Font(fontType, fontStyle, fontSize);// 获取Graphics2d对象Graphics2D g2d = image.createGraphics();image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);g2d.dispose();g2d = image.createGraphics();g2d.setColor(new java.awt.Color(0, 0, 0, 80)); //设置字体颜色和透明度// 设置字体g2d.setStroke(new BasicStroke(1));// 设置字体类型  加粗 大小g2d.setFont(font);//设置倾斜度g2d.rotate(Math.toRadians(-10), (double) image.getWidth() / 2, (double) image.getHeight() / 2);FontRenderContext context = g2d.getFontRenderContext();Rectangle2D bounds = font.getStringBounds(content, context);double x = (width - bounds.getWidth()) / 2;double y = (height - bounds.getHeight()) / 2;double ascent = -bounds.getY();double baseY = y + ascent;// 写入水印文字原定高度过小,所以累计写水印,增加高度g2d.drawString(content, (int) x, (int) baseY);// 设置透明度g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));// 释放对象g2d.dispose();String targetImagePath = Thread.currentThread().getContextClassLoader().getResource("").getPath()+fileName;try {ImageIO.write(image, "png", new File(targetImagePath));} catch (IOException e) {e.printStackTrace();}return targetImagePath;}
​/*** 为Excel打上水印工具函数 请自行确保参数值,以保证水印图片之间不会覆盖。在计算水印的位置的时候,并没有考虑到单元格合并的情况,请注意* @param wb Excel Workbook* @param sheet 需要打水印的Excel* @param waterRemarkPath 水印地址,classPath,目前只支持png格式的图片,*                        因为非png格式的图片打到Excel上后可能会有图片变红的问题,且不容易做出透明效果。*                        同时请注意传入的地址格式,应该为类似:"\\excelTemplate\\test.png"* @param startXCol 水印起始列* @param startYRow 水印起始行* @param betweenXCol 水印横向之间间隔多少列* @param betweenYRow 水印纵向之间间隔多少行* @param XCount 横向共有水印多少个* @param YCount 纵向共有水印多少个* @param waterRemarkWidth 水印图片宽度为多少列* @param waterRemarkHeight 水印图片高度为多少行* @throws IOException*/private static void putWaterRemarkToExcel(Workbook wb, Sheet sheet, String waterRemarkPath, int startXCol,int startYRow, int betweenXCol, int betweenYRow, int XCount, int YCount, int waterRemarkWidth,int waterRemarkHeight) throws IOException {​// 校验传入的水印图片格式if (!waterRemarkPath.endsWith("png") && !waterRemarkPath.endsWith("PNG")) {throw new RuntimeException("向Excel上面打印水印,目前支持png格式的图片。");}// 加载图片ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();//InputStream imageIn = new FileInputStream(waterRemarkPath);InputStream imageIn = Thread.currentThread().getContextClassLoader().getResourceAsStream(waterRemarkPath);if (null == imageIn || imageIn.available() < 1) {throw new RuntimeException("向Excel上面打印水印,读取水印图片失败(1)。");}BufferedImage bufferImg = ImageIO.read(imageIn);if (null == bufferImg) {throw new RuntimeException("向Excel上面打印水印,读取水印图片失败(2)。");}ImageIO.write(bufferImg, "png", byteArrayOut);
​// 开始打水印Drawing drawing = sheet.createDrawingPatriarch();
​// 按照共需打印多少行水印进行循环for (int yCount = 0; yCount < YCount; yCount++) {// 按照每行需要打印多少个水印进行循环for (int xCount = 0; xCount < XCount; xCount++) {// 创建水印图片位置int xIndexInteger = startXCol + (xCount * waterRemarkWidth) + (xCount * betweenXCol);int yIndexInteger = startYRow + (yCount * waterRemarkHeight) + (yCount * betweenYRow);
​/** 参数定义:第一个参数是(x轴的开始节点);第二个参数是(是y轴的开始节点);第三个参数是(是x轴的结束节点);* 第四个参数是(是y轴的结束节点);第五个参数是(是从Excel的第几列开始插入图片,从0开始计数);* 第六个参数是(是从excel的第几行开始插入图片,从0开始计数);第七个参数是(图片宽度,共多少列);* 第8个参数是(图片高度,共多少行);*/
​ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, xIndexInteger,yIndexInteger, xIndexInteger + waterRemarkWidth, yIndexInteger + waterRemarkHeight);
​Picture pic = drawing.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG));pic.resize();}}}
​
}

以上代码亲测有效,可以直接复制下来根据业务修改部分代码进行测试。

效果:

怎么样?看起来是不是和正常水印一样的效果!ᥬ᭄


公众号:沉默木头人

CSDN:沉默木头人(ID:qq_44322555)

喜欢感兴趣长按下面二维码关注吧!

原创不易,不喜勿喷,如果能够帮助到你或对你有所启发欢迎下方留言。

喜欢就开始你无情的三连击:点赞、分享、关注。这将是我写作更多有趣有益有知的好文章的动力;

接上一篇:Java实现导出Excel并附带水印相关推荐

  1. java实现导出Excel的功能

    这篇文章主要为大家详细介绍了java实现导出Excel的功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 导出excel是咱Java开发的必备技能啦,之前项目有这个功能,现在将其独立出来,分享一 ...

  2. Java分页导出Excel文件

    Java分页导出Excel文件 1.开发微信小程序接入广告获取收益 技术: Springboot + mongodb + maven +Layui + thymeleaf 上一篇博客已经讲解了Java ...

  3. java poi导出Excel表格超大数据量解决方案

    Java实现导出excel表格功能,大部分都会使用apache poi,apache poi API 地址 POI之前的版本不支持大数据量处理,如果数据过多则经常报OOM错误,有时候调整JVM大小效果 ...

  4. java 导入导出excel表格

    java 导入导出excel表格 业务上有需求上传excel表格并读取内容,本文记录一下该方法 表格导入 引入相应的工具包 <dependency><groupId>cn.af ...

  5. java利用poi导出excel功能-附带图片导出

    java利用poi导出excel功能-附带图片导出 写在前面 最近刚离职,闲来无事,于是把上两家公司都有碰到过的需求但都没有去研究实现:即导出带图片的excel报表.于是就折腾了一下这个功能,研究出来 ...

  6. java实现这个无表头空表格,《java程序导出excel表格是空白的没有数据?》 java怎么导入数据库...

    java程序导出excel表格是空白的没有数据? 看一下是否可以链接上数据库,或者查看一下链接的数据库是否有数据 java从数据库中导出excel poi 建议你使用pageoffice. java ...

  7. java实现导出Excel多行表头复杂模板

    java实现导出Excel多行表头复杂模板 一般我们都会选择poi来导出,选择一个比较好的ExcelUtils 但是对于初学者而言不了解poi的,还需从poi API文档去学习,如果是自学的话更好,如 ...

  8. java导入导出excel操作(jxl)

    java导入导出excel操作(jxl) Java解释Excel数据(jxl.jar包的使用) 关键字: java excel jxl.jar jxl.jar 包 下载地址: http://www.a ...

  9. java poi 导出excel不能超过65536行

    java poi 导出excel不能超过65536行 报这个异常 Exception in thread "main" java.lang.IllegalArgumentExcep ...

  10. java 动态导出excel表单 无模板文件下载

    java 动态导出excel表单 无模板文件下载 public ResponseEntity<byte[]> exportStanding(@PathVariable Long signu ...

最新文章

  1. Spring boot容器导入组件
  2. MicroRNA Ranking(Tehran2016)
  3. python 保留的类标识符
  4. 牛客网暑期ACM多校训练营(第二场): H. travel(树形线头DP)
  5. WIN10 动软代码生成器报错
  6. U盘装机助理-PE环境
  7. 操作 神通数据库_神通数据库安装及操作笔记
  8. 使用N2N搭建虚拟局域网|可用于红警、我的世界联机
  9. 小米平板2(2015716)官方线刷包_救砖包_解账户锁
  10. 学小易有微型计算机接口答案吗,学小易接口更新+新的接口+成品
  11. CPU/显卡GPU/CUDA/内存/缓存/SDK/API/DLL【转载整理】
  12. 董宝珍:巴菲特是如何选股的?——从底层逻辑看巴菲特核心重仓股的思路、原则和条件...
  13. CentOS 7 从本地 ISO 映像文件安装 Gnome GUI
  14. HTTPS证书过期|SSL证书过期 |华硕路由器| NAS|Certtificate is not valid
  15. oracle dbs文件夹,Oracle10g 目录$ORACLE_HOME/dbs 下有文件 hc_.dat ,用处是 ?
  16. 基于RFID技术的预制件管理系统的开发
  17. AutoIt3病毒杀毒攻略(详)
  18. 【得物技术】浅尝UI自动化之Airtest实践
  19. direct3D 学习笔记【转】
  20. 联想电脑自带记事本软件如何设置提醒

热门文章

  1. 通信协议之一线协议(1-Wire)解析
  2. Redhat7.5安装谷歌浏览器
  3. java 防重复提交_Java中如何避免重复提交请求
  4. linux驱动开发:mma7660 sensor的配置
  5. 计算机程序员求职信英语作文,电脑程序员英文求职信
  6. 将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5
  7. 局域网打印机共享怎么设置_一篇文章弄懂局域网打印机共享
  8. Photoshop更换证件照底色
  9. Unity 大面积花草风吹动效果以及编辑
  10. GitHub AI 编程工具自动写代码神器Copilot插件体验