【技能储备】关于自学FreeMarker导出word的那些事

【新技能Get】关于自学FreeMarker导出word的那些事

 

 

       最近,项目中需要做一个导出word文件的功能。

这个,简单!原来在公司就用过一个叫什么什么的软件,网上查找了好久,突然发现是要收费的!!!心如死灰的时候,发现大家都在推荐FreeMarker来做word导出。

找了几篇大神写的文章,对着敲代码,试了一下,发现果真是好用,基本可以实现导出简单字段,动态行的表格什么什么的。

为了巩固一下记忆(看自己的写的习惯一点),决定记录一下学习过程。下面开始上代码,走起!

 

一、前期准备

1、软件环境:Sublime Text2(替Sublime吹嘘一下,这款文本编辑工具功能真的很强大)、Eclipse

2、需要下载的jar包:freemarker2.3.20.jar  (也可以去官网看看,我是在站内下载的2.3.20版本。官网地址:http://freemarker.org/)

二、懒得起名字了

代码:

import java.io.BufferedWriter; 

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException; 

import java.io.FileOutputStream; 

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStreamWriter; 

import java.io.Writer; 

import java.util.ArrayList; 

import java.util.HashMap; 

import java.util.List; 

import java.util.Map; 

 

import freemarker.template.Configuration; 

import freemarker.template.Template; 

import freemarker.template.TemplateException; 

 

import sun.misc.BASE64Encoder;

 

/**

 * <P>Title:关于使用FreeMarker导出Word的测试 </p>

 * <P>Description: </p>

 * @author

 * @date

 */

public class Test { 

     

    private Configurationconfiguration = null

     

    public Test(){ 

        configuration = newConfiguration(); 

        configuration.setDefaultEncoding("UTF-8"); 

    } 

     

    public staticvoid main(String[] args) { 

    Test test = new Test(); 

        test.createWord(); 

    } 

     

    public void createWord(){ 

        Map<String,Object>dataMap=new HashMap<String,Object>(); 

        getData(dataMap); 

        configuration.setClassForTemplateLoading(this.getClass(),"/com");  //FTL文件所存在的位置 

        Template t=null

        try

            t = configuration.getTemplate("简历模板.ftl");//文件名 

        } catch (IOExceptione) { 

            e.printStackTrace(); 

        } 

        File outFile = newFile("C:/Users/zpx/Desktop/"+Math.random()*10000+".doc"); 

        Writer out = null

        try

            out = new BufferedWriter(newOutputStreamWriter(new FileOutputStream(outFile))); 

        } catch (FileNotFoundExceptione1) { 

            e1.printStackTrace(); 

        } 

          

        try

            t.process(dataMap,out); 

        } catch (TemplateExceptione) { 

            e.printStackTrace(); 

        } catch (IOExceptione) { 

            e.printStackTrace(); 

        } 

    } 

 

    private void getData(Map<String,Object> dataMap) { 

        dataMap.put("name","张三"); 

        dataMap.put("birthday","1993-07-27"); 

        dataMap.put("telphone","1123123123"); 

        dataMap.put("sex","女");

        dataMap.put("email","sejfis23@154.com");

        dataMap.put("img",getImageStr());

        //dataMap.put("check_box",""==null?"■":"□");

    //Word模板中表格的遍历循环

        List<Userlist> list= new ArrayList<Userlist>(); 

        for (int i= 0; i < 10; i++) { 

          Userlist userlist = new Userlist();

          userlist.setEmpolyeeid(i+""); 

          userlist.setEmpolyeename("内容"+i);

          userlist.setLast_update_by("李四");

          userlist.setLast_update_date("2016-09-15");

            list.add(userlist); 

        } 

         

         

        dataMap.put("list",list); 

}

//对图片进行base64编码

    private String getImageStr(){

        String imgFile ="E:/Photo圖片/img.jpg";

        InputStream in =null;

        byte[] data= null;

        try {

            in = new FileInputStream(imgFile);

            data = new byte[in.available()];

            in.read(data);

            in.close();

        } catch (IOExceptione) {

            e.printStackTrace();

        }

        BASE64Encoder encoder= new BASE64Encoder();

        return encoder.encode(data);

    }

}

