package com.casic.missiles.utils; import cn.afterturn.easypoi.word.WordExportUtil; import cn.hutool.core.lang.Assert; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.dto.business.certificate.ElectronicImage; import com.casic.missiles.dto.business.certificate.FilePrintRegister; import com.spire.doc.*; import com.spire.doc.documents.*; import com.spire.doc.fields.DocPicture; import com.spire.doc.fields.TextRange; import org.apache.commons.lang3.StringUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.util.ArrayList; import java.util.Map; import java.util.List; import java.util.stream.Collectors; /** * @Author:zt * @Create:2023/3/7/9:30 * @Description:TODO Word文件操作工具类 * @Version:1.0 */ public class StampUtils { //关键字索引 (-1) private final static Integer keyWordIndex = -1; // 电子印章水平位置 private final static float horizontal = 300f; // 电子印章垂直位置 private final static float vertical = -55f; // 电子印章宽度 private final static float stampWidth = 120; // 电子印章高度 private final static float stampHeight = 120; //照片透明度设置 private final static int alpha = 150; /** * @param filePrintRegister 标准文件注册表 */ public static void filePrintGenerate(FilePrintRegister filePrintRegister) throws RuntimeException { //1、按照模板填充数据,并导出word String wordOldUrl = exportWord(filePrintRegister.getTemplatePath(), filePrintRegister.getTemDir(), filePrintRegister.getFileName(), filePrintRegister.getParams()); //设置透明属性 1、获取照片 2、签章背景透明设置 3、设置照片路径和照片类型进行图片保存 for (ElectronicImage electronicSeal : filePrintRegister.getElectronicImageList()) { BufferedImage bi = readImage(electronicSeal.getElectronicSealImgeUrl()); BufferedImage electronSealImage = convertLayout(bi, electronicSeal.getDiaphaneity()); String stampImgUrl = electronicSeal.getElectronicSealImgeUrl(); String imagePath = stampImgUrl.substring(0, stampImgUrl.length() - 4) + "1.png"; String[] imageCutOffContents = stampImgUrl.split("."); electronicSeal.setElectronicSealImgeUrl(imagePath); saveFile(electronSealImage, imageCutOffContents[imageCutOffContents.length - 1], imagePath); } //按关键字进行分组 Map<String, List<ElectronicImage>> sameKeySealMaps = filePrintRegister.getElectronicImageList().stream().collect( Collectors.groupingBy(ElectronicImage::getKeyWord) ); // 初始化world,pdf名称参数 String[] filePrintType = filePrintRegister.getTemplatePath().split("."); String wordNewUrl = filePrintRegister.getFileName() + filePrintType[filePrintType.length - 1]; String pdfNewUrl = filePrintRegister.getFileName() + "pdf"; //3、根据关键字进行添加签章和签字 for (Map.Entry<String, List<ElectronicImage>> entry : sameKeySealMaps.entrySet()) { String mapKey = entry.getKey(); List<ElectronicImage> electronicSeals = entry.getValue(); addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSeals); } // 4、将新word转化为pdf文件 wordToPdf(wordNewUrl, pdfNewUrl); } /** * 按照模板 填充数据生成word 只支持docx * * @param templatePath 模板文件路径 * @param temDir 生成文件的目录 * @param fileName 生成文件名 * @param params 参数 */ public static String exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params) { Assert.notNull(templatePath, "模板路径不能为空"); Assert.notNull(temDir, "临时文件路径不能为空"); Assert.notNull(fileName, "导出文件名不能为空"); Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); if (!temDir.endsWith("/")) { temDir = temDir + File.separator; } File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } String tmpPath = ""; try { XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params); tmpPath = temDir + fileName; FileOutputStream fos = new FileOutputStream(tmpPath); doc.write(fos); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } return tmpPath; } /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 * @param electronicSealList 电子印章信息 */ private static void addSameKeyWordStamp(String wordOldUrl, String wordNewUrl, List<ElectronicImage> electronicSealList) throws RuntimeException { // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); //获取关键字位置 TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); for (ElectronicImage electronicSeal : electronicSealList) { //加签章照片 if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImgeUrl())) { throw new RuntimeException("image url is empty or key word not exist in the word template ..."); } Paragraph paragraph = textSelections[keyWordIndex > -1 ? 0 : textSelections.length - 1].getAsOneRange().getOwnerParagraph(); //添加公司印章 DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImgeUrl()); //设置图片位于文字顶层 docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); //指定电子章位置 //水平位置 docPicture.setHorizontalPosition(horizontal); //垂直位置 docPicture.setVerticalPosition(vertical); //设置电子章大小 docPicture.setWidth(stampWidth); docPicture.setHeight(stampHeight); } //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); } /** * 替换书签名位置文本内容 * * @param document word文档对象 * @param bookmarkName 书签名 * @param newBookmarkText 新文本内容 */ private void replaceBookmarkContent(Document document, String bookmarkName, String newBookmarkText) { //定位到指定书签位置 BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document); bookmarksNavigator.moveToBookmark(bookmarkName); //用文本内容替换原有书签位置的文本,新替换的内容与原文格式一致 bookmarksNavigator.replaceBookmarkContent(newBookmarkText, true); } /** * word转PDF * * @param wordNewUrl word文件路径 * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { // 将新Word文档转换为PDF文件 Document document = new Document(); document.loadFromFile(wordNewUrl); document.saveToFile(pdfNewUrl, FileFormat.PDF); document.dispose(); } /** * 图片透明背景转换 * * @param imgsrc * @param alpha * @return */ public static BufferedImage convertLayout(BufferedImage imgsrc, int alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 BufferedImage back = new BufferedImage(imgsrc.getWidth(), imgsrc.getHeight(), BufferedImage.TYPE_INT_ARGB); int width = imgsrc.getWidth(); int height = imgsrc.getHeight(); for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { int rgb = imgsrc.getRGB(i, j); Color color = new Color(rgb); Color newcolor = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); back.setRGB(i, j, newcolor.getRGB()); } } return back; } catch (Exception e) { e.printStackTrace(); return null; } } //读取图片 private static BufferedImage readImage(String imgpath) { try { BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); return bufferedImage; } catch (Exception e) { e.printStackTrace(); return null; } } //保存图片,extent为格式,"jpg"、"png"等 private static void saveFile(BufferedImage img, String extent, String newfile) { try { ImageIO.write(img, extent, new File(newfile)); } catch (Exception e) { e.printStackTrace(); } } /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 * @param stampImgUrl 电子印章图片路径 * @param horizontal 电子印章水平位置 (当前文件推荐260f) * @param vertical 电子印章垂直位置 (当前推荐455f) * @param stampWidth 电子印章宽度(推荐120) * @param stampHeight 电子印章高度(推荐120) * @param bookmarkName 书签名,通过名称寻找书签文本所在位置 * @param newBookmarkText 替换的文本新内容 */ public void addStamp(String wordOldUrl, String wordNewUrl, String stampImgUrl, Float horizontal, Float vertical, Float stampWidth, Float stampHeight, String bookmarkName, String newBookmarkText) { // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); //获取指定段落 Section section = document.getSections().get(0); //获取段落总数 int count = section.getParagraphs().getCount(); //log.info("获取文档内容段落总数{}",count); Paragraph paragraph = section.getParagraphs().get(0); // 判断是否需要替换书签位置文本内容 if (StringUtils.isNotEmpty(bookmarkName)) { replaceBookmarkContent(document, bookmarkName, newBookmarkText); } // 添加电子印章 DocPicture docPicture = paragraph.appendPicture(stampImgUrl); // 指定电子章位置 // 水平位置 docPicture.setHorizontalPosition(horizontal); // 垂直位置 docPicture.setVerticalPosition(vertical); // 设置电子章大小 docPicture.setWidth(stampWidth); docPicture.setHeight(stampHeight); // 设置图片位于文字顶层 docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); // log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } /** * 替换书签名位置文本内容为图片 * * @param document word文档对象 * @param bookmarkName 书签名 * @param newImgUrl 图片地址 */ public void replaceBookmarkContentToImg(Document document, String bookmarkName, String newImgUrl) { //定位到指定书签位置 BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document); bookmarksNavigator.moveToBookmark(bookmarkName); //添加图片,替换原有书签内容 Paragraph para = new Paragraph(document); para.appendPicture(newImgUrl); TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(para); bookmarksNavigator.replaceBookmarkContent(bodyPart); } /** * 替换书签名位置文本内容为表格 * * @param document word文档对象 * @param bookmarkName 书签名 */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 String[][] data = { new String[]{"分类", "等级", "编号"}, new String[]{"A", "一级", "01A"}, new String[]{"B", "二级", "02B"}, new String[]{"C", "三级", "03C"}, }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); for (int i = 0; i < data.length; i++) { TableRow dataRow = table.getRows().get(i); for (int j = 0; j < data[i].length; j++) { TextRange range = dataRow.getCells().get(j).addParagraph().appendText(data[i][j]); range.getOwnerParagraph().getFormat().setHorizontalAlignment(HorizontalAlignment.Center); range.getCharacterFormat().setFontName("楷体"); dataRow.getRowFormat().setHorizontalAlignment(RowAlignment.Center); dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } /** * 文件转流 * * @param wordNewUrl * @return */ public byte[] getBytesByFile(String wordNewUrl) { try { // byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); File file = new File(wordNewUrl); FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = -1; while ((len = fis.read(b)) != -1) { bos.write(b, 0, len); } fis.close(); bos.close(); byte[] bytes = bos.toByteArray(); System.out.println("successful..."); return bytes; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 流转文件 * * @param buf 流字节数组 * @param filePath 新文件路径 * @param fileName 新文件名称 */ public void byte2File(byte[] buf, String filePath, String fileName) { BufferedOutputStream bos = null; FileOutputStream fos = null; File file = null; try { File dir = new File(filePath); if (!dir.exists() && dir.isDirectory()) { dir.mkdirs(); } file = new File(filePath + File.separator + fileName); fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos); bos.write(buf); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws RuntimeException { String pathUrl = "D:\\cz\\upload"; //文件与BufferedImage间的转换 //读取图片 BufferedImage bi = readImage(pathUrl + "\\sign1.png"); BufferedImage bii = convertLayout(bi, alpha); //生成透明背景图片 saveFile(bii, "PNG", pathUrl + "\\sign3.png"); //文件与BufferedImage间的转换 //读取图片 BufferedImage b = readImage(pathUrl + "\\name1.png"); BufferedImage b0 = convertLayout(b, alpha); //生成透明背景图片 saveFile(b0, "PNG", pathUrl + "\\name3.png"); // 目标文件地址 String wordOldUrl = pathUrl + "\\wordExport.docx"; // 添加电子印章后文件存放地址 String wordNewUrl = pathUrl + "\\tem.docx"; //WORD转PDF存放位置 String pdfNewUrl = pathUrl + "\\tem.pdf"; //电子印章图片地址 String stampImgUrl = pathUrl + "\\sign3.png"; //电子签名图片地址 String stampImgUrl1 = pathUrl + "\\name3.png"; // word文档内容关键字 String keyWord = "盖章"; StampUtils addStampUtils = new StampUtils(); List<ElectronicImage> electronicSealList = new ArrayList(11); int count = 0; for (; count < 2; count++) { ElectronicImage electronicSeal = new ElectronicImage(); String tempStampImgUrl = count == 0 ? stampImgUrl : stampImgUrl1; electronicSeal.setElectronicSealImgeUrl(tempStampImgUrl); electronicSeal.setMereFlag(count == 1); electronicSeal.setKeyWord(keyWord); electronicSeal.setKeyWordIndex(keyWordIndex); electronicSeal.setHorizontal(horizontal); electronicSeal.setVertical(vertical); electronicSeal.setStampHeight(stampHeight); electronicSeal.setStampWidth(stampWidth); electronicSealList.add(electronicSeal); } addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); // 将新word转化为pdf文件 addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); } }