Procházet zdrojové kódy

上传POI导出工具类,BUG待修复

wuhonghao před 4 roky
rodič
revize
7c191bba5f

+ 34 - 0
railway-admin/src/main/java/com/railway/web/controller/business/catenary/BusJcbFdfxjyqController.java

@@ -3,6 +3,7 @@ package com.railway.web.controller.business.catenary;
 import com.railway.business.catenary.domain.BusJcbFdfxjyq;
 import com.railway.business.catenary.domain.BusJcbGlkg;
 import com.railway.business.catenary.service.IBusJcbFdfxjyqService;
+import com.railway.common.utils.poi.WordUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -13,8 +14,15 @@ import org.springframework.web.bind.WebDataBinder;
 import com.railway.common.core.controller.BaseController;
 import com.railway.common.core.domain.AjaxResult;
 import com.railway.common.core.page.TableDataInfo;
+
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.validation.Valid;
 
@@ -91,4 +99,30 @@ public class BusJcbFdfxjyqController extends BaseController {
         return toAjax(busJcbFdfxjyqService.confirm(busJcbFdfxjyq));
     }
 
+    @ApiOperation(value = "导出")
+    @PutMapping("/export")
+    public void export(@RequestParam String id, HttpServletResponse response) {
+        WordUtils wordUtil=new WordUtils();
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("${fdh}", "测试分段号");
+        params.put("${qj}", "测试区间");
+        params.put("${wd}", "85");
+        try{
+            Map<String,Object> header = new HashMap<String, Object>();
+            header.put("width", 400);
+            header.put("height", 100);
+            header.put("type", "jpg");
+            header.put("content", WordUtils.inputStream2ByteArray(new FileInputStream("D:/fdjyq-20211016.png"), true));
+            params.put("${header}",header);
+            //InputStream inputStream = this.getClass().getResourceAsStream("/word/template/DXF分段绝缘器手册.docx");
+            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("word/template/DXF分段绝缘器手册.docx");
+            String fileName= URLEncoder.encode("测试文档.docx", "UTF-8");    //生成word文件的文件名
+            wordUtil.getWord(inputStream,params,null,fileName,response);
+
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+
+    }
+
 }

binární
railway-business/src/main/resources/word/template/DXF分段绝缘器手册.docx


+ 103 - 0
railway-common/src/main/java/com/railway/common/utils/poi/CustomXWPFDocument.java

@@ -0,0 +1,103 @@
+package com.railway.common.utils.poi;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlToken;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
+import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
+import java.io.IOException;
+import java.io.InputStream;
+
+/*******************************************
+ *
+ * @Package com.railway.common.utils.poi
+ * @Author wuhonghao
+ * @Date 2021/10/16
+ *******************************************/
+public class CustomXWPFDocument extends XWPFDocument {
+
+    public CustomXWPFDocument(InputStream in) throws IOException {
+        super(in);
+    }
+
+    public CustomXWPFDocument() {
+        super();
+    }
+
+    public CustomXWPFDocument(OPCPackage pkg) throws IOException {
+        super(pkg);
+    }
+
+
+
+    /**
+     * @param id
+     * @param width 宽
+     * @param height 高
+     * @param paragraph  段落
+     */
+    public void createPicture(String blipId,int id, int width, int height,XWPFParagraph paragraph) throws Exception {
+        final int EMU = 9525;
+        width *= EMU;
+        height *= EMU;
+        //String blipId = getAllPictures().get(id).getPackagePart().getRelationships().getRelationship(id).getId();
+        CTInline inline = paragraph.createRun().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>";
+
+        inline.addNewGraphic().addNewGraphicData();
+        XmlToken xmlToken = null;
+        try{
+            xmlToken = XmlToken.Factory.parse(picXml);
+        }catch(XmlException xe) {
+            xe.printStackTrace();
+        }
+        inline.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("图片"+ id);
+        docPr.setDescr("测试");
+    }
+}

+ 281 - 0
railway-common/src/main/java/com/railway/common/utils/poi/WordUtils.java

