java使用poi导出word并且带图片

最近在开发中有按照模板导出word的需求,并且把echarts图例附到word里,我开始使用freework取ftl模板的,不过由于转换麻烦,需定义好格式xml再转为ftl文件所以改为使用poi取word模板直接赋值的方式,并且通过拼接标签实现图片的附带和定义宽度高度

1、controller代码

package com.springboot.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
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.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 org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import net.sf.json.JSONObject;


@Controller
public class WordTest {

    @RequestMapping("/exportSellPlan")
    public @ResponseBody void exportSellPlan(Long id, HttpServletRequest request, HttpServletResponse response)throws Exception{
         String rpName=request.getParameter("rpName")==null?"":request.getParameter("rpName");
            rpName=java.net.URLDecoder.decode(rpName,"UTF-8")  ;
            String title = rpName;
            OutputStream out = null;
            String path="C:\\Users\\Administrator\\Desktop\\demo.docx";
            //String path = request.getSession().getServletContext().getRealPath("/efficiency/EnergyCellReport/中能瑞通模板.docx"); 
            try {
                out = response.getOutputStream();
                
                /**
                 * 读取word
                 */
                XWPFDocument docx = PropertiesUtil.importWord(path);
                //docx = mFaultReportManageService.fillWordDataByList(docx, maps);
                /**
                 * 数据组装
                 */
                //获取所有需要填充的数据
                //List<Map<String,String>> codeList = energyUnitService.queryEnergyReportDiList(rpId, consId);
                
                Map<String, String> wdmap = new HashMap<String, String>();
                com.alibaba.fastjson.JSONObject json=new com.alibaba.fastjson.JSONObject();
//                String appId=UserUtil.getAppId();
//                json.put("appId", appId);        
//                TenantAppClone app=energyUnitService.selectObjectByID(json);
                wdmap.put("Title-N01","aaa");
                Map<String,Object> map = new HashMap<>();
                map.put("filepath", "C:\\Users\\Administrator\\Desktop\\50a6dcc7ly1g2g62aqxzpj22re1ulx6p.jpg");
                map.put("width", "100");
                map.put("height", "100");
                wdmap.put("img-scoreimg",String.valueOf(JSONObject.fromObject(map)));
                replaceInPara(docx,wdmap);
                /*boolean flag_cp=false;
                if(codeList!=null&&codeList.size()>0){
                    for(Map<String,String> map:codeList){
                         if(map.get("CODE_VALUE").equals("the-cpname")){
                             flag_cp=true;
                         }
                         
                    }
                }
                //填充word中的产品表格
                if(flag_cp){
                    this.queryProduct(docx,rpTime);
                }
                //填充值 
                //this.writeInWord(codeList,docx,rpTime);
                Map<String, String> wdmap = new HashMap<String, String>();
                if(codeList!=null&&codeList.size()>0){
                    for(int i=0;i<codeList.size();i++){
                        Map map = codeList.get(i);
                        wdmap.put(map.get("CODE_VALUE").toString(),map.get("RP_VALUE").toString());  //公司名称
                    }
                }
                //修改word中的值
                replaceInPara(docx,wdmap);*/
                /**
                 * 生成word
                 */
                PropertiesUtil.exportWord(docx, title, out, request, response);
                
                
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }
    
    
    /**
     *  word中 的文字填入
     * @param docx
     * @param params
     */
    public void replaceInPara(XWPFDocument docx, Map<String, String> params) {
        Iterator<XWPFParagraph> itPara = docx.getParagraphsIterator();
        while (itPara.hasNext()) {
            XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
            Set<String> set = params.keySet();
            Iterator<String> iterator = set.iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                List<XWPFRun> run = paragraph.getRuns();
                for (int i = 0; i < run.size(); i++) {
                    System.out.println(run.get(i).getText(run.get(i).getTextPosition())+"-------------------------");
                    if (run.get(i).getText(run.get(i).getTextPosition()) != null&& run.get(i).getText(run.get(i).getTextPosition()).equalsIgnoreCase(key)) {
                        if (!(key.startsWith("img-"))) { 
                            run.get(i).setText(params.get(key), 0);
                        } else {

                            run.get(i).setText("", 0);
                            
                            Map<String, String> pic = new HashMap<String, String>();
                            System.err.println(params.get(key));
                            JSONObject jsonObject = JSONObject.fromObject(params.get(key));
                            for (Iterator<?> iter = jsonObject.keys(); iter.hasNext();)
                            {
                                String k = (String) iter.next();
                                String v = jsonObject.get(k).toString();
                                pic.put(k, v);
                            }
                            
                            int width = Integer.parseInt(pic.get("width").toString()); 
                            int height = Integer.parseInt(pic.get("height").toString()); 

                            byte[] byteArray = null;  
                            FileInputStream in = null;
                            try {  
                                in = new FileInputStream(pic.get("filepath").toString());
                                int total = in.available();  
                                byteArray = new byte[total];  
                                in.read(byteArray);  
                            } catch (IOException e) {  
                                e.printStackTrace();
                            }finally{
                                try {
                                    in.close();
                                } catch (Exception e2) {
                                    System.out.println("关闭流失败");
                                }
                            }
                            
                            int picType = XWPFDocument.PICTURE_TYPE_PNG;  
                            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);  
                            try {  
                                String ind = docx.addPictureData(byteInputStream,picType);  
                                //docx.createPicture(width , height,paragraph);
                                
                                final int EMU = 9525;    
                                width *= EMU;    
                                height *= EMU;    
                                String blipId = ind;    
                                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=\""    
                                        + 1    
                                        + "\" 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(1);      
                                docPr.setName("图片" + 1);      
                                docPr.setDescr("测试");
                                    
                                    
                                
                            } catch (Exception e) {  
                                e.printStackTrace();  
                            }  
                            
                        }
                    }
                    
                }
            }
        }

    }
}

