Spire.Doc for Java实现根据关键字位置加盖电子签章及转换PDF

Spire.Doc for Java 是一款专业的 Java Word 组件,开发人员使用它可以轻松地将 Word 文档创建、读取、编辑、转换和打印等功能集成到自己的 Java 应用程序中。作为一款完全独立的组件,Spire.Doc for Java 的运行环境无需安装 Microsoft Office。

Spire.Doc for Java 能执行多种 Word 文档处理任务,包括生成、读取、转换和打印 Word 文档,插入图片,添加页眉和页脚,创建表格,添加表单域和邮件合并域,添加书签,添加文本和图片水印,设置背景颜色和背景图片,添加脚注和尾注,添加超链接,加密和解密 Word 文档,添加批注,添加形状等。

官方文档:https://www.e-iceblue.cn/content/spiredocforjava.html

 实现代码:

1.maven依赖:

  <!--      电子签章实现  &lt;!&ndash; 免费版 .free  只支持前三页转化 &ndash;&gt;-->
    <!-- https://mvnrepository.com/artifact/e-iceblue/spire.doc.free -->
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.doc.free</artifactId>
        <version>5.3.1</version>
    </dependency>

  <!-- 图片处理 如: 图片背景透明化 -->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.8</version>
        </dependency>

    <repositories>
        epository>
            <id>com.e-iceblue</id>
            <url>http://repo.e-iceblue.cn/repository/maven-public/</url>
        </repository>
    </repositories>

2.工具类

SignUtil

public class SignUtil {

    /**
     * 创建带电子签章的文档
     *
     * @param oldWordPath    无签章文件地址 "D:\\sign\\origin.docx"
     * @param signPath       电子印章图片地址 "D:\\sign\\sign.png"
     * @param pdfPath        WORD转PDF存放位置  "D:\\sign\\3.pdf"
     * @param folderName     生成目标word文件夹名称  "D:\\sign\\"
     * @param targetFileName 生成目标word文件名称 "target.docx"
     * @param keyWord      word文档内容关键字决定盖章位置 比如 "盖章"
     */
    public static void createSign(String oldWordPath, String signPath, String pdfPath, String folderName, String targetFileName,String keyWord) {
        //       目标文件地址
        String wordOldUrl = oldWordPath;
        //       添加电子印章后文件存放地址
        String wordNewUrl = folderName + targetFileName;
        //       WORD转PDF存放位置
        String pdfNewUrl = pdfPath;
        //        电子印章图片地址
        String stampImgUrl = signPath;
        //        索引,默认就填-1即可
        Integer keyWordIndex = -1;
        //        电子印章水平位置
        float horizontal = 270;
        //        电子印章垂直位置
        float vertical = -60f;
        //        电子印章宽度
        float stampWidth = 140;
        //        电子印章高度
        float stampHeight = 120;
        //        书签名
        String bookmarkName = "ZWSTTCJKBH";
        //        书签位置文本替换新内容
        String newBookmarkText = "公开";
        AddStampUtils addStampUtils = new AddStampUtils();
        //        获取关键字位置并加盖印章并替换书签名位置文本内容
        addStampUtils.addKeyWordStamp(wordOldUrl, wordNewUrl, stampImgUrl, keyWord, keyWordIndex, horizontal, vertical, stampWidth, stampHeight, bookmarkName, newBookmarkText);

        //  转换为流 字节数组
        byte[] bytesByFile = addStampUtils.getBytesByFile(wordNewUrl);
        //  流转换为文件
        addStampUtils.byte2File(bytesByFile, folderName, targetFileName);

        //  将新word转化为pdf文件
        addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl);

    }


}

AddStampUtils

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.legendenergy.common.utils.StringUtils;
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.DocPicture;
import com.spire.doc.fields.TextRange;
import lombok.extern.slf4j.Slf4j;

import java.io.*;

/**
 * @Description: Word文件操作工具类
 */
@Slf4j
public class AddStampUtils {

