Java利用POI 操作word

package com.mis.webdemo.word3;


import lombok.SneakyThrows;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * https://blog.csdn.net/weixin_44076772/article/details/97797654
 * 测评文件导出工具类
 * https://blog.csdn.net/qq_53739052/article/details/130348820
 */
public class ExportUtils3 {
    //占位符数组
    private static String[] PLACEHOLDER = {"${company}", "${address}", "${secondParty}", "${quickMark}", "${a}", "${b}","${c}"};
    //图片占位符单独处理
    private static String[] PICTURE_PLACEHOLDER = {"${quickMark}"};

    private static int WIDTH = 100; //100%
    private static int HEIGHT = 100; //100%

    public static final String XPATH_TXBX_TXBXCONTENT = "declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' \n"
            + "        declare namespace mc='http://schemas.openxmlformats.org/markup-compatibility/2006' .//mc:Choice/*/w:txbxContent";
    public static final String XPATH_TEXTBOX_TXBXCONTENT = "declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' \n"
            + "        declare namespace mc='http://schemas.openxmlformats.org/markup-compatibility/2006' .//mc:Fallback/*/w:txbxContent";
    public static final String XPATH_PICT_TEXTBOX_TXBXCONTENT = "declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' \n"
            + "        declare namespace v='urn:schemas-microsoft-com:vml' ./v:shape/v:textbox/w:txbxContent";


    public static final String XPATH_TEXTBOX_TXBXCONTENT2 = "declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r";

