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); |
| |
| 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(); |
| |
| PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null); |
| |
| sheet.getCTWorksheet().addNewPicture().setId(pr.getId()); |
| downLoadExcel(fileName, response, workbook); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| 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("水印水印水印"); |
| 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); |
| } |
| |
| 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); |
| |
| tempPdfFile.delete(); |
| } |
| |
| public static void setPdfWaterMarForFileTest(String inputFile, String fileName, String waterText, HttpServletResponse response) throws Exception { |
| |
| PdfReader reader = new PdfReader(inputFile); |
| |
| |
| try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { |
| PdfStamper stamper = new PdfStamper(reader, byteArrayOutputStream); |
| PdfContentByte waterMar; |
| |
| 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(); |
| |
| |
| 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(); |
| |
| |
| response.reset(); |
| response.setContentType("application/pdf"); |
| response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName+".pdf", "UTF-8")); |
| |
| |
| 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; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~