java poi之word中的XWPFParagraph中的XWPFRun

java poi操作之word中的XWPFParagraph中的XWPFRun

1.引言

需求:双语对照

  • 读取word docx中的每一行文本并进行翻译处理
  • 复原的同时 在其段落上面复制一行原语对照

2.pom依赖

<dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poiartifactId>
            <version>4.1.2version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-ooxmlartifactId>
            <version>4.1.2version>
        dependency>

        
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-scratchpadartifactId>
            <version>4.1.2version>
        dependency>

3.上处理代码

  • word中:
    * 第一行: 你好,今天天气很好
    * 第二行: 天气不错,出去溜溜
    * 第三行: 注意养发
    * 每一行对应一个XWPFParagraph
    * 每一行的XWPFParagraph对应多个XWPFRun
    * 第一行: 你好[run0],今天天气很好[run1]
    * 第二行: 天气不错[run0],出去溜溜[run1]
    * 第三行: 注意养发[run0]
    *
    * run当中又包括文本[pos 0,pos 1,pos 2,…]、字体、脚注等
    * run才是操作文本的基本单元

而且在段落在创建run时,默认从所有run的末尾创建,不支持插到前面,
可以将runs迭代成ArrayList进行操作

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;

import java.io.*;
import java.util.List;

/**
 * @ClassName: test2
 * @Date: 2021/4/29 9:20
 * @Author: lvxy
 * @Description: TODO 处理word docx中的表格测试
 * @Version: TODO
 */
public class DealDocx {

    public static void main(String[] args) throws IOException {

        File inputFile = new File("D:\\Users\\lvxy\\Desktop\\2.docx");

        File outputFile = new File("D:\\Users\\lvxy\\Desktop\\deal2.docx");

        InputStream inputStream = new FileInputStream(inputFile);

        FileOutputStream outputStream = new FileOutputStream(outputFile);

        dealDocx(inputStream, outputStream);

    }

    /**
     * 处理docx
     * @param inputStream
     * @param outputStream
     * @throws IOException
     */
    private static void dealDocx(InputStream inputStream, OutputStream outputStream) throws IOException {

        // 读取docx
        XWPFDocument xwpfDocument = new XWPFDocument(inputStream);

        // 读取所有段落 存入列表
        List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs();

        // 处理所有段落
        dealParagraph(paragraphs);

        // 写入输出文件
        xwpfDocument.write(outputStream);
    }

    /**
     * 处理段落
     *  word中:
     *      第一行: 你好,今天天气很好
     *      第二行: 天气不错,出去溜溜
     *      第三行: 注意养发
     *  每一行对应一个XWPFParagraph
     *  每一行的XWPFParagraph对应多个XWPFRun
     *      第一行: 你好[run0],今天天气很好[run1]
     *      第二行: 天气不错[run0],出去溜溜[run1]
     *      第三行: 注意养发[run0]
     *
     *      run当中又包括文本[pos 0,pos 1,pos 2,...]、字体、脚注等
     *      run才是操作文本的基本单元
     * @param paragraphs
     * @param
     */
    private static void dealParagraph(List<XWPFParagraph> paragraphs) {
        // 段落合法性判断
        if (ObjectUtil.isNotNull(paragraphs) && paragraphs.size() > 0) {

            // 将段落列表迭代展开
            for (XWPFParagraph paragraph : paragraphs) {

                // 记录原段落的文本
                StringBuffer stringBuffer = new StringBuffer();
                for (XWPFRun run : paragraph.getRuns()) {
                    // 去除文本中的脚注以及null字符
                    if (run.getText(0) instanceof String) {
                        stringBuffer.append(run.getText(0));
                    }
                }

                int flag = 0;

                // 迭代每个段落的run(最小执行单元)
                for (XWPFRun run : paragraph.getRuns()){
                    flag ++;
                    // 在第一个run中进行拼接 中间放置回车达到换行效果
                    if (flag == 1){

                        // todo 防止空指针异常  这里会出现"" 空串  则不处理 赋原值 返回
                        if(StrUtil.isBlank(run.getText(0))){
                            run.setText(run.getText(0), 0);
                            continue ;
                        }
                        // todo 被孤立出来的 run0 的文本 翻译时应单独翻译
                        String runText = run.getText(0);
                        // 开启双语 添加到译文上一行
                        if (true){
                            run.setText(stringBuffer.toString(),0);
                            if (!StrUtil.isBlankIfStr(stringBuffer.toString())){
                                run.addBreak();
                            }
                            // pos 0 是原文 这里要pos 1
                            run.setText(runText,1);
                        }else {
                            // pos
                            run.setText(runText,0);
                        }
                        // 保持字体一致
                        setRunFont(run);
                        continue;

                    }

                    // 当前run的txt为空 则赋原值 进入下次循环
                    if(StrUtil.isBlank(run.getText(0))){
                        run.setText(run.getText(0), 0);
                        continue ;
                    }

                    // todo 对原语进行一系列处理得到target 这里只做简单复原
                    String tgt_text = run.getText(0);

                    if (StrUtil.isNotBlank(tgt_text)) {
                        // 放回翻译之后的值
                        run.setText(tgt_text.replaceAll("\n", "").replaceAll("\r",""), 0);
                        setRunFont(run);
                    }

                }


            }
        }
    }

    /**
     * 设置字体
     * @param run
     */
    private static void setRunFont(XWPFRun run){
        //设置字体信息
        CTRPr rpr = run.getCTR().isSetRPr() ? run.getCTR().getRPr() : run.getCTR().addNewRPr();
        //设置字体
        CTFonts fonts = rpr.isSetRFonts() ? rpr.getRFonts() : rpr.addNewRFonts();
        fonts.setEastAsia("宋体");
        fonts.setHAnsi("Times New Roman");
        fonts.setAscii("Times New Roman");
    }

}

你可能感兴趣的:(java,poi,java)