poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档。
poi-tl 基于 Microsoft Word 模板和 Data 生成新的 Word 文档,是 Java 中最好的 Word 模板引擎,也可能是你使用 Java 处理 Word 最中意的伙伴。
poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性。
最新文档地址 —— 点我前往
一、导入pom依赖
<dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.12.0</version> </dependency>
二、编写对应模版
我们这里需要双模版
主模版
内嵌子模版
三、编写主、子实体类
主实体类
import com.deepoove.poi.data.DocxRenderData; import com.deepoove.poi.data.NumberingRenderData; import com.deepoove.poi.data.PictureRenderData; import lombok.Data; /** * @author DBC */ @Data public class ResumeData { private DocxRenderData experience; private String test1; private String test2; private String test3; private String test4; }
子实体类
import com.deepoove.poi.data.NumberingRenderData; import com.deepoove.poi.data.PictureRenderData; import lombok.Data; import java.util.List; import java.util.Map; @Data public class ExperienceData { private String title1; private String title2; private String content; private List<Map<String, PictureRenderData>> pictures; }
四、编写主体代码
ResumeData datas = new ResumeData(); @BeforeEach public void init() { datas.setTest1("测试1"); datas.setTest2("测试2"); datas.setTest3("测试3"); datas.setTest4("测试4"); // 模板文档循环合并 List<ExperienceData> experiences = new ArrayList<ExperienceData>(); ExperienceData data1 = new ExperienceData(); data1.setTitle1("第一块标题1"); data1.setTitle2("第一块图片标题2"); data1.setContent("第一块内容"); ExperienceData data2 = new ExperienceData(); data2.setTitle1("第二块标题1"); data2.setTitle2("第二块图片标题2"); data2.setContent("第二块内容"); PictureRenderData pictureRenderData1 = Pictures.ofUrl("https://www.dbc655.top/wp-content/uploads/1637587423-4.png", PictureType.PNG) .size(100, 100).create(); PictureRenderData pictureRenderData2 = Pictures.ofUrl("https://www.dbc655.top/wp-content/uploads/img_61854270c2a64.png", PictureType.PNG) .size(100, 100).create(); List<Map<String, PictureRenderData>> listEnd1 = new ArrayList<>(); List<Map<String, PictureRenderData>> listEnd2 = new ArrayList<>(); List<PictureRenderData> imgList = new ArrayList<>(); imgList.add(pictureRenderData1); imgList.add(pictureRenderData2); for (PictureRenderData imglist :imgList){ Map<String, PictureRenderData> map = new HashMap<>(); map.put("picture", imglist); listEnd1.add(map); } for (int i = imgList.size() - 1;i >= 0;i--){ Map<String, PictureRenderData> map = new HashMap<>(); map.put("picture", imgList.get(i)); listEnd2.add(map); } data1.setPictures(listEnd1); data2.setPictures(listEnd2); experiences.add(data1); experiences.add(data2); datas.setExperience( Includes.ofLocal("src\\main\\resources\\templates\\title1.docx").setRenderModel(experiences).create()); } @Test public void testResumeExample() throws Exception { XWPFTemplate template = XWPFTemplate.compile("src\\main\\resources\\templates\\visitWordTemplate.docx").render(datas); template.writeToFile("C:/Users/dbc/Desktop/gxyf/test.docx"); }
五、导出后具体效果
有可能出现的问题
1.POI版本比较低,但是没有办法升级POI
@Test public void testResumeExample() throws Exception { ResumeData datas = new ResumeData(); datas.setTest1("测试1"); datas.setTest2("测试2"); datas.setTest3("测试3"); datas.setTest4("测试4"); // 模板文档循环合并 List<ExperienceData> experiences = new ArrayList<ExperienceData>(); ExperienceData data1 = new ExperienceData(); data1.setTitle1("第一块标题1"); data1.setTitle2("第一块图片标题2"); data1.setContent("第一块内容"); ExperienceData data2 = new ExperienceData(); data2.setTitle1("第二块标题1"); data2.setTitle2("第二块图片标题2"); data2.setContent("第二块内容"); PictureRenderData pictureRenderData1 = new PictureRenderData(500, 300, ".png", BytePictureUtils.getUrlBufferedImage("https://www.dbc655.top/wp-content/uploads/1637587423-4.png")); PictureRenderData pictureRenderData2 = new PictureRenderData(500, 300, ".png", BytePictureUtils.getUrlBufferedImage("https://www.dbc655.top/wp-content/uploads/1637587423-4.png")); List<Map<String, PictureRenderData>> listEnd1 = new ArrayList<>(); List<Map<String, PictureRenderData>> listEnd2 = new ArrayList<>(); List<PictureRenderData> imgList = new ArrayList<>(); imgList.add(pictureRenderData1); imgList.add(pictureRenderData2); for (PictureRenderData imglist :imgList){ Map<String, PictureRenderData> map = new HashMap<>(); map.put("picture", imglist); listEnd1.add(map); } for (int i = imgList.size() - 1;i >= 0;i--){ Map<String, PictureRenderData> map = new HashMap<>(); map.put("picture", imgList.get(i)); listEnd2.add(map); } data1.setPictures(listEnd1); data2.setPictures(listEnd2); Resource resource = new ClassPathResource("templates/title1.docx"); InputStream is = resource.getInputStream(); experiences.add(data1); experiences.add(data2); datas.setExperience( new DocxRenderData(is, experiences)); XWPFTemplate template = XWPFTemplate.compile("src\\main\\resources\\templates\\visitWordTemplate.docx").render(datas); template.writeToFile("C:/Users/dbc/Desktop/gxyf/test.docx"); }
具体区别老铁们就自己找了哈!不找直接粘贴也没问题![aru_43]
2.打成Jar包之后无法识别src下面的文件
org.springframework.core.io.Resource resource = new ClassPathResource("template/dbc/dbc.docx"); InputStream is = resource.getInputStream(); org.springframework.core.io.Resource resource2 = new ClassPathResource("template/dbc/dbc1.docx"); InputStream is2 = resource2.getInputStream(); dataFamilyVisitEndVO.setExperience( new DocxRenderData(is, experiences)); XWPFTemplate template = XWPFTemplate.compile(is2).render(dataFamilyVisitEndVO);
仅仅就是将之前传入src文件路径转换为传入流而已,没有什么大的变动
本文作者为DBC,转载请注明。