2、PropertiesUtil代码:

package com.springboot.util;
    

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;


/**
 * @Description 加载属性配置文件工具类
 */
public class PropertiesUtil {
    /**
     * 导出word
     * @param docx
     * @param title
     * @param out
     * @param request
     * @param response
     * @throws Exception
     */
    public static void exportWord(XWPFDocument docx, String title, OutputStream out, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        // 兼容浏览器
        String userAgent = request.getHeader("USER-AGENT");
        if (!StringUtils.contains(userAgent, "Mozilla")) {// 火狐浏览器
            title = URLEncoder.encode(title, "UTF-8");// 其他浏览器
        } else {
            title = new String(title.getBytes("UTF-8"), "ISO8859-1");
        }
        response.setContentType("application/msword");
        response.addHeader("Accept-Ranges", "bytes");
        response.addHeader("Content-Disposition", "attachment;filename=" + title + ".doc");
        // 创建word文档
        try {
            docx.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            out.close();
        }
    }
    /**
     * 读取word
     * @param fileName
     * @return
     * @throws Exception
     */
    public static XWPFDocument importWord(String fileName) throws Exception {
        InputStream in = null;
        XWPFDocument docx = null;
        try {
            in = new FileInputStream(new File(fileName));
            docx = new XWPFDocument(in);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            in.close();
        }
        return docx;
    }
    
        /**
         * 表格填充值
         * @param table
         * @return
         */
        public static int getNullValuePos(XWPFTable table) {
            List<XWPFTableRow> rows = null;
            List<XWPFTableCell> cells = null;
            XWPFTableRow row = null;
            rows = table.getRows();
            // 至少第一行是标题行 从表题行的下一行进行查询
            int t = -1;
            for (int i = 0; i < rows.size(); i++) {
                // 获取当前行
                row = rows.get(i);
                // 获取当前行的所有cell
                cells = row.getTableCells();
                // 获取cell的size
                int cellSize = cells.size();
                // 获取最后一个cell的内容
                XWPFTableCell cell = cells.get(cellSize - 1);
                String text = cell.getText().trim();
                if (StringUtils.isBlank(text)) {
                    t = i;
                    break;
                }
            }
            return t;
        }
}

3、excel模板:(根据代码我只示例了一个赋值的参数一个图片的参数)

填充值:

java使用poi导出word并且带图片

填充图片:

java使用poi导出word并且带图片

代码赋值示例:(图片需要三个参数地址、宽度、高度)

java使用poi导出word并且带图片

 

3、效果

值效果:

java使用poi导出word并且带图片

图片效果:

java使用poi导出word并且带图片