aspose通过开始和结束位置关键词截取word另存为新文件

 关键词匹配实体类:

@Data
@EqualsAndHashCode(callSuper = false)
public class TextConfig implements Serializable {

    private static final long serialVersionUID = 1L;

    
    /**
     * 开始关键词,多个逗号分隔
     */
    private String textStart ;

    /**
     * 结束关键词,多个逗号分隔
     */
    private String textEnd ;

    /**
     * 包含关键词,多个逗号分隔
     */
    private String textInclude ;

    /**
     * 不包含关键词,多个逗号分隔
     */
    private String textExclude ;

}
import com.aspose.words.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*;


@EqualsAndHashCode(callSuper = false)
@Slf4j
@Data
public class WordResolve extends Document {
    /**
     * 查找文本类型另存为word
     * @param filePathName  文件保存路径
     * @param copyFirst     是否复制关键词开始节点
     * @param copyLast      是否复制关键词结束节点
     */
    @SneakyThrows
    public File findBetweenFile(TextConfig textConfig, String filePathName, boolean copyFirst, boolean copyLast) {
        List<Paragraph> paragraphs = getAllParagraph();
        Integer[] sec = findBetweenIndex(textConfig,getAllText());
        if(sec == null){
            return null;
        }
        Document doc = new Document();
        Body body = doc.getFirstSection().getBody();
        body.removeAllChildren();
        NodeImporter importer = new NodeImporter(this, doc, ImportFormatMode.KEEP_SOURCE_FORMATTING);
        Paragraph first = paragraphs.get(sec[0]);
        Paragraph last = paragraphs.get(sec[1]);

        List<CompositeNode<?>> parentNodes = new ArrayList<>(20);

        boolean startCopying = false;
        //读取文档的所有节点
        NodeCollection<?> allNodeList = this.getChildNodes(NodeType.ANY, true);
        for (int i = 0, j = allNodeList.getCount(); i < j; i++) {
            Node node = allNodeList.get(i);
            try{
                if (node == first) {
                    startCopying = true;
                    if(!copyFirst){
                        continue;
                    }
                }
                if (node == last && !copyLast) {
                    // 到达结束节点后停止复制
                    break;
                }
                if (startCopying) {
                    boolean append = true;
                    for (CompositeNode<?> parentNode : parentNodes) {
                        NodeCollection<?> childNodes = parentNode.getChildNodes(node.getNodeType(), true);
                        if(childNodes.contains(node)){
                            append = false;
                            break;
                        }
                    }
                    if(append){
                        try{
                            body.appendChild(importer.importNode(node, true));
                        }catch (Exception e){
                            log.error("插入节点出错:{}",e.getMessage());
                            //ignore
                        }
                    }
                }
                if (node == last) {
                    // 到达结束节点后停止复制
                    break;
                }
            }finally {
                if(startCopying && node.isComposite()){
                    CompositeNode<?> compositeNode = (CompositeNode<?>) node;
                    if(!parentNodes.contains(compositeNode)){
                        parentNodes.add(compositeNode);
                    }
                }
            }
        }
        File file = FileUtils.getFile(filePathName);
        doc.save(filePathName);
        return file;
    }

