Java使用XDocReport和FreeMarker模板引擎导出Word文档

Java使用XDocReport和FreeMarker模板引擎导出Word文档

本篇介绍配合前端控制输入,调用后端接口导出Word的方法,后端通过 XDocReport 和 FreeMarker 模板引擎生成Word文档后直接返回文件流给前端下载。

示例

前端页面
前端页面
在这里插入图片描述

word导出样例
word导出样例

前端

前端使用vueelement-ui编写页面,此篇不做赘述。

后端

1、准备模版

示例模版
将word中需要动态填充的字段变为word域,word域是引导Word在文档中自动插入文字、图形、页码或其他信息的一组代码。在这里表示Word文档中要被替换的内容。

编辑普通word模版文本步骤:

1、在word模板中选中要替换的文本,拿姓名为例,光标放置在姓名表格后,点击插入“域”:
在这里插入图片描述
2、在弹出的对话框中,类别选择“邮件合并”,在后侧域代码的 "MERGEFIELD "后面编写FreeMarker模板表达式${name!},点击【确定】按钮:
注:name后面的!是为防止空值导致报错,若有可能为空值的最好都加上。
在这里插入图片描述
3、编辑好后的效果如下图:
在这里插入图片描述
4、把word模板需要替换的内容都替换成模板变量:
在这里插入图片描述

处理word模版中的表格数据

表格数据的处理其实和上面对普通文本的处理是类似的,只不过要在Word模板中加上集合的变量。

具体步骤如下:

1、选定表格中要替换的文本,光标放置在此后,点击插入“域”;
2、在弹出的对话框中,类别选择“邮件合并”,在后侧域代码的 "MERGEFIELD "后面编写FreeMarker模板表达式${eduBack.startingEndingDay!},点击【确定】按钮:
在这里插入图片描述
3、重复步骤2,替换表格中的其他需要替换的地方:
在这里插入图片描述
注: Word模板中的表格的长度最好充满Word文档的左右两边,否则如果表格下面还有其他文本内容,下面的文本内容会自动填充到表格的缝隙处,而且会对下面的文本内容进行覆盖。

2、将准备好的模版放到项目中

放在java项目的resources目录下:
在这里插入图片描述

3、代码

添加maven依赖到pom.xml

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.1</version>
</dependency>
<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls</artifactId>
    <version>2.6.0</version>
    <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls-poi</artifactId>
    <version>1.2.0</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.xdocreport.core</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.xdocreport.document</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.xdocreport.template</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.23</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
</dependency>

java代码

package wordExport;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.images.FileImageProvider;
import fr.opensagres.xdocreport.document.images.IImageProvider;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
import javax.servlet.http.HttpServletResponse;
import XXXX.entity.*;

@Service
public class Test {
	//实现类
    public void export(Map<String, Object> params,HttpServletResponse response) throws Exception {
        //获取Word模板
        InputStream ins = this.getClass().getResourceAsStream("/model1.docx");
        //注册xdocreport实例并加载FreeMarker模板引擎
        IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins,TemplateEngineKind.Freemarker);
        
        //设置集合数组
        List<EduBack> listEduBack = new ArrayList<EduBack>();
        List<Map<String, String>> paramEduBackList = (List<Map<String, String>>) params.get("eduBackTableData");
        for (Map<String, String> eduBack : paramEduBackList) {
            EduBack eduBackMap = new EduBack();
            eduBackMap.setStartingEndingDay(eduBack.get("startingEndingDay"));
            eduBackMap.setGraduateSchool(eduBack.get("graduateSchool"));
            eduBackMap.setEducationalBackground(eduBack.get("educationalBackground"));
            eduBackMap.setProfession(eduBack.get("profession"));
            eduBackMap.setLearningForm(eduBack.get("learningForm"));
            listEduBack.add(eduBackMap);
        }

        //创建xdocreport上下文对象
        IContext context = report.createContext();
        context.put("name",params.get("name"));
        context.put("sex",params.get("sex"));
        context.put("birthDay",params.get("birthDay"));
        context.put("eduBack",listEduBack);//加入到上下文对象中

        //创建字段元数据
        FieldsMetadata fm = report.createFieldsMetadata();
        //Word模板中的表格数据对应的集合类型
        fm.load("eduBack", EduBack.class, true);
        report.setFieldsMetadata(fm);

        //输出到本地目录
        String fileName = params.get("name")+"模版.docx";
        //FileOutputStream out = new FileOutputStream(new File("D://"+fileName));
        //report.process(context, out);
        
		//浏览器端下载
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/*");
        response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
        report.process(context, response.getOutputStream());
    }
}

4、补充-生成带有图片的word

在之前准备好的word模版中要加入图片的位置插入一张模版图片,然后选中模版图片插入一个书签,设置书签名,点击添加按钮。
若需要添加多张图片,重复此操作即可。
在这里插入图片描述
java代码

//创建字段元数据
FieldsMetadata fm = report.createFieldsMetadata();
//Word模板中的表格数据对应的集合类型
fm.load("eduBack", EduBack.class, true);
fm.addFieldAsImage("img1");
context.put("img1",params.get("imgInputStream"));//放入前端传入的图片流
report.setFieldsMetadata(fm);

导出效果如下

在这里插入图片描述
在这里插入图片描述

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用XDocReportFreeMarker模板来生成带页数的Word文档。以下是一个示例代码: 1. 添加以下依赖项到您的项目中: ```xml <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>xdocreport</artifactId> <version>1.0.6</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>xdocreport-template-freemarker</artifactId> <version>1.0.6</version> </dependency> ``` 2. 创建一个FreeMarker模板,包含一个名为“page”的变量,用于显示当前页数。例如,以下是一个简单的模板: ``` <html> <head> <title>My Document</title> </head> <body> <p>Page ${page} of ${nbPages}</p> <p>This is the content of my document.</p> </body> </html> ``` 3. 在Java代码中使用XDocReportFreeMarker模板来填充Word文档。以下是一个示例代码: ```java import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import org.apache.poi.xwpf.usermodel.XWPFDocument; import fr.opensagres.xdocreport.core.XDocReportException; import fr.opensagres.xdocreport.core.io.XOutputStream; import fr.opensagres.xdocreport.document.registry.XDocReportRegistry; import fr.opensagres.xdocreport.template.TemplateEngineKind; import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; public class GenerateWordDoc { public static void main(String[] args) { try { // Load the template InputStream in = GenerateWordDoc.class.getResourceAsStream("template.docx"); XWPFDocument document = new XWPFDocument(in); FieldsMetadata metadata = new FieldsMetadata(); metadata.addFieldAsTextStyling("page"); XDocReportRegistry.getRegistry().register(document, metadata, TemplateEngineKind.Freemarker); // Populate the template Map<String, Object> context = new HashMap<>(); context.put("page", "${page}"); context.put("nbPages", "${nbPages}"); OutputStream out = new FileOutputStream("output.docx"); XDocReportRegistry.getRegistry().getReport(document, null).process(context, new XOutputStream(out)); // Close the streams in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` 此代码将使用名为“template.docx”的模板创建一个新的Word文档,并将“page”变量替换为当前页数。请注意,您需要使用FieldsMetadata对象来标识文档中的字段,并将其注册到XDocReportRegistry中。最后,代码将输出生成的Word文档到名为“output.docx”的文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值