建一个实体类用户列表循环

public class Userlist {

  

      publicString empolyeeid;

  

      publicString empolyeename;

  

      publicString last_update_by;

  

      publicString last_update_date;

 

      publicString getEmpolyeeid() {

         return empolyeeid;

      }

 

      publicvoid setEmpolyeeid(String empolyeeid) {

         this.empolyeeid = empolyeeid;

      }

  

      publicString getEmpolyeename() {

         return empolyeename;

      }

  

      publicvoid setEmpolyeename(String empolyeename) {

         this.empolyeename = empolyeename;

      }

 

      publicString getLast_update_by() {

         return last_update_by;

      }

 

      publicvoid setLast_update_by(String last_update_by) {

         this.last_update_by = last_update_by;

      }

 

      publicString getLast_update_date() {

         returnlast_update_date;

      }

 

      publicvoid setLast_update_date(String last_update_date) {

         this.last_update_date= last_update_date;

      }

}

 

三、模板的制作

怎么说,就是首先做一个word模板(.doc后缀),然后另存为Word2003 XML文档(.xml),这时候就需要用到上面提到的Sublime Test打开另存为的.xml模板了。

第一次打开开到源码的时候都要疯了。(图1)


用Sublime Text的Indent xml插件,可以把代码格式化。

按照你的需求,把你需要替换的标签替换

(图2)

如姓名后面这块你要导出进数据,这时候就需要你去模板.xml文件中相同位置,添加上${name},然后通过程序里面操作流,替换掉这个${name}标签。

 (图3)

到这里,我觉得基本就可以满足一大半的word导出任务了。

然后图片的话,

(图4)

就是红框中的${img}位置本来是有一段好长好长的图片数据流的,用代码中的方法就可以和字段一样替换掉

 

下面就是重中之重,list列表的导入了。

上面的”模板.xml”文件,这时候需要改变后缀为”模板.ftl”,然后还是用Sublime打开,在需要循环展示的代码段外套加上<#list listas userlist></#list>

,标签中的list是代码中拼装的列表展示数据的集合名称,userlist是实体类的名称,都是可以自定义的。

  (图4)

   差不多就是这样,欢迎大家指教!

 

参考资料:http://blog.csdn.net/zhanwentao2/article/details/7255432

      http://blog.csdn.net/cheung1021/article/details/6146239

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Apache POI 和 FreeMarker 来实现 Word 导出。具体步骤如下: 1. 引入依赖: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.31</version> </dependency> ``` 2. 编写模板文件,例如 `template.ftl`: ```xml <?xml version="1.0" encoding="UTF-8"?> <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"> <w:body> <w:p> <w:r> <w:t>${title}</w:t> </w:r> </w:p> <w:p> <w:r> <w:t>${content}</w:t> </w:r> </w:p> </w:body> </w:document> ``` 3. 编写 Java 代码: ```java import freemarker.template.Configuration; import freemarker.template.Template; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import java.io.*; import java.util.HashMap; import java.util.Map; public class WordExportUtil { public static void export(Map<String, Object> dataMap, String templatePath, String outputPath) throws Exception { // 1. 创建 Configuration 对象 Configuration configuration = new Configuration(Configuration.VERSION_2_3_31); configuration.setDefaultEncoding("UTF-8"); // 2. 加载模板文件 Template template = configuration.getTemplate(templatePath); // 3. 创建 Word 文档对象 XWPFDocument document = new XWPFDocument(); // 4. 填充数据到 Word 文档中 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8"); template.process(dataMap, outputStreamWriter); outputStreamWriter.flush(); ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) { XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); run.setText(line); } // 5. 输出 Word 文档 FileOutputStream fileOutputStream = new FileOutputStream(outputPath); document.write(fileOutputStream); fileOutputStream.close(); } } ``` 其中,`dataMap` 是模板中需要填充的数据,`templatePath` 是模板文件的路径,`outputPath` 是输出文件的路径。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值