java如何用Freemarker导出word

前言:

在项目中应该会经常遇到导出word需求,Java中有5种方式导出word:

所用技术 优点 缺点
Jacob 功能强大 代码量大,设置样式繁琐;需要windows平台支持,无法跨平台
Apache POI 读写excel功能强大、操作简单 一般只用它读取word,能够创建简单的word,不能设置样式,功能太少
Java2word 功能强大,操作简单 能满足一般要求,不支持07格式,国人开发的,参考资料较多,需要windows平台支持
iText 功能全,能满足一般要求 不能直接生成或操作doc文档,只能生成rtf格式的文档,rtf也可以用word打开
JSP 操作简单,代码量少 能把当前页面导出简单的word,不能设置样式,美观性差,无法操作word
Freemarker 代码量少,样式、内容容易控制,打印不变形,完全符合office标准 需要提前设计好word模板,把需要替换的地方用特殊标记标出来

具体选择哪种方式实现Java导出word,要根据自己的需求和实际情况灵活选择,今天这篇文章主要讲解下java怎么结合freemarker导出word的,我选择freemarker主要因为相对于poi导出word,它更灵活。

正文:

Freemarker导出word的思路是,先把word文件中插入特殊的字符串占位符,另存为xml,然后将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板,编码调用FreeMarker实现文本替换并输出Doc。

一、把插入占位符word文件另存为xml

网上很多说不建议用wps,但是我用的wps发现也没有太大的影响,这是我word制作的表格。

java如何用Freemarker导出word_第1张图片

 

然后另存为Word XML文档,把生成的xml放到WEB-INF目录下,我在这个目录下又建了word目录,最后我放到word目录下啦

java如何用Freemarker导出word_第2张图片

java如何用Freemarker导出word_第3张图片

 

 直接打开xml会发现,格式很错乱,代码挤到一块了,如下图

java如何用Freemarker导出word_第4张图片

我们可以通过idea格式化代码的快捷键,把代码格式化下,方便阅读

Ctrl+Alt+L

 

java如何用Freemarker导出word_第5张图片

 二、引入Freemarker的maven依赖和lombok的依赖


	org.freemarker
	freemarker
	2.3.20


	org.projectlombok
	lombok
	1.16.18

三、编写模板展示的类和导出的工具类以及测试类代码

 User类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private String sex;
    private String age;
    private String phone;
    private String email;
}

导出的工具类:

public class exportWord {

	
	public void export(Map map) {
		try {
			
			Configuration configuration = new Configuration();
			configuration.setDefaultEncoding("UTF-8");
			//模板文件配置路径
			configuration.setDirectoryForTemplateLoading(new File("F:\\dao\\exportWord\\src\\main\\webapp\\WEB-INF\\word"));
			configuration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
			//文件输出路径,文件名
			File outFile = new File("E:\\测试模板.doc");
			//扫描模板路径下 模板文件
			Template template = configuration.getTemplate("测试模板.xml", "UTF-8");
			Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"), 10240);
            template.process(map, out);
            out.flush();
            out.close();
		
		System.out.println("导出完成");
		
		
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 测试类:

public class Test {

	public static void main(String[] args) {
		exportWord ew = new exportWord();
		Map dataMap = new HashMap();
		List list = new ArrayList();
		User user1 = new User("ada", "男", "18", "10000000", "[email protected]");
		User user2 = new User("ada", "男", "18", "10000000", "[email protected]");
		User user3 = new User("ada", "男", "18", "10000000", "[email protected]");
		list.add(user1);
		list.add(user2);
		list.add(user3);
		dataMap.put("userList", list);
		ew.export(dataMap);
	}
}

四、如果数据是集合,需要遍历展示的

 找到 xml文件中 标签 用 <#list map中键值 as 别名> 标签包裹在内即可

java如何用Freemarker导出word_第6张图片

java如何用Freemarker导出word_第7张图片

五、启动测试类,看导出效果

java如何用Freemarker导出word_第8张图片

六、 常见bug

顺利的话,你应该会出现如下图的bug,你只要格式化代码啦,按照这个错误报的行数,去看下,就知道为什么了,原因是word转xml的时候解析错误啦,需要去手动去调节下

freemarker.core.ParseException: Parsing error in template "测试模板.xml" in line 320, column 48:
Encountered "<", but was expecting one of:
    
    
    "false"
    "true"
    
    
    "."
    "+"
    "-"
    "!"
    "["
    "("
    "{"
    
	at freemarker.core.FMParser.generateParseException(FMParser.java:4672)
	at freemarker.core.FMParser.jj_consume_token(FMParser.java:4543)
	at freemarker.core.FMParser.UnaryExpression(FMParser.java:340)
	at freemarker.core.FMParser.MultiplicativeExpression(FMParser.java:452)
	at freemarker.core.FMParser.AdditiveExpression(FMParser.java:402)
	at freemarker.core.FMParser.RangeExpression(FMParser.java:573)
	at freemarker.core.FMParser.RelationalExpression(FMParser.java:528)
	at freemarker.core.FMParser.EqualityExpression(FMParser.java:493)
	at freemarker.core.FMParser.AndExpression(FMParser.java:602)
	at freemarker.core.FMParser.OrExpression(FMParser.java:625)
	at freemarker.core.FMParser.Expression(FMParser.java:238)
	at freemarker.core.FMParser.StringOutput(FMParser.java:1076)
	at freemarker.core.FMParser.Content(FMParser.java:2550)
	at freemarker.core.FMParser.OptionalBlock(FMParser.java:2761)
	at freemarker.core.FMParser.Root(FMParser.java:2933)
	at freemarker.template.Template.(Template.java:193)
	at freemarker.cache.TemplateCache.loadTemplate(TemplateCache.java:419)
	at freemarker.cache.TemplateCache.getTemplate(TemplateCache.java:330)
	at freemarker.cache.TemplateCache.getTemplate(TemplateCache.java:205)
	at freemarker.template.Configuration.getTemplate(Configuration.java:740)
	at freemarker.template.Configuration.getTemplate(Configuration.java:681)
	at com.util.exportWord.export(exportWord.java:25)
	at com.util.test.Test.main(Test.java:54)

java如何用Freemarker导出word_第9张图片

 我们提前写好的占位符有时候转完后会错误,被拆解了,只要把多余的部分删除就可以啦,我们看下标签是一个标签,把多余的删掉即可,删完后如下。

                         
                                
                                    
                                
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                    
                                        
                                            
                                            
                                            
                                            
                                        
                                        ${user.name}
                                    
                                
                            

总结:

freemarker导出word还是很方便的,转化后的xml咋看很复杂,其实认真看下,规律还是很明显的,改动几个保存下,你就试出作用啦。

我是阿达,一名喜欢分享知识的程序员,时不时的也会荒腔走板的聊一聊电影、电视剧、音乐、漫画,这里已经有373小伙伴在等你们啦,感兴趣的就赶紧来点击关注我把,哪里有不明白或有不同观点的地方欢迎留言。

你可能感兴趣的:(开发问题)