精华内容
下载资源
问答
  • POI根据模板导出word文件,以及word转PDF,PDF转图片再插入PDF中(防止PDF被修改)
    2020-05-21 18:19:40

    POI根据模板导出word文件

    一、制作word模版,${xxxx}是一会要替换的内容,最下面的表格是要插入数据,根据是否以$开头来判断是需要替换还是插入数据。
            注意如果是需要插入数据,制作的表格模版需要一行空行,也只能有一行空行,原因可以看代码的逻辑,表格中${header}${hearder2}是放入需要替换的图片
    word模板
    二、添加poi所需要的jar包文件,我用的maven对jar包进行管理

    <dependency>
         <groupId>org.apache.poi</groupId>
         <artifactId>poi</artifactId>
         <version>3.11</version>
    </dependency>
    <dependency>
         <groupId>org.apache.poi</groupId>
         <artifactId>poi-ooxml</artifactId>
         <version>3.11</version>
    </dependency>
    

    三、由于poi自身bug,会出现图片无法显示问题,这里需要自定义一个类继承XWPFDocument类,接下来使用的都是我们自己创建的这个类来操作word对象,这个类对XWPFDocument进行了继承,所以不用担心会有什么问题

    import java.io.InputStream;
    
    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;
    
    public class CustomXWPFDocument extends XWPFDocument {
    
       public CustomXWPFDocument(InputStream in) throws java.io.IOException {
               super(in);
       }
    
       public CustomXWPFDocument() {
               super();
       }
    
       public CustomXWPFDocument(OPCPackage pkg)throws java.io.IOException {
               super(pkg);
       }
    
       /**
        * @param id
        * @param width 宽
        * @param height 高
        * @param paragraph  段落
        */
       public void createPicture(int id, int width, int height,XWPFParagraph paragraph) {
       final int EMU = 9525;
       width *= EMU;
       height *= EMU;
       String blipId = getAllPictures().get(id).getPackageRelationship().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("测试");
       }
    }
    

    四、接下来就是导出word的工具类了

    import java.io.*;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.poi.xwpf.usermodel.*;
    import org.springframework.stereotype.Component;
    
    /*******************************************
    * 通过word模板生成新的word工具类
    *
    * @Author Administrator
    * @Date 2020/03/10
    * @Version V1.0
    *******************************************/
    @Component
    public class WordUtil {
    
       /**
        * 根据模板生成word
        *
        * @param path
        *            模板的路径
        * @param params
        *            需要替换的参数
        * @param tableList
        *            需要插入的参数,里面的list为每个表的数据
        * @param fileName
        *            生成word文件的文件名
        * @return 生成的word的路径
        */
       public String getWord(String path, Map<String, Object> params, List<List<String[]>> tableList, String fileName,String outFileName) 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.setContentType("application/x-download");
    //        response.setHeader("Content-disposition", "attachment; filename=" + fileName);
    //        doc.write(os);
           File newFile = new File(outFileName);
           OutputStream os = new FileOutputStream(newFile);
           doc.write(os);
           this.close(os);
           this.close(is);
    
           return outFileName;
       }
    
       /**
        * 替换段落里面的变量
        *
        * @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--;
               }
               if (params != null) {
                   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);
                                   doc.addPictureData(byteInputStream, picType);
                                   doc.createPicture(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();
           //i为表格标题行数
           for (int i = 2; i < length - 1; i++) {
               XWPFTableRow newRow = table.getRow(i);
               newRow.setHeight(600);    //设置表格行高
               List<XWPFTableCell> cells = newRow.getTableCells();
               for (int j = 0; j < cells.size(); j++) {
                   XWPFTableCell cell = cells.get(j);
                   cell.getParagraphs().get(0).setAlignment(ParagraphAlignment.CENTER); //设置单元格居中显示
                   String s = tableList.get(i - 2)[j];  //i减去的数字也为表格行数
                   cell.setText(s);
               }
           }
       }
    
       /**
        * 替换表格里面的变量
        *
        * @param doc
        *            要替换的文档
        * @param params
        *            参数
        */
       private void replaceInTable(CustomXWPFDocument doc, Map<String, Object> params, List<List<String[]>> tableList) {
           Iterator<XWPFTable> iterator = doc.getTablesIterator();
           XWPFTable table;
           List<XWPFTableRow> rows;
           List<XWPFTableCell> cells;
           List<XWPFParagraph> paras;
           int i = 0;
           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.get(i)); // 插入数据
                           i++;
                       }
                   }
               }
           }
       }
    
       /**
        * 正则匹配字符串
        *
        * @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();
               }
           }
       }
    
    }
    

    五、最后就是进行测试了,我是用的是ssm框架,这里放出测试代码

    @RequestMapping("exportWordData")
       public void exportWordData(HttpServletRequest request,HttpServletResponse response){
           WordUtils wordUtil=new WordUtils();
           Map<String, Object> params = new HashMap<String, Object>();
           params.put("${position}", "java开发");
           params.put("${name}", "段然涛");
           params.put("${sex}", "男");
           params.put("${national}", "汉族");
           params.put("${birthday}", "生日");
           params.put("${address}", "许昌");
           params.put("${height}", "165cm");
           params.put("${biYeDate}", "1994-02-03");
           params.put("${landscape}", "团员");
           params.put("${zhuanYe}", "社会工作");
           params.put("${xueLi}", "本科");
           params.put("${school}", "江西科技师范大学");
           params.put("${phone}", "177");
           params.put("${eMail}", "157");
    
           try{
               Map<String,Object> header = new HashMap<String, Object>();
               header.put("width", 100);
               header.put("height", 150);
               header.put("type", "jpg");
               header.put("content", WordUtils.inputStream2ByteArray(new FileInputStream("C:/Users/Administrator/Desktop/jar包/11.jpg"), true));
               params.put("${header}",header);
               Map<String,Object> header2 = new HashMap<String, Object>();
               header2.put("width", 100);
               header2.put("height", 150);
               header2.put("type", "jpg");
               header2.put("content", WordUtils.inputStream2ByteArray(new FileInputStream("C:/Users/Administrator/Desktop/jar包/22.jpg"), true));
               params.put("${header2}",header2);       
               List<List<String[]>> list = new ArrayList<List<String[]>>();
               List<String[]> testList = new ArrayList<String[]>();//一个需要插入的表是一个集合
               testList.add(new String[]{"1","1AA","1BB","1CC"});
               testList.add(new String[]{"2","2AA","2BB","2CC"});
               testList.add(new String[]{"3","3AA","3BB","3CC"});
               testList.add(new String[]{"4","4AA","4BB","4CC"});       list.add(testList);
               String path="C:/Users/Administrator/Desktop/jar包/mobanFile.docx";  //模板文件位置
               String fileName= new String("测试文档.docx".getBytes("UTF-8"),"iso-8859-1");    //生成word文件的文件名
               wordUtil.getWord(path,params,list,fileName,newFilePath);
    
           }catch(Exception e){
               e.printStackTrace();
           }
       }
    

    原文链接:https://www.cnblogs.com/duanrantao/p/8682897.html

    word转PDF

    WORD转PDF所需jar包:
    https://yangtaotao.lanzous.com/ice1jlc
    PDF转图片所需jar包:
    https://yangtaotao.lanzous.com/ice169c

    word转pdf使用的是ASPOSE.word,它的licence需要收费,百度有的文章中有,大家可以自行百度,这里就不放了。调用时传入word的路径和生成后的pdf的路径就行。
    注意:在linux下不可以直接FileOutputSteram(path)生成文件,所以需要先new File(path),如果生成之后的文件中文乱码,可能是服务器没有字库,安装一个就可以了

    package com.biolims.report.service;
    
    import java.io.FileOutputStream;
    import java.io.InputStream;
    
    import com.aspose.words.Document;
    import com.aspose.words.License;
    import com.aspose.words.SaveFormat;
    
    /**
     * 
     * 由于ASPOSE比较吃内存,操作大一点的文件就会堆溢出,所以请先设置好java虚拟机参数:-Xms512m -Xmx512m(参考值)<br>
     * 如有疑问,请在CSDN下载界面留言,或者联系QQ569925980<br>
     * 
     * @author Spark
     *
     */
    public class Test {
    
        /**
         * 获取license
         * 
         * @return
         */
        public static boolean getLicense() {
            boolean result = false;
            try {
                InputStream is = Test.class.getClassLoader().getResourceAsStream("\\license.xml");
                License aposeLic = new License();
                aposeLic.setLicense(is);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
        public static void savedocx(String inPath, String outPath) {
             if (!getLicense()) {
                    return;
                }
    
                try {
                    long old = System.currentTimeMillis();
                    Document doc = new Document(inPath);// 原始word路径
                   File file = new File(outPath);
                    FileOutputStream fileOS = new FileOutputStream(file );
    
                    doc.save(fileOS, SaveFormat.PDF);
    
                    long now = System.currentTimeMillis();
                    System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
        /**
         * 支持DOC, DOCX, OOXML, RTF, HTML, OpenDocument, PDF, EPUB, XPS, SWF等相互转换<br>
         * 
         * @param args
         */
        public static void main(String[] args) {
            // 验证License
            if (!getLicense()) {
                return;
            }
    
            try {
                long old = System.currentTimeMillis();
                Document doc = new Document("D:\\home\\lims\\报告管理需求 - 20190905.docx");// 原始word路径
               
                String pdfFile = "D:\\home\\ff.pdf";
                FileOutputStream fileOS = new FileOutputStream(pdfFile);
    
                doc.save(fileOS, SaveFormat.PDF);
    
                long now = System.currentTimeMillis();
                System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    PDF转图片再插入PDF中(防止PDF被修改)

    公司大佬说这种防止修改的方法在pdf有多页时可能会出问题,也没测试过,试过的朋友帮忙评论一下

    public static String pdf2Image(String PdfFilePath) throws Exception {
            File file = new File(PdfFilePath);
            PdfDocument template_writer_pdfdoc = new PdfDocument(new PdfReader(PdfFilePath));
            Rectangle size=template_writer_pdfdoc.getFirstPage().getPageSize();
            int pages = template_writer_pdfdoc.getNumberOfPages();
            PDDocument pdDocument;
            String pdfPath="";
            try {
                String imgPDFPath = file.getParent();
                int dot = file.getName().lastIndexOf('.');
                String imagePDFName = file.getName().substring(0, dot); // 获取图片文件名
                pdDocument = PDDocument.load(file);
                PDFRenderer renderer = new PDFRenderer(pdDocument);
                /* dpi越大转换后越清晰,相对转换速度越慢 */
                StringBuffer imgFilePath = null;
                List<String> pathList=new ArrayList<String>();
                for (int i = 0; i < pages; i++) {
                    String imgFilePathPrefix = imgPDFPath + File.separator + imagePDFName;
                    imgFilePath = new StringBuffer();
                    imgFilePath.append(imgFilePathPrefix);
                    imgFilePath.append("_");
                    imgFilePath.append(String.valueOf(i + 1));
                    imgFilePath.append(".jpg");
                    File dstFile = new File(imgFilePath.toString());
                    BufferedImage image = renderer.renderImageWithDPI(i, 300);
                    ImageIO.write(image, "jpg", dstFile);
                    pathList.add(imgFilePath.toString());
                }
    
                template_writer_pdfdoc.close();
                File file2 = new File(imgPDFPath + File.separator + file.getName());
                // 第一步:创建一个document对象。
                com.itextpdf.text.Document document = new com.itextpdf.text.Document();
                document.setMargins(0, 0, 0, 0);
                // 第二步:
                // 创建一个PdfWriter实例,
                com.itextpdf.text.pdf.PdfWriter.getInstance(document, new FileOutputStream(file2));
                // 第三步:打开文档。
    
                document.open();
                for(String s:pathList) {
                    com.itextpdf.text.Image img = com.itextpdf.text.Image.getInstance(s);
                    img.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
                    img.scaleAbsoluteHeight(size.getHeight());
                    img.scaleAbsoluteWidth(size.getWidth());
                    // 根据图片大小设置页面,一定要先设置页面,再newPage(),否则无效
                    document.setPageSize(new com.itextpdf.text.Rectangle(size.getWidth(), size.getHeight()));
                    document.newPage();
                    document.add(img);
                }
                document.close();
                pdfPath=imgPDFPath + File.separator + file.getName();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
    
            }
            return pdfPath;
        }
    
    更多相关内容
  • word模板模板在项目中的存放位置: 直接上代码: /** * * 对docx文件中的文本及表格中的内容进行替换 --模板仅支持对 {key} 标签的替换 * * @ClassName: WordTemplate * @Description: TODO(!!!使用word...

    模板中需要填充的数据,就是map中的key,我们需要将数据封装到map里。
    word模板:
    在这里插入图片描述
    模板在项目中的存放位置:
    在这里插入图片描述
    直接上代码:

    /**
     *
     * 对docx文件中的文本及表格中的内容进行替换 --模板仅支持对 {key} 标签的替换
     *
     * @ClassName: WordTemplate
     * @Description: TODO(!!!使用word2013 docx文件)
     * @author chencaidao
     * @creat 2020-05-27 20:28
     * <br>(1)word模板注意页边距的问题,存在问题:比如页边距默认为3cm,画表格时,仍然可以通过
     * 拖拽,把表格边框拖动到看起来就像页边距只有1cm的样子,但是实际上此时页边距还是3cm,生成的
     * word报表的页边距还是会按照3cm来生成。解决办法,在word文件里,设置好页边距,如果需要表格
     * 两边页边距很窄,需要在word里设置页边距窄一点,而不是直接拖动表格边框来实现。
     *
     */
    
    public class WordTemplate {
    
        private XWPFDocument document;
    
        public XWPFDocument getDocument() {
            return document;
        }
    
        public void setDocument(XWPFDocument document) {
            this.document = document;
        }
    
        /**
         * 初始化模板内容
         *
         * @author Juveniless
         * @date 2017年11月27日 下午3:59:22
         * @param inputStream
         *            模板的读取流(docx文件)
         * @throws IOException
         *
         */
        public WordTemplate(InputStream inputStream) throws IOException {
            document = new XWPFDocument(inputStream);
        }
    
        /**
         * 将处理后的内容写入到输出流中
         *
         * @param outputStream
         * @throws IOException
         */
        public void write(OutputStream outputStream) throws IOException {
            document.write(outputStream);
        }
    
    
    
    
    
        /**
         * 根据dataMap对word文件中的标签进行替换; <br><br>
         * !!!!***需要注意dataMap的数据格式***!!!! <br><br>
         * 对于需要替换的普通标签数据标签(不需要循环)-----必须在dataMap中存储一个key为parametersMap的map,
         * 来存储这些不需要循环生成的数据,比如:表头信息,日期,制表人等。 <br><br>
         * 对于需要循环生成的表格数据------key自定义,value为 --ArrayList&lt;Map&lt;String, String>>
         * @author Juveniless
         * @date 2017年11月27日 下午3:29:27
         * @param dataMap
         *
         */
        public void replaceDocument(Map<String, Object> dataMap) {
    
            if (!dataMap.containsKey("parametersMap")) {
                System.out.println("数据源错误--数据源(parametersMap)缺失");
                return;
            }
            @SuppressWarnings("unchecked")
            Map<String, Object> parametersMap = (Map<String, Object>) dataMap
                    .get("parametersMap");
    
            List<IBodyElement> bodyElements = document.getBodyElements();// 所有对象(段落+表格)
            int templateBodySize = bodyElements.size();// 标记模板文件(段落+表格)总个数
    
            int curT = 0;// 当前操作表格对象的索引
            int curP = 0;// 当前操作段落对象的索引
            for (int a = 0; a < templateBodySize; a++) {
                IBodyElement body = bodyElements.get(a);
                if (BodyElementType.TABLE.equals(body.getElementType())) {// 处理表格
                    XWPFTable table = body.getBody().getTableArray(curT);
    
                    List<XWPFTable> tables = body.getBody().getTables();
                    table = tables.get(curT);
                    if (table != null) {
    
                        // 处理表格
                        List<XWPFTableCell> tableCells = table.getRows().get(0).getTableCells();// 获取到模板表格第一行,用来判断表格类型
                        String tableText = table.getText();// 表格中的所有文本
    
                        if (tableText.indexOf("##{foreach") > -1) {
                            // 查找到##{foreach标签,该表格需要处理循环
                            if (tableCells.size() != 2
                                    || tableCells.get(0).getText().indexOf("##{foreach") < 0
                                    || tableCells.get(0).getText().trim().length() == 0) {
                                System.out
                                        .println("文档中第"
                                                + (curT + 1)
                                                + "个表格模板错误,模板表格第一行需要设置2个单元格,"
                                                + "第一个单元格存储表格类型(##{foreachTable}## 或者 ##{foreachTableRow}##),第二个单元格定义数据源。");
                                return;
                            }
    
                            String tableType = tableCells.get(0).getText();
                            String dataSource = tableCells.get(1).getText();
                            System.out.println("读取到数据源:"+dataSource);
                            if (!dataMap.containsKey(dataSource)) {
                                System.out.println("文档中第" + (curT + 1) + "个表格模板数据源缺失");
                                return;
                            }
                            @SuppressWarnings("unchecked")
                            List<Map<String, Object>> tableDataList = (List<Map<String, Object>>) dataMap
                                    .get(dataSource);
                            if ("##{foreachTable}##".equals(tableType)) {
                                // System.out.println("循环生成表格");
                                addTableInDocFooter(table, tableDataList, parametersMap, 1);
    
                            } else if ("##{foreachTableRow}##".equals(tableType)) {
                                // System.out.println("循环生成表格内部的行");
                                addTableInDocFooter(table, tableDataList, parametersMap, 2);
                            }
    
                        } else if (tableText.indexOf("{") > -1) {
                            // 没有查找到##{foreach标签,查找到了普通替换数据的{}标签,该表格只需要简单替换
                            addTableInDocFooter(table, null, parametersMap, 3);
                        } else {
                            // 没有查找到任何标签,该表格是一个静态表格,仅需要复制一个即可。
                            addTableInDocFooter(table, null, null, 0);
                        }
                        curT++;
    
                    }
                } else if (BodyElementType.PARAGRAPH.equals(body.getElementType())) {// 处理段落
                    // System.out.println("获取到段落");
                    XWPFParagraph ph = body.getBody().getParagraphArray(curP);
                    if (ph != null) {
                        // htmlText = htmlText+readParagraphX(ph);
                        addParagraphInDocFooter(ph, null, parametersMap, 0);
    
                        curP++;
                    }
                }
    
            }
            // 处理完毕模板,删除文本中的模板内容
            for (int a = 0; a < templateBodySize; a++) {
                document.removeBodyElement(0);
            }
    
        }
    
    
    
    
    
    
    
    
        /**
         * 根据 模板表格 和 数据list 在word文档末尾生成表格
         * @author Juveniless
         * @date 2017年12月6日 上午10:12:05
         * @param templateTable 模板表格
         * @param list   循环数据集
         * @param parametersMap  不循环数据集
         * @param flag   (0为静态表格,1为表格整体循环,2为表格内部行循环,3为表格不循环仅简单替换标签即可)
         *
         */
        public void addTableInDocFooter(XWPFTable templateTable, List<Map<String, Object>> list,
                                        Map<String, Object> parametersMap, int flag) {
    
            if (flag == 1) {// 表格整体循环
                for (Map<String, Object> map : list) {
                    List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
                    XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
                    for (int i = 1; i < templateTableRows.size(); i++) {
                        XWPFTableRow newCreateRow = newCreateTable.createRow();
                        CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
                    }
                    newCreateTable.removeRow(0);// 移除多出来的第一行
                    document.createParagraph();// 添加回车换行
                    replaceTable(newCreateTable, map);//替换标签
                }
    
            } else if (flag == 2) {// 表格表格内部行循环
                XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
                List<XWPFTableRow> TempTableRows = templateTable.getRows();// 获取模板表格所有行
                int tagRowsIndex = 0;// 标签行indexs
                for (int i = 0, size = TempTableRows.size(); i < size; i++) {
                    String rowText = TempTableRows.get(i).getCell(0).getText();// 获取到表格行的第一个单元格
                    if (rowText.indexOf("##{foreachRows}##") > -1) {
                        tagRowsIndex = i;
                        break;
                    }
                }
    
                /* 复制模板行和标签行之前的行 */
                for (int i = 1; i < tagRowsIndex; i++) {
                    XWPFTableRow newCreateRow = newCreateTable.createRow();
                    CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行
                    replaceTableRow(newCreateRow, parametersMap);// 处理不循环标签的替换
                }
    
                /* 循环生成模板行 */
                XWPFTableRow tempRow = TempTableRows.get(tagRowsIndex + 1);// 获取到模板行
                for (int i = 0; i < list.size(); i++) {
                    XWPFTableRow newCreateRow = newCreateTable.createRow();
                    CopyTableRow(newCreateRow, tempRow);// 复制模板行
                    replaceTableRow(newCreateRow, list.get(i));// 处理标签替换
                }
    
                /* 复制模板行和标签行之后的行 */
                for (int i = tagRowsIndex + 2; i < TempTableRows.size(); i++) {
                    XWPFTableRow newCreateRow = newCreateTable.createRow();
                    CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行
                    replaceTableRow(newCreateRow, parametersMap);// 处理不循环标签的替换
                }
                newCreateTable.removeRow(0);// 移除多出来的第一行
                document.createParagraph();// 添加回车换行
    
            } else if (flag == 3) {
                //表格不循环仅简单替换标签
                List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
                XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
                for (int i = 0; i < templateTableRows.size(); i++) {
                    XWPFTableRow newCreateRow = newCreateTable.createRow();
                    CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
                }
                newCreateTable.removeRow(0);// 移除多出来的第一行
                document.createParagraph();// 添加回车换行
                replaceTable(newCreateTable, parametersMap);
    
            } else if (flag == 0) {
                List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
                XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
                for (int i = 0; i < templateTableRows.size(); i++) {
                    XWPFTableRow newCreateRow = newCreateTable.createRow();
                    CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
                }
                newCreateTable.removeRow(0);// 移除多出来的第一行
                document.createParagraph();// 添加回车换行
            }
    
        }
    
    
    
    
    
    
        /**
         * 根据 模板段落 和 数据 在文档末尾生成段落
         *
         * @author Juveniless
         * @date 2017年11月27日 上午11:49:42
         * @param templateParagraph
         *            模板段落
         * @param list
         *            循环数据集
         * @param parametersMap
         *            不循环数据集
         * @param flag
         *            (0为不循环替换,1为循环替换)
         *
         */
        public void addParagraphInDocFooter(XWPFParagraph templateParagraph,
                                            List<Map<String, String>> list, Map<String, Object> parametersMap, int flag) {
    
            if (flag == 0) {
                XWPFParagraph createParagraph = document.createParagraph();
                // 设置段落样式
                createParagraph.getCTP().setPPr(templateParagraph.getCTP().getPPr());
                // 移除原始内容
                for (int pos = 0; pos < createParagraph.getRuns().size(); pos++) {
                    createParagraph.removeRun(pos);
                }
                // 添加Run标签
                for (XWPFRun s : templateParagraph.getRuns()) {
                    XWPFRun targetrun = createParagraph.createRun();
                    CopyRun(targetrun, s);
                }
    
                replaceParagraph(createParagraph, parametersMap);
    
            } else if (flag == 1) {
                // 暂无实现
            }
    
        }
    
    
    
    
        /**
         * 根据map替换段落元素内的{**}标签
         * @author Juveniless
         * @date 2017年12月4日 下午3:09:00
         * @param xWPFParagraph
         * @param parametersMap
         *
         */
        public void replaceParagraph(XWPFParagraph xWPFParagraph, Map<String, Object> parametersMap) {
            List<XWPFRun> runs = xWPFParagraph.getRuns();
            String xWPFParagraphText = xWPFParagraph.getText();
            String regEx = "\\{.+?\\}";
            Pattern pattern = Pattern.compile(regEx);
            Matcher matcher = pattern.matcher(xWPFParagraphText);//正则匹配字符串{****}
    
            if (matcher.find()) {
                // 查找到有标签才执行替换
                int beginRunIndex = xWPFParagraph.searchText("{", new PositionInParagraph()).getBeginRun();// 标签开始run位置
                int endRunIndex = xWPFParagraph.searchText("}", new PositionInParagraph()).getEndRun();// 结束标签
                StringBuffer key = new StringBuffer();
    
                if (beginRunIndex == endRunIndex) {
                    // {**}在一个run标签内
                    XWPFRun beginRun = runs.get(beginRunIndex);
                    String beginRunText = beginRun.text();
    
                    int beginIndex = beginRunText.indexOf("{");
                    int endIndex = beginRunText.indexOf("}");
                    int length = beginRunText.length();
    
                    if (beginIndex == 0 && endIndex == length - 1) {
                        // 该run标签只有{**}
                        XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                        insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                        // 设置文本
                        key.append(beginRunText.substring(1, endIndex));
                        insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
                        xWPFParagraph.removeRun(beginRunIndex + 1);
                    } else {
                        // 该run标签为**{**}** 或者 **{**} 或者{**}**,替换key后,还需要加上原始key前后的文本
                        XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                        insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                        // 设置文本
                        key.append(beginRunText.substring(beginRunText.indexOf("{")+1, beginRunText.indexOf("}")));
                        String textString=beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(),parametersMap)
                                + beginRunText.substring(endIndex + 1);
                        insertNewRun.setText(textString);
                        xWPFParagraph.removeRun(beginRunIndex + 1);
                    }
    
                }else {
                    // {**}被分成多个run
    
                    //先处理起始run标签,取得第一个{key}值
                    XWPFRun beginRun = runs.get(beginRunIndex);
                    String beginRunText = beginRun.text();
                    int beginIndex = beginRunText.indexOf("{");
                    if (beginRunText.length()>1  ) {
                        key.append(beginRunText.substring(beginIndex+1));
                    }
                    ArrayList<Integer> removeRunList = new ArrayList<>();//需要移除的run
                    //处理中间的run
                    for (int i = beginRunIndex + 1; i < endRunIndex; i++) {
                        XWPFRun run = runs.get(i);
                        String runText = run.text();
                        key.append(runText);
                        removeRunList.add(i);
                    }
    
                    // 获取endRun中的key值
                    XWPFRun endRun = runs.get(endRunIndex);
                    String endRunText = endRun.text();
                    int endIndex = endRunText.indexOf("}");
                    //run中**}或者**}**
                    if (endRunText.length()>1 && endIndex!=0) {
                        key.append(endRunText.substring(0,endIndex));
                    }
    
    
    
                    //*******************************************************************
                    //取得key值后替换标签
    
                    //先处理开始标签
                    if (beginRunText.length()==2 ) {
                        // run标签内文本{
                        XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                        insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                        // 设置文本
                        insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
                        xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
                    }else {
                        // 该run标签为**{**或者 {** ,替换key后,还需要加上原始key前的文本
                        XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                        insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                        // 设置文本
                        String textString=beginRunText.substring(0,beginRunText.indexOf("{"))+getValueBykey(key.toString(),parametersMap);
                        insertNewRun.setText(textString);
                        xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
                    }
    
                    //处理结束标签
                    if (endRunText.length()==1 ) {
                        // run标签内文本只有}
                        XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                        insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                        // 设置文本
                        insertNewRun.setText("");
                        xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
    
                    }else {
                        // 该run标签为**}**或者 }** 或者**},替换key后,还需要加上原始key后的文本
                        XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                        insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                        // 设置文本
                        String textString=endRunText.substring(endRunText.indexOf("}")+1);
                        insertNewRun.setText(textString);
                        xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
                    }
    
                    //处理中间的run标签
                    for (int i = 0; i < removeRunList.size(); i++) {
                        XWPFRun xWPFRun = runs.get(removeRunList.get(i));//原始run
                        XWPFRun insertNewRun = xWPFParagraph.insertNewRun(removeRunList.get(i));
                        insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());
                        insertNewRun.setText("");
                        xWPFParagraph.removeRun(removeRunList.get(i) + 1);//移除原始的run
                    }
    
                }// 处理${**}被分成多个run
    
                replaceParagraph( xWPFParagraph, parametersMap);
    
            }//if 有标签
    
        }
    
    
    
    
    
    
    
    
        /**
         * 复制表格行XWPFTableRow格式
         *
         * @param target
         *            待修改格式的XWPFTableRow
         * @param source
         *            模板XWPFTableRow
         */
        private void CopyTableRow(XWPFTableRow target, XWPFTableRow source) {
    
            int tempRowCellsize = source.getTableCells().size();// 模板行的列数
            for (int i = 0; i < tempRowCellsize - 1; i++) {
                target.addNewTableCell();// 为新添加的行添加与模板表格对应行行相同个数的单元格
            }
            // 复制样式
            target.getCtRow().setTrPr(source.getCtRow().getTrPr());
            // 复制单元格
            for (int i = 0; i < target.getTableCells().size(); i++) {
                copyTableCell(target.getCell(i), source.getCell(i));
            }
        }
    
    
    
    
    
        /**
         * 复制单元格XWPFTableCell格式
         *
         * @author Juveniless
         * @date 2017年11月27日 下午3:41:02
         * @param newTableCell
         *            新创建的的单元格
         * @param templateTableCell
         *            模板单元格
         *
         */
        private void copyTableCell(XWPFTableCell newTableCell, XWPFTableCell templateTableCell) {
            // 列属性
            newTableCell.getCTTc().setTcPr(templateTableCell.getCTTc().getTcPr());
            // 删除目标 targetCell 所有文本段落
            for (int pos = 0; pos < newTableCell.getParagraphs().size(); pos++) {
                newTableCell.removeParagraph(pos);
            }
            // 添加新文本段落
            for (XWPFParagraph sp : templateTableCell.getParagraphs()) {
                XWPFParagraph targetP = newTableCell.addParagraph();
                copyParagraph(targetP, sp);
            }
        }
    
        /**
         * 复制文本段落XWPFParagraph格式
         *
         * @author Juveniless
         * @date 2017年11月27日 下午3:43:08
         * @param newParagraph
         *            新创建的的段落
         * @param templateParagraph
         *            模板段落
         *
         */
        private void copyParagraph(XWPFParagraph newParagraph, XWPFParagraph templateParagraph) {
            // 设置段落样式
            newParagraph.getCTP().setPPr(templateParagraph.getCTP().getPPr());
            // 添加Run标签
            for (int pos = 0; pos < newParagraph.getRuns().size(); pos++) {
                newParagraph.removeRun(pos);
    
            }
            for (XWPFRun s : templateParagraph.getRuns()) {
                XWPFRun targetrun = newParagraph.createRun();
                CopyRun(targetrun, s);
            }
    
        }
    
        /**
         * 复制文本节点run
         * @author Juveniless
         * @date 2017年11月27日 下午3:47:17
         * @param newRun
         *            新创建的的文本节点
         * @param templateRun
         *            模板文本节点
         *
         */
        private void CopyRun(XWPFRun newRun, XWPFRun templateRun) {
            newRun.getCTR().setRPr(templateRun.getCTR().getRPr());
            // 设置文本
            newRun.setText(templateRun.text());
    
    
        }
    
    
    
    
        /**
         * 根据参数parametersMap对表格的一行进行标签的替换
         *
         * @author Juveniless
         * @date 2017年11月23日 下午2:09:24
         * @param tableRow
         *            表格行
         * @param parametersMap
         *            参数map
         *
         */
        public void replaceTableRow(XWPFTableRow tableRow, Map<String, Object> parametersMap) {
    
            List<XWPFTableCell> tableCells = tableRow.getTableCells();
            for (XWPFTableCell xWPFTableCell : tableCells) {
                List<XWPFParagraph> paragraphs = xWPFTableCell.getParagraphs();
                for (XWPFParagraph xwpfParagraph : paragraphs) {
    
                    replaceParagraph(xwpfParagraph, parametersMap);
                }
            }
    
        }
    
    
    
    
    
        /**
         * 根据map替换表格中的{key}标签
         * @author Juveniless
         * @date 2017年12月4日 下午2:47:36
         * @param xwpfTable
         * @param parametersMap
         *
         */
        public void replaceTable(XWPFTable xwpfTable,Map<String, Object> parametersMap){
            List<XWPFTableRow> rows = xwpfTable.getRows();
            for (XWPFTableRow xWPFTableRow : rows ) {
                List<XWPFTableCell> tableCells = xWPFTableRow.getTableCells();
                for (XWPFTableCell xWPFTableCell : tableCells ) {
                    List<XWPFParagraph> paragraphs2 = xWPFTableCell.getParagraphs();
                    for (XWPFParagraph xWPFParagraph : paragraphs2) {
                        replaceParagraph(xWPFParagraph, parametersMap);
                    }
                }
            }
    
        }
    
    
    
        private String getValueBykey(String key, Map<String, Object> map) {
            String returnValue="";
            if (key != null) {
                try {
                    returnValue=map.get(key)!=null ? map.get(key).toString() : "";
                } catch (Exception e) {
                    // TODO: handle exception
                    System.out.println("key:"+key+"***"+e);
                    returnValue="";
                }
    
            }
            return returnValue;
        }
    
    
    
    
    
    
    
    
    }
    
    @Logger(action = "导出", logger = "导出。。。。工作表word文档",model="报表报送")
        @RequestMapping(value = "/toJusticeWord")
        public void toJusticeWord(@RequestParam(value="sTime") String startTime,
                                  @RequestParam(value = "eTime") String endTime,
                                  HttpServletRequest request, HttpServletResponse response) throws WebUIException {
            ServletOutputStream out=null;
            try {
                String year = startTime.substring(0, 4);
                String month = startTime.substring(5, 7);
                String day = startTime.substring(8, 10);
                String date = year+month+day;
                //设置相应到客户端的文件名编码
                // 解决乱码
                response.setCharacterEncoding("UTF-8");
                //定义下载的文件名字
                String fileName = "。。。。视频点名报告词"+date+".docx";
                response.setContentType("application/msword;charset=UTF-8");
                response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
                response.addHeader("Pargam", "no-cache");
                response.addHeader("Cache-Control", "no-cache");
                //获取响应报文输出流对象
                out = response.getOutputStream();
                //调用业务方法,获得需要下载的word文件
                XWPFDocument document = dailyBasicWorksheetService.exportJusticeWord(request,startTime,endTime);
                document.write(out);
                out.flush();
                out.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
    XWPFDocument exportJusticeWord(HttpServletRequest request, String startTime, String endTime) throws IOException;
    
    @Override
        public XWPFDocument exportJusticeWord(HttpServletRequest request, String startTime, String endTime) throws IOException {
            Map<String, Object> map = this.getDao().summaryJusticeWordData(startTime, endTime);
            String ZC_ZFS="0";
            String ZY_ZFS="0";
            String JWZX_ZFS="0";
            String ZXYYZY_ZFS="";
            String QHYYZY_ZFS="";
            String LKYYZY_ZFS="";
            String SHYYZY_ZFS="";
            String XSY_MAN_ZFS="0";
            String XSY_WOMAN_ZFS="0";
            int jyzys=0;
            int xsyZfs=0;
            if(map!=null){
                ZC_ZFS = map.get("ZC_ZFS").toString();
                ZY_ZFS = map.get("ZY_ZFS").toString();
                JWZX_ZFS = map.get("JWZX_ZFS").toString();
                ZXYYZY_ZFS = map.get("ZXYYZY_ZFS").toString();
                QHYYZY_ZFS = map.get("QHYYZY_ZFS").toString();
                LKYYZY_ZFS = map.get("LKYYZY_ZFS").toString();
                SHYYZY_ZFS = map.get("SHYYZY_ZFS").toString();
                XSY_MAN_ZFS = map.get("XSY_MAN_ZFS").toString();
                XSY_WOMAN_ZFS = map.get("XSY_WOMAN_ZFS").toString();
                jyzys =Integer.parseInt(ZXYYZY_ZFS)+Integer.parseInt(QHYYZY_ZFS)+Integer.parseInt(LKYYZY_ZFS)+Integer.parseInt(SHYYZY_ZFS);
                int MAN = Integer.parseInt(XSY_MAN_ZFS);
                int WOMAN=Integer.parseInt(XSY_WOMAN_ZFS);
                xsyZfs=MAN +WOMAN;
            }
            Integer zggjZS = this.getDao().findZggjZS(startTime, endTime);
            if(zggjZS==null){
                zggjZS=0;
            }
            Map<String, Object> wordDataMap = new HashMap<String, Object>();// 存储报表全部数据
            Map<String, Object> parametersMap = new HashMap<String, Object>();// 存储报表中不循环的数据
            String month = startTime.substring(6, 7);
            String day = startTime.substring(8, 10);
            String date = month+"月"+day+"日";
            System.out.println(date);
            parametersMap.put("zcZfzs", ZC_ZFS);
            parametersMap.put("zyZfzs", ZY_ZFS);
            parametersMap.put("jyzxrs", JWZX_ZFS);
            parametersMap.put("jyzys", jyzys+"");
            parametersMap.put("xsyZfs", xsyZfs+"");
            parametersMap.put("xsyManZfs", XSY_MAN_ZFS);
            parametersMap.put("xsyWomanZfs", XSY_WOMAN_ZFS);
            parametersMap.put("bqjls", zggjZS+"");
            parametersMap.put("date", date);
            wordDataMap.put("parametersMap", parametersMap);
            String filePath = request.getSession().getServletContext().getRealPath("")+"/WEB-INF/static/wordMoudle/sfbbgc.docx";
            // 读取word模板
            FileInputStream fileInputStream = new FileInputStream(filePath);
            WordTemplate template = new WordTemplate(fileInputStream);
            // 替换数据
            template.replaceDocument(wordDataMap);
            XWPFDocument document = template.getDocument();
            return document;
        }
    

    导出后的文档效果:
    在这里插入图片描述

    展开全文
  • POI导出word文档模版直接用于下载和html页面展示

    Java POI导出word模板,POI转化word为html代码

    需求起因
    做项目的时候按照客户需求在系统上填写一些数据,这些数据最后要导出为word文档存档,文档有严格的样式,主要是表格构成。参考相关代码后github上找到了一个POI操作word并导出的开源项目,github地址点击前往。话不多说看结果。
    源文档
    这是下发的文件
    模板文档
    对照源文档修改自己的模板,后面会详细介绍模板的构造。
    模板文档
    系通填写界面
    做出的系统
    最终导出的文档
    导出的效果
    具体实现
    首先这功能分三部分,1.要导出的模板,2.代码 获取数据,对数据封装,填充到模板文件。3.导出要下载的文档。
    1.要导出的模板
    拿到源文档后,找到要改变的地方,这里拿一个测试文档test.docx举例。比如说我们要导出各个地区的气象数据,每个地区都可以导出,这时候就可以抽出一个模板来(有做过短信模板的这里一目了然,一模一样)。
    在这里插入图片描述
    这个文档里红色的部分要改成可变的,可能是浙江省,江苏省等其他省份信息,这时候抽取要改变的地方用双大括号加变量名代替。eg:{{value}}。
    这份文档就可以改为如下样式
    在这里插入图片描述
    2.代码实现
    这里用的是spring boot框架,maven管理依赖包,首先导入需要的依赖包

    <dependency>
      <groupId>com.deepoove</groupId>
      <artifactId>poi-tl</artifactId>
      <version>1.5.0</version>
    </dependency>
    

    下面是核心的代码

     @RequestMapping("/word")
        @ResponseBody
        public ResultJson uploadImg() {
            Map<String, Object> data = new HashMap<>();//通过map存放要填充的数据
            data.put("province","浙江省");//把每项数据写进map,key的命名要与word里面的一样
            data.put("temp",27.8);
            data.put("shidu",33.3);
            
            data.put("water",220);
            data.put("windir","西北风");
            data.put("winforce","7-8");
            data.put("chuanyi","天气热,适合T恤短裤");
            data.put("chuxing","太阳光强,宜做好防晒");
            data.put("advice1","适合海边游玩降温");
            data.put("advice2","适合洗车");
            data.put("advice3","不宜长时间吹空调");
            data.put("date", DateUtils.getCurDate());
            XWPFTemplate template = XWPFTemplate.compile("D:\\test.docx").render(data);//调用模板,填充数据
            try {
                FileOutputStream out = new FileOutputStream("D:\\天气预报.docx");//要导出的文件名
                template.write(out);
                out.flush();
                out.close();
                template.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    

    代码非常简单,就一个map搞定,这里我只是在controller里面随便测试的,真正要用当然要把这些字段放到实体来然后通过反向映射解析对象,循环填充。
    用postman请求一下,看一下导出的效果。
    在这里插入图片描述
    在这里插入图片描述
    以上就是全部过程,如果要下载直接通过response把数据流返给前端就OK了。

    原本到这里就结束了,但是用户有来了一个需求,需要预览文档,这里大家就会说了,直接转成json扔给前端处理就好了。如果说文档规则的话其实前端通过table很简单就画出来了,就怕样式很复杂,画起来非常麻烦。这里在提供一个直接将word转为html代码的方法。(做后端的我就是这么心疼前端)
    引入依赖包

        <!--poi转化-->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.14</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-scratchpad</artifactId>
                <version>3.14</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.14</version>
            </dependency>
            <dependency>
                <groupId>fr.opensagres.xdocreport</groupId>
                <artifactId>fr.opensagres.poi.xwpf.converter.xhtml</artifactId>
                <version>2.0.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml-schemas</artifactId>
                <version>3.14</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>ooxml-schemas</artifactId>
                <version>1.3</version>
            </dependency>
    

    好像包有点多。。。。。。。。。

    实现代码

    try {
            InputStream in = new FileInputStream(new File("D:\\天气预报.docx"));//要转化的word
            XWPFDocument document = new XWPFDocument(in);
            OutputStream baos = new ByteArrayOutputStream();
            XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance();
            xhtmlConverter.convert(document, baos,null);
            String content = baos.toString();//转化好的html代码
            baos.close();
            return ResultJson.returnRightObj(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    

    最终效果
    在这里插入图片描述
    代码返给前端展示就好了,跟word一模一样。

    END

    展开全文
  • java 使用poi根据模版导出word文件 将文件中的标签替换成文字或者文件 文件中标签用{xxxx}生成新文件
  • 2.创建docx模板(doc不可以) 第一步:准备好jar(这里面的 ooxml-schemas-1.1.jar 大家可以尝试用poi-shemas-3.12-20150511.jar替换试试,但是偶尔会报java.lang.NoSuchMethodException: org.openxmlformats.schemas....

    准备工作:

    1.需要的jar(jar包在资源处已上传,可下载)

    2.创建docx模板(doc不可以)

    第一步:准备好jar(这里面的 ooxml-schemas-1.1.jar 大家可以尝试用poi-shemas-3.12-20150511.jar替换试试,但是偶尔会报java.lang.NoSuchMethodException: org.openxmlformats.schemas.wordprocessingml.x2006.....等错误,网络说poi-shemas-3.12-20150511.jar是简化版,需要用 ooxml-schemas-1.1.jar替换)

    第二步:准备好docx模板(这里我写入了四个表格,根据您的需要制作,${date} 是段落部分, $符号不能没有,代码中需要判断替换的)

    准备工作完成  下面是代码部分

    BaseXWPFDocument.java

    package word;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    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;
    
    /**
     * 自定义 XWPFDocument,并重写 createPicture()方法
     */
    public class BaseXWPFDocument extends XWPFDocument{
        public BaseXWPFDocument(InputStream in) throws IOException {
            super(in);
        }
    
        public BaseXWPFDocument() {
            super();
        }
    
        public BaseXWPFDocument(OPCPackage pkg) throws IOException {
            super(pkg);
        }
    
        /**
         * @param id
         * @param width 宽
         * @param height 高
         * @param paragraph  段落
         */
        public void createPicture(int id, int width, int height,XWPFParagraph paragraph) {
            final int EMU = 9525;
            width *= EMU;
            height *= EMU;
            String blipId = getAllPictures().get(id).getPackageRelationship().getId();
            CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();
    
            System.out.println(blipId+":"+inline);
    
            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("描述部分");
        }
    }
    

    CrtWordUtils.java

    package word;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import org.apache.poi.POIXMLDocument;
    import org.apache.poi.util.Units;
    import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.poi.xwpf.usermodel.XWPFTable;
    import org.apache.poi.xwpf.usermodel.XWPFTableCell;
    import org.apache.poi.xwpf.usermodel.XWPFTableRow;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHMerge;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
    
    
    /**
     * 生成word工具类
     */
    public class CrtWordUtils{
    	
    	//private static Log logger = LogFactory.getLog(CrtWordUtils.class);
    	
        /**
         * 根据模板生成word文档
         * @param inputUrl 模板路径
         * @param textMap 需要替换的文本内容
         * @param mapList 需要动态生成的内容
         * @return
         */
        public static BaseXWPFDocument changWord(String inputUrl, Map<String, Object> textMap, List<Object> mapList) {
            BaseXWPFDocument document = null;
            try {
                //获取docx解析对象
                document = new BaseXWPFDocument(POIXMLDocument.openPackage(inputUrl));
                //解析替换文本段落对象
                //logger.info("CrtWordUtils--生成word中文本段落开始...");
                changeText(document, textMap);
                //logger.info("CrtWordUtils--生成word中文本段落结束...");
                //解析替换表格对象
                //logger.info("CrtWordUtils--生成word中表格开始...");
                changeTable(document,textMap, mapList);
                //logger.info("CrtWordUtils--生成word中表格结束...");
            } catch (IOException e) {
            	//logger.error("CrtWordUtils--生成word失败,原因:"+e.getMessage());
            }
            return document;
        }
    
        /**
         * 替换表格对象方法
         * @param document docx解析对象
         * @param mapList 需要动态生成的内容
         */
        public static void changeTable(BaseXWPFDocument document,Map<String, Object> textMap, List<Object> mapList){
            //获取表格对象集合
            List<XWPFTable> tables = document.getTables();
            
          //循环所有需要进行替换的文本,进行替换
            for (int i = 0; i < tables.size(); i++) {
                XWPFTable table = tables.get(i);
                
                
                XWPFParagraph p = document.getParagraphArray(0);
                p.setAlignment(ParagraphAlignment.LEFT);
                XWPFRun run = p.insertNewRun(0);
                
                List<XWPFTableRow> rows = table.getRows();
                
                //--------------------------------在第二个表格的第一行第一列的框中插入图片-----------------------------------
                if(i == 1){
                	 XWPFTableRow rowTest = table.getRow(0);
                     XWPFTableCell imageCell = rowTest.getCell(0);
                     List<XWPFParagraph> paragraphs = imageCell.getParagraphs();
                     XWPFParagraph newPara = paragraphs.get(0);
                     XWPFRun imageCellRunn = newPara.createRun();
                     try {
    					imageCellRunn.addPicture(new FileInputStream("D:/1.png"), BaseXWPFDocument.PICTURE_TYPE_PNG, "1.png", Units.toEMU(40), Units.toEMU(30));
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
                     run.addBreak();
                }
              //--------------------------------在第二个表格的第一行第一列的框中插入图片-----------------------------------
                
                if(checkText(table.getText())){
                    //遍历表格,并替换模板
                    eachTable(document,rows, textMap);
                }
            }
            
            int index=0;
            //操作word中的表格
            for (int i = 0; i < tables.size(); i++) {
                //只处理行数大于等于2的表格,且不循环表头
                XWPFTable table = tables.get(i);
                List<String[]> list = (List<String[]>) mapList.get(index);
                if (!list.isEmpty()){
                	//logger.info("CrtWordUtils--生成word中表格第"+(index+1)+"个表格开始");
                	if(i == 3){
                		changeTable_quality(document, mapList);
                	}else{
                		insertTable(table,list,i);
                    	//logger.info("CrtWordUtils--生成word中表格第"+(index+1)+"个表格结束");
                        if(i == 1){//第二个表格需要列合并
        	                List<Integer[]> indexList = startEnd(list);
        	                for (int c=0;c<indexList.size();c++){ //合并行
        	                	//logger.info("CrtWordUtils--生成word中表格需要合并的表格开始...");
        	                    mergeCellVertically(table,0,indexList.get(c)[0]+2,indexList.get(c)[1]+2);
        	                    //mergeCellVertically(table,1,indexList.get(c)[0]+1,indexList.get(c)[1]+1);
        	                    // logger.info("CrtWordUtils--生成word中表格需要合并的表格结束...");
        	                }
                        }
                	}
                }
                index++;
            }
        }
        public static void changeTable_quality(BaseXWPFDocument document, List<Object> mapList){
        	//获取表格对象集合
        	List<XWPFTable> tables = document.getTables();
        	//int index=0;
        	//操作word中的表格
        	for (int i = 0; i < tables.size(); i++) {
        		//只处理行数大于等于2的表格,且不循环表头
        		XWPFTable table = tables.get(i);
        		List<String[]> list = (List<String[]>) mapList.get(i);
        		if (null != list && 0 < list.size()){
        			//logger.info("CrtWordUtils--生成word中表格第"+(i+1)+"个表格开始");
        			//logger.info("CrtWordUtils--生成word中表格第"+(i+1)+"个表格结束");
        			if(i == 3){//--i:第i个表格
        				insertTable_quality(table,list,i);
    	                for (int c=0;c<list.size();c++){ //合并列
    	                	mergeColumnsCellVertically(table,c+2,0,1);
    	                }
        			}
        		}
        		//index++;
        	}
        }
        
        /**
         * 此处做了特殊处理 如果文本段落中出现有需要换行, replaceTabStr对应下面的数据格式
         * 
         * List<Object[]> resultBydeptList = baseMapList.get("resultBydeptList");
    	        StringBuilder sbResultStr = new StringBuilder();
    	        for (Iterator iter = resultBydeptList.iterator(); iter.hasNext();) {
    	        	Object[] objArr = (Object[])iter.next();
    	        	Object yearResultStr = objArr[2];
    	        	if(yearResultStr != null){
    	        		sbResultStr.append(objArr[0]).append(objArr[1]).append("replaceTabStr").append(objArr[2]).append("replaceTabStr");
    	        	}
    	        }
    	        data.put("${paragraph1_yearresult}", sbResultStr.toString().isEmpty()?"无":sbResultStr.toString());
         * 
         * 替换段落文本
         * @param document docx解析对象
         * @param textMap 需要替换的信息集合
         */
        public static void changeText(BaseXWPFDocument document, Map<String, Object> textMap){
            //获取段落集合
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            for (XWPFParagraph paragraph : paragraphs) {
                //判断此段落是否需要进行替换
                String text = paragraph.getText();
                if(checkText(text)){
                    List<XWPFRun> runs = paragraph.getRuns();
                    for (int i = 0;i<runs.size();i++) {
                        //替换模板原来位置
                        Object obstr = changeValue(text, textMap);
                        // logger.info("CrtWordUtils--段落信息..."+runs.get(i).toString());
                        //分段显示的情况
                    	String[] values = obstr.toString().split("replaceTabStr");
                    	if(values.length > 1) {
                    		runs.get(i).setText(values[0],0);
                    		for (int j = 1; j < values.length; j++) {
                    		       //存在分段则新建一个run
                    			XWPFRun newrun = paragraph.insertNewRun(j);
                    			newrun.getCTR().setRPr(runs.get(i).getCTR().getRPr());//copy样式
                    			newrun.addBreak();//换行
                    			newrun.getCTR().addNewTab();//缩进
                    			newrun.setText(values[j]);
                    		}
                    		break;
                    	}else{
                    		runs.get(i).setText(obstr.toString().replace("replaceTabStr", ""),0);
                    	}
                        if(i > 0){
                        	runs.get(i).setText("",0);
                        }
                    }
                }
            }
        }
    
        /**
         * 为表格插入数据,行数不够添加新行
         * @param table 需要插入数据的表格
         * @param daList 表格的插入数据
         * @param type 表格类型:0-第一个表格 以此类推
         */
        public static void insertTable(XWPFTable table, List<String[]> daList,Integer type){
    		//创建行和创建需要的列(有行样式要求的)
    		for(int i = 1; i < daList.size(); i++){
    			//添加一个新行
    			int startRow = type.equals(2)?3:2;//  第二个表格  插入新行从3开始 其他2开始
    			int rowPos = startRow;  //rowPos 的作用是获取新行的下一行,便于复制新行的样式
    			insertNewRow(table,table.getRow(rowPos),rowPos+1);
    			//logger.info("CrtWordUtils--创建表格行成功");
    		}
    		//创建行,根据需要插入的数据添加新行,不处理表头
    		for(int i = 0; i < daList.size(); i++){
    			int startRow = type.equals(2)?3:2;//  第二个表格  插入新行从3开始 其他2开始
    			int rowPos = startRow;  //rowPos 的作用是获取新行的下一行,便于复制新行的样式
    			List<XWPFTableCell> cells = table.getRow(i+rowPos).getTableCells();
    			//logger.info("CrtWordUtils--表格中每个单元格插入元素开始");
    			for(int j = 0; j < cells.size(); j++){
    				XWPFTableCell cell02 = cells.get(j);
    				CTTc ctTc = cell02.getCTTc(); 
    				// here is need to change... 设置边框
    				CTTcPr tcPr = ctTc.addNewTcPr();
    				CTTcBorders border = tcPr.addNewTcBorders();
    				border.addNewRight().setVal(STBorder.SINGLE);
    				border.addNewLeft().setVal(STBorder.SINGLE);
    				border.addNewBottom().setVal(STBorder.SINGLE);
    				//设置字体居中
    				tcPr.addNewVAlign().setVal(STVerticalJc.CENTER);
    				ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
    				if(type.equals(2) && daList.get(i)[j].equals("否")){//内容显示红色
    					//logger.info("CrtWordUtils--表格3中开始特殊处理");
    					cell02.removeParagraph(0);
    					XWPFParagraph newPara = new XWPFParagraph(cell02.getCTTc().addNewP(), cell02);                                                                                                                               
                        XWPFRun run=newPara.createRun();                       
                        newPara.setAlignment(ParagraphAlignment.CENTER);
                        run.getCTR().addNewRPr().addNewColor().setVal("FF0000");/**FF0000红色*/                               
                        run.setText(daList.get(i)[j]);    
                        cell02.setColor("cc99ff");
    				}else{
    					cell02.setText(daList.get(i)[j]);
    				}
    			}
    		}
        }
        /**
         * 为表格插入数据,行数不够添加新行
         * @param table 需要插入数据的表格
         * @param daList 表格的插入数据
         * @param type 表格类型:0-第一个表格 以此类推
         */
        public static void insertTable_quality(XWPFTable table, List<String[]> daList,Integer type){
        	//创建行和创建需要的列
        	for(int i = 1; i < daList.size(); i++){
        		//添加一个新行
        		insertNewRow(table,table.getRow(2),3);
        		//logger.info("CrtWordUtils--创建表格行成功");
        	}
        	//创建行,根据需要插入的数据添加新行,不处理表头
        	for(int i = 0; i < daList.size(); i++){
        		List<XWPFTableCell> cells = table.getRow(i+2).getTableCells();
        		//String [] rowdatas  = daList.get(i);
        		//logger.info("CrtWordUtils--表格中每个单元格插入元素开始");
        		for(int j = 0; j < cells.size(); j++){
        			XWPFTableCell cell02 = cells.get(j);
        			CTTc ctTc = cell02.getCTTc(); 
        			// here is need to change... 设置边框
        			CTTcPr tcPr = ctTc.addNewTcPr();
        			CTTcBorders border = tcPr.addNewTcBorders();
        			border.addNewRight().setVal(STBorder.SINGLE);
        			border.addNewLeft().setVal(STBorder.SINGLE);
        			border.addNewBottom().setVal(STBorder.SINGLE);
        			//设置字体居中
        			tcPr.addNewVAlign().setVal(STVerticalJc.CENTER);
        			ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
        			//if(type.equals(0)&&j==1){
        			if(type.equals(0)&&j==1&&daList.get(i)[5].equals("0")){
        				cell02.removeParagraph(0);
        				XWPFParagraph newPara = new XWPFParagraph(cell02.getCTTc().addNewP(), cell02);                                                                                                                               
        				XWPFRun run=newPara.createRun();                       
        				newPara.setAlignment(ParagraphAlignment.CENTER);
        				run.getCTR().addNewRPr().addNewColor().setVal("008000");/**#008000绿色*/                               
        				run.setText(daList.get(i)[j]); 
        			}else{
        				cell02.setText(daList.get(i)[j]);
        			}
        		}
        	}
        }
    
        /**
         * 判断文本中是否包含$
         * @param text 文本
         * @return 包含返回true,不包含返回false
         */
        public static boolean checkText(String text){
            boolean check  =  false;
            if(text.indexOf('$')!= -1){
                check = true;
            }
            return check;
        }
    
        /**
         * 匹配传入信息集合与模板
         * @param value 模板需要替换的区域
         * @param textMap 传入信息集合
         * @return 模板需要替换区域信息集合对应值
         */
        public static Object changeValue(String value, Map<String, Object> textMap){
            Set<Map.Entry<String, Object>> textSets = textMap.entrySet();
            Object valu = value;
            for (Map.Entry<String, Object> textSet : textSets) {
                String key = textSet.getKey();
                if(value.indexOf(key)!= -1){
                    valu = String.valueOf(valu).replace("$"+textSet.getKey().substring(1), textSet.getValue().toString());
                }
            }
            return valu;
        }
    
        /**
         * 合并行
         * @param table
         * @param col 需要合并的列
         * @param fromRow 开始行
         * @param toRow 结束行
         */
        public static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
            for(int rowIndex = fromRow; rowIndex <= toRow; rowIndex++){
                CTVMerge vmerge = CTVMerge.Factory.newInstance();
                if(rowIndex == fromRow){
                    vmerge.setVal(STMerge.RESTART);
                } else {
                    vmerge.setVal(STMerge.CONTINUE);
                }
                XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
                CTTcPr tcPr = cell.getCTTc().getTcPr();
                if (tcPr != null) {
                    tcPr.setVMerge(vmerge);
                } else {
                    tcPr = CTTcPr.Factory.newInstance();
                    tcPr.setVMerge(vmerge);
                    cell.getCTTc().setTcPr(tcPr);
                }
            }
        }
        /**
         * 合并列
         * @param table
         * @param col 需要合并的列
         * @param fromRow 开始行
         * @param toRow 结束行
         */
        public static void mergeColumnsCellVertically(XWPFTable table, int rownum, int fromCol, int toCol) {
        	XWPFTableRow row = table.getRow(rownum);
        	for(int rowIndex = fromCol; rowIndex <= toCol; rowIndex++){
        		CTHMerge hMerge = CTHMerge.Factory.newInstance();
        		if(rowIndex == fromCol){
        			hMerge.setVal(STMerge.RESTART);
        		} else {
        			hMerge.setVal(STMerge.CONTINUE);
        		}
        		XWPFTableCell cell = row.getCell(rowIndex);
        		CTTcPr tcPr = cell.getCTTc().getTcPr();
        		if (tcPr != null) {
        			tcPr.setHMerge(hMerge);
        		} else {
        			tcPr = CTTcPr.Factory.newInstance();
        			tcPr.setHMerge(hMerge);
        			cell.getCTTc().setTcPr(tcPr);
        		}
        	}
        }
        /**
         * 获取需要合并单元格的下标
         * @return
         */
        public static List<Integer[]> startEnd(List<String[]> daList){
            List<Integer[]> indexList = new ArrayList();
            List<String> list = new ArrayList();
            for (int i=0;i<daList.size();i++){
                list.add(daList.get(i)[0]);
            }
            Map<Object, Integer> tm = new HashMap();
            for (int i=0;i<daList.size();i++){
                if (!tm.containsKey(daList.get(i)[0])) {
                    tm.put(daList.get(i)[0], 1);
                } else {
                    int count = tm.get(daList.get(i)[0]) + 1;
                    tm.put(daList.get(i)[0], count);
                }
            }
            for (Map.Entry<Object, Integer> entry : tm.entrySet()) {
                String key = entry.getKey().toString();
                if (list.indexOf(key) != (-1)){
                    Integer[] index = new Integer[2];
                    index[0] = list.indexOf(key);
                    index[1] = list.lastIndexOf(key);
                    indexList.add(index);
                }
            }
            return indexList;
        }
        
        /**
         * 插入新行 同时复制首行的样式 
         * table 操作的表格
         * copyRow 表头下面的行
         * newRowIndex  copyRow该行下面的行的索引,复制copyRow该行的样式
         * 
         * */
        public static XWPFTableRow insertNewRow(XWPFTable table,XWPFTableRow copyRow,Integer newRowIndex){
        	XWPFTableRow targetRow = table.insertNewTableRow(newRowIndex);
        	targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
        	List<XWPFTableCell> copyCells = copyRow.getTableCells();
        	
        	XWPFTableCell targetCell = null;
        	for (int i = 0; i < copyCells.size(); i++) {
        		XWPFTableCell copyCell = copyCells.get(i);
        		targetCell = targetRow.addNewTableCell();
        		targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
        		if(copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0){
        			targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
        			if(copyCell.getParagraphs().get(0).getRuns() !=null && copyCell.getParagraphs().get(0).getRuns().size() > 0){
        				XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
        				cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());
        			}
        		}
    			
    		}
        	return targetRow;
        }
        
        /**
         * 根据图片类型,取得对应的图片类型代码
         * @param picType
         * @return int
         */
        private static int getPictureType(String picType){
            int res = BaseXWPFDocument.PICTURE_TYPE_PICT;
            if(picType != null){
                if(picType.equalsIgnoreCase("png")){
                    res = BaseXWPFDocument.PICTURE_TYPE_PNG;
                }else if(picType.equalsIgnoreCase("dib")){
                    res = BaseXWPFDocument.PICTURE_TYPE_DIB;
                }else if(picType.equalsIgnoreCase("emf")){
                    res = BaseXWPFDocument.PICTURE_TYPE_EMF;
                }else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){
                    res = BaseXWPFDocument.PICTURE_TYPE_JPEG;
                }else if(picType.equalsIgnoreCase("wmf")){
                    res = BaseXWPFDocument.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) {
                        System.out.println("关闭流失败");
                    }
                }
            }
            return byteArray;
        }
        
        /**
         * 遍历表格
         * @param rows 表格行对象
         * @param textMap 需要替换的信息集合
         */
        public static void eachTable(BaseXWPFDocument document, List<XWPFTableRow> rows , Map<String, Object> textMap){
            for (XWPFTableRow row : rows) {
                List<XWPFTableCell> cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    //判断单元格是否需要替换
                    if(checkText(cell.getText())){
                        List<XWPFParagraph> paragraphs = cell.getParagraphs();
                        for (XWPFParagraph paragraph : paragraphs) {
                            List<XWPFRun> runs = paragraph.getRuns();
                            for (XWPFRun run : runs) {
                                Object ob = changeValue(run.toString(), textMap);
                                if (ob instanceof String){
                                    run.setText((String)ob,0);
                                }else if (ob instanceof Map){
                                   /* 此处本想实现表格中插入图片 ,但是失效 所以在89行中自行处理 -^^-
                                    * run.setText("",0);
                                    Map pic = (Map)ob;
                                    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 {
                                        String ind = document.addPictureData(byteInputStream,picType);
                                        document.createPicture(Integer.valueOf(ind), width , height,paragraph);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }*/
                                }
                            }
                        }
                    }
                }
            }
        }
        /**
         * 关闭输入流
         *
         * @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();
                }
            }
        }
    }

    Main.java

    package word;
    
    import java.io.ByteArrayInputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.imageio.ImageIO;
    
    import org.apache.poi.util.IOUtils;
    import org.apache.poi.util.Units;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    
    public class Main {
    
        public static void main(String[] args) throws Exception {
            //需要进行文本替换的信息
            Map<String, Object> data = new HashMap<String, Object>();
            data.put("${date}", "2020");
            
            //需要进行动态生成的信息
            List<Object> mapList = new ArrayList<Object>();
    
            //第一个动态生成的数据列表
            List<String[]> list01 = new ArrayList<String[]>();
            list01.add(new String[]{"张三","男","23"});
            list01.add(new String[]{"李四","女","24"});
            list01.add(new String[]{"王五","女","25"});
            
            //第二个动态生成的数据列表
            List<String[]> list02 = new ArrayList<String[]>();
            list02.add(new String[]{"张三","语文","134"});
            list02.add(new String[]{"张三","数学","141"});
            list02.add(new String[]{"张三","英语","132"});
            list02.add(new String[]{"李四","语文","131"});
            list02.add(new String[]{"李四","数学","131"});
            list02.add(new String[]{"李四","英语","134"});
            list02.add(new String[]{"王五","语文","136"});
            list02.add(new String[]{"王五","数学","145"});
            list02.add(new String[]{"王五","英语","134"});
    
            //第三个动态生成的数据列表
    	    List<String[]> list03 = new ArrayList<String[]>();
    	    list03.add(new String[]{"甲老师","是","否","否"});
    	    list03.add(new String[]{"乙老师","否","是","否"});
    	    list03.add(new String[]{"丙老师","否","是","否"});
    	    list03.add(new String[]{"丁老师","是","否","否"});
            
            //第四个动态生成的数据列表
            List<String[]> list04 = new ArrayList<String[]>();
            list04.add(new String[]{"语文","语文","英语","数学"});
            list04.add(new String[]{"英语","英语","语文","数学"});
    
            mapList.add(list01);
            mapList.add(list02);
            mapList.add(list03);
            mapList.add(list04);
           
            BaseXWPFDocument doc = CrtWordUtils.changWord("D:/test.docx",data,mapList);
            FileOutputStream fopts = new FileOutputStream("D:/stu.doc");
            
            
            /**--------此处实在文档的最后插入一张图片       可尝试在指定的段落中插入(此处未实现) ------*/
            FileInputStream fis = new FileInputStream("D:/1.png");
            byte[] byteArray = IOUtils.toByteArray(fis);
            ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
            ImageIO.read(bais);
            
            XWPFParagraph paragraph = doc.createParagraph();
            XWPFRun run2 = paragraph.createRun();
            /*//原始值
            int width = Units.toEMU(image.getWidth());
            int height = Units.toEMU(image.getHeight());*/
            
            //自定义值
            int width = Units.toEMU(360);
            int height = Units.toEMU(360);
            
            run2.addPicture(new FileInputStream("D:/1.png"), BaseXWPFDocument.PICTURE_TYPE_PNG, "test",
                    width, height);
            /**--------此处实在文档的最后插入一张图片------*/
            
            doc.write(fopts);
            fopts.close();
        }
    
    }
    

    最终生成的文档(方便观看,多页展示了-^^-)

    展开全文
  • 使用java Apache poi 根据word模板生成word报表 仅支持docx格式的word文件,大概是word2010及以后版本,doc格式不支持。 使用说明:https://blog.csdn.net/u012775558/article/details/79678701
  • 实现了POI根据模板导出word,实现文字、表格、图表的替换生成。支持生成多种结构的表格、图表,关键代码都添加了注释,简单易懂。 其中表格和图表都写了两种实现方式,既可以只传简单的参数生成多个同结构的表格和...
  • 一个使用Apache的poi使用word模板循环输出表格行并导出的例子
  • -- poi Excel、Word操作--&gt; &lt;dependency&gt; &lt;groupId&gt;org.apache.poi&lt;/groupId&gt; &lt;artifactId&gt;poi&lt;/artifactId&gt; &lt;version&...
  • 最近从新写了一下根据Word模板导出Word。注意:Word只包含表格和段落,不使用表格布局。图片样式也保留,但是预先需要知道图片的资源ID。删除多余模块时,有顶部对不齐的问题。可能还存在其他细节问题。首先模板样式...
  • POI结构与常用类 Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。 .NET的开发人员则可以利用NPOI (POI for .NET) 来存取 Microsoft Office文档的功能。 ...
  • 网络上的根据模板填充Word我都看过一些, 它们的功能在数据换行的时候用的是run对象的.addCarriageReturn()方法,或者是直接用\n实现换行。这些都不符合我的需求, 因为我要的是分段,而不是换行。换行的word导致另一...
  • java poi 通过模板生成word文档

    热门讨论 2014-07-22 17:10:34
    java使用poi根据模板,生成word文档.
  • POI根据Word模板导出

    2021-04-08 19:45:13
    段落/表格混合导出 有结束符号“##{foreachRows}##” /** * 表格+段落 * @param inputUrl 模板路径 * @param out OutputStream 输出流 * @param map 表格外数据 * @param list 表格数据 */ public void ...
  • Java 使用poi,根据word模板导出word文件

    千次阅读 2020-01-16 17:16:37
    标题 使用poi导出word文件 项目需求:需要将数据按照一定的格式导出成word文档。文本替换,表格循环(表格内部行循环,整个表格循环),插入图片等。 参考连接:...
  • 从别人那里看的,结果后来发版到服务器导出时报错,访问不到模板路径位置,后来改成了。这里我自己整理一下 重点:解决 访问不到Word模板路径 //word模板文件流 这种方法不会在linux上或者jar启动失效 ...
  • POI根据模板导出word-yellowcong

    千次阅读 2017-11-21 16:46:19
    根据模版导出word这个东西在实际开发中,是很常用的,我今天遇到坑了,就是如何根据word模版生成word。网上的代码好多都是坑爹,不是缺环境,就是却方法,所以我自己做了一个小例子。如果希望有图片替换的教程,大家...
  • Springboot--使用POI根据word模板导出word文件

    千次阅读 热门讨论 2020-08-14 14:36:09
    需求:根据一个word模板,在程序中替换模板中的参数,然后根据这个模板导出word文件。 引入POI对word操作的依赖: <dependency> <groupId>org.apache.poi</groupId> <artifactId>...
  • Apache poi 根据word模板生成word报表 替换 循环列表 图片,代码调试过了,修改相应的图片位置,word模板路径即可运行
  • 最近一直在做与导出这部分相关的事情,有一个就是需要将数据库中查询到的信息写入到word模板中再进行导出。下面的代码直接复制使用即可,没啥毛病,无论是段落中的,还是表格中的,都是有效的。使用过程中遇到的一些...
  • 使用java poi动态编辑生成word文件,生成报表信息。支持插入循环list数据和单个数据得工具类,和测试模板,直接导入就能使用
  • org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.12</version> </dependency> <dependency> <groupId>org.apache.poi<...
  • poi-tl使用模板导出word文档
  • 1、poi版本3.13 2、可进行表格替换。复制、图片导出 3、可直接运行
  • 通过 apache poi导出带表格的 word 文件,并且表格的宽度可能过宽,需要纸张横向或者更大的纸张
  • Java使用POI通过模板生成Word

    千次阅读 2021-06-17 10:10:42
    Java使用POI通过模板生成Word 前言 最近工作需要用到,所以记录下来以便查找。 一、概述 POI读写word使用的核心类是XWPFDocument。一个XWPFDocument代表一个docx文档,其可以用来读docx文档,也可以用来写docx文档。...
  • 如果不介意使用xml作为模板文件生成word文档,推荐使用freemark,但是生成的word上传后可能会出现格式问题不支持预览,因为freemark生成的word实质上还是xml格式,预览的时候是xml文件(不兼容openoffice或liboffice)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,872
精华内容 1,148
关键字:

poi根据模板导出word