Freemaker模板替换word封装工具类

一、工具类如下

package com.enter.net.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * @Author: zhangshizhe
 *
 * @Date: 2020年05月30日 9:00:33
 *
 * @Description: 使用模板导出工具类
 *
 * @Version: 1.0
 *
 */
public class ExportFreemakerUtil {
	//注:如果使用表格宽度的话,每次添加新表格时需要重新new对象
	private List table_widths = new ArrayList<>();//当前表格宽度数组
	private static final int SUM_TABLE_WIDTH = 9326;//表格默认总宽度

	/**
	 * 自动计算列宽
	 * @param num
	 */
	public ExportFreemakerUtil(Integer num) {
		for (int i = 0; i < num; i++) {
			table_widths.add(SUM_TABLE_WIDTH / num);
		}
	}

	/**
	 * 自动计算剩余列宽
	 * @param num 共几列
	 * @param widths 需要固定的宽度(key:列数,value:宽度)
	 */
	public ExportFreemakerUtil(Integer num, Map widths) {
		Integer sum = 0;
		for (Integer column : widths.keySet()) {
			sum += widths.get(column);
		}
		Integer average = (SUM_TABLE_WIDTH - sum) / num;
		for (int i = 0; i < num; i++) {
			Integer integer = widths.get(i);
			if (integer == null) {//添加平均数
				table_widths.add(average);
			}else {//添加手动的
				table_widths.add(integer);
			}
		}
	}

