使用java按模板导出word,有很多方案,比如freemarker,jacob,openoffice,aspose(非开源收费,需破解版)apache poi等,其中比较常用的是freemarker导出,但是必须把预先做好的word模板转换成xml格式(ooxml)并且要到xml中找到需要循环的位置,插入freemarker的循环语法表达式,每次模板一变动都要重新做模板,比较不友好,其次就是poi,这个开源框架对excel支持多,对word支持少一点,文档不充分,因为缺少文档,使用起来很困难,easypoi是建立在poi的基础之上,弥补了poi的不足,因为依赖poi,同样是对excel支持多,word支持少,那么怎么使用easypoi来循环模板里的行列导出呢,根据官方的文档,在模板里插入形如{{$fe: list t.id t.name t.pwd}}即可实现,插入#fe支持横向循环,可是我使用#fe导出并没有生效,于是查看源码发现根本没有实现#fe,没办法,只有把easypoi的源码pull下来,自己修改实现。
模板如下:
导出效果如下:
测试代码如下:
package test;
import cn.afterturn.easypoi.word.WordExportUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author ww
* @date 2022-05-20 0:08
*/
public class Test {
public static void main(String[] args) {
Map<String,Object> params = new HashMap<>();
params.put("companyName","卢佳玉电站222");
params.put("serialNo","20220504011");
params.put("startTime","2022-05-19 19:30:00");
params.put("endTime","2022-05-20 19:30:00");
params.put("signer","吴晓丽");
params.put("signTime","2022-05-18 00:30:00");
params.put("workleaName","张三");
params.put("workappName","张四");
params.put("teamName","张wu");
params.put("teamMemberLabel","li1,li2,li3");
params.put("workplaceDevice","测试任务和设备名称");
params.put("workTask","测试任务");
params.put("dutyName","李波");
List<Map<String,Object>> workSecs = new ArrayList<Map<String,Object>>();
Map<String,Object> workSec1 = new HashMap<>();
workSec1.put("index",1);
workSec1.put("secMeasure","措施1");
workSec1.put("execCondition","已执行");
workSec1.put("confirmExec","已确认");
workSecs.add(workSec1);
Map<String,Object> workSec2 = new HashMap<>();
workSec2.put("index",2);
workSec2.put("secMeasure","措施2");
workSec2.put("execCondition","已执行");
workSec2.put("confirmExec","已确认");
workSecs.add(workSec2);
params.put("workSecs",workSecs);
List<Map<String,Object>> perSecs = new ArrayList<Map<String,Object>>();
Map<String,Object> perSec1 = new HashMap<>();
perSec1.put("index",1);
perSec1.put("secMeasure","人员措施1");
perSec1.put("execCondition","已执行");
perSecs.add(perSec1);
Map<String,Object> perSec2 = new HashMap<>();
perSec2.put("index",2);
perSec2.put("secMeasure","人员措施2");
perSec2.put("execCondition","已执行");
perSecs.add(perSec2);
params.put("perSecs",perSecs);
List<Map<String,Object>> teamMems = new ArrayList<Map<String,Object>>();
Map<String,Object> teamMem1 = new HashMap<>();
teamMem1.put("mem","陕小军");
teamMem1.put("title","告知 ");
teamMem1.put("notify","已通知");
teamMems.add(teamMem1);
Map<String,Object> teamMem2 = new HashMap<>();
teamMem2.put("mem","郭晓东");
teamMem2.put("title","告知 ");
teamMem2.put("notify","已通知 ");
teamMems.add(teamMem2);
Map<String,Object> teamMem3 = new HashMap<>();
teamMem3.put("mem","郭睿洪");
teamMem3.put("title","告知");
teamMem3.put("notify","已通知");
teamMems.add(teamMem3);
Map<String,Object> teamMem4 = new HashMap<>();
teamMem4.put("mem","郭睿洪");
teamMem4.put("title","告知");
teamMem4.put("notify","已通知");
teamMems.add(teamMem4);
Map<String,Object> teamMem5 = new HashMap<>();
teamMem5.put("mem","郭睿洪");
teamMem5.put("title","告知");
teamMem5.put("notify","已通知");
teamMems.add(teamMem5);
/*Map<String,Object> teamMem6 = new HashMap<>();
teamMem6.put("mem","郭睿洪");
teamMem6.put("title","告知");
teamMem6.put("notify","已通知");
teamMems.add(teamMem6);
Map<String,Object> teamMem7 = new HashMap<>();
teamMem7.put("mem","郭睿洪");
teamMem7.put("title","告知");
teamMem7.put("notify","已通知");
teamMems.add(teamMem7);*/
params.put("teamMems",teamMems);
exportWord2("d:/test/t1_A4.docx","D:/test","aaa.docx",params);
}
public static void exportWord2(String templatePath, String temDir, String fileName, Map<String, Object> params) {
/* Assert.notNull(templatePath,"模板路径不能为空");
Assert.notNull(temDir,"临时文件路径不能为空");
Assert.notNull(fileName,"导出文件名不能为空");
Assert.isTrue(fileName.endsWith(".docx"),"word导出请使用docx格式");*/
if (!temDir.endsWith("/")){
temDir = temDir + File.separator;
}
File dir = new File(temDir);
if (!dir.exists()) {
dir.mkdirs();
}
try {
XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
String tmpPath = temDir + fileName;
FileOutputStream fos = new FileOutputStream(tmpPath);
doc.write(fos);
fos.flush();
// 设置强制下载不打开
// 设置文件名
//doc.write(out);
//out.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
//delFileWord(temDir,fileName);//这一步看具体需求,要不要删
}
}
}
如果有不足之处,欢迎大家共同讨论,email:395263841@qq.com