java实现导出excel添加水印或excel转pdf并添加水印
1.通过Map对象存入excel模板中获得excel表,并添加水印
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public static void exportExcelWatermark(TemplateExportParams templatePath, Map<String, Object> map, String fileName, String markText, HttpServletResponse response){
XSSFWorkbook workbook = (XSSFWorkbook) ExcelExportUtil.exportExcel(templatePath, map);
ExcelMark.Watermark watermark = new ExcelMark.Watermark();
//设置水印文字
watermark.setText(markText);
BufferedImage image = ExcelMark.createWatermarkImage(watermark);
// 导出到字节流byte
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);
XSSFSheet sheet = workbook.getSheetAt(0);
PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
String relType = XSSFRelation.IMAGES.getRelation();
//add relation from sheet to the picture data
PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
//set background picture to sheet
sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
downLoadExcel(fileName, response, workbook);
}
/**
* excel下载
*
* @param fileName 下载时的文件名称
* @param response
* @param workbook excel数据
*/
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
workbook.write(response.getOutputStream());
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
/**
*添加水印方法
*/
@Data
public static class Watermark {
private Boolean enable;
private String text;
private String dateFormat;
private String color;
}
public static BufferedImage createWatermarkImage(Watermark watermark) {
if (watermark == null) {
watermark = new ExcelMark.Watermark();
watermark.setEnable(true);
// watermark.setText("userName");
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 = 500;
Integer height = 200;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 背景透明 开始
Graphics2D g = image.createGraphics();
image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
g.dispose();
// 背景透明 结束
g = image.createGraphics();
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 = 100;
for (int i = 0; i < textArray.length; i++) {
g.drawString(textArray[i], 0, y);// 画出字符串
y = y + font.getSize();
}
g.drawString(DateUtils.dateTimeNow(watermark.getDateFormat()), 0, y);// 画出字符串
g.dispose();// 释放画笔
return image;
}
2.将excel转pdf并添加水印(先给excel添加水印会导致导出为pdf后消失)
在pom.xml中引入
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls.free</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
public static void exportExcelWatermark(TemplateExportParams templatePath, Map<String, Object> map, String fileName, String markText, HttpServletResponse response) throws Exception {
XSSFWorkbook workbook = (XSSFWorkbook) ExcelExportUtil.exportExcel(templatePath, map);
File tempFile = File.createTempFile(fileName, ".xlsx");
try (FileOutputStream out = new FileOutputStream(tempFile)) {
workbook.write(out);
}
//加载Excel工作表
com.spire.xls.Workbook wb = new com.spire.xls.Workbook();
wb.loadFromFile(tempFile.getAbsolutePath());
Worksheet excelSheet = wb.getWorksheets().get(0);
File tempPdfFile = File.createTempFile(fileName, ".pdf");
wb.getConverterSetting().setSheetFitToPage(true);
excelSheet.saveToPdf(tempPdfFile.getAbsolutePath());
// 添加水印
setPdfWaterMarForFileTest(tempPdfFile.getAbsolutePath(),fileName, markText, response);
// 步骤 7: 清理临时文件
tempPdfFile.delete();
}
public static void setPdfWaterMarForFileTest(String inputFile, String fileName, String waterText, HttpServletResponse response) throws Exception {
// 创建PdfReader对象读取原始PDF文件
PdfReader reader = new PdfReader(inputFile);
// 使用 ByteArrayOutputStream 来避免创建临时文件
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
PdfStamper stamper = new PdfStamper(reader, byteArrayOutputStream);
PdfContentByte waterMar;
//试了很多字体,这个是itextpdf自带的支持中文的字体
BaseFont base = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.3f);
gs.setStrokeOpacity(0.3f);
int n = reader.getNumberOfPages();
for (int i = 1; i <= n; i++) {
waterMar = stamper.getOverContent(i);
waterMar.setGState(gs);
waterMar.setFontAndSize(base, 12);
com.itextpdf.text.Rectangle pageSizeWithRotation = reader.getPageSizeWithRotation(i);
float height = pageSizeWithRotation.getHeight();
float width = pageSizeWithRotation.getWidth();
String[] marTextArray = stringToStringArray(waterText, 15);
waterMar.beginText();
//打印的行数和列数可自行修改
//135为横向偏移量,可以自行修改
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 7; x++) {
for (int t = 0; t < marTextArray.length; t++) {
float xFloat = x * 190 + 135 + t * 10;
float yFloat = y * 100 + 87 - t * 10;
waterMar.showTextAligned(Element.ALIGN_CENTER, marTextArray[t], xFloat, yFloat, 30);
}
}
}
waterMar.endText();
}
stamper.close();
reader.close();
// 设置响应头以便下载 PDF
response.reset();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName+".pdf", "UTF-8"));
// 将生成的 PDF 写入响应输出流
try (OutputStream out = response.getOutputStream()) {
byteArrayOutputStream.writeTo(out);
out.flush();
}
} catch (Exception e) {
throw new RuntimeException("pdf生成水印失败"); // 可以根据需求进行异常处理
}
}
public static String[] stringToStringArray(String text, int length) {
//检查参数是否合法
if (StringUtils.isEmpty(text)) {
return null;
}
if (length <= 0) {
return null;
}
// 首尾空格去除
text = text.trim();
//获取整个字符串可以被切割成字符子串的个数
int n = (text.length() + length - 1) / length;
String[] splitArr = new String[n];
for (int i = 0; i < n; i++) {
if (i < (n - 1)) {
splitArr[i] = text.substring(i * length, (i + 1) * length);
} else {
splitArr[i] = text.substring(i * length);
}
}
return splitArr;
}