总结之数据导出到word模板——使用poi导出

我们先看看需求:
在这里插入图片描述
我们要在模板标题插入内容,在多个表格中填充数据

先看东西

这里我写了个poi工具类方便操作

import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
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.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;

public class Word2007Util {
	
	/**
	 * Description: 根据指定的参数值、模板,生成 word 文档
	 * @param replaceParamMap 需要替换的参数map
	 * @param doc 文档对象
	 * @return 生成后的 word 文档对象
	 */
	public static XWPFDocument replaceWord(Map<String, Object> replaceParamMap, XWPFDocument doc) {
		try {
			if (replaceParamMap != null && replaceParamMap.size() > 0) {
				// 处理段落
				List<XWPFParagraph> paragraphList = doc.getParagraphs();
				processParagraphs1(paragraphList, replaceParamMap, doc);

				// 处理表格
				Iterator<XWPFTable> it = doc.getTablesIterator();
				while (it.hasNext()) {
					XWPFTable table = it.next();
					List<XWPFTableRow> rows = table.getRows();
					for (XWPFTableRow row : rows) {
						List<XWPFTableCell> cells = row.getTableCells();
						for (XWPFTableCell cell : cells) {
							List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
							processParagraphs1(paragraphListTable, replaceParamMap, doc);
						}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return doc;
	}
	
	/**
	 * Description: 根据指定的参数值、模板,生成 word 文档
	 * @param replaceParamMap 需要替换的参数map
	 * @param is 文档输入流
	 * @return 生成后的 word 文档对象
	 */
	public static XWPFDocument replaceWord(Map<String, Object> replaceParamMap, InputStream is) {
		try {
			return replaceWord(replaceParamMap, new XWPFDocument(is));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Description: 根据指定的参数值、模板,生成 word 文档
	 * @param replaceParamMap 需要替换的参数map
	 * @param docTemplate 文档模版路径
	 * @return 生成后的 word 文档对象
	 */
	public static XWPFDocument replaceWord(Map<String, Object> replaceParamMap, String docTemplate) {
		OPCPackage pack;
		try {
			pack = POIXMLDocument.openPackage(docTemplate);
			return replaceWord(replaceParamMap, new XWPFDocument(pack));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * Description: 处理段落中的文字和图片替换
	 * @param paragraphList 段落集合
	 * @param replaceParamMap 需要替换的参数map
	 * @param doc 文档对象
	 */
	public static void processParagraphs1(List<XWPFParagraph> paragraphList, Map<String, Object> replaceParamMap, XWPFDocument doc) {
		if (paragraphList == null || paragraphList.size() <= 0) {
			return;
		}
		//循环段落
		for (XWPFParagraph paragraph : paragraphList) {
			List<XWPFRun> runs = paragraph.getRuns();
			//循环每个小节,拼接为一个字符串,避免拆分的时候,误把替换字段标记 拆分
			StringBuffer buffer = new StringBuffer();
			for (XWPFRun xwpfRun : runs) {
				String text = xwpfRun.getText(0);
				if (text == null) {
					continue;
				}
				buffer.append(text);
			}
			//循环替换字段map,替换内容
			String textString = buffer.toString();
			for (Entry<String, Object> entry : replaceParamMap.entrySet()) {
				String key = entry.getKey();
				if (textString.indexOf(key) != -1) {
					//isSetText = true;
					Object value = entry.getValue();
					if(value == null) {
						textString = textString.replace(key, "");
					}
					if (value instanceof Map) {// 图片替换
						// TODO 待实现
					} else {//非map,则将值转换为string类型
						textString = textString.replace(key, StringUtil.isNotEmpty(String.valueOf(value)) ? String.valueOf(value) : "");
					}
				}
			}
			//再次循环 把替换后的字符串 赋值给每个段落的最后一个小节,前面的小节全部设为空
			for(int i=0;i<runs.size();i++){
				XWPFRun run = runs.get(i);
				if(i<(runs.size()-1)){
					run.setText(null, 0);
				}else{
					//如果内容里面有换行标签  需要替换掉换行标签  并加入换行功能
					if(textString.indexOf("<br>") !=-1){
						String s[] = textString.split("<br>");
						for (int j = 0; j < s.length; j++) {
							run.setText(s[j],j);
							if(j<s.length-1){
							run.addBreak();	//换行
							}
						}
								
					}else{
						run.setText(textString, 0);
					}
				}
			}
		}
	}
	/**
	 * Description: 处理段落中的文字和图片替换
	 * @param paragraphList 段落集合
	 * @param replaceParamMap 需要替换的参数map
	 * @param doc 文档对象
	 */
	public static void processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> replaceParamMap, XWPFDocument doc) {
		if (paragraphList == null || paragraphList.size() <= 0) {
			return;
		}
		for (XWPFParagraph paragraph : paragraphList) {
			List<XWPFRun> runs = paragraph.getRuns();
			for (XWPFRun run : runs) {
				String text = run.getText(0);
				if (text == null) {
					continue;
				}
				boolean isSetText = false;
				for (Entry<String, Object> entry : replaceParamMap.entrySet()) {
					String key = entry.getKey();
					if (text.indexOf(key) != -1) {
						isSetText = true;
						Object value = entry.getValue();
						if(value == null) {
							text = text.replace(key, "");
						}
						if (value instanceof String 
								|| value instanceof Integer 
								|| value instanceof Float 
								|| value instanceof Double) {// 文本替换
							text = text.replace(key, StringUtil.isNotEmpty(value.toString()) ? value.toString() : "-");
						}
						if (value instanceof Map) {// 图片替换
							// TODO 待实现
						}
					}
				}
				if (isSetText) {
					run.setText(text, 0);
				}
			}
		}
	}

	/**
	 * Description: 将输入流中的数据写入字节数组
	 * @param in 输入流
	 * @param isClose 是否关闭输入流
	 * @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;
	}
	
	/**
	 * 取消表格边框
	 */
	public static void removeTableBroder(XWPFTable table){
		/**************************************/
		CTTblBorders borders=table.getCTTbl().getTblPr().addNewTblBorders();  
        CTBorder hBorder=borders.addNewInsideH();  
        hBorder.setVal(STBorder.Enum.forString("none"));  
        hBorder.setSz(new BigInteger("1"));  
        hBorder.setColor("0000FF");  
          
        CTBorder vBorder=borders.addNewInsideV();  
        vBorder.setVal(STBorder.Enum.forString("none"));  
        vBorder.setSz(new BigInteger("1"));  
        vBorder.setColor("00FF00");  
          
        CTBorder lBorder=borders.addNewLeft();  
        lBorder.setVal(STBorder.Enum.forString("none"));  
        lBorder.setSz(new BigInteger("1"));  
        lBorder.setColor("3399FF");  
          
        CTBorder rBorder=borders.addNewRight();  
        rBorder.setVal(STBorder.Enum.forString("none"));  
        rBorder.setSz(new BigInteger("1"));  
        rBorder.setColor("F2B11F");  
          
        CTBorder tBorder=borders.addNewTop();  
        tBorder.setVal(STBorder.Enum.forString("none"));  
        tBorder.setSz(new BigInteger("1"));  
        tBorder.setColor("C3599D");  
          
        CTBorder bBorder=borders.addNewBottom();  
        bBorder.setVal(STBorder.Enum.forString("none"));  
        bBorder.setSz(new BigInteger("1"));  
        bBorder.setColor("F7E415");  
	}
	/**
	 * 设置单元格样式
	 */
	public static void setCellStyle(XWPFTableCell cell,String text,String fontFamily){
		
    	cell.removeParagraph(0);
    	cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); //垂直居中
    	XWPFParagraph paragraphX = cell.addParagraph();
    	paragraphX.setFontAlignment(2);
    	XWPFRun run = paragraphX.createRun();
    	run.setFontFamily(fontFamily);
    	run.setText(text);
	}
}

调用Controller

public class ExportController {

    @Autowired
    private ProjectApplyFlowService projectApplyFlowService;

    @Autowired
    private SpecialInfoService specialInfoService;

    @Autowired
    private StartSpecialInfoService startSpecialInfoService;
    /***
    * @Param [id, request, response]
    * @return void
    * @Description 导出项目汇总表
    * @author liuzonghua
    * @date 2020/6/30 17:48
    **/
    @RequestMapping("exportSpecialProject")
    public void expertSpecialProject(String id, HttpServletRequest request, HttpServletResponse response){
        try {
            InputStream in = ResourceUtil.getResourceAsStream("/doc/applyCollectTable.docx");
            XWPFDocument doc = null;

            //数据
            SearchCondition jqGridSearch = new JQGridSearch();

            User currentUser = (User) this.getCurrentUser(request, response);
            ConditionGroupsBuilder conditionGroupsBuilder = new ConditionGroupsBuilder();
            conditionGroupsBuilder.addConditionField(new ConditionField("", "areaDepartmentId", ConditionFieldOp.BASE_EQUAL, currentUser.getDepartmentId()));
            if(StringUtils.isNotBlank(id)) {
                conditionGroupsBuilder.addConditionField(new ConditionField("", "projectBatchId", ConditionFieldOp.BASE_EQUAL, id));
            }
            jqGridSearch.addExtraConditionGroups(conditionGroupsBuilder.build());
            //word多表结构(可再封装方法)
            List<List<Map<String, Object>>> data = new ArrayList<>();
            List<Map<String, Object>> list = projectApplyFlowService.findCollectByProjectBatchIdAndAreaDepartmentId(id,currentUser.getDepartmentId());
            data.add(list);
            StartSpecialInfo startSpecialInfo = startSpecialInfoService.findById(id);
            if(CollectionUtil.isNotEmpty(startSpecialInfo)){
                SpecialInfo specialInfo = specialInfoService.findById(startSpecialInfo.getSpecialId());
                if(CollectionUtil.isNotEmpty(specialInfo)){
                    doc = this.exportListDoc(in, data,specialInfo.getSpecialName());
                }
            }

            String fileName =  "项目申报汇总表"+ ".docx";
            response.reset();
            this.setDownloadResponse(request, response, fileName);
            ByteArrayOutputStream ostream = new ByteArrayOutputStream();
            ServletOutputStream servletOS = response.getOutputStream();
            doc.write(ostream);
            servletOS.write(ostream.toByteArray());
            servletOS.flush();
            servletOS.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
    * @Param [in, data, specialName]
    * @return org.apache.poi.xwpf.usermodel.XWPFDocument
    * @Description 导出doc
    * @author liuzonghua
    * @date 2020/6/30 17:49
    **/
    public XWPFDocument exportListDoc(InputStream in, List<List<Map<String, Object>>> data,String specialName) {
        Map<String, Object> map = new LinkedHashMap<String, Object>();
        map.put("${special}", specialName);
        XWPFDocument doc = Word2007Util.replaceWord(map, in);
        docList(data, doc);
        return doc;
    }

    /**
     * 导出列表
     * @param data
     * @param doc
     * Description:
     * Date: 2019年9月27日
     * Time: 上午10:27:47
     * @author liu.zonghua
     */
    private void docList(List<List<Map<String, Object>>> data,XWPFDocument doc){
        //得到表格对象列表
        List<XWPFTable> tables = doc.getTables();
        for(int j=0;j<data.size();j++) {
            if(CollectionUtil.isNotEmpty(data.get(j))){
                int i = 0;
                for(Map<String, Object> map : data.get(j)){
                    //取第j+1个列表
                    XWPFTable table = tables.get(j);
                    //获取表格行对象
                    XWPFTableRow row = null;
                    row = table.createRow();
                    XWPFTableCell cell0 = row.getCell(0);
                    Word2007Util.setCellStyle(cell0, StringUtil.parseString(i + 1),"仿宋");
                    XWPFTableCell cell1 = row.getCell(1);
                    Word2007Util.setCellStyle(cell1, MapUtils.getString(map, "title","") ,"仿宋");
                    XWPFTableCell cell2 = row.getCell(2);
                    Word2007Util.setCellStyle(cell2,MapUtils.getString(map, "startNum",""),"仿宋");
                    XWPFTableCell cell3 = row.getCell(3);
                    Word2007Util.setCellStyle(cell3,MapUtils.getString(map, "projectLeader",""),"仿宋");
                    XWPFTableCell cell4 = row.getCell(4);
                    Word2007Util.setCellStyle(cell4, MapUtils.getString(map, "phone",""),"仿宋");
                    XWPFTableCell cell5 = row.getCell(5);
                    Word2007Util.setCellStyle(cell5, MapUtils.getString(map, "enterpriseStartTime",""),"仿宋");
                    XWPFTableCell cell6 = row.getCell(6);
                    Word2007Util.setCellStyle(cell6, MapUtils.getString(map, "enterpriseEndTime",""),"仿宋");
                    i++;
                }
            }else {
                //取第j+1个列表
                XWPFTable table = tables.get(j);
                //获取表格行对象
                XWPFTableRow row = null;
                row = table.createRow();
                XWPFTableCell cell0 = row.getCell(0);
                Word2007Util.setCellStyle(cell0,"","仿宋");
                XWPFTableCell cell1 = row.createCell();
                Word2007Util.setCellStyle(cell1, "","仿宋");
                XWPFTableCell cell2 = row.createCell();
                Word2007Util.setCellStyle(cell2, "","仿宋");
                XWPFTableCell cell3 = row.createCell();
                Word2007Util.setCellStyle(cell3, "","仿宋");
                XWPFTableCell cell4 = row.createCell();
                Word2007Util.setCellStyle(cell4, "","仿宋");
                XWPFTableCell cell5 = row.createCell();
                Word2007Util.setCellStyle(cell5, "","仿宋");
            }
        }

    }
    /***
    * @Param [request, response, fileName]
    * @return void
    * @Description 下载相关
    * @author liuzonghua
    * @date 2020/6/30 17:49
    **/
    public void setDownloadResponse(HttpServletRequest request, HttpServletResponse response,
                                    String fileName) throws Exception {
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        String downloadFileName = "";
        if (request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0) {
            downloadFileName = URLEncoder.encode(fileName, "UTF-8");
        } else {
            downloadFileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
        }
        response.setHeader("Content-disposition", "attachment; filename=" + downloadFileName);
    }
}

解析

 public XWPFDocument exportListDoc(InputStream in, List<List<Map<String, Object>>> data,String specialName) {
        Map<String, Object> map = new LinkedHashMap<String, Object>();
        map.put("${special}", specialName);
        XWPFDocument doc = Word2007Util.replaceWord(map, in);
        docList(data, doc);
        return doc;
    }

这块来替换word中${}数据

得到多个表格对象

List<XWPFTable> tables = doc.getTables();

通过List<List<Map<String, Object>>数据来与表格对应

然后获取表格,填充内容,设置样式。

//获取表格行对象
                    XWPFTableRow row = null;
                    row = table.createRow();
                    XWPFTableCell cell0 = row.getCell(0);
                    Word2007Util.setCellStyle(cell0, StringUtil.parseString(i + 1),"仿宋");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章