2021-09-24

poi填充word文档

图片插入word三种实现方式,两种插入图片会打乱word原有的布局,第三种采用环绕插入并设置图片大小,偏移量等 使图片悬浮于文字 上或下 不会打乱word原有布局

package common.redis.utils;

import org.apache.commons.collections.CollectionUtils;
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.XmlOptions;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class DocUtils {

    public DocMen docMen = new DocMen();

    /**
     * 如果传值方法数据太长可以使用JSONObject或 Map类型进行传递参数
     * 启动运行类
     * 由于事先对序号做了截取分段,避免了static序号错乱 追加的问题
     * 可以使用多线程操作生成
     * 对于一次性生成多种类型表格可以使用多线程,同一表格操作使用多线程
     * 导致原有的有序数据错乱
     * 如果使用同步操作相当于串行这样多线程和单线程运行性能没啥区别,锁的出现,可能比单线程运行速度更慢
     * @param file
     * @param params
     * @param details
     * @param isStatus
     * @param strings
     * @param start
     * @param end
     * @throws IOException
     */
    public void start(File file, Map<String, Object> params, List<Map<String, Object>> details, Boolean isStatus, String[] strings, int start, int end, int columns) throws Exception {
        List<XWPFDocument> list = documents(file,params,details,isStatus,strings,start,end,columns);
        if(!CollectionUtils.isEmpty(list)){
            saveFiles(list,null);
        }
    }

    /**
     * 生成复杂的数据表 续表数据启动方法
     * @param mainFile
     * @param detailFile
     * @param params
     * @param detailData
     * @param strings
     * @param mainStart
     * @param mainEnd
     * @param mainColumns
     * @param isTrue
     * @param detailStart
     * @param detailEnd
     * @param columns
     */
    public void start(File mainFile, File detailFile, Map<String,Object> params, List<Map<String,Object>>detailData,String[] strings,Integer mainStart, Integer mainEnd,Integer mainColumns,Boolean isTrue,Integer detailStart,Integer detailEnd,Integer columns) throws Exception {
        Integer sear = 0;
        //判断明细数据大小 如果明细数据等于或小于主表中明细列
        if(detailData.size() == mainColumns || detailData.size() < mainColumns){
            start(mainFile, params, detailData, isTrue, strings, mainStart, mainEnd, mainColumns);
        }else {
            //计算序号
            List<XWPFDocument> list = documents(mainFile,params,detailData.subList(0,mainColumns),isTrue,strings,mainStart,mainEnd,mainColumns);
            List<XWPFDocument> characters = characters(detailFile, params, detailData, isTrue, strings, detailStart, detailEnd, columns, mainColumns + 1);
            List<XWPFDocument> collect = Stream.of(list, characters).flatMap(Collection::stream).collect(Collectors.toList());
            saveFiles(collect,null);
        }
    }

    /**
     * 执行保存操作,保存文件到本地操作 使用 ByteArrayOutputStream 输入流可以提高性能
     * @param list
     * @param path
     * @throws XmlException
     * @throws IOException
     */
    public void saveFiles(List<XWPFDocument> list, String path) throws XmlException, IOException {
        XWPFDocument xmd = list.get(0); //默认获取第一个作为模板
        for (int i=0;i<list.size()-1;i++) {
            xmd = docMen.mergeWord(xmd,list.get(i+1)); //相继合并
        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        xmd.write((OutputStream)byteArrayOutputStream);
        OutputStream outputStream = new FileOutputStream("C:\\Users\\31034\\Desktop\\新建.docx");
        outputStream.write(byteArrayOutputStream.toByteArray());
        outputStream.close();
        //collector中传入HttpServletResponse 直接调用 IOUtils.copy(inputStream,response.getOutputStream);
        // 可以直接保存本地电脑 貌似该框架无法实现该功能
        // InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        // IOUtils.copy(inputStream,outputStream);
    }

    /**
     * 续页表格的操作生成实现,先判断明细数据是否小于或等于主表信息数据,如果符合这些信息 则不需要附表直接生成主表信息
     * 明细数据大于主表存储数据则计算需要明细表的数量, 同时计算明细表开始下标
     * @param file
     * @param params
     * @param details
     * @param isState
     * @param strings
     * @param start
     * @param end
     * @param columns
     * @param serial
     * @return
     * @throws Exception
     */
    public List<XWPFDocument> characters(File file, Map<String, Object> params, List<Map<String, Object>> details, Boolean isState, String[] strings, Integer start, Integer end,int columns,Integer serial) throws Exception {
        List<XWPFDocument> list = new LinkedList<>();
        Integer num = 1;
        if(isState){
            num = details.size() / columns;
            //先取余数后取模
            Integer IntegerNum = details.size() % columns;
            if(IntegerNum>0) num++;
        }
        for(int i = 0; i < num; i++){
            if(i == 1){
                serial = columns+i;
            }else if(i==0){
                serial = serial;
            }else{
                serial = columns+serial;
            }
            XWPFDocument xwpfDocument = docMen.replaceInTable(new XWPFDocument(new FileInputStream(file)), params, details, isState, strings, start, end, serial);
            list.add(xwpfDocument);
        }
        return list;
    }

    /**
     * 执行生成表格数据操作
     * 同时对数据序号进行分段,同时根据明细数据进行表格数量的计算 foreach调用获取表格最后调取sava进行合并本地保存等操作
     * @param file
     * @param params
     * @param details
     * @param isState
     * @param strings
     * @param start
     * @param end
     * @param columns
     * @return
     * @throws Exception
     */
    public List<XWPFDocument> documents(File file, Map<String, Object> params, List<Map<String, Object>> details, Boolean isState, String[] strings, Integer start, Integer end,int columns) throws Exception {
        List<XWPFDocument> list = new LinkedList<>();
        Integer num = 1;
        Integer serial = 0;
        if(isState){
            num = details.size() / columns;
            //先取余数后取模
            Integer IntegerNum = details.size() % columns;
            if(IntegerNum>0) num++;
        }
        for(int i = 0; i < num; i++){
            if(i == 1){
                serial = columns+i;
            }else if(i==0){
                serial = 1;
            }else{
                serial = columns+serial;
            }
            XWPFDocument xwpfDocument = docMen.replaceInTable(new XWPFDocument(new FileInputStream(file)), params, details, isState, strings, start, end, serial);
            list.add(xwpfDocument);
        }
        return list;
    }

    public class DocMen extends Doc implements word{

        /**
         * 对表格数据进行追加
         * @param document
         * @param docDocument2
         * @return
         * @throws XmlException
         */
        @Override
        public XWPFDocument mergeWord(XWPFDocument document, XWPFDocument docDocument2) throws XmlException {
            XWPFDocument src1Document =document ;
            XWPFParagraph p = src1Document.createParagraph();
            //设置分页符
            p.setPageBreak(true);
            CTBody src1Body = src1Document.getDocument().getBody();
            XWPFDocument src2Document = docDocument2;
            CTBody src2Body = src2Document.getDocument().getBody();
            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 = CTBody.Factory.parse(prefix+mainPart+addPart+sufix);
            src1Body.set(makeBody);
            return src1Document;
        }

        /**
         * 读取明细行数据
         * 如果段落中的数据读取完成以后则设置 以下内容空白提示
         * @param para 段落
         * @param params 明细参数信息
         * @param index 第几行
         * @param key
         * @param tableFontsize
         * @param column
         */
        @Override
        public void replaceInPara(XWPFParagraph para, List<Map<String, Object>> params, Integer index, String key, int tableFontsize, Integer column) {
            List<XWPFRun> runs;
            runs = para.getRuns();
            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                String runText = run.toString();
                if(index < params.size()){
                    runText = String.valueOf(params.get(index).get(key));
                    run.setText(runText, 0);
                    run.setFontSize(tableFontsize);
                } else  if(index == params.size()){
                    if(column == 1){
                        runText = "以下内容空白";
                        run.setText(runText, 0);
                        run.setFontSize(tableFontsize);
                    }else {
                        runText = "";
                        run.setText(runText, 0);
                        run.setFontSize(tableFontsize);
                    }
                } else {
                    runText = "";
                    run.setText(runText, 0);
                    run.setFontSize(tableFontsize);
                }
            }
        }

        /**
         * 替换段落中的数据信息 如果序号大于列则不对列做取值操作 直接把列内容赋值为null
         * @param para
         * @param index
         * @param tableFontsize
         * @param column
         */
        @Override
        public void replaceInPara(XWPFParagraph para, Integer index, int tableFontsize, Integer column) {
            List<XWPFRun> runs;
            runs = para.getRuns();
            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                if(column < index){
                    String runText = run.toString();
                    runText = "";
                    run.setText(runText, 0);
                }else {
                    String runText = run.toString();
                    runText = String.valueOf(index);
                    run.setText(runText, 0);
                    run.setFontSize(tableFontsize);
                }
            }
        }

        /**
         * 替换表格之外的段落数据信息
         * 注:doc.getTablesIterator(); 只能读取表格内的东西 表格外的数据无法获取
         * @param document docx解析对象
         * @param textMap 需要替换的信息集合
         * @throws Exception
         */
        @Override
        public void changeText(XWPFDocument document, Map<String, Object> textMap) throws Exception {
            //获取段落集合
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            for (XWPFParagraph paragraph : paragraphs) {
                //判断此段落时候需要进行替换
                replaceInPara(paragraph,textMap,document);
            }
        }

        /**
         * 替换表格中的数据信息
         * @param doc    要替换的文档
         * @param params 参数
         * @param details
         * @param isStatus
         * @param strings
         * @param start
         * @param end
         * @param serial
         * @return
         * @throws Exception
         */
        @Override
        public XWPFDocument replaceInTable(XWPFDocument doc, Map<String, Object> params, List<Map<String, Object>> details, Boolean isStatus, String[] strings, int start, int end,int serial) throws Exception {
            changeText(doc, params);
            Iterator<XWPFTable> iterator = doc.getTablesIterator();
            XWPFTable table;
            Integer index = 0;
            List<XWPFTableRow> rows;
            List<XWPFTableCell> cells;
            List<XWPFParagraph> paras;
            while (iterator.hasNext()) {
                table = iterator.next();
                rows = table.getRows();
                for (int i = 0; i< rows.size(); i++){
                    if(isStatus){
                        if(i == start){
                            for (i = start; i < end; i++){
                                cells = rows.get(i).getTableCells();
                                for (int n = 0; n < cells.size(); n++){
                                    paras = cells.get(n).getParagraphs();
                                    for (int j = 0; j < paras.size(); j++) {
                                        if(n==0){
                                            replaceInPara(paras.get(j),serial,8,details.size());
                                        }else {
                                            replaceInPara(paras.get(j), details, serial-1,strings[n-1],8,n);
                                            index++;
                                        }
                                        if(index == strings.length){ index = 0; }
                                    }
                                }
                                serial++;
                            }
                            if(i >= rows.size()){
                                return doc;
                            }
                        }
                    }
                    cells = rows.get(i).getTableCells();
                    for (int n = 0; n < cells.size(); n++){
                        paras = cells.get(n).getParagraphs();
                        for (int j = 0; j < paras.size(); j++) {
                            replaceInPara(paras.get(j), params,doc);
                        }
                    }
                }
            }
            return doc;
        }

        /**
         * 正则表达式判断读取数据是否否合正则表达式
         * @param str
         * @return
         */
        @Override
        public Matcher matcher(String str) {
            Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(str);
            return matcher;
        }

        /**
         * 替换段落数据
         * matcher正则读取段落数据,
         * 如果段落中有符合正则的数据则从map集合中读取数据并且赋值
         * @param para   要替换的段落
         * @param params 参数
         * @param doc
         * @throws Exception
         */
        @Override
        public void replaceInPara(XWPFParagraph para, Map<String, Object> params,XWPFDocument doc) throws Exception {
            List<XWPFRun> runs;
            Matcher matcher;
            if (matcher(para.getParagraphText()).find()) {
                runs = para.getRuns();
                for (int i = 0; i < runs.size(); i++) {
                    XWPFRun run = runs.get(i);
                    String runText = run.toString();
                    matcher = matcher(runText);
                    if (matcher.find()) {
                        if("${price}".equals(runText)){
                            InputStream stream = covInputStream("https://img-blog.csdnimg.cn/img_convert/b26750936b8d00e60053e7dda335f9aa.png");
                            aroundImage(run,stream,65,65);
                            break;
                        }else {
                            while ((matcher = matcher(runText)).find()) {
                                runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));
                            }
                            run.setText(runText, 0);
                            run.setFontSize(9);
                        }
                    }
                }
            }
        }

        /**
         * 流转换 根据网络图片地址转换为inputStream输出流
         * @param url
         * @return
         * @throws IOException
         */
        @Override
        InputStream covInputStream(String url) throws IOException {
            URL path = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)path.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5 * 1000);
            InputStream inputStream = conn.getInputStream();//通过输入流获取图片数据
            //最终返回处理好的数据
            return inputStream;
        }

        /**
         * 插入图片 给段落中插入图片并设置图片的宽高
         * 使用
         * //int priceId = priceType(doc, "png");
         * //replaceImg(run,stream,"https://img-blog.csdnimg.cn/img_convert/b26750936b8d00e60053e7dda335f9aa.png");
         * @param run
         * @param stream
         * @param path
         * @throws IOException
         * @throws InvalidFormatException
         */
        @Override
        void replaceImg(XWPFRun run,InputStream stream,String path) throws IOException, InvalidFormatException {
            XWPFPicture xwpfPicture = run.addPicture(stream, XWPFDocument.PICTURE_TYPE_PNG, path, Units.toEMU(60), Units.toEMU(60));// 100x100 pixels
            stream.close();
            run.setText("  ",0);
        }

        /**
         * 根据 图片的后坠名判断图片的属性值
         * @param docx
         * @param suffix
         * @return
         */
        @Override
        public int priceType(XWPFDocument docx,String suffix) {
            int res = docx.PICTURE_TYPE_PICT;
            if (suffix != null) {
                if (suffix.equalsIgnoreCase("png")) {
                    res = docx.PICTURE_TYPE_PNG;
                } else if (suffix.equalsIgnoreCase("dib")) {
                    res = docx.PICTURE_TYPE_DIB;
                } else if (suffix.equalsIgnoreCase("emf")) {
                    res = docx.PICTURE_TYPE_EMF;
                } else if (suffix.equalsIgnoreCase("jpg") || suffix.equalsIgnoreCase("jpeg")) {
                    res = docx.PICTURE_TYPE_JPEG;
                } else if (suffix.equalsIgnoreCase("wmf")) {
                    res = docx.PICTURE_TYPE_WMF;
                }
            }
            return res;
        }

        /**
         * 使用方法
         *int priceId = priceType(doc, "png"); 图片属性id
         *String Id = doc.addPictureData(stream,priceId); 图片id
         *rangImag(run,Id,priceId,200,200);
         * @param run
         * @param blipId
         * @param id
         * @param width
         * @param height
         */
        @Override
        public void rangImag(XWPFRun run,String blipId,int id,int width, int height) {
            final int EMU = 9525;
            width *= EMU;
            height *= EMU;
            //String blipId = getAllPictures().get(id).getPackageRelationship().getId();

            CTInline inline =run.getCTR().addNewDrawing().addNewInline();

            String picXml = "" +
                    "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
                    "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                    "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                    "         <pic:nvPicPr>" +
                    "            <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" +
                    "            <pic:cNvPicPr/>" +
                    "         </pic:nvPicPr>" +
                    "         <pic:blipFill>" +
                    "            <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
                    "            <a:stretch>" +
                    "               <a:fillRect/>" +
                    "            </a:stretch>" +
                    "         </pic:blipFill>" +
                    "         <pic:spPr>" +
                    "            <a:xfrm>" +
                    "               <a:off x=\"0\" y=\"0\"/>" +
                    "               <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" +
                    "            </a:xfrm>" +
                    "            <a:prstGeom prst=\"rect\">" +
                    "               <a:avLst/>" +
                    "            </a:prstGeom>" +
                    "         </pic:spPr>" +
                    "      </pic:pic>" +
                    "   </a:graphicData>" +
                    "</a:graphic>";

            //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData();
            XmlToken xmlToken = null;
            try {
                xmlToken = XmlToken.Factory.parse(picXml);
            } catch(XmlException xe) {
                xe.printStackTrace();
            }
            inline.set(xmlToken);
            //graphicData.set(xmlToken);

            inline.setDistT(0);
            inline.setDistB(0);
            inline.setDistL(0);
            inline.setDistR(0);

            CTPositiveSize2D extent = inline.addNewExtent();
            extent.setCx(width);
            extent.setCy(height);

            CTNonVisualDrawingProps docPr = inline.addNewDocPr();
            docPr.setId(id);
            docPr.setName("Picture " + id);
            docPr.setDescr("Generated");
            run.setText("  ",0);
        }

        @Override
        public void aroundImage(XWPFRun run,InputStream stream,int width,int height) throws IOException, InvalidFormatException {
            Random random = new Random();
            //产生随机数
            int number = random.nextInt(999) + 1;
            run.addPicture(stream, Document.PICTURE_TYPE_PNG, "Seal"+number, Units.toEMU(62), Units.toEMU(62));
            stream.close();
            // 2. 获取到图片数据
            CTDrawing drawing = run.getCTR().getDrawingArray(0);
            CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();

            //拿到新插入的图片替换添加CTAnchor 设置浮动属性 删除inline属性
            CTAnchor anchor = getAnchorWithGraphic(graphicalobject, "Seal"+number,
                    Units.toEMU(width), Units.toEMU(height),//图片大小
                    Units.toEMU(0), Units.toEMU(0), false);//相对当前段落位置 需要计算段落已有内容的左偏移
            drawing.setAnchorArray(new CTAnchor[]{anchor});//添加浮动属性
            drawing.removeInline(0);//删除行内属性
            run.setText("  ",0);
        }

        /**
         * @param ctGraphicalObject 图片数据
         * @param deskFileName      图片描述
         * @param width             宽
         * @param height            高
         * @param leftOffset        水平偏移 left
         * @param topOffset         垂直偏移 top
         * @param behind            文字上方,文字下方
         * @return
         * @throws Exception
         */
        public CTAnchor getAnchorWithGraphic(CTGraphicalObject ctGraphicalObject, String deskFileName, int width, int height, int leftOffset, int topOffset, boolean behind) {
            System.out.println(">>width>>"+width+"; >>height>>>>"+height);
            String anchorXML =
                    "<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "
                            + "simplePos=\"0\" relativeHeight=\"0\" behindDoc=\"" + ((behind) ? 1 : 0) + "\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
                            + "<wp:simplePos x=\"0\" y=\"0\"/>"
                            + "<wp:positionH relativeFrom=\"column\">"
                            + "<wp:posOffset>" + leftOffset + "</wp:posOffset>"
                            + "</wp:positionH>"
                            + "<wp:positionV relativeFrom=\"paragraph\">"
                            + "<wp:posOffset>" + topOffset + "</wp:posOffset>" +
                            "</wp:positionV>"
                            + "<wp:extent cx=\"" + width + "\" cy=\"" + height + "\"/>"
                            + "<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>"
                            + "<wp:wrapNone/>"
                            + "<wp:docPr id=\"1\" name=\"Drawing 0\" descr=\"" + deskFileName + "\"/><wp:cNvGraphicFramePr/>"
                            + "</wp:anchor>";

            CTDrawing drawing = null;
            try {
                drawing = CTDrawing.Factory.parse(anchorXML);
            } catch (XmlException e) {
                e.printStackTrace();
            }
            CTAnchor anchor = drawing.getAnchorArray(0);
            anchor.setGraphic(ctGraphicalObject);
            return anchor;
        }

    }

    protected abstract class Doc{

        /**
         * 文件对象进行追加
         * @param document
         * @param docDocument2
         * @return
         * @throws Exception
         */
        abstract XWPFDocument mergeWord(XWPFDocument document, XWPFDocument docDocument2) throws XmlException;

        /**
         * 替换明细字段数据库自取字段信息 (明细表操作)
         * @param para 段落
         * @param params 明细参数信息
         * @param index 第几行
         * @param key
         */
        abstract void replaceInPara(XWPFParagraph para, List<Map<String, Object>> params,Integer index,String key,int tableFontsize,Integer column);

        /**
         * 替换明细数据字段为 serial 序号 (明细表操作)
         * @param para
         * @param index
         */
        abstract void replaceInPara(XWPFParagraph para,Integer index,int tableFontsize,Integer column);

        /**
         * 替换段落文本
         * @param document docx解析对象
         * @param textMap 需要替换的信息集合
         */
        abstract void changeText(XWPFDocument document, Map<String, Object> textMap) throws Exception;

        /**
         * 替换表格里面的变量 (表格操作)
         *
         * @param doc    要替换的文档
         * @param params 参数
         */
        abstract XWPFDocument replaceInTable(XWPFDocument doc, Map<String, Object> params,List<Map<String,Object>> details,Boolean isStatus,String[] strings,int start,int end,int serial) throws Exception;

        /**
         * 正则匹配字符串 (主表变量操作)
         */
        abstract Matcher matcher(String str);

        /**
         * 替换段落里面的变量 (主表操作)
         *
         * @param para   要替换的段落
         * @param params 参数
         */
        abstract void replaceInPara(XWPFParagraph para, Map<String, Object> params,XWPFDocument doc) throws Exception;

        /**
         * 网络文件转换为InputStream
         * @param url
         * @return
         */
        abstract InputStream covInputStream(String url) throws IOException;

        /**
         * 替换表格中的图片
         * @param xwpfRun
         */
        abstract void replaceImg(XWPFRun xwpfRun,InputStream stream,String path) throws FileNotFoundException, IOException, InvalidFormatException;
    }

    protected interface word {

        /**
         * 获取图片属性
         *
         * @param suffix
         * @return
         */
        int priceType(XWPFDocument docx, String suffix);

        /**
         * 给run添加图片
         * @param run
         * @param blipId
         * @param id
         * @param width
         * @param height
         */
        void rangImag(XWPFRun run,String blipId,int id,int width, int height);

        /**
         * 环绕插入图片 注: 此方法不存在顶出外边
         * @param run
         * @param stream
         * @param width
         * @param height
         */
        void aroundImage(XWPFRun run,InputStream stream,int width,int height) throws IOException, InvalidFormatException;
    }

}

