poi导出excel加水印,单元格可修改 java 下载生成Excel文件添加水印

发布时间 2023-07-20 18:29:51作者: sunny123456

poi导出excel加水印,单元格可修改 java 下载生成Excel文件添加水印
原文链接:https://blog.csdn.net/weixin_40077255/article/details/112848376

目录

poi导出excel加水印,单元格可修改(只支持XSSFWorkbook)

引入的jar包:

操作水印的工具类:

最终效果

 小提示


poi导出excel加水印,单元格可修改(只支持XSSFWorkbook)


引入的jar包:

  1. <dependency>
  2. <groupId>org.apache.poi</groupId>
  3. <artifactId>poi</artifactId>
  4. <version>3.9</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.poi</groupId>
  8. <artifactId>poi-ooxml</artifactId>
  9. <version>3.9</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.apache.poi</groupId>
  13. <artifactId>ooxml-schemas</artifactId>
  14. <version>1.4</version>
  15. </dependency>

操作水印的工具类:

  1. import org.apache.poi.POIXMLDocumentPart;
  2. import org.apache.poi.openxml4j.opc.PackagePartName;
  3. import org.apache.poi.openxml4j.opc.PackageRelationship;
  4. import org.apache.poi.openxml4j.opc.TargetMode;
  5. import org.apache.poi.ss.usermodel.Workbook;
  6. import org.apache.poi.xssf.usermodel.XSSFRelation;
  7. import org.apache.poi.xssf.usermodel.XSSFSheet;
  8. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. import javax.imageio.ImageIO;
  12. import java.awt.*;
  13. import java.awt.image.BufferedImage;
  14. import java.io.ByteArrayOutputStream;
  15. import java.io.IOException;
  16. /**
  17. * <p>Title: 水印设置 </p>
  18. * <p>Description: 水印设置 </p>
  19. */
  20. public class WatermarkUtils {
  21. private final static Logger logger = LoggerFactory.getLogger(WatermarkUtils.class);
  22. static class FontImage {
  23. final static String[] TEXT = new String[]{"XXXX系统"};
  24. final static Integer fontSize = 12;
  25. /**
  26. * <p>Title: 设置水印相关信息 </p>
  27. * <p>Description: 水印信息 </p>
  28. */
  29. static class Watermark {
  30. private Boolean enable;
  31. private String[] text;
  32. private String dateFormat;
  33. private String color;
  34. public Watermark() {}
  35. public Watermark(Boolean enable, String[] text, String dateFormat, String color) {
  36. this.enable = enable;
  37. this.text = text;
  38. this.dateFormat = dateFormat;
  39. this.color = color;
  40. }
  41. public Boolean getEnable() {
  42. return enable;
  43. }
  44. public void setEnable(Boolean enable) {
  45. this.enable = enable;
  46. }
  47. public String[] getText() {
  48. return text;
  49. }
  50. public void setText(String[] text) {
  51. this.text = text;
  52. }
  53. public String getDateFormat() {
  54. return dateFormat;
  55. }
  56. public void setDateFormat(String dateFormat) {
  57. this.dateFormat = dateFormat;
  58. }
  59. public String getColor() {
  60. return color;
  61. }
  62. public void setColor(String color) {
  63. this.color = color;
  64. }
  65. }
  66. /**
  67. * <p>Title: 生成水印图片信息 </p>
  68. * <p>Description: 生成水印图片信息 </p>
  69. */
  70. public static BufferedImage createWatermarkImage(Watermark watermark) {
  71. if (watermark == null) {
  72. watermark = new Watermark();
  73. watermark.setEnable(true);
  74. watermark.setText(TEXT);
  75. watermark.setColor("#C5CBCF");
  76. watermark.setDateFormat("yyyy-MM-dd HH:mm");
  77. } else {
  78. if (StringUtils.isEmpty(watermark.getDateFormat())) {
  79. watermark.setDateFormat("yyyy-MM-dd HH:mm");
  80. } else if (watermark.getDateFormat().length() == 16) {
  81. watermark.setDateFormat("yyyy-MM-dd HH:mm");
  82. } else if (watermark.getDateFormat().length() == 10) {
  83. watermark.setDateFormat("yyyy-MM-dd");
  84. }
  85. if (watermark.getText().length==0) {
  86. watermark.setText(TEXT);
  87. }
  88. if (StringUtils.isEmpty(watermark.getColor())) {
  89. watermark.setColor("#C5CBCF");
  90. }
  91. }
  92. Font font = new Font("微软雅黑", Font.BOLD, fontSize);
  93. Integer width = 300;
  94. Integer height = 100 * watermark.getText().length;
  95. // 设置最大的宽度
  96. for (int j=0;j<watermark.getText().length;j++){
  97. int textWidth = fontSize*watermark.getText()[j].length();
  98. if(textWidth>width){
  99. width=textWidth;
  100. }
  101. }
  102. height=(width/2);
  103. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  104. // 背景透明 开始
  105. Graphics2D g = image.createGraphics();
  106. image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
  107. g.dispose();
  108. // 背景透明 结束
  109. g = image.createGraphics();
  110. // 设定画笔颜色
  111. g.setColor(new Color(Integer.parseInt(watermark.getColor().substring(1), 16)));
  112. // 设置画笔字体
  113. g.setFont(font);
  114. // 设定倾斜度
  115. g.shear(0, -0.3);
  116. // 消除文字锯齿
  117. g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
  118. //设置字体平滑
  119. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  120. int y =(height/2)+font.getSize()*2;
  121. int x =0;
  122. for (int j=0;j<watermark.getText().length;j++){
  123. String[] textArray = watermark.getText()[j].split("\n");
  124. y+= 1*(j+1);
  125. // 计算文字长度,计算居中的x点坐标
  126. FontMetrics fm = g.getFontMetrics(font);
  127. int textWidth = fm.stringWidth(watermark.getText()[j]);
  128. x = (width - textWidth) / 2;
  129. for (int i = 0; i < textArray.length; i++) {
  130. // 画出字符串
  131. g.drawString(textArray[i], x, y);
  132. y = y + font.getSize();
  133. }
  134. }
  135. g.dispose();// 释放画笔
  136. return image;
  137. }
  138. }
  139. /**
  140. * <p>Title: 添加水印 </p>
  141. * <p>Description: 添加水印信息 </p>
  142. * @param wb 工作薄
  143. * @param sheet 工作表
  144. * @param waterMark 水印信息
  145. */
  146. public static void addWaterMark(XSSFWorkbook wb, XSSFSheet sheet, String waterMark){
  147. //是否添加水印
  148. if(StringUtils.isEmpty(waterMark)){
  149. FontImage.Watermark watermark = new FontImage.Watermark();
  150. watermark.setText(new String[]{waterMark});
  151. watermark.setEnable(true);
  152. BufferedImage image = FontImage.createWatermarkImage(watermark);
  153. // 导出到字节流B
  154. ByteArrayOutputStream os = new ByteArrayOutputStream();
  155. try {
  156. ImageIO.write(image, "png", os);
  157. } catch (IOException e) {
  158. logger.error("add watermark error: {}", e.getMessage());
  159. }
  160. int pictureIdx = wb.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
  161. POIXMLDocumentPart poixmlDocumentPart = wb.getAllPictures().get(pictureIdx);
  162. PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
  163. String relType = XSSFRelation.IMAGES.getRelation();
  164. //add relation from sheet to the picture data
  165. PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
  166. //set background picture to sheet
  167. sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
  168. }
  169. }
  170. /**
  171. * <p>Title: 添加水印 </p>
  172. * <p>Description: 添加水印信息 </p>
  173. * @param wb 工作薄
  174. * @param sheet 工作表
  175. * @param waterMarks 水印信息
  176. */
  177. public static void addWaterMarks(XSSFWorkbook wb, XSSFSheet sheet, String[] waterMarks){
  178. // 是否添加水印
  179. if(waterMarks!=null && waterMarks.length>0){
  180. FontImage.Watermark watermark = new FontImage.Watermark();
  181. watermark.setText(waterMarks);
  182. watermark.setEnable(true);
  183. BufferedImage image = FontImage.createWatermarkImage(watermark);
  184. // 导出到字节流B
  185. ByteArrayOutputStream os = new ByteArrayOutputStream();
  186. try {
  187. ImageIO.write(image, "png", os);
  188. } catch (IOException e) {
  189. logger.error("add watermark error: {}", e.getMessage());
  190. }
  191. int pictureIdx = wb.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
  192. POIXMLDocumentPart poixmlDocumentPart = wb.getAllPictures().get(pictureIdx);
  193. PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
  194. String relType = XSSFRelation.IMAGES.getRelation();
  195. //add relation from sheet to the picture data
  196. PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
  197. //set background picture to sheet
  198. sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
  199. }
  200. }
  201. /**
  202. * <p>Title: 添加水印 </p>
  203. * <p>Description: 添加水印 </p>
  204. * @param workbook 工作薄
  205. * @param waterMark 水印信息
  206. */
  207. public static void addWorkbookWaterMark(Workbook workbook, String waterMark){
  208. if (workbook != null){
  209. XSSFWorkbook xssfWorkbook = (XSSFWorkbook)workbook;
  210. for(int i = 0; i < xssfWorkbook.getNumberOfSheets(); i++){
  211. addWaterMark(xssfWorkbook, xssfWorkbook.getSheetAt(i),waterMark);
  212. }
  213. }
  214. }
  215. /**
  216. * <p>Title: 添加水印 </p>
  217. * <p>Description: 添加水印 </p>
  218. * @param workbook 工作薄
  219. * @param waterMarks 水印信息
  220. */
  221. public static void addWorkbookWaterMarks(Workbook workbook, String[] waterMarks){
  222. if (workbook != null){
  223. XSSFWorkbook xssfWorkbook = (XSSFWorkbook)workbook;
  224. for(int i = 0; i < xssfWorkbook.getNumberOfSheets(); i++){
  225. addWaterMarks(xssfWorkbook, xssfWorkbook.getSheetAt(i), waterMarks);
  226. }
  227. }
  228. }
  229. public static void main(String[] args){
  230. try {
  231. XSSFWorkbook workbook = new XSSFWorkbook();
  232. Sheet sheet = workbook.createSheet("0");
  233. Sheet sheet1 = workbook.createSheet("1");
  234. // 水印信息
  235. String[] waterMarks = {"XXX系统", DateUtils.getDate("yyyy-MM-dd HH:ss")};
  236. WatermarkUtils.addWorkbookWaterMarks(workbook, waterMarks);
  237. FileOutputStream fileOut = new FileOutputStream("C:\\Users\\rong\\Desktop\\123.xlsx");
  238. workbook.write(fileOut);
  239. fileOut.close();
  240. fileOut.flush();
  241. } catch(Exception e) {
  242. e.printStackTrace();
  243. }
  244. }
  245. }

最终效果

 小提示

1、如果需要导出.xls文件,建议创建XSSFWorkbook,添加水印后,输出时修改文件后缀。

2、大批量数据情况下注意HSSFWorkbook数据区域,防止修改后缀导致数据丢失。

3、此方法弊端,打印无法显示水印信息,如需要打印显示水印,请选择图片方式进行添加水印。