FreeMarker 通过ftl 导出word

例子    里面  有3个  普通的  带图片的   带表格的

     链接:https://pan.baidu.com/s/1oH1Qoa9GSyTAeUt6eUN-KQ      提取码:kuol

 

1:需要的jar

freemarker.jar    https://pan.baidu.com/s/105Ma9aVPha8YvlBkuuO4bA   提取码:b9k8

或者

<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20</version>
</dependency>

2:Java 代码

******************************开始****************************************

package word.moban1;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
/**
* 通过模板下载word word 转成 ftl
* @author cheng
* freemarker.jar
* <dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
*
*/
public class mobandachuWord {
public static String exportWord(Map<String,Object> dataMap, String templName, String fileName) throws ParseException {
String pathName = fileName;
String appPath = mobandachuWord.class.getResource("").toString() +templName+ ".ftl";
appPath = appPath.replace("file:/", "");
//path = path.replace("/", "//");
appPath = appPath.substring(0, appPath.lastIndexOf("/"))+"/";
System.out.println("路径:"+appPath);
try {
SimpleDateFormat sdfNow = new SimpleDateFormat("yyyy-MM-dd");
String nowDateStr = sdfNow.format(new Date().getTime());
Date nowDate = sdfNow.parse(nowDateStr);
//Configuration 用于读取ftl文件
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setDirectoryForTemplateLoading(new File(appPath));
Template template = configuration.getTemplate(templName + ".ftl", "utf-8");
SimpleDateFormat sdfNow1 = new SimpleDateFormat("yyyyMMddHHmmss");
pathName = fileName +sdfNow1.format(new Date())+".doc";
String download_path = appPath;
// 输出文档路径及名称
if (!(new File(download_path).isDirectory())) {
new File(download_path).mkdirs();
}
File outFile = new File(download_path + pathName);
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 102400);
template.process(dataMap, out);
} catch (Exception e) {
e.printStackTrace();
}
return pathName;
}

public static void main(String[] args) throws Exception {
Map<String,Object> dataMap =new HashMap();
dataMap.put("name", "测试数据导出");
dataMap.put("title1", "测试数标题");
dataMap.put("text1", "测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出测试数据导出");

//构造数据 , 模板名称 , 导出word名称
exportWord(dataMap,"123","测试模板导出");
System.out.println("导出成功!!!!!!!!路径:");
}
}

******************************结束****************************************

3:模板设置 

1:创建word,word的样式直接自己编辑

 

 

 2:将word 内容更改为  占位符   ${ }  {}内写变量  ,word的样式不变

 

 另存为 xml文件

 

 

 

 

 

 https://tool.ip138.com/xml/

 

 

 

 

 

 

 

 

将ftl文件  和  Java  类   放在同一个文件夹下     执行Java  main方法    ,生成文件的路径   打印再控制台了

通过ftl  导出word   主要的工作是 ftl 模板的设计, 大概的步骤 

先设计word文档包括样式---将文档内容设置成变量${}---将文档另存为xml格式---格式化xml文档---

修改 xml文档的内容----将xml 文档更改为ftl文件

 修改xml文档  1: 要注意文档中  ${} 的地方是否正确 ,有时候 $ 和{}会分开生成,手动合成一个就行  . 2:可以 手动添加   if 标签和 list 标签  来控制 word内容是否展示循环展示内容

<#if str == "success">

${name} 

</#if>

<#list userList as user>
    <li>
        ${user.name}
    </li>
</#list>

 

<#if str == "success">    --------控制标签是否显示

<w:p>                                       
</w:p>

</#if>

<#list userList as user>   -----------控制标签循环展示
    <li>
     <w:p>
     </w:p>
    </li>
</#list>

 

3:图片的设置   

  设计word 的时候 插入一个图片  ,   将word 转义为 xml的时候  会生成  <pkg:binaryData> 标签  ,

<pkg:binaryData> 的内容是图片转义的字很长的一段字符串,将字符串设置成变量,通过java代码变量  将字符串传进

${imgpath}   imgpath 是Java 将 图片转义的字符串

<pkg:part pkg:name="/word/media/image1.jpeg" pkg:contentType="image/jpeg">
<pkg:binaryData>${imgpath}</pkg:binaryData>
</pkg:part>

 

//如下代码 将图片转成字符串 

InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(appPath);//  appPath   D:/123.jpg
data = new byte[in.available()];
in.read(data);
in.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String imgpath = Base64.getEncoder().encodeToString(data);

dataMap.put("imgpath", imgpath);

 4: 表格设置  

设计word的时候   如下图  设计标题+ 需要循环的一列   两行就可以  生成ftl 后将list 循环加在第2行上

 导出结果例子

 

 

posted @ 2023-03-12 11:49  雪儿蛇王  阅读(695)  评论(0编辑  收藏  举报