IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> POI excel 添加水印 xls,xlsx -> 正文阅读

[Java知识库]POI excel 添加水印 xls,xlsx

依赖jar包

<dependency>
? ? <groupId>org.apache.poi</groupId>
? ? <artifactId>ooxml-schemas</artifactId>
? ? <version>1.0</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.8</version>
</dependency>

package com.excelTool.util;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.imageio.ImageIO;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.record.ContinueRecord;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.StandardRecord;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExcelWaterMarkUtil {
	private final static Logger logger = LoggerFactory.getLogger(ExcelWaterMarkUtil.class);
	public static void main(String[] args) {
		String filePath = excelWaterMarkForXlsx("C:\\123.xlsx","牛哄哄");
		String filePath1 = excelWaterMarkForXls("C:\\1234.xls","牛哄哄");
	}

	/**
	 *  xlsx 类型添加水印
	 * @param inputFilePath
	 * @param text
	 * @return
	 */
	public static String excelWaterMarkForXlsx(String inputFilePath,String text) {
		FileInputStream is = null;
		FileOutputStream out = null;
		XSSFWorkbook workbook = null;
		ByteArrayOutputStream os = null;
		try {
			//生成水印图片并导出字节流
			BufferedImage image = FontImageUtil.createWatermarkImage(new FontImageUtil.Watermark(true,text, null,null));
			os = new ByteArrayOutputStream();
			ImageIO.write(image, "png", os);
			//获取excel工作簿
			is = new FileInputStream(inputFilePath);
			workbook = new XSSFWorkbook(is);
			int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
			POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);
			//获取每个Sheet表并插入水印
			for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
				XSSFSheet sheet1 = workbook.getSheetAt(i);
				PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
				String relType = XSSFRelation.IMAGES.getRelation();
				//add relation from sheet to the picture data
				PackageRelationship pr = sheet1.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
				//set background picture to sheet
				sheet1.getCTWorksheet().addNewPicture().setId(pr.getId());
			}
			//生成添加水印的excel文件
			File f = new File(inputFilePath);
			String outputFilePath = f.getParent() + File.separator+System.currentTimeMillis()+ f.getName();
			out = new FileOutputStream(outputFilePath);
			workbook.write(out);
			return outputFilePath;
		} catch (Exception e) {
			logger.error("excel文件添加水印异常",e);
		}finally {
			if (is != null){
				try {
					is.close();
				}catch (Exception e){
					logger.error("excel输入文件关闭异常",e);
				}
			}
			if (out != null){
				try {
					out.close();
				}catch (Exception e){
					logger.error("excel输出文件关闭异常",e);
				}
			}
			if (workbook != null){
				try {
					workbook.close();
				}catch (Exception e){
					logger.error("excel工作簿关闭异常",e);
				}
			}
			if (os != null){
				try {
					os.close();
				}catch (Exception e){
					logger.error("水印图片字节流关闭异常",e);
				}
			}
		}
		return "";
	}

	/**
	 *  xls 类型添加水印
	 * @param inputFilePath
	 * @param text
	 * @return
	 */
	public static String excelWaterMarkForXls(String inputFilePath,String text) {
		FileInputStream is = null;
		FileOutputStream out = null;
		HSSFWorkbook workbook = null;
		ByteArrayOutputStream os = null;
		//水印图片
		String tarImgPath = "";
		try {
			//生成水印图片并导出字节流
			BufferedImage image = FontImageUtil.createWatermarkImage(new FontImageUtil.Watermark(true,text, null,null));
			File f1 = new File(inputFilePath);
			tarImgPath = f1.getParent() + File.separator+System.nanoTime()+text+ ".png";
			FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
			ImageIO.write(image, "png", outImgStream);

			//获取excel工作簿
			is = new FileInputStream(inputFilePath);
			workbook = new HSSFWorkbook(is);

			//获取每个Sheet表并插入水印
			// get bytes of the image file
			byte[] data = getBackgroundBitmapData(tarImgPath); //PNG must not have transparency
			for (int k = 0; k < workbook.getNumberOfSheets(); k++) {
				HSSFSheet sheet1 = workbook.getSheetAt(k);

				Field _sheet = HSSFSheet.class.getDeclaredField("_sheet");
				_sheet.setAccessible(true);
				InternalSheet internalsheet = (InternalSheet)_sheet.get(sheet1);
				// get List of RecordBase
				Field _records = InternalSheet.class.getDeclaredField("_records");
				_records.setAccessible(true);
				@SuppressWarnings("unchecked")
				List<RecordBase> records = (List<RecordBase>)_records.get(internalsheet);



				// do creating BitmapRecord and ContinueRecords from the data in parts of 8220 bytes
				BitmapRecord bitmapRecord;
				List<ContinueRecord> continueRecords = new ArrayList<>();
				int bytes;

				if (data.length > 8220) {
					bitmapRecord = new BitmapRecord(Arrays.copyOfRange(data, 0, 8220));
					bytes = 8220;
					while (bytes < data.length) {
						if ((bytes + 8220) < data.length) {
							continueRecords.add(new ContinueRecord(Arrays.copyOfRange(data, bytes, bytes + 8220)));
							bytes += 8220;
						} else {
							continueRecords.add(new ContinueRecord(Arrays.copyOfRange(data, bytes, data.length)));
							break;
						}
					}
				} else {
					bitmapRecord = new BitmapRecord(data);
				}

				// add the records after PageSettingsBlock
				int i = 0;
				for (RecordBase r : records) {
					if (r instanceof org.apache.poi.hssf.record.aggregates.PageSettingsBlock) {
						break;
					}
					i++;
				}
				records.add(++i, bitmapRecord);
				for (ContinueRecord continueRecord : continueRecords) {
					records.add(++i, continueRecord);
				}

//				// debug output
//				for (RecordBase r : internalsheet.getRecords()) {
//					System.out.println(r);
//				}
			}
			//生成添加水印的excel文件
			File f = new File(inputFilePath);
			String outputFilePath = f.getParent() + File.separator+System.currentTimeMillis()+ f.getName();
			out = new FileOutputStream(outputFilePath);
			logger.info(outputFilePath);
			outImgStream.close();
			boolean res = new File(tarImgPath).delete();
			workbook.write(out);
			return outputFilePath;
		} catch (Exception e) {
			logger.error("excel文件添加水印异常",e);
		}finally {
			if (is != null){
				try {
					is.close();
				}catch (Exception e){
					logger.error("excel输入文件关闭异常",e);
				}
			}
			if (out != null){
				try {
					out.close();
				}catch (Exception e){
					logger.error("excel输出文件关闭异常",e);
				}
			}
			if (workbook != null){
				try {
					workbook.close();
				}catch (Exception e){
					logger.error("excel工作簿关闭异常",e);
				}
			}
			if (os != null){
				try {
					os.close();
				}catch (Exception e){
					logger.error("水印图片字节流关闭异常",e);
				}
			}
			new File(tarImgPath).delete();
		}
		return "";
	}
	static byte[] getBackgroundBitmapData(String filePath) throws Exception {

		//see https://www.openoffice.org/sc/excelfileformat.pdf - BITMAP

		// get file byte data in type BufferedImage.TYPE_3BYTE_BGR
		FileInputStream fio = new FileInputStream(filePath);
		BufferedImage in = ImageIO.read(fio);
		BufferedImage image = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
		Graphics2D graphics = image.createGraphics();
		graphics.drawImage(in, null, 0, 0);
		graphics.dispose();

		// calculate row size (c)
		int rowSize = ((24 * image.getWidth() + 31) / 32) * 4;

		ByteArrayOutputStream output = new ByteArrayOutputStream(image.getHeight() * rowSize * 3 + 1024);

		// put the record headers into the data
		ByteBuffer header = ByteBuffer.allocate(8 + 12);
		header.order(ByteOrder.LITTLE_ENDIAN);

		// Undocumented XLS stuff
		header.putShort((short) 0x09);
		header.putShort((short) 0x01);
		header.putInt(image.getHeight() * rowSize + 12); // Size of image stream

		// BITMAPCOREHEADER (a)
		header.putInt(12);

		header.putShort((short) image.getWidth());
		header.putShort((short) image.getHeight()); // Use -height if writing top-down

		header.putShort((short) 1); // planes, always 1
		header.putShort((short) 24); // bitcount

		output.write(header.array());

		// Output rows bottom-up (b)
		Raster raster = image.getRaster()
				.createChild(0, 0, image.getWidth(), image.getHeight(), 0, 0, new int[]{2, 1, 0}); // Reverse BGR -> RGB (d)
		byte[] row = new byte[rowSize]; // padded (c)

		for (int i = image.getHeight() - 1; i >= 0; i--) {
			row = (byte[]) raster.getDataElements(0, i, image.getWidth(), 1, row);
			output.write(row);
		}
		fio.close();

		return output.toByteArray();
	}

	static class BitmapRecord extends StandardRecord {

		//see https://www.openoffice.org/sc/excelfileformat.pdf - BITMAP

		byte[] data;

		BitmapRecord(byte[] data) {
			this.data = data;
		}

		@Override
		public int getDataSize() {
			return data.length;
		}

		@Override
		public short getSid() {
			return (short)0x00E9;
		}
		@Override
		public void serialize(LittleEndianOutput out) {
			out.write(data);
		}
	}

	static class ContinueRecord extends StandardRecord {

		//see https://www.openoffice.org/sc/excelfileformat.pdf - CONTINUE

		byte[] data;

		ContinueRecord(byte[] data) {
			this.data = data;
		}
		@Override
		public int getDataSize() {
			return data.length;
		}
		@Override
		public short getSid() {
			return (short)0x003C;
		}
		@Override
		public void serialize(LittleEndianOutput out) {
			out.write(data);
		}
	}
}
package com.excelTool.util;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.util.StringUtils;