    /**
     * 一页一码word导出
     * @param dtos 二维码数据列表
     * @param response
     */
    @SneakyThrows
    public static void UniqueCodeWordExport(List<TicketProject3> dtos, HttpServletResponse response) {
        //生成文档的名称列表
        //List<String> fileNameList = new ArrayList<>();
        for (TicketProject3 dto : dtos) {
            String filePath = "C:\\PLM系统-ESS产品开发过程-文档自动生成功能 SOW_V5.0.docx"; //模板地址
            InputStream fis = new FileInputStream(new File(filePath));
            XWPFDocument doc = new XWPFDocument(fis);


//            List<XWPFParagraph> paragraphList = doc.getParagraphs();
//            for (XWPFParagraph paragraph : paragraphList){
//                List<XWPFRun> runList = paragraph.getRuns();
//                for (XWPFRun run : runList){
//                    //System.out.println(run.getCTR());
//                    XmlObject xmlObject = (XmlObject) run.getCTR();
//                    XmlObject[] xmlObjects = xmlObject.selectPath(XPATH_TEXTBOX_TXBXCONTENT2);
//                    if (xmlObjects !=null && xmlObjects.length>=1){
//                        CTR ctr = CTR.Factory.parse(xmlObjects[0].xmlText());
//                        XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);
//                        //System.out.println(bufferrun);
//                        String text = bufferrun.text();
//                        if (text != null && text.contains("${a}")) {
//                            text = text.replace("${a}","replaced");
//                            bufferrun.setText(text, 0);
//                        }
//                        xmlObjects[0].set(bufferrun.getCTR());
//                    }
//                }
//            }


            Iterator<XWPFParagraph> itPara = doc.getParagraphsIterator();
            while (itPara.hasNext()) {
                XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
                List<String> placeholderList = Arrays.asList(PLACEHOLDER);
                placeholderList.forEach(s->{
                    List<XWPFRun> runs=paragraph.getRuns();
                    //文字替换
                    for (int i = 0; i < runs.size(); i++) {
                        //获取字符
                        String text = runs.get(i).getText(runs.get(i).getTextPosition());
                        if (text == null){

                            XmlObject xmlObject = (XmlObject) runs.get(i).getCTR();
                            XmlObject[] xmlObjects = xmlObject.selectPath(XPATH_TEXTBOX_TXBXCONTENT2);
                            if (xmlObjects !=null && xmlObjects.length>=1){
                                CTR ctr = null;
                                try {
                                    ctr = CTR.Factory.parse(xmlObjects[0].xmlText());
                                } catch (XmlException e) {
                                    e.printStackTrace();
                                }
                                XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);

                                String txtBoxVal = bufferrun.text();
                                System.out.println("txtBoxVal:"+txtBoxVal+",s:"+s);
                                if (txtBoxVal != null && txtBoxVal.contains(s)) {
                                    txtBoxVal = txtBoxVal.replace(s ,getValue(dto, s));
                                    bufferrun.setText(txtBoxVal, 0);
                                }
                                xmlObjects[0].set(bufferrun.getCTR());
                            }
                        }else  if (text != null && text.contains("$")) {
                            //System.out.println("text:"+text);
                            //包含占位符的字符缓存
                            StringBuilder cache = new StringBuilder(text);
                            //记录run结束的角标,开始的角标为i
                            int endIndex = 0;
                            boolean contains = text.contains("}");
                            //同一个run中是否包含完成占位符
                            if (!contains) {
                                int j = i + 1 ;
                                for (; j < runs.size(); j++) {
                                    String text1 = runs.get(j).getText(runs.get(j).getTextPosition());
                                    if (text1 == null) {
                                        continue;
                                    }
                                    cache.append(text1);
                                    if (text1.contains("}")) {
                                        endIndex = j;
                                        break;
                                    }
                                }
                            }
                            if (contains || endIndex != 0) {
                                //处理替换
                                String key = cache.toString(); //这里是完整的占位符
                                System.out.println("key:"+key+",s:"+s);
                                if (key.contains(s)) {
                                    if (key.contains(PICTURE_PLACEHOLDER[0])) { //替换图片
                                        InputStream in = null;

                                        String evaluationQrcode = dto.getImg();
                                        System.out.println("=======:"+evaluationQrcode);
                                        String type = evaluationQrcode.substring(evaluationQrcode.lastIndexOf(".") + 1); //二维码图片后缀
                                        //创建Random类对象

                                        try {
                                            if (endIndex == 0) {
                                                paragraph.removeRun(endIndex); //endIndex为0时,直接删掉run
                                            }else {
                                                for (int j = endIndex; j > i; j--) {
                                                    //角标移除后,runs会同步变动,直接继续处理i就可以
                                                    paragraph.removeRun(j);
                                                }
                                            }
                                            //重新创建一个run,用来放二维码图片
                                            XWPFRun run = paragraph.createRun();

                                            in = new FileInputStream("C:\\pic.png");//设置图片路径
                                            run.addPicture(in, Document.PICTURE_TYPE_PNG, "picTest",
                                                    Units.toEMU(WIDTH), Units.toEMU(HEIGHT)); //图片写入
                                            break;
                                        } catch (InvalidFormatException | IOException e) {
                                            e.printStackTrace();
                                        } finally {
                                            try {
                                                if (in != null) {
                                                    in.close();
                                                }
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    }else {
                                        System.out.println("执行文字替换");
                                        //文字替换
                                        /**
                                         * 参数0表示生成的文字是要从哪一个地方开始放置,设置文字从位置0开始
                                         * 就可以把原来的文字全部替换掉了
                                         */
                                        runs.get(i).setColor("FF0000");
                                        runs.get(i).setText(getValue(dto, s), 0);
                                        for (int j = endIndex; j > i; j--) {
                                            //角标移除后,runs会同步变动,直接继续处理i就可以
                                            paragraph.removeRun(j);
                                        }
                                        break;
                                    }

                                }
                            }
                        }
                    }
                });
            }


            //fileNameList.add(fileName);
            FileOutputStream outStream = new FileOutputStream("C:\\wqxiea.docx"); //单个文件保存路径
            doc.write(outStream);
            outStream.close();
        }
//        //合并word
//        if (fileNameList.size() > 0) {
//            String mainFileName = fileNameList.get(0);
//            FileInputStream fis = new FileInputStream("D:/file/evaluation/word/"+mainFileName);
//            XWPFDocument doc = new XWPFDocument(fis);
//            for (int i = 1; i < fileNameList.size(); i++) { //循环合并
//                FileInputStream fisTail = new FileInputStream("D:/file/evaluation/word/"+fileNameList.get(i));
//                XWPFDocument docTail = new XWPFDocument(fisTail);
//                doc = mergeWord(doc, docTail);
//            }
//            //TODO 以下写文件改为使用response下载文件
//            FileOutputStream outStream = null;
//            outStream = new FileOutputStream("D:/file/evaluation/word/合并文件.docx");
//            doc.write(outStream);
//            outStream.close();
//            //TODO 删除fileNameList列表的文件
//        }
    }

    private static String getValue(TicketProject3 dto, String s) {
        if (s.equals("${company}")){
            return dto.getCompany();
        }else if (s.equals("${address}")){
            return dto.getAddress();
        }else if (s.equals("${secondParty}")){
            return dto.getSecondParty();
        }else if (s.equals("${a}")){
            return dto.getA();
        }else if (s.equals("${b}")){
            return dto.getB();
        }else if (s.equals("${c}")){
            return dto.getC();
        }
        return "";
//        if (s.equals("${evaluationProjectName}")) {
//            return dto.getEvaluationProjectName();
//        }else if (s.equals("${ticketName}")) {
//            return dto.getTicketName();
//        }else if (s.equals("${guide}")) {
//            return dto.getGuide();
//        }else if (s.equals("${attention}")) { //注意事项
//            return dto.getAttention();
//        }else if (s.equals("${evaluationCode}")) {
//            return dto.getEvaluationCode();
//        }else if (s.equals("${createdDate}")) {
//            return dto.getCreatedDate();
//        }else return null;
    }
    /**
     * 根据图片类型,取得对应的图片类型代码
     * @param picType
     * @return int
     */
    private static int getPictureType(String picType){
        int res = Document.PICTURE_TYPE_PICT;
        if(picType != null){
            if(picType.equalsIgnoreCase("png")){
                res = Document.PICTURE_TYPE_PNG;
            }else if(picType.equalsIgnoreCase("dib")){
                res = Document.PICTURE_TYPE_DIB;
            }else if(picType.equalsIgnoreCase("emf")){
                res = Document.PICTURE_TYPE_EMF;
            }else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){
                res = Document.PICTURE_TYPE_JPEG;
            }else if(picType.equalsIgnoreCase("wmf")){
                res = Document.PICTURE_TYPE_WMF;
            }
        }
        return res;
    }