@@ -0,0 +1,281 @@
+package com.railway.common.utils.poi;
+
+import org.apache.poi.xwpf.usermodel.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/*******************************************
+ * 通过word模板生成新的word工具类
+ * @Package com.railway.common.utils.poi
+ * @Author wuhonghao
+ * @Date 2021/10/16
+ *******************************************/
+public class WordUtils {
+
+    /**
+     * 根据模板生成word
+     * @param is     模板的路径
+     * @param params   需要替换的参数
+     * @param tableList   需要插入的参数
+     * @param fileName 生成word文件的文件名
+     * @param response
+     */
+    public void getWord(InputStream is, Map<String, Object> params, List<String[]> tableList, String fileName, HttpServletResponse response) throws Exception {
+        //File file = new File(path);
+        //InputStream is = new FileInputStream(file);
+        CustomXWPFDocument doc = new CustomXWPFDocument(is);
+        this.replaceInPara(doc, params);    //替换文本里面的变量
+        this.replaceInTable(doc, params, tableList); //替换表格里面的变量
+        OutputStream os = response.getOutputStream();
+        response.setHeader("Content-disposition", "attachment; filename=" + fileName);
+        doc.write(os);
+        this.close(os);
+        this.close(is);
+
+    }
+
+    /**
+     * 替换段落里面的变量
+     * @param doc    要替换的文档
+     * @param params 参数
+     */
+    private void replaceInPara(CustomXWPFDocument doc, Map<String, Object> params) {
+        Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
+        XWPFParagraph para;
+        while (iterator.hasNext()) {
+            para = iterator.next();
+            this.replaceInPara(para, params, doc);
+        }
+    }
+
+    /**
+     * 替换段落里面的变量
+     *
+     * @param para   要替换的段落
+     * @param params 参数
+     */
+    private void replaceInPara(XWPFParagraph para, Map<String, Object> params, CustomXWPFDocument doc) {
+        List<XWPFRun> runs;
+        Matcher matcher;
+        if (this.matcher(para.getParagraphText()).find()) {
+            runs = para.getRuns();
+            int start = -1;
+            int end = -1;
+            String str = "";
+            for (int i = 0; i < runs.size(); i++) {
+                XWPFRun run = runs.get(i);
+                String runText = run.toString();
+                if ('$' == runText.charAt(0) && '{' == runText.charAt(1)) {
+                    start = i;
+                }
+                if ((start != -1)) {
+                    str += runText;
+                }
+                if ('}' == runText.charAt(runText.length() - 1)) {
+                    if (start != -1) {
+                        end = i;
+                        break;
+                    }
+                }
+            }
+
+            for (int i = start; i <= end; i++) {
+                para.removeRun(i);
+                i--;
+                end--;
+            }
+
+            for (Map.Entry<String, Object> entry : params.entrySet()) {
+                String key = entry.getKey();
+                if (str.indexOf(key) != -1) {
+                    Object value = entry.getValue();
+                    if (value instanceof String) {
+                        str = str.replace(key, value.toString());
+                        para.createRun().setText(str, 0);
+                        break;
+                    } else if (value instanceof Map) {
+                        str = str.replace(key, "");
+                        Map pic = (Map) value;
+                        int width = Integer.parseInt(pic.get("width").toString());
+                        int height = Integer.parseInt(pic.get("height").toString());
+                        int picType = getPictureType(pic.get("type").toString());
+                        byte[] byteArray = (byte[]) pic.get("content");
+                        ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
+                        try {
+                            //int ind = doc.addPicture(byteInputStream,picType);
+                            //doc.createPicture(ind, width , height,para);
+                            String blipId = doc.addPictureData(byteInputStream, picType);
+                            doc.createPicture(blipId,doc.getAllPictures().size() - 1, width, height, para);
+                            para.createRun().setText(str, 0);
+                            break;
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 为表格插入数据,行数不够添加新行
+     *
+     * @param table     需要插入数据的表格
+     * @param tableList 插入数据集合
+     */
+    private static void insertTable(XWPFTable table, List<String[]> tableList) {
+        //创建行,根据需要插入的数据添加新行,不处理表头
+        for (int i = 0; i < tableList.size(); i++) {
+            XWPFTableRow row = table.createRow();
+        }
+        //遍历表格插入数据
+        List<XWPFTableRow> rows = table.getRows();
+        int length = table.getRows().size();
+        for (int i = 1; i < length - 1; i++) {
+            XWPFTableRow newRow = table.getRow(i);
+            List<XWPFTableCell> cells = newRow.getTableCells();
+            for (int j = 0; j < cells.size(); j++) {
+                XWPFTableCell cell = cells.get(j);
+                String s = tableList.get(i - 1)[j];
+                cell.setText(s);
+            }
+        }
+    }
+
+    /**
+     * 替换表格里面的变量
+     * @param doc    要替换的文档
+     * @param params 参数
+     */
+    private void replaceInTable(CustomXWPFDocument doc, Map<String, Object> params, List<String[]> tableList) {
+        Iterator<XWPFTable> iterator = doc.getTablesIterator();
+        XWPFTable table;
+        List<XWPFTableRow> rows;
+        List<XWPFTableCell> cells;
+        List<XWPFParagraph> paras;
+        while (iterator.hasNext()) {
+            table = iterator.next();
+            if (table.getRows().size() > 1) {
+                //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
+                if (this.matcher(table.getText()).find()) {
+                    rows = table.getRows();
+                    for (XWPFTableRow row : rows) {
+                        cells = row.getTableCells();
+                        for (XWPFTableCell cell : cells) {
+                            paras = cell.getParagraphs();
+                            for (XWPFParagraph para : paras) {
+                                this.replaceInPara(para, params, doc);
+                            }
+                        }
+                    }
+                } else {
+                    if(tableList!=null){
+                        insertTable(table, tableList);  //插入数据
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 正则匹配字符串
+     *
+     * @param str
+     * @return
+     */
+    private Matcher matcher(String str) {
+        Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(str);
+        return matcher;
+    }
+
+
+    /**
+     * 根据图片类型,取得对应的图片类型代码
+     *
+     * @param picType
+     * @return int
+     */
+    private static int getPictureType(String picType) {
+        int res = CustomXWPFDocument.PICTURE_TYPE_PICT;
+        if (picType != null) {
+            if (picType.equalsIgnoreCase("png")) {
+                res = CustomXWPFDocument.PICTURE_TYPE_PNG;
+            } else if (picType.equalsIgnoreCase("dib")) {
+                res = CustomXWPFDocument.PICTURE_TYPE_DIB;
+            } else if (picType.equalsIgnoreCase("emf")) {
+                res = CustomXWPFDocument.PICTURE_TYPE_EMF;
+            } else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {
+                res = CustomXWPFDocument.PICTURE_TYPE_JPEG;
+            } else if (picType.equalsIgnoreCase("wmf")) {
+                res = CustomXWPFDocument.PICTURE_TYPE_WMF;
+            }
+        }
+        return res;
+    }
+
+    /**
+     * 将输入流中的数据写入字节数组
+     *
+     * @param in
+     * @return
+     */
+    public static byte[] inputStream2ByteArray(InputStream in, boolean isClose) {
+        byte[] byteArray = null;
+        try {
+            int total = in.available();
+            byteArray = new byte[total];
+            in.read(byteArray);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (isClose) {
+                try {
+                    in.close();
+                } catch (Exception e2) {
+                    e2.getStackTrace();
+                }
+            }
+        }
+        return byteArray;
+    }
+
+
+    /**
+     * 关闭输入流
+     *
+     * @param is
+     */
+    private void close(InputStream is) {
+        if (is != null) {
+            try {
+                is.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 关闭输出流
+     *
+     * @param os
+     */
+    private void close(OutputStream os) {
+        if (os != null) {
+            try {
+                os.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+
+}