package commons.redis;

import common.redis.RedisClientApplication;
import common.redis.utils.DocUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import javax.print.Doc;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = RedisClientApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DocTest {

    @Autowired
    private JdbcTemplate template;

    private DocUtils docUtils = new DocUtils();

    /**
     * 射线检测底片评定
     * @throws Exception
     */
    @Test
    public void tests() throws Exception {
        List<Map<String, Object>> list = template.queryForList("select * from t_dppdjl where id = 427167304577187841");
        List<Map<String, Object>> list1 = template.queryForList("select * from t_dppdjl_mx where zbid = 427167304577187841 ");
        System.out.println(list);
        System.out.println(list1);
        String[] strings = new String[]{"bjbh","dpbh","hgdh","xjh","qxwz","qxpd","pj","dphd"};
        File file = new File("C:\\Users\\31034\\Desktop\\新建 DOCX 文档 (3).docx");
        new DocUtils().start(file,list.get(0),list1, true,strings,5,21,16);
    }

    /*无损检测委托单*/
    @Test
    public void test1s() throws Exception {
        List<Map<String, Object>> list = template.queryForList("select * from t_wsjcwtd where id = 427756396761055233");
        List<Map<String, Object>> list1 = template.queryForList("select * from t_wsjcwtd_mx where zbid = 427756396761055233 ");
        System.out.println(list);
        System.out.println(list1.size());
        String[] strings = new String[]{"hkh","ggcz","hgdh"};
        File file = new File("C:\\Users\\31034\\Desktop\\新建 DOCX 文1档.docx");
        new DocUtils().start(file,list.get(0),list1, true,strings,12,18,6);
    }

    /*射线检测操作指导书*/
    @Test
    public void test2s() throws Exception {
        List<Map<String, Object>> list = template.queryForList("select * from t_sxjcczzds where id = 425496946658770945");
        List<Map<String, Object>> list1 = template.queryForList("select * from t_sxjcczzds_mx where zbid = 425496946658770945 ");
        System.out.println(list);
        System.out.println(list1.size());
        String[] strings = new String[]{"qrxm","jg","dxqrjl"};
        File file = new File("C:\\Users\\31034\\Desktop\\新建 DOCX 文档.docx");
        List<XWPFDocument> documents = docUtils.documents(file, list.get(0), list1, false, strings, 0, 0,0 );
        File files = new File("C:\\Users\\31034\\Desktop\\新建 DOCX 文档 (2).docx");
        List<XWPFDocument> documents1 = docUtils.documents(files, list.get(0), list1, true, strings, 4, 21, 17);
        List<XWPFDocument> result = Stream.of(documents, documents1).flatMap(Collection::stream).collect(Collectors.toList());
        docUtils.saveFiles(result,null);
    }


    /*文件续页操作*/
    @Test
    public void test3s() throws Exception {
        List<Map<String, Object>> list = template.queryForList("select * FROM t_csbjcbg where id = 427741302551478273");
        List<Map<String, Object>> list1 = template.queryForList("select * from t_csbjcbg_mx where zbid = 427741302551478273 ");
        System.out.println(list);
        System.out.println(list1.size());
        String[] strings = new String[]{"hkbh","qxxh","qxlx","zd","sd","gd","qxwz","zgbf","pj","pd","bz"};
        File file = new File("C:\\Users\\31034\\Desktop\\超声波检测报告.docx");
        File files = new File("C:\\Users\\31034\\Desktop\\新建 DOCX 文档 (5).docx");
        List<XWPFDocument> documents = docUtils.documents(file, list.get(0), list1, false, strings, 0, 0,0 );
        docUtils.start(file,files,list.get(0),list1,strings,17,21,4,true,5,26,21);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cim</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>redis-client</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <commons-version>3.8</commons-version>
        <commons.io.version>3.2.2</commons.io.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- Spring Boot JDBC -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j</artifactId>
            <version>3.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-version}</version>
        </dependency>
        <!--java util工具包-->
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>${commons.io.version}</version>
        </dependency>
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--spring-boot-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--logs end-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>
        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--java工具包-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>common.minio.MinioServerApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pursue?????

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值