public class FontImageUtil {
	/**
	 * 水印内容类
	 */
	public static class Watermark {
		private Boolean enable;
		private String text;
		private String dateFormat;
		private String color;

		public Watermark(Boolean enable, String text, String dateFormat, String color) {
			this.enable = enable;
			this.text = text;
			this.dateFormat = dateFormat;
			this.color = color;
		}

		public Watermark() {
		}

		public Boolean getEnable() {
			return enable;
		}

		public void setEnable(Boolean enable) {
			this.enable = enable;
		}

		public String getText() {
			return text;
		}

		public void setText(String text) {
			this.text = text;
		}

		public String getDateFormat() {
			return dateFormat;
		}

		public void setDateFormat(String dateFormat) {
			this.dateFormat = dateFormat;
		}

		public String getColor() {
			return color;
		}

		public void setColor(String color) {
			this.color = color;
		}
	}

	/**
	 * 生成水印图片
	 * @param watermark
	 * @return
	 */
	public static BufferedImage createWatermarkImage(Watermark watermark) {
		if (watermark == null) {
			watermark = new Watermark();
			watermark.setEnable(true);
			watermark.setText("内部资料");
			watermark.setColor("#C5CBCF");
			watermark.setDateFormat("yyyy-MM-dd HH:mm");
		} else {
			if (StringUtils.isEmpty(watermark.getDateFormat())) {
				watermark.setDateFormat("yyyy-MM-dd HH:mm");
			} else if (watermark.getDateFormat().length() == 16) {
				watermark.setDateFormat("yyyy-MM-dd HH:mm");
			} else if (watermark.getDateFormat().length() == 10) {
				watermark.setDateFormat("yyyy-MM-dd");
			}
			if (StringUtils.isEmpty(watermark.getText())) {
				watermark.setText("内部资料");
			}
			if (StringUtils.isEmpty(watermark.getColor())) {
				watermark.setColor("#C5CBCF");
			}
		}
		String[] textArray = watermark.getText().split("\n");
		Font font = new Font("microsoft-yahei", Font.PLAIN, 20);
		Integer width = 400;
		Integer height = 200;

		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		// 背景透明 开始
		Graphics2D g = image.createGraphics();
//		image = g.getDeviceConfiguration().createCompatibleImage(width, height);
//		g.dispose();
		// 背景透明 结束
		g.setColor(Color.white);
		g.fillRect(0, 0, width , height);

		g.setColor(new Color(Integer.parseInt(watermark.getColor().substring(1), 16)));// 设定画笔颜色
		g.setFont(font);// 设置画笔字体
		g.shear(0.1, -0.26);// 设定倾斜度


		//        设置字体平滑
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		int y = 50;
		for (int i = 0; i < textArray.length; i++) {
			g.drawString(textArray[i], 0, y);// 画出字符串
			y = y + font.getSize();
		}
		SimpleDateFormat sdf = new SimpleDateFormat(watermark.getDateFormat());
		g.drawString(sdf.format(new Date()), 0, y);// 画出字符串

		g.dispose();// 释放画笔
		return image;

	}
}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-24 15:08:34  更:2022-02-24 15:11:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:59:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码