freemarker根据模板导出word文件

前言

项目中都会遇到关于文件的导出,这里主要使用freemarker来根据ftl来生成word文档,这里使用的例子中我只考虑到一些常见的情况,如果你遇到问题或是其他特殊情况,希望留下你问题和见解。

word文件导出

引入依赖

  1. 首先是导入freemarker的jar包
            <dependency>
                <groupId>org.freemarker</groupId>
                <artifactId>freemarker</artifactId>
                <version>2.3.30</version>
            </dependency>
    

模板填充

  1. 然后我们在word的模板上填充上对应的参数:
    在这里插入图片描述
    上面模板中个人荣誉和工作经历是存在多个,对应了一个list对象,在此我们先不在页面上进行参数填充,而头像和个人风采需要插入图片,所以我们先默认插入一些图片进行占位和设置其大小属性;值得注意的是如果你需要像上图个人风采部分动态的展示图片的话,其图片一定要设置为四周型环绕

  2. 将word另存为xml格式:
    在这里插入图片描述
    在另存为时,提供了两种xml格式的转储,请用Word XML 文档格式进行转储。

  3. 将导出的xml文件的后缀更改为ftl,并放入项目的resources资源包的templates文件夹中
    在这里插入图片描述

list数据的遍历填充

  1. 打开该ftl文件,上面我们提到了关于个人荣誉和工作经历都是存在多条的,所以需要用list对象来存储,在ftl文件中就需要对list数据进行遍历,以下是对工作经历数据的遍历
    <#--这里的使用if标签来对list进行判空操作-->
    <#if workExperienceList?? && (workExperienceList?size > 0) >
    <#--这里是对list进行遍历循环,workExperience为每次被遍历到的对象-->
       <#list workExperienceList as workExperience>
       <#--在ftl模板中,一个w:p标签代表一个段落,这里不要直接将这份代码粘贴过去,因为你本身的格式与我不同,导出后可能会出现的格式不一的问题-->
            <w:p>
                <w:pPr>
                    <w:bidi w:val="0"/>
                    <w:jc w:val="center"/>
                    <w:rPr>
                        <w:rFonts w:hint="default" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312"
                                  w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
                        <w:sz w:val="24"/>
                        <w:szCs w:val="24"/>
                        <w:vertAlign w:val="baseline"/>
                        <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
                    </w:rPr>
                </w:pPr>
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312" w:hAnsi="仿宋_GB2312"
                                  w:eastAsia="仿宋_GB2312" w:cs="仿宋_GB2312"/>
                        <w:sz w:val="24"/>
                        <w:szCs w:val="24"/>
                        <w:vertAlign w:val="baseline"/>
                        <w:lang w:val="en-US" w:eastAsia="zh-CN"/>
                    </w:rPr>
                    <#--在w:t标签中填充值,通过time?string("yyyy-MM-dd")!,首先判断time是否为空,如果不为空则对时间进行格式转换,这里的?!其实类似于java的三目运算符 -->
                    <w:t>${(workExperience.workStartTime?string("yyyy-MM-dd"))!}~${(workExperience.workEndTime?string("yyyy-MM-dd"))!'至今'}在${workExperience.unitName!}担任${workExperience.title!},${workExperience.jobDescription!}</w:t>
                </w:r>
            </w:p>
        </#list>
    </#if>
    

