告别XML模板的繁琐!Word文档导出,easy!
word模板导出
最近项目中有个功能,导出月报,发现同事使用了docx格式模板,感觉比之前转成xml的简单多了,这边记录下使用方法。
xml方式导出word,模板太复杂了
资料
poi-tl
一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性
官方文档地址 ,还是很详细的,有多个场景的示例
如何使用
- 必要的标签知识
- 文字
{{var}}
- 数据模型:
String :文本 TextRenderData :有样式的文本 HyperlinkTextRenderData :超链接和锚点文本 Object :调用 toString() 方法转化为文本
-
图片
图片标签以@开始:{{@var}}
- 数据模型:
String :图片url或者本地路径,默认使用图片自身尺寸 ByteArrayPictureRenderData FilePictureRenderData UrlPictureRenderData
-
表格行循环
配合插件-LoopRowTableRenderPolicy
-
图标
- 多系列图表指的是条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、散点图等
数据模型ChartMultiSeriesRenderData
- 单系列图表指的是饼图(3D饼图)、圆环图等。
- 引入依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version>
</dependency>
- 简单的demo
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import com.deepoove.poi.data.Charts;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.policy.RenderPolicy;
import org.springframework.stereotype.Service;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @program: learn_summary
* @description:
* @author: zzg@xnj
* @create: 2025-03-10 15:58
**/
@Service
public class WordService {
public void makeWord(){
HashMap<String, Object> dates = new HashMap<>();
//字符串
String wenzi="这个是文字";
dates.put("wenzi", wenzi);
//单个图片
// dates.put("pic", Pictures.ofUrl( "https://img.tukuppt.com/ad_preview/00/10/23/5c992ae114e20.jpg!/fw/980").size(200, 200).create());
dates.put("pic", "https://img.tukuppt.com/ad_preview/00/10/23/5c992ae114e20.jpg!/fw/980");
//多个图片
ArrayList<String> urls = new ArrayList<>();
urls.add("https://pic.52112.com/2020/04/13/JPG-200413_328/gCaPae4zjp_small.jpg");
urls.add("https://img.tukuppt.com/ad_preview/00/10/23/5c992ae114e20.jpg!/fw/980");
dates.put("pictures", createPictureList("picture",urls,200,200));
//插件使用
HashMap<String, RenderPolicy> policyHashMap = new HashMap<>();
//表格 使用LoopRowTableRenderPolicy
LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy();
ArrayList<HashMap<String, String>> tables = new ArrayList<>();
HashMap<String, String> map = new HashMap<>();
map.put("name", "大豆");
map.put("count", "18");
map.put("price", "100");
tables.add(map);
map = new HashMap<>();
map.put("name", "黄豆");
map.put("count", "38");
map.put("price", "110");
tables.add(map);
dates.put("goods",tables);
policyHashMap.put("goods", loopRowTableRenderPolicy);
//图表
ChartMultiSeriesRenderData chart = Charts
.ofMultiSeries("商品售卖情况", new String[] { "大豆", "黄豆" })
.addSeries("北京", new Double[] { 15.0, 6.0 })
.addSeries("上海", new Double[] { 223.0, 119.0 })
.create();
dates.put("barChart", chart);
try {
WordService.createWordOfList("E:\\data\\text2.doc",new FileInputStream("E:\\data\\word_template.docx"),dates,policyHashMap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private List<Map<String, PictureRenderData>> createPictureList(String mapKey,List<String> urls,int width, int height) {
List<Map<String, PictureRenderData>> list = new ArrayList<>();
for (String url : urls) {
list.add(createPictureMap(mapKey,url, width, height));
}
return list;
}
private Map<String, PictureRenderData> createPictureMap(String mapKey,String imgUrl, int width, int height) {
Map<String, PictureRenderData> map = new HashMap<>();
map.put(mapKey, Pictures.ofUrl( imgUrl).size(width, height).create());
return map;
}
/**
* 创建word文档
* @param outputPath 输出路径
* @param templatePath 模板路径
* @param data 数据
* @param placeholderPolicy 占位标签使用插件
* @return
*/
public static boolean createWordOfList(String outputPath, InputStream templatePath, Map<String, Object> data, Map<String, RenderPolicy> placeholderPolicy) {
try {
FileOutputStream out = new FileOutputStream(outputPath);
BufferedOutputStream bos = new BufferedOutputStream(out);
// 使用Configure.ConfigureBuilder而不是Builder
ConfigureBuilder builder = Configure.builder();
// 动态绑定插件
if (placeholderPolicy!=null) {
for (Map.Entry<String, RenderPolicy> entry : placeholderPolicy.entrySet()) {
builder.bind(entry.getKey(), entry.getValue());
}
}
Configure configure = builder.build();
// 读取模板并渲染数据
XWPFTemplate template = XWPFTemplate.compile(templatePath, configure).render(data);
try {
template.write(bos);
template.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
out.flush();
bos.flush();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}
- 模板