目录结构
首先给maven添加velocity依赖
<velocity.version>1.7</velocity.version> 版本声明
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>${velocity.version}</version>
</dependency>
创建word文本模板,建议多写几行,这样容易在后期的xml中找到规律。然后另存为xml格式。
将重复类型的tr行删除,留一个模板就行,表头可以自定义,标题自定义为一个变量。格式化xml文件,使用xml在线格式化
接着把表名.xml文件放在resource/templates/目录下
创建People 类
public class People {
private String name;
private Integer age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
创建ExportWord类
package test;/**
* @author simba@onlying.cn
* @date 2020/3/20 9:55
*/
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* @Author: wangchen
* @Date: 12313
*/
public class ExportWord {
static{
Properties p = new Properties();
// 设置输入输出编码类型。和这次说的解决的问题无关
p.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
p.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
//文件缓存
p.setProperty(Velocity.FILE_RESOURCE_LOADER_CACHE, "false");
// 这里加载类路径里的模板而不是文件系统路径里的模板
p.setProperty("file.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(p);
}
public static Template getTemplateInstance(String templtePath){
Template template = Velocity.getTemplate(templtePath);
return template;
}
public static void main(String[] args){
List<People> peopleList = new ArrayList<>();
for(int i=0;i<3;i++){
People people = new People();
people.setName("王"+i);
people.setAge(i*10);
people.setAddress("中国"+i);
peopleList.add(people);
}
Template template = getTemplateInstance("templates/.vm");
try {
Writer writer = new FileWriter(new File("E:/test.doc"));
Context con = new VelocityContext();
System.out.println(peopleList);
con.put("peopleList", peopleList);
con.put("wordName", "导出人员统计表"); //word的标题
template.merge(con, writer);
writer.flush();
writer.close();
System.out.println("over");
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
注意
注意:①如果例子中的右值是null, 则左值不会被赋值,也就是说会保留以前的值。
②velocity模板中未被定义的变量将被认为是一个字符串。例如:
#set($foo = "gibbous")
$moon = $foo
输出结果为:
$moon = gibbous
③velocity模板中不会将reference解释为对象的实例变量。例如:$foo.Name将被解释为Foo对象的getName()方法,而不是Foo对象的Name实例变量。例如:
$foo.getBar() 等同于$foo.Bar ;
$data.getUser("jon") 等同于$data.User("jon") ;
data.getRequest().getServerName() 等同于
$data.Request.ServerName等同于${data.Request.ServerName}
出现的错误
12:04:24.120 [main] ERROR org.apache.velocity - ResourceManager.getResource() parse exception
org.apache.velocity.exception.ParseErrorException: Encountered "data" at templates/test.xml[line 936, column 17]
Was expecting one of:
"[" ...
"{" ...
"(" ...
<WHITESPACE> ...
<STRING_LITERAL> ...
"true" ...
"false" ...
<INTEGER_LITERAL> ...
<FLOATING_POINT_LITERAL> ...
<IDENTIFIER> ...
"{" ...
<WHITESPACE> ...
at org.apache.velocity.Template.process(Template.java:151) ~[velocity-1.7.jar:1.7]
at org.apache.velocity.runtime.resource.ResourceManagerImpl.loadResource(ResourceManagerImpl.java:437) ~[velocity-1.7.jar:1.7]
at org.apache.velocity.runtime.resource.ResourceManagerImpl.getResource(ResourceManagerImpl.java:352) [velocity-1.7.jar:1.7]
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1533) [velocity-1.7.jar:1.7]
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1514) [velocity-1.7.jar:1.7]
at org.apache.velocity.runtime.RuntimeSingleton.getTemplate(RuntimeSingleton.java:299) [velocity-1.7.jar:1.7]
at org.apache.velocity.app.Velocity.getTemplate(Velocity.java:358) [velocity-1.7.jar:1.7]
at com.meinergy.chargingpile.common.util.ExportWordUtils.getTemplateInstance(ExportWordUtils.java:37) [classes/:?]
at com.meinergy.chargingpile.common.util.ExportWordUtils.getExportWord(ExportWordUtils.java:43) [classes/:?]
at com.meinergy.chargingpile.web.VelocityTest.testGeneratorWord(VelocityTest.java:38) [test-classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_211]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_211]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_211]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_211]
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:?]
解决方案
仔细检查一下自己是否在模板中对象写错了,少写了$符号,data --> $data
补充:
给word导入图片
只有把图片的二进制内容修改为变量,
修改后:
这个是索引,与图片的内容相匹配。
图片的处理内容。
BASE64Encoder encoder = new BASE64Encoder();
File file = new File("E:\\images-file-dir\\2020-04\\aa.png");
byte[] data = null;
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
byte[] buffer = new byte[1024];
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
data = baos.toByteArray();
fis.close();
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
//对字节数组Base64编码
String image = encoder.encode(data);