草庐IT

Word书签替换,加盖电子印章及转换PDF(Java实用版)

阿尔法哲 2023-04-15 原文

一、前言

在项目中有需要对word进行操作的,可以看看哈,本次使用比较强大的spire组件来对word进行操作,免费版支持三页哦,对于不止三页的word文件,可以购买收费版,官网:https://www.e-iceblue.cn/tutorials.html#,也可使用其他组件实现,如poi、docx4j等,我将代码整理成工具类了,大家可以拿下来直接使用哈,一起努力吧。

二、Spire的使用

1、引入pom.xml

<!-- 免费版 .free  只支持前三页转化 -->
<dependency>
    <groupId>e-iceblue</groupId>
    <artifactId>spire.office.free</artifactId>
    <version>5.3.1</version>
</dependency>

2、AddStampUtils

工具类
/**
 * @Author:wk
 * @Slogan:无论风雨,和自己一决胜负吧
 * @Create:2022/7/15/9:30
 * @Description:TODO Word文件操作工具类
 * @Version:1.0
 */
@Slf4j
public class AddStampUtils {

//    转换目标文件地址
//    public static String WORD_OLD_URL = "src/main/resources/word/20200429宋体服务器同步版.doc";

//    转换后文件存放地址
//    public static String WORD_NEW_URL = "src/main/resources/word/20200429宋体服务器同步版2.doc";

//    WORD转PDF存放位置
//    public static String PDF_NEW_URL = "src/main/resources/pdf/20200429宋体服务器同步版2.pdf";

//    电子印章图片地址
//    public static String STAMP_IMG_URL = "src/main/resources/word/stamp.png";

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

3、测试

Main主函数测试
public static void main(String[] args) {
    //       目标文件地址
    String wordOldUrl = "src/main/resources/word/20200429宋体服务器同步版.doc";
    //       添加电子印章后文件存放地址
    String wordNewUrl = "src/main/resources/word/20200429宋体服务器同步版2.doc";
    //       WORD转PDF存放位置
    String pdfNewUrl = "src/main/resources/pdf/20200429宋体服务器同步版2.pdf";
    //        电子印章图片地址
    String stampImgUrl = "src/main/resources/word/stamp.png";
    //        word文档内容关键字
    String keyWord = "盖章";
    //        索引,默认就填-1即可
    Integer keyWordIndex = -1;
    //        电子印章水平位置
    float horizontal = 260f;
    //        电子印章垂直位置
    float vertical = -55f;
    //        电子印章宽度
    float stampWidth = 120;
    //        电子印章高度
    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,"src/main/resources/word/","20200429宋体服务器同步版3.doc");
    
    //        将新word转化为pdf文件
    addStampUtils.wordToPdf(wordNewUrl,pdfNewUrl);
}

4、效果展示

Before

旧书签位置内容

文档盖章地方:

After

5、注意事项

将word转化为PDF时,打开pdf,发现顶部多了一条横线,如下:

这条横线的由来:传说这条横线是由于word文件的页眉导致的,经过我的证实,发现将鼠标移动至页面顶端,并且双击进入了页眉编辑状态,退出时有时就会在留下一根页眉横线(即使啥都不输入),由此得出传说也可信。哈哈哈,心情愉悦一下

处理方法:

第一种方法:首先将点击页眉,进入页眉编辑状态,并将光标置于页眉处。然后单击“开始”,找到“样式”里面的“正文”样式,轻松删除。

 

第二种方法(推荐):将光标置于页眉处,同时按住键盘上的:Ctrl+Shift+N,页眉横线立即消失,再按ESC键退出页眉编辑即可。

 

有关Word书签替换,加盖电子印章及转换PDF(Java实用版)的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  4. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  5. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  6. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  7. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  8. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  9. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  10. ruby-on-rails - Prawn PDF : I need to generate nested tables - 2

    我需要一个表,其中行实际上是2行表,一个嵌套表是..我怎样才能在Prawn中做到这一点?也许我需要延期..但哪一个? 最佳答案 现在支持子表:Prawn::Document.generate("subtable.pdf")do|pdf|subtable=pdf.make_table([["sub"],["table"]])pdf.table([[subtable,"original"]])end 关于ruby-on-rails-PrawnPDF:Ineedtogeneratenested

随机推荐