    /**
     * 将两个word文档合并
     * @param document
     * @param doucDocument2
     * @return 合并后的文档
     */
    public static XWPFDocument mergeWord(XWPFDocument document,XWPFDocument doucDocument2) {
        XWPFParagraph p = document.createParagraph();
        //设置分页符
        p.setPageBreak(true);
        CTBody src1Body = document.getDocument().getBody();
        CTBody src2Body = doucDocument2.getDocument().getBody();
//      XWPFParagraph p2 = src2Document.createParagraph();
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = src2Body.xmlText(optionsOuter);
        String srcString = src1Body.xmlText();
        String prefix = srcString.substring(0,srcString.indexOf(">")+1);
        String mainPart = srcString.substring(srcString.indexOf(">")+1,srcString.lastIndexOf("<"));
        String sufix = srcString.substring( srcString.lastIndexOf("<") );
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        CTBody makeBody = null;
        try {
            makeBody = CTBody.Factory.parse(prefix+mainPart+addPart+sufix);
        } catch (XmlException e) {
            e.printStackTrace();
        }
        src1Body.set(makeBody);
        return document;
    }


}
package com.mis.webdemo.word3;

import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class TicketProject3 {
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    private String company;
    private String address;
    private String secondParty;
    private String img;
    private String a;
    private String b;
    private String c;

//    /**
//     * 序列码 VvjiN63o9m
//     */
//    private String evaluationCode;
//    /**
//     * 二维码文件地址 https://www.hjhrcloud.com/e/
//     */
//    private String evaluationQrcode;
//    /**
//     * 项目名称
//     */
//    private String evaluationProjectName;
//    /**
//     * 票种角色(领导班子、外部董事、中层)
//     */
//    private String ticketName;
//    /**
//     * 描述 请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分
//     */
//    private String describe;
//
//    /**
//     * 简介(一页一码使用:欢迎参加2023年×××民主测评。。。)
//     */
//    private String information;
//    /**
//     * 指导语
//     */
//    private String guide;
//    /**
//     * 注意事项
//     */
//    private String attention;
//
//    /**
//     * 日期
//     */
//    private String createdDate;

}
package com.mis.webdemo.word3;

import java.util.ArrayList;
import java.util.List;

public class Word3 {

    public static void main(String[] args)  {
        try{
            String line = System.getProperty("line.separator");
            List<TicketProject3> entitys = new ArrayList<>();
            entitys.add(TicketProject3
                    .builder()
                    .company("宁德时代")
                    .address("东湖片区")
                    .secondParty("2303")
                    .img("C:\\pic.png")
                    .a("a1")
                    .b("b1")
                    .c("c1")
                    .build());

//        entitys.add(TicketProject
//                .builder()
//                .evaluationCode("VvjiN6678o")
//                .evaluationProjectName("2023年×××民主测评")
//                .ticketName("领导班子")
//                .describe("请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分")
//                .guide("欢迎参加2023年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。")
//                .attention("1.请务必在限定的时间内完成评价并提交,评价通道将于2023年3月01日关闭;" +line+
//                        "    2.中途因故退出,可用同一手机再次扫码进入考评系统;" +line+
//                        "    3.评价一经提交无法进行修改;" +line+
//                        "    4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!")
//                .evaluationQrcode("D:/file/evaluation/1682057427848.jpg")
//                .createdDate("2023年03月11日")
//                .build());

            //合并导出word文档
            ExportUtils3.UniqueCodeWordExport(entitys, null);
        }catch (Exception exception){
            exception.printStackTrace();
        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值