	/**
	 * 没有宽度,加载段落使用,不能加载表格
	 */
	public ExportFreemakerUtil() {
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取表格的开始(需手动传宽度)
	 * @Fcunction getTableStart
	 * @return String
	 *
	 */
	public String getTableStart(){
		//表格固定开始
		String str =
				"      \n" +
				"        \n" +
				"          \n" +
				"          \n" +
				"          \n" +
				"          \n" +
				"            \n" +
				"            \n" +
				"            \n" +
				"            \n" +
				"            \n" +
				"            \n" +
				"          \n" +
				"          \n" +
				"          \n" +
				"            \n" +
				"            \n" +
				"          \n" +
				"        ";
		//表格宽度设置
		str += "		  ";
		for (Integer width : table_widths) {
			str += "		    ";
		}
		str += "		  ";
		return str;
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取表格的结束
	 * @Fcunction getTableEnd
	 * @return String
	 *
	 */
	public String getTableEnd(){
		//表格固定结束
		String str ="      ";
		return str;
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取表格的每一行的开始
	 * @Fcunction getTableRowStart
	 * @return String
	 *
	 */
	public String getTableRowStart(){
		return "        \n" +
				"          \n" +
				"            \n" +
				"              \n" +
				"              \n" +
				"            \n" +
				"          \n" +
				"          \n" +
				"            \n" +
				"            \n" +
				"            \n" +
				"          ";
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取表格的每一行的结束
	 * @Fcunction getTableRowEnd
	 * @return String
	 *
	 */
	public String getTableRowEnd(){
		return "        ";
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取每一列
	 * @Fcunction getColumn
	 * @param str
	 * @param count 第几列
	 * @return String
	 *
	 */
	public String getColumn(String str,Integer count){
		return "          \n" +
				"            \n" +
				"              \n" +
				"              \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"              \n" +
				"              \n" +
				"            \n" +
				"            \n" +
				"              \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"                  \n" +
				"                  \n" +
				"                \n" +
				"              \n" +
				"              \n" +
				"                \n" +
				"                  \n" +
				"                  \n" +
				"                  \n" +
				"                \n" +
				"                " + str + "\n" +
				"              \n" +
				"            \n" +
				"          ";
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取列合并的列
	 * @Fcunction getMergeColumn
	 * @param str 文字
	 * @param num 合并几列
	 * @param count 第几列
	 * @return String
	 *
	 */
	public String getMergeColumn(String str,Integer num,Integer count){
		Integer sum = 0;
		for (int i = count; i < count + num; i++) {
			if (i < table_widths.size()) {
				sum += table_widths.get(i);
			}
		}
		return "          \n" +
				"            \n" +
				"              \n" +
				"              \n" +
				"              \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"              \n" +
				"              \n" +
				"            \n" +
				"            \n" +
				"              \n" +
				"                \n" +
				"              \n" +
				"              \n" +
				"                \n" +
				"                  \n" +
				"                  \n" +
				"                  \n" +
				"                \n" +
				"                " + str + "\n" +
				"              \n" +
				"            \n" +
				"          ";
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取行合并的列(合并起始列)
	 * @Fcunction getMergeRowColumnStart
	 * @param str
	 * @param count 第几列
	 * @return String
	 *
	 */
	public String getMergeRowColumnStart(String str,Integer count){
		return "          \n" +
				"            \n" +
				"              \n" +
				"              \n" +
				"              \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"              \n" +
				"              \n" +
				"            \n" +
				"            \n" +
				"              \n" +
				"                \n" +
				"                \n" +
				"                  \n" +
				"                \n" +
				"              \n" +
				"              \n" +
				"                \n" +
				"                  \n" +
				"                  \n" +
				"                  \n" +
				"                  \n" +
				"                \n" +
				"                " + str + "\n" +
				"              \n" +
				"            \n" +
				"          ";
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取行合并的列(合并结束列)
	 * @Fcunction getMergeRowColumnEnd
	 * @param count 第几列
	 * @return String
	 *
	 */
	public String getMergeRowColumnEnd(Integer count){
		return "          \n" +
				"            \n" +
				"              \n" +
				"              \n" +
				"              \n" +
				"                \n" +
				"                \n" +
				"                \n" +
				"              \n" +
				"              \n" +
				"            \n" +
				"            \n" +
				"              \n" +
				"                \n" +
				"                \n" +
				"                  \n" +
				"                \n" +
				"              \n" +
				"            \n" +
				"          ";
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:06:03
	 * @Description 获取空行
	 * @Fcunction getBlankParagraph
	 * @return String
	 *
	 */
	public String getBlankParagraph(){
		return "\n" +
				"        \n" +
				"          \n" +
				"          \n" +
				"            \n" +
				"            \n" +
				"          \n" +
				"        \n" +
				"      ";
	}

	/**
	 *
	 * @Author zhangshizhe
	 * @Date 2020年05月30日 9:16:03
	 * @Description 获取word的段落
	 * @Fcunction getParagraph
	 * @param str 内容
	 * @param type 字体
	 * @return String
	 *
	 */
	public String getParagraph(String str,String type){
		return "\n" +
				"        \n" +
				"          \n" +
				"          \n" +
				"          \n" +
				"            \n" +
				"            \n" +
				"          \n" +
				"        \n" +
				"        \n" +
				"          \n" +
				"            \n" +
				"            \n" +
				"            \n" +
				"            \n" +
				"          \n" +
				"          " + str + "\n" +
				"        \n" +
				"      ";
	}
}

二、使用方法如下

public static void main(String[] args) {
    //造数据--表头第一行第二行
    Map head_map = new HashMap<>();
    head_map.put("111","测试1");
    head_map.put("222","测试2");
    head_map.put("222","测试3");
    Map head_type_map = new HashMap<>();//指标id对应类型(系统、人工)
    head_map.put("111","0");
    head_map.put("222","0");
    head_map.put("222","1");
    Map norm_calculation_map = new HashMap<>();//0系统计算,1人工录入
    norm_calculation_map.put("0", new String[]{"月度计划","月度完成","超欠","增减分"});
    norm_calculation_map.put("1", new String[]{"完成情况","增减分"});
    //造数据--内容
    List> rows = new ArrayList<>();
    for (int i = 0; i < 3; i++) {//造三行数据
        List row = new ArrayList<>();
        row.add(i+1+"");//第一列序号
        for (int j = 0; j < 11; j++) {//因为表头造的数据是12列,所以内容也造12列
            row.add(j+"");
        }
        rows.add(row);
    }
    //造数据--段落
    String txt = "测试段落";
    //调用方法
    String str = "";//导出中心内容
    Map widths = new HashMap<>();//设置第一列第二列的宽度
    widths.put(0, 695);
    widths.put(1, 1418);
    //使用工具类
    ExportFreemakerUtil util = new ExportFreemakerUtil(rows.get(0).size(), widths);
    //加载段落
    str += new ExportFreemakerUtil().getParagraph(txt,"黑体");
    //第一行
    str = getTableRowOne(str, util, head_map, head_type_map, norm_calculation_map);
    //第二行
    str = getTableRowTwo(str, util, head_map, head_type_map, norm_calculation_map);
    //内容
    str = getTableRowContent(str, util, rows);
    str += util.getTableEnd();//表格结束
    str += util.getBlankParagraph();//添加空行
    //把数据放到map中
    Map map = new HashMap<>();
    map.put("content", str);
    map.put("org_main_name", "user1");
    map.put("month_", "2020-06");
    map.put("depar_head", "user2");
    map.put("name_input_user", "user3");
    map.put("contact", "11111");
    map.put("input_time", "2020-05-31");
    OutputStream outputStream = response.getOutputStream();//导出的话response是HttpServletResponse,从Controller传过来
    WordGenerator.createDoc(map, "doc_table.ftl", outputStream);
}

/**
* 表头第二行
* @param str
* @param util
* @param head_map
* @param head_type_map
* @param norm_calculation_map
* @return
*/
private String getTableRowTwo(String str, ExportFreemakerUtil util, Map head_map, Map head_type_map, Map norm_calculation_map) {
   Integer count;
   count = -1;//计列
   str += util.getTableRowStart();//行开始
   count++;
   str += util.getMergeRowColumnEnd(count);//第一行第一列
   count++;
   str += util.getMergeRowColumnEnd(count);//第一行第二列
   for (String key : head_map.keySet()) {
      String[] strings = norm_calculation_map.get(head_type_map.get(key));
      for (String string : strings) {
         count++;
         str += util.getColumn(string, count);
      }
   }
   str += util.getTableRowEnd();//行结束
   return str;
}


/**
* 表头第一行
* @param str
* @param util
* @param head_map
* @param head_type_map
* @param norm_calculation_map
* @return
*/
private String getTableRowOne(String str, ExportFreemakerUtil util, Map head_map, Map head_type_map, Map norm_calculation_map) {
   Integer count = -1;//计列
   str += util.getTableRowStart();//行开始
   count++;
   str += util.getMergeRowColumnStart("序号", count);//第一行第一列
   count++;
   str += util.getMergeRowColumnStart("单位名称", count);//第一行第二列
   for (String key : head_map.keySet()) {
      count++;
      String[] strings = norm_calculation_map.get(head_type_map.get(key));
      int length = strings.length;
      str += util.getMergeColumn(head_map.get(key), length, count);
      count += length - 1;
   }
   str += util.getTableRowEnd();//行结束
   return str;
}

/**
* 行内容
* @param str
* @param util
* @param rows
* @return
*/
private String getTableRowContent(String str, ExportFreemakerUtil util, List> rows) {
   for (List row : rows) {//每一行
      Integer count = -1;//计列
      str += util.getTableRowStart();//行开始
      for (String value : row) {//每一列
         count++;
         str += util.getColumn(value, count);//行结束
      }
      str += util.getTableRowEnd();//行结束
   }
   return str;
}

/**
* 模板动态替换
* @param dataMap
* @param templateName
* @param output
* @return
*/
public void createDoc(Map dataMap,String templateName,OutputStream output) throws TemplateException, IOException {
        //创建配置实例
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
        //设置编码
        configuration.setDefaultEncoding("UTF-8");
        //空值
        configuration.setClassicCompatible(true);
        
        //ftl模板文件统一放至 com.fh.template 包下面
        configuration.setClassForTemplateLoading(WordGenerator.class,"/templates/");
        
        //获取模板
        Template template = configuration.getTemplate(templateName);
        
        //将模板和数据模型合并生成文件
        Writer out = new BufferedWriter(new OutputStreamWriter(output,"UTF-8"));
        
        //这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开  
//      Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");

        //生成文件
        template.process(dataMap, out);
        
        //关闭流
        out.flush();
        out.close();
}

三、doc_table.ftl模板如下,具体怎么生成模板可以参考java使用freemarker模板导出word,合并单元格,单元格内换行






  
  
    tlj
    dell
    2
    0
    2020-05-19T02:05:00Z
    2020-05-19T02:05:00Z
    1
    52
    302
    Microsoft
    2
    1
    353
    14
  
  
    2052-11.1.0.9513
  
  
    
    
      
      
      
      
      
    
    
      
      
      
      
      
      
    
    
      
      
      
      
      
    
    
      
      
      
      
      
    
    
      
      
      
      
      
    
    
      
      
      
      
      
    
    
      
      
      
      
      
    
  
  
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    
      
      
      
        
        
      
      
        
        
        
        
        
      
    
    
      
      
    
    
      
      
      
        
        
      
      
        
          
          
          
          
        
      
    
    
      
      
    
    
      
      
      
        
        
        
      
    
    
      
      
      
        
        
        
      
    
    
      
      
      
      
      
        
          
        
        
          
          
        
        
        
      
      
        
        
        
      
    
    
      
      
      
      
      
        
          
          
        
        
        
      
      
        
        
        
      
    
    
      
      
      
      
        
      
      
        
          
          
          
          
          
          
        
        
          
          
          
          
        
      
    
  
  
    
    
      
    
  
  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
      
        
          
            
          
        
      
      
        
          
            
          
        
      
    
    
      
        
          
            
          
        
      
      
        
          
            
          
        
      
    
    
      
      
      
      
      
      
      
      
      
      
      
      
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
  
  
    
       
                        
                            
                            
                            
                                
                                
                                
                                
                            
                        
                        
                            
                                
                                
                                
                                
                            
                            所属单位月度组织绩效考核生产经营指标完成情况
                        
                    
      
        
          
          
          
            
            
            
          
        
        
          
            
            
            
            
            
          
          提供部门:${org_main_name}(公章)
        
        
          
            
            
            
            
            
          
          <#--          -->
              
        
        
          
            
            
            
            
            
          
          考核月份:
        
        
          
            
            
            
            
            
          
          ${month_}
        
      
      ${content}
      
        
          
          
          
            
            
            
          
        
        
          
            
            
            
            
          
          部门负责人:
        
        
          
            
            
            
          
          ${depar_head}
        
        
          
            
            
            
          
             
        
        
          
            
            
            
            
          
          填表人:
        
        
          
            
            
            
          
          ${name_input_user}
        
        
          
            
            
            
          
             
        
        
          
            
            
            
            
          
          电话:
        
        
          
            
            
            
          
          ${contact}   
        
      
      
        
          
          
          
            
            
            
          
        
        
          
            
            
            
          
          ${input_time}
        
      
      
        
          
            
              
              
            
            
              
            
            
               PAGE   \* MERGEFORMAT 
            
            
              
            
            
              
                
                
              
              1
            
            
              
            
          
          
            
              
            
          
        
        
        
        
        
      
    
  

四、效果如下

Freemaker模板替换word封装工具类_第1张图片

五、xml标签的官方文档:http://officeopenxml.com/WPtableProperties.php

你可能感兴趣的:(Freemaker模板替换word封装工具类)