poi导出数据到word,带图片且图片数量不确定(能确定数量范围,这里是3-20张)

注:有更好解决方法,参考:https://blog.csdn.net/m0_49605579/article/details/122583318

1.导入依赖
maven版:

<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>

gradle版:

    compile "fr.opensagres.xdocreport:fr.opensagres.xdocreport.core:2.0.2"
    compile "fr.opensagres.xdocreport:fr.opensagres.xdocreport.document:2.0.2"
    compile "fr.opensagres.xdocreport:fr.opensagres.xdocreport.document.docx:2.0.2"
    compile "fr.opensagres.xdocreport:fr.opensagres.xdocreport.template:2.0.2"
    compile "fr.opensagres.xdocreport:fr.opensagres.xdocreport.template.freemarker:2.0.2"
    compile "org.freemarker:freemarker:2.3.23"
    compile "commons-io:commons-io:2.5"
    compile "org.apache.poi:poi:3.14"
    compile "org.apache.poi:poi-ooxml:3.14"

2.创建导出模板
在这里插入图片描述
纯文字使用${}占位,图片使用建立初始化图片并添加书签的方式占位,
书签名就是datamap的键名,多张图片添加多个书签
在这里插入图片描述

3.编写代码(这里使用浏览器下载方式导出)
(1)导出工具方法

/**
     * 导出工具方法
     * //    *
     * //    * @param response 相应头
     * //    * @param map 集合外数据
     * //    * @param list 遍历数据
     * //    * @param fileName 文件名称(带后缀)
     * //    * @return 是否导出成功
     * //    * @throws IOException
     * //    * @throws XDocReportException
     */
    public static void exportFile (
            HttpServletResponse response,
            Map<String, File> fileDataMap,
            String fileName,
            Map<String, Object> map,
            List<Object> list) throws IOException, XDocReportException {
            // 获取Word模板,模板存放路径在项目的resources目录下
            // 这里的Kit为当前工具方法的类名,如果不是静态方法可以直接用this
          InputStreamins= Kit.class.getResourceAsStream(fileName);
            // 注册xdocreport实例并加载FreeMarker模板引擎
		  IXDocReportreport=XDocReportRegistry.getRegistry().loadReport(ins, TemplateEngineKind.Freemarker);
            // 创建xdocreport上下文对象
            IContext context = report.createContext();
            //添加文本数据
            if (map != null) {
                for (String s : map.keySet()) {
                    context.put(s, map.get(s));
                }
            }
            //添加循环表格数据(需要自行添加,模板对应加上关键字)
            if (list != null) {
                context.put("resultList", list);
                // 创建字段元数据
                FieldsMetadata fm = report.createFieldsMetadata();
                // Word模板中的表格数据对应的集合类型
                fm.load("resultList", Object.class, true);
            }
            FieldsMetadata metadata = report.createFieldsMetadata();
            // 替换word模板中的动态图片
            if (fileMap != null) {
                for (String s : fileMap.keySet()) {
                    IImageProvider zp = new FileImageProvider((fileMap.get(s)), true);
                    zp.setSize(130F, 130F);
                    metadata.addFieldAsImage(s);
                    report.setFieldsMetadata(metadata);
                    context.put(s, zp);
                }
            }
            // 浏览器端下载
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            response.setHeader(
                    "Content-Disposition",
                    "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
            report.process(context, response.getOutputStream());

    }

(2)业务逻辑代码

try{
		Map<String, File> fileMap = null;
		Map<String, Object> exportMap = new hashMap();
		exportMap.put("???","data");
            int num = 1;
            //由于poitl和导入功能用的poi版本冲突,无法用,这里使用IXDocReport对象做导出
            //可以循环添加,键名可以拼接为img1,img2,img3。。。,模板书签名对应
            //需要导出的文件集合,对接实际业务service
            List<File> list = new arrayList();
           	if(list != null) {
           	fileMap = new hashMap();
            for (File f : list) {
            	fileMap.put("img" + num , f);
            	num ++;
           }
        }
         Kit.exportFile(response, fileMap, "模板名称.docx", exportMap, null);
       } catch (Exception e) {
         e.printStackTrace();
       }

(3)因为我们业务文件接口返回的是byte数组,所以这里提供一个byte数组转File对象的方法(网上c的)

    /**
     * byte数组转file对象工具方法(中方法)
     *
     * @param inputStream
     * @param name
     * @param ext
     * @param tmpDirFile
     * @return
     * @throws IOException
     */
    public static File createTmpFile(
            InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException {
        File resultFile = File.createTempFile(name, '.' + ext, tmpDirFile);
        resultFile.deleteOnExit();
        FileUtils.copyToFile(inputStream, resultFile);
        return resultFile;
    }

    /**
     * byte数组转file对象工具方法
     *
     * @param bytes    文件byte数组
     * @param fileType 输出文件类型
     * @return file对象
     * @throws IOException io异常
     */
    public static File bytesToFile(byte[] bytes, String fileType) throws IOException {
        return createTmpFile(
                new ByteArrayInputStream(bytes),
                UUID.randomUUID().toString(),
                fileType,
                Files.createTempDirectory("tempFile").toFile());
    }

4.那么问题来了,图片数量不定怎么确定初始化图片再添加书签呢,困扰了很久,最后直接用20张纯白图片(这里采用微信截图,截了很小一张,100张也没有几k,全都添加对应书签,不够20张也看不出来,缺点是不满20张会空一行出来),弄好后调用方法点击导出ok

注:方法思路由该贴而来
https://blog.csdn.net/plxddyxnmd/article/details/109129838
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值