    /**
     * 查找文本类型解析规则的开始结束段落索引
     * @param   strings word全部段落,每个段落的文本
     */
    public Integer[] findBetweenIndex(TextConfig textConfig, List<String> strings){
        String textStart = textConfig.getTextStart();
        String textEnd = textConfig.getTextEnd();
        //规定开始关键词必须包含哪些文字,多个逗号分隔(作为附加判断,可为空)
        textInclude = StringUtil.defaultString(textConfig.getTextInclude(), "").replace(",", "");
        //规定结束关键词必须不包含哪些文字,多个逗号分隔(作为附加判断,可为空)
        textExclude = StringUtil.defaultString(textConfig.getTextExclude(), "").replace(",", "");
        String[] in = StringUtil.isBlank(textInclude) ? null : textInclude.split(",");
        String[] out = StringUtil.isBlank(textExclude) ? null : textExclude.split(",");
        //满足开始位置和结束位置的全部关键词索引
        List<Integer> startArr = new ArrayList<>();
        List<Integer> endArr = new ArrayList<>();

        for (int i = 0; i < strings.size(); i++) {
            String text = strings.get(i);
            if (text.contains(textStart)) {
                startArr.add(i);
            }
            if (text.contains(textEnd)) {
                endArr.add(i);
            }
        }
        //进行包含和非包含的判断过滤
        if(!startArr.isEmpty() && !endArr.isEmpty()){
            for (Integer start : startArr) {
                for (Integer end : endArr) {
                    //中间至少隔了一个段落
                    if(start + 1 < end){
                        StringJoiner jo = new StringJoiner("\n");
                        for (int i = start + 1; i < end; i++) {
                            jo.add(strings.get(i));
                        }
                        String word = jo.toString();
                        boolean match = true;
                        if(in != null){
                            for (String s : in) {
                                if(!word.contains(s)){
                                    match = false;
                                    break;
                                }
                            }
                        }
                        if(match && out != null){
                            for (String s : out) {
                                if(word.contains(s)){
                                    match = false;
                                    break;
                                }
                            }
                        }
                        if(match){
                            return new Integer[]{start,end};
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 拿到文档全部段落文本
     */
    public List<String> getAllText(){
        List<String> strings = new ArrayList<>();
        getAllParagraph().forEach(a-> strings.add(StringTool.safeToString(a.getText(), "")));
        return strings;
    }

    /**
     * 拿到文档全部段落
     */
    public List<Paragraph> getAllParagraph(){
        if(allParagraph == null){
            allParagraph = findNodeByType(NodeType.PARAGRAPH, Paragraph.class);
        }
        return allParagraph;
    }
}

使用方式:

word文档内容如下:

要截取标题三和标题四之间的内容,生成新的word,代码如下:

public class Test {

    public static void main(String[] args) throws Exception{
        //验证license
        //new AsposeLicense().validate();
        //读取word文件
        WordResolve word = new WordResolve(new File("C:\\Users\\zhou\\Desktop\\测试.docx"));
        TextConfig detail = new TextConfig();
        detail.setTextStart("poi导出大数据量问题、写入速度慢");
        detail.setTextEnd("国密验签失败");
        File betweenFile = word.findBetweenFile(detail, "C:\\Users\\zhou\\Desktop\\betweenFile.docx", false, false);
        System.out.println(betweenFile);
    }


}

 截取保存的文件如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/294287.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

接口自动化-mysql和其他数据操作

学习目的&#xff1a; 1、理解接口测试中数据的存储位置以及常见的存放数据的方式 2、重点介绍python连接数据库的方法 3、把python连接数据库的方法封装&#xff0c;应用到项目中 4、再介绍下操作init文件的方法 具体学习内容&#xff1a; 1、理解接口测试中数据的…

java: java.lang.ExceptionInInitializerError com.sun.tools.javac.code.TypeTags

背景 rebuild 时候报错 解决 jdk版本不匹配&#xff0c;不兼容&#xff0c;降低或者升级即可。

17周刷题(6~10)

编写int fun(char s[])函数&#xff0c;将八进制参数串s转换为十进制整数返回&#xff0c;若传入"77777"返回32767。 #include<string.h> int fun(char s[]) {int i strlen(s)-1, h 0, q 1;while (i>0) {h (s[i] - 0) * q;q * 8;i--;}return h; } …

(vue)el-popover鼠标移入提示效果

(vue)el-popover鼠标移入提示效果 效果&#xff1a; 代码&#xff1a; <el-form-itemv-for"(item,index) of ele.algorithmParameters":key"index":label"item.parametersName"class"descInput" ><el-input v-model"i…

商城小程序(5.商品列表)

目录 一、定义请求参数对象二、获取商品列表数据三、渲染商品列表结构四、把商品item封装为自定义组件五、使用过滤器处理价格六、上拉加载更多七、下拉刷新八、点击商品item项跳转到详情页面 这章主要完成商品列表页面的编写&#xff1a;位于subpkg分包下的goods_list页面 一…

消化性溃疡与胃肠道微生物群

谷禾健康 据柳叶刀统计&#xff0c;消化性溃疡(PUD)每年影响全球400万人&#xff0c;据估计普通人群终生患病率为5−10%(Lanas A et al., 2017)。尽管消化性溃疡的全球患病率在过去几十年中有所下降&#xff0c;但其并发症的发生率却保持不变。 消化性溃疡是指胃或十二指肠黏膜…

k Nearest Neighbour(KNN)建模

目录 介绍&#xff1a; 一、建模 二、调参 2.1手动调参 2.2 GridSearchCV调参 2.3RandomizedSearchCV调参 介绍&#xff1a; K最近邻&#xff08;K-Nearest Neighbors&#xff0c;KNN&#xff09;是一种基本的分类和回归算法。它的基本思想是对未知样本进行预测时&#…

16、Kubernetes核心技术 - 节点选择器、亲和和反亲和

目录 一、概述 二、节点名称 - nodeName 二、节点选择器 - nodeSelector 三、节点亲和性和反亲和性 3.1、亲和性和反亲和性 3.2、节点硬亲和性 3.3、节点软亲和性 3.4、节点反亲和性 3.5、注意点 四、Pod亲和性和反亲和性 4.1、亲和性和反亲和性 4.2、Pod亲和性/反…

爱了!水浸监测这个技术,看了都说好!

在当今社会&#xff0c;水浸事件可能对各类场所和设施造成严重的损害&#xff0c;从而威胁到财产安全和业务持续性。 水浸监控系统不仅仅是一种技术手段&#xff0c;更是对于防范水灾的一项战略性解决方案。水浸监控系统实时了解局势并采取迅速而有效的措施&#xff0c;从而最大…

vue项目报错RangeError: Maximum call stack size exceeded

我的代码–> <script> import groupSettings from ./groupSetting.vue export default {name: groupSettings,components: {groupSettings}, </script>答应我&#xff0c;你的子组件引入名称一定不能和name一样&#xff01;&#xff01;&#xff01;

IPv6和IPv4在技术层面的区别

随着互联网的不断发展&#xff0c;IPv4地址资源已经逐渐枯竭&#xff0c;而IPv6地址的使用逐渐成为趋势。IPv6和IPv4作为互联网协议的两个版本&#xff0c;在技术层面存在许多区别。本文将从地址空间、地址表示方法、路由协议、安全性、移动性以及网络性能等方面对IPv6和IPv4进…

精进单元测试技能 —— Pytest断言的艺术!

本篇文章主要是阐述Pytest在断言方面的应用。让大家能够了解和掌握Pytest针对断言设计了多种功能以适应在不同测试场景上使用。 了解断言的基础 在Pytest中&#xff0c;断言是通过 assert 语句来实现的。简单的断言通常用于验证预期值和实际值是否相等&#xff0c;例如&#…

python-查漏补缺笔记-更新中

包导入时__init__.py中命令的执行顺序和sys.modules变化 ref: https://edu.csdn.net/skill/practice/python-3-6/164 在有父包和子包的情况下&#xff0c;父包中的“ __ init__.py”语句会在子包的“ __ init__.py”语句之前执行&#xff0c;然后按下列顺序执行导入子包和模块…

Python selenium 自动化脚本打包成一个exe文件(推荐)

目标 打包Python selenium 自动化脚本&#xff08;如下run.py文件&#xff09;为exe执行文件&#xff0c;使之可以直接在未安装python环境的windows下运行 run.py文件源码&#xff1a; 文件路径&#xff1a;D:\gongcheng 注&#xff1a;chromedriver.exe 文件在D:\gongchen…

嵌入式Linux之MX6ULL裸机开发学习笔记(IMX启动方式-启动设备的选择)

一,硬件启动方式选择 1.启动方式的选择 6ull支持多种启动方式。 比如可以从 SD/EMMC、 NAND Flash、 QSPI Flash等启动。 6ull是怎么支持多种外置flash启动程序的。 1.启动方式选择&#xff1a; BOOT_MODE0 and BOOT_MODE1&#xff0c;这两个是两个IO来控制的&#xff0c;…

从技术角度分析:HTTP 和 HTTPS 有何不同

网络安全问题正变得日益重要&#xff0c;而 HTTP 与 HTTPS 对用户数据的保护十分关键。本文将深入探讨这两种协议的特点、工作原理&#xff0c;以及保证数据安全的 HTTPS 为何变得至关重要。 认识 HTTP 与 HTTPS HTTP 的工作原理 HTTP&#xff0c;全称超文本传输协议&#xf…

哪种猫粮好?最好的主食冻干猫粮品牌排行榜

虽然很多铲屎官可能认为给猫咪喂猫粮就足够了&#xff0c;但实际上猫咪对蛋白质的需求很高&#xff0c;并且作为肉食动物&#xff0c;它们更喜欢肉的味道。而冻干猫粮是采用低温和真空干燥处理技术将鲜肉制成&#xff0c;去除水分并保持蛋白质等营养物质不变性&#xff0c;同时…

leaflet呼吸闪烁效果

leaflet呼吸闪烁效果 1.功能背景 这个效果一把用于点击选中&#xff0c;报警提升效果。 2.功能开发 2.1 marker 这个效果还是很好实现&#xff0c;主要通过计时器设置透明度的组合实现。 function setTargetSelect(e){var i 1var int setInterval(() > {if(!e._map…

华为bgp之多级RR及团体属性、正则表达式多种应用案例

1、实现总部和分部的oa、财务网段互通 2、分部之间oa也能互通 3、分部之间不能互通财务 主要用到bgp自定义团体属性、一级二级RR配置、bgp正则表达式匹配规则 R1 router id 1.1.1.1 //配全局地址池&#xff0c;又可以给ospf用也可以给bgp用 interface GigabitEthernet0/0/0 …

时序预测 | Matlab实现GJO-VMD-LSTM金豺-变分模态分解-长短期记忆网络时间序列预测

时序预测 | Matlab实现GJO-VMD-LSTM金豺-变分模态分解-长短期记忆网络时间序列预测 目录 时序预测 | Matlab实现GJO-VMD-LSTM金豺-变分模态分解-长短期记忆网络时间序列预测预测效果基本介绍模型设计程序设计参考资料 预测效果 基本介绍 Matlab实现GJO-VMD-LSTM金豺-变分模态分…