插入图片

  1. 首先插入图片前我们需要知道在ftl中图片分为三部分

    • 第一部分:
      在创建模板之前因为插入了几张图片,所以你能看到占位
      在这里插入图片描述
      <#--pkg:name中填充的是图片在ftl模板中的位置,pkg:contentTyped代表了当前的标签内容的类型-->
      <pkg:part pkg:name="/word/media/image1.jpeg" pkg:contentType="image/jpeg">
             <pkg:binaryData>存放图片的base64位编码</pkg:binaryData>
        	</pkg:part>
      
    • 第二部分:
      在这里插入图片描述
      <pkg:part pkg:name="/word/_rels/document.xml.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml">
        <pkg:xmlData>
           <Relatiaonships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
               <Relationship Id="指定ID" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
                              Target="对应第一部分中pkg:name,只是去掉了/word/"/>
               
                </Relationships>
             </Relationships>   
         </pkg:xmlData>
       </pkg:part>
      
      这一部分可以说是对图片的一个申明,我们看到使用Relationship标签对图片进行了申明,这里只有三张图片(其他的非图片为了方便截图我将其隐藏了)是因为我的模板中虽然展示了四张图片,但是因为有两张图片相同,所以这里就只有三个声明,通过Target属性指向图片所在的路径,而Id则必须唯一它是连接连接第三部分的重要参数。
    • 第三部分:
      该部分的xml比较长,我就只截重要的部分说明
      在这里插入图片描述
      以上就是对图片插入的说明,如果说你只有一张图片插入,那直接在第一部分中填充入你图片的Base64位编码就能实现图片的插入,而当你需要动态的插入图片就必须要通过循环来指定图片
  2. 动态插入图片

    • 首先我将图片都封装为一个实体类,然后多张图片对应一个list集合
      import lombok.Data;
      /**
       * @Author HomeWellGo
       * @Date 2020/10/18 20:10
       * @Description 图片信息类
       */
      @Data
      public class ImgInfo {
          //图片的base64位编码
          private String imgBaseCode;
          //图片的路径
          private String imgUrl;
          //序号
          private Integer imgIndex;
      }
      
    • 填充图片的base64位编码
      <#if personalStyle?? && (personalStyle?size > 0) >
          <#list personalStyle as style>
               <pkg:part pkg:name="/word/media/image${style.imgIndex}.jpeg" pkg:contentType="image/jpeg">
                  <pkg:binaryData>
                      ${(style.imgBaseCode)!''}
                  </pkg:binaryData>
              </pkg:part>
          </#list>
      </#if>
      
    • 声明图片
      <#if personalStyle?? && (personalStyle?size > 0) >
       <#list personalStyle as style>
           <Relationship Id="rId${style.imgIndex}jpg" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
                         Target="media/image${style.imgIndex}.jpeg"/>
           <Relationship Id="rId${style.imgIndex}jpg" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
                         Target="media/image${style.imgIndex}.jpeg"/>
           <Relationship Id="rId${style.imgIndex}jpg" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
                         Target="media/image${style.imgIndex}.jpeg"/>
        </#list>
      </#if>
      
    • 指定图片
      在这里插入图片描述

java代码

  1. 代码部分
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import freemarker.template.TemplateException;
    import freemarker.template.Version;
    import sun.misc.BASE64Encoder;
    
    import java.io.*;
    
    /**
     * @author HomeWellGo
     * @createTime 2021-09-01 09:47
     * @Description
     */
    public class ExportWordUtils {
    
    	/**
    	 * 根据ftl模板导出word文件
    	 * @param t 实体类
    	 * @param templateName 模板文件名
    	 * @param path 导出的word文件路径
    	 * */
    	public static  <T> void exportWordForFreemarker(T t,String templateName,String path){
    		//Configuration 用于读取ftl文件
    		Configuration configuration = new Configuration(new Version("2.3.0"));
    
    		configuration.setDefaultEncoding("utf-8");
    
    		configuration.setClassForTemplateLoading(ExportWordUtils.class, File.separator+"templates");
    
    		Writer out=null;
    
    		try {
    			//输出文档路径及名称
    			File outFile = new File(path);
    			//以utf-8的编码读取ftl文件
    			Template template = configuration.getTemplate(File.separator+templateName, "utf-8");
    
    			out= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
    
    			template.process(t, out);
    
    		} catch (IOException e) { e.printStackTrace();
    
    		}catch (TemplateException e1){  e1.printStackTrace();
    
    		}finally {
    
    			try {
    
    				if(out!=null) out.close();
    
    			} catch (IOException e) {   e.printStackTrace();  }
    
    		}
    
    	}
    
    	/**
    	 * 获取图片的Base64位编码
    	 * */
    	public  static String getImgBase64(String path){
    
    		InputStream in = null;
    
    		byte[] data = null;
    
    		try{
    
    			in = new FileInputStream(path);
    
    			data = new byte[in.available()];
    
    			in.read(data);
    
    			in.close();
    
    		}catch (IOException e){   e.printStackTrace();
    
    		}finally {
    
    			try {
    
    				if (in!=null) in.close();
    
    			} catch (IOException e) {  e.printStackTrace();  }
    
    		}
    		//对字节数组Base64编码
    		BASE64Encoder encoder = new BASE64Encoder();
    
    		return encoder.encode(data);
    
    	}
    
    }
    
    
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值