zl程序教程

您现在的位置是:首页 >  其他

当前栏目

导出Excel添加水印

2023-03-31 10:45:33 时间

需求背景:

  要求导出的Excel有水印,且水印不要是可点击的图片影响正常操作。

开发环境:

  JDK 1.8

  SpringBoot v2.2.5.RELEASE

导入依赖:

 1 <!-- poi 相关-->
 2         <dependency>
 3             <groupId>org.apache.poi</groupId>
 4             <artifactId>poi</artifactId>
 5             <version>3.8</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>org.apache.poi</groupId>
 9             <artifactId>poi-ooxml</artifactId>
10             <version>3.8</version>
11         </dependency>
12         <dependency>
13             <groupId>org.apache.poi</groupId>
14             <artifactId>ooxml-schemas</artifactId>
15             <version>1.0</version>
16         </dependency>

 

 

demo样例:

private void makeExcelWithWaterMark(){
    // todo 生成Excel代码
    setWaterMarkToExcel(workbook,createWatermarkImage(null));
    // todo 生成文件、输出流代码
}

设置为Excel设置水印

 1 public static void setWaterMarkToExcel(XSSFWorkbook workbook, BufferedImage bfi) throws Exception {
 2     ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
 3     ImageIO.write(bfi, "png", byteArrayOut);
 4     int pictureIdx = workbook.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG);
 5     //add relation from sheet to the picture data
 6     POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);
 7     for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
 8         XSSFSheet xssfSheet = workbook.getSheetAt(i);
 9         PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
10         String relType = XSSFRelation.IMAGES.getRelation();
11         PackageRelationship pr = xssfSheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
12         xssfSheet.getCTWorksheet().addNewPicture().setId(pr.getId());
13     }
14 }

创建水印方法

 1 public static BufferedImage createWatermarkImage(WaterMarkContent watermark) {
 2         if (watermark == null) {
 3             watermark = new WaterMarkContent();
 4             watermark.setEnable(true);
 5             watermark.setText("水印内容");
 6             watermark.setColor("#C5CBCF");
 7             watermark.setDateFormat("yyyy-MM-dd HH:mm");
 8         }
 9         String[] textArray = watermark.getText().split(",");
10         Font font = new Font("microsoft-yahei", Font.PLAIN, 20);
11         Integer width = 300;
12         Integer height = 100;
13 
14         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
15         // 背景透明 开始
16         Graphics2D g = image.createGraphics();
17         image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
18         g.dispose();
19         // 背景透明 结束
20         g = image.createGraphics();
21         // 设定画笔颜色
22         g.setColor(new Color(Integer.parseInt(watermark.getColor().substring(1), 16)));
23         // 设置画笔字体
24         g.setFont(font);
25         // 设定倾斜度
26         g.shear(0.1, -0.26);
27 
28         // 设置字体平滑
29         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
30 
31         int y = 50;
32         for (int i = 0; i < textArray.length; i++) {
33             // 画出字符串
34             g.drawString(textArray[i], 0, y);
35             y = y + font.getSize();
36         }
37         // 画出字符串
38         g.drawString("2022-10-12 11:24:00", 0, y);
39         // 释放画笔
40         g.dispose();
41         return image;
42     }

 


 

 

一般情况下,只需要根据需求修改创建水印方法中第5行、第7行、第38行代码setText、setDateFormat、g.drawString方法的第一个参数即可

若要生成多行水印,在setText中用【,】(英文逗号)进行分隔。也可以修改第9行分隔字符,进行分隔。

 


 

 

导出后样式如图