    /**
     * 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);

    }

    /**
     * 1、根据关键词位置添加电子印章
     * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作
     *
     * @param wordOldUrl      word文件路径
     * @param wordNewUrl      新word文件路径
     * @param stampImgUrl     电子印章图片路径
     * @param keyWord         关键字 (自定义)
     * @param keyWordIndex    关键字索引 (-1)
     * @param horizontal      电子印章水平位置 (260f)
     * @param vertical        电子印章垂直位置 (-55f)
     * @param stampWidth      电子印章宽度 (推荐120)
     * @param stampHeight     电子印章高度(推荐120)
     * @param bookmarkName    书签名,通过名称寻找书签文本所在位置
     * @param newBookmarkText 替换的文本新内容
     */
    public void addKeyWordStamp(
            String wordOldUrl, String wordNewUrl, String stampImgUrl,
            String keyWord, Integer keyWordIndex, Float horizontal,
            Float vertical, Float stampWidth, Float stampHeight,
            String bookmarkName, String newBookmarkText
    ) {
        //        加载文档
        Document document = new Document();
        document.loadFromFile(wordOldUrl);

//        判断是否需要替换书签位置文本内容
        if (StringUtils.isNotEmpty(bookmarkName)) {
            replaceBookmarkContent(document, bookmarkName, newBookmarkText);
        }

//        获取关键字位置
        TextSelection[] textSelections = document.findAllString(keyWord, false, false);
        if (ObjectUtils.isNotEmpty(textSelections)) {
            Paragraph paragraph = textSelections[keyWordIndex > -1 ? 0 : textSelections.length - 1].getAsOneRange().getOwnerParagraph();
            //        添加电子印章
            DocPicture docPicture = paragraph.appendPicture(stampImgUrl);
            //        设置图片位于文字顶层
            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();
        log.info("文档添加电子印章结束,新WORD文档地址:{}", wordNewUrl);
    }

    /**
     * 替换书签名位置文本内容
     *
     * @param document        word文档对象
     * @param bookmarkName    书签名
     * @param newBookmarkText 新文本内容
     */
    public void replaceBookmarkContent(Document document, String bookmarkName, String newBookmarkText) {
        //定位到指定书签位置
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document);
        bookmarksNavigator.moveToBookmark(bookmarkName);
        //用文本内容替换原有书签位置的文本,新替换的内容与原文格式一致
        bookmarksNavigator.replaceBookmarkContent(newBookmarkText, true);
    }

    /**
     * 替换书签名位置文本内容为图片
     *
     * @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();
                }
            }
        }
    }

    /**
     * word转PDF
     *
     * @param wordNewUrl word文件路径
     * @param pdfNewUrl  存储新PDF文件路径
     */
    public void wordToPdf(String wordNewUrl, String pdfNewUrl) {
//        将新Word文档转换为PDF文件
        Document document = new Document();
        document.loadFromFile(wordNewUrl);
        document.saveToFile(pdfNewUrl, FileFormat.PDF);
        document.dispose();
        log.info("文档转换结束,新PDF文档地址:{}", pdfNewUrl);
    }
}
ImageUtils(将图章图片透明化)
import net.coobird.thumbnailator.Thumbnails;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class ImageUtils {
    /**
     * 创建缩略图
     * @param sourcePath
     * @param outputPath
     */
    public static void createThumbnail(String sourcePath, String outputPath, int x1, int y1, int w, int h) throws IOException {
        File inputfile = new File(sourcePath);
        File outfile = new File(outputPath);
        Thumbnails.of(inputfile).sourceRegion(x1, y1, w, h).size(w, h).outputFormat("png").toFile(outfile);
    }

    /**
     * 将图章图片透明化
     *
     * @param sourcePath "D:\\sign\\22.png"
     * @param outputPath "D:\\sign\\33.png"
     */
    public static void transparentImage(String sourcePath, String outputPath) {
        InputStream is = null;
        try {
            File file = new File(sourcePath);
            is = new FileInputStream(file);
            // 如果是MultipartFile类型,那么自身也有转换成流的方法:is = file.getInputStream();
            BufferedImage bi = ImageIO.read(is);
            Image image = (Image) bi;
            ImageIcon imageIcon = new ImageIcon(image);
            BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
                    BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
            g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
            int alpha = 0;
            for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage.getHeight(); j1++) {
                for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage.getWidth(); j2++) {
                    int rgb = bufferedImage.getRGB(j2, j1);
                    int R = (rgb & 0xff0000) >> 16;
                    int G = (rgb & 0xff00) >> 8;
                    int B = (rgb & 0xff);
                    if (((255 - R) < 30) && ((255 - G) < 30) && ((255 - B) < 30)) {
                        rgb = ((alpha + 1) << 24) | (rgb & 0x00ffffff);
                    }
                    bufferedImage.setRGB(j2, j1, rgb);
                }
            }
            g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
            ImageIO.write(bufferedImage, "png", new File(outputPath));// 直接输出文件
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                }
            }
        }
    }
}

3.测试

yml文件

#文件下载路径
file:
  path:
    signPath: D:/sign

service实现类

   @Value("${file.path.signPath}")
    private String signPath;

   //将签章图片透明化
   ImageUtils.transparentImage(signPath + "/signOld.png", signPath + "/signNew.png");
   //生成带签章的文档
   SignUtil.createSign(signPath + "/合伙人协议.docx", signPath + "/signNew.png", signPath + "/南通xx合伙人协议.pdf", signPath + "/", "最终合伙人协议.docx", "乙方");

4:效果

 

5、注意事项

将word转化为PDF时,打开pdf,发现只有前三页有效 ,因为免费spire依赖只能转化前三页

posted @ 2024-09-19 16:37  江南大才子  阅读(204)  评论(0编辑  收藏  举报