java实现将数据导出为word功能(文字,表格,图片的循环导出)

文章介绍了如何使用Easypoi库在Java中配置导出Word文档,包括添加所需依赖、创建配置类以处理模板、填充数据,以及处理图片循环导出。在模板中,变量和循环结构被用来动态填充固定数据和表格图片。控制器部分展示了如何从数据库获取信息并将其插入到模板中,最后导出成Word文档。
摘要由CSDN通过智能技术生成

1.配置文件的准备

1.导出功能实现所需要的pom文件

<!--   导出到word(循环图片)     -->
        <!-- word导出  方式:easypoi-->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.4.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>4.4.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>4.4.0</version>
        </dependency>
        <!--注意:word中要使用循环等标签必须单独导入以下依赖-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.4</version>
        </dependency>

这里需要注意的点!!!!!!!!!!!!!!!!!

easypoi的版本必须在4.3.0以上,否则在导出图片的时候,只会导出图片的内存地址,却不能显示出图片。

2.在配置目录下添加一个配置类

package com.state.grid.substation.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.afterturn.easypoi.word.WordExportUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.util.Assert;

public class WordUtil {
    public static void exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        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 {

            String userAgent = request.getHeader("user-agent").toLowerCase();
            if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
            }
            XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
            String tmpPath = temDir + fileName;
            FileOutputStream fos = new FileOutputStream(tmpPath);
            doc.write(fos);
            // 设置强制下载不打开
            response.setContentType("application/force-download");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            OutputStream out = response.getOutputStream();
            doc.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            delFileWord(temDir,fileName);//这一步看具体需求,要不要删
        }

    }

    /**
     * 删除零时生成的文件
     */
    public static void delFileWord(String filePath, String fileName) {
        File file = new File(filePath + fileName);
        File file1 = new File(filePath);
        file.delete();
        file1.delete();
    }

}

3.准备一个导出模板(固定位置填充固定数据,表格和图片的循环导出)

 解释一下模板中所填充的东西:

1.像这种:用两个花括号括起来的变量名,到时候会将变量名所指代的数据填充进去

 2.像这种:需要将批量数据循环导出的表格以及图片

 2.功能的实现(写一个Controller)

调用service和mapper没写,具体以实际需求为准

1.先理一些这个功能实现的逻辑:

去数据库查表获取想要的信息----用一个集合将这些信息都装起来----将这些信息都插入到模板的指定位置当中去

2.功能的实现(带注释)

这个肯定不能直接拿来运行,注意看我写的注释,理解代码逻辑,我写的很清楚,每一行代码干了什么我都有写。

/**
     * 巡视报告的导出(循环图片版)
     * @param substationId
     * @param calendarId
     * @param request
     * @param response
     * @return
     */
    //请求路径是/taskResultToWord,请求方式是get请求
    @RequestMapping(value = "/taskResultToWord", method = RequestMethod.GET)
    //返回Result类型,传进来变电站id,日历id
    public Result taskResultToWord(String substationId, String calendarId, HttpServletRequest request, HttpServletResponse response) throws Exception {  // 分页查询
        int code = 0;
        String msg = "";
//        定义List集合list,泛型是TaskResultEquipment
        List<TaskResultEquipment> list = new ArrayList<>();
//        List<TaskProgress> uplist = new ArrayList<>();
        //定义Map集合resmap
//        Map<String, Object> resmap = new HashMap<>();
        try {
            //token验证
            Des3Util des = new Des3Util();
            String token = request.getHeader("token");
            String jsonUser = des.parseDES(token);
            JSONObject jsonData = JSONObject.fromObject(jsonUser);
            String userId = (String) jsonData.get("u");
            String roleId = (String) jsonData.get("r");

            boolean access = this.roleService.getAccess(roleId, "task/taskList");
            if(access){
                //定义Map集合map
                Map<String, Object> map = new HashMap<>();
                //将输入的设备id添加到map集合里面
//                map.put("substationId", substationId);
                //将输入的日历id添加到calendarId里面
                map.put("calendarId", calendarId);
                //返回表v_task_result_equipment中的数据条数
                int count = this.taskService.taskResultEquipmentCount(map);

                //将查询到的基本信息赋给taskProgress
                TaskProgress taskProgress = this.taskService.taskResultInfo(map);
                //添加字段startRow(开始行)的值为0
                map.put("startRow", 0);
                //添加字段endRow(结束行)的值为count,count的值就是表v_task_result_equipment中的数据条数
                map.put("endRow", count);
                //分页查询表v_task_result_equipment中的数据,起始行是0,结束行是count,就是一页查询所有数据,
                list = this.taskService.taskResultEquipmentList(map);
                System.out.println(list);

                //路径
                String path1 = ResourceUtils.getURL("classpath:").getPath();
                String path2 = path1.substring(1);
                String terminalType = System.getProperty("os.name");
                String path = "";
                if (Objects.equals(terminalType, "Linux")){
                    path = path1.replace("ROOT/WEB-INF/classes/", "").replace("ROOT\\WEB-INF\\classes\\", "");
                }else {
                    path = path2.replace("ROOT/WEB-INF/classes/", "").replace("ROOT\\WEB-INF\\classes\\", "");
                }
                System.out.println("path!!!!!!" + path);
                //PATH是文件导出路径resource/excel/
                String PATH = path + config.getExportUrl();
                //ImagePath是图片导入路径resource/cameraImage/
                String ImagePath = path + config.getCameraImageUrl();

                //导出表头信息
                //定义一个Map集合params
                Map<String, Object> params = new HashMap<>();
                //模板文件的路径templatePath
                String templatePath = "E:/template/patrolWord.docx"; //模板路径

                //简单渲染文本
                params.put("substationName", taskProgress.getSubstationName());
                params.put("voltageLevel", taskProgress.getVoltageLevel());
                params.put("viewStartTime",taskProgress.getViewStartTime());
                params.put("patrolType",taskProgress.getPatrolType());
                params.put("taskName",taskProgress.getTaskName());
                params.put("className",taskProgress.getClassName());
                params.put("totalNumber",taskProgress.getTotalNumber());
                params.put("execresult1",taskProgress.getExecresult1());
                params.put("execresult2",taskProgress.getExecresult2());
                params.put("execresult0",taskProgress.getExecresult0());
                params.put("execresult3",taskProgress.getExecresult3());
                params.put("execStartTime",taskProgress.getExecStartTime());
                params.put("execEndTime",taskProgress.getExecEndTime());

               

                //声明了一个名为alarms的变量,它是一个List类型,其中每个元素都是一个Map<String, Object>类型的键值对集合。
                List<Map<String, Object>> alarms = new ArrayList<>();
                //声明了一个名为alarm的变量,它是一个Map类型的键值对集合。具体来说,这个Map对象中每个键都是一个String类型,每个值都是一个Object类型。
                Map<String, Object> alarm;


                //会遍历list集合中的每个元素,并将每个元素赋值给循环变量taskResultEquipment。
                // 在每次循环迭代中,可以使用taskResultEquipment变量来访问集合中当前元素的属性和方法。
                //数据来源是摄像头
                String source = "摄像头";
                //序号从1开始
                int order = 1;
                for (TaskResultEquipment taskResultEquipment : list){
                    //img_path得到表中一行数据的图片路径
                    String img_path = taskResultEquipment.getPicture();
                    //ImagePath是图片导入路径resource/cameraImage/,realImagePath是图片真正的路径
                    String realImagePath = ImagePath + img_path;
                    //将图片路径打印出来
                    System.out.println(realImagePath);

//                    File imagefile = new File(realImagePath);
//                    if (imagefile.exists()){
//                        taskResultEquipment.setImageData(realImagePath);
//                    }else {
//                        String errorFile = ImagePath +  config.getErrorCameraImageUrl();
//                        taskResultEquipment.setImageData(errorFile);
//                    }

                    //创建了一个名为alarm的新的HashMap对象
                    alarm = new HashMap<>();
                    //将循环中获取到的信息添加到集合里面
                    //变电站
//                    alarm.put("name", taskResultEquipment.getTaskName());
                    //设备名称
                    alarm.put("order",order);
                    alarm.put("equipmentInterval", taskResultEquipment.getEquipmentInterval());
                    alarm.put("equipmentName", taskResultEquipment.getEquipmentName());
                    alarm.put("equipmentPart",taskResultEquipment.getEquipmentPart());
                    alarm.put("pointName", taskResultEquipment.getPointName());
                    alarm.put("importance", taskResultEquipment.getImportance());
                    alarm.put("result", taskResultEquipment.getResult());
                    alarm.put("realAlarmLevel", taskResultEquipment.getRealAlarmLevel());
                    alarm.put("confirmUser", taskResultEquipment.getConfirmUser());
                    alarm.put("execStartTime", taskResultEquipment.getExecStartTime());
                    alarm.put("source",source);
                    //表格内循环添加图片(easypoi 4.3以后才支持,不然只能打印出ImageEntity的内存地址)

                    //创建了一个名为simage的新的ImageEntity对象,并将其赋值给simage变量。
                    // 具体来说,ImageEntity是一个Java类,用于表示一个图像实体,其中包含了图像的各种属性和数据。
                    ImageEntity simage = new ImageEntity();
                    simage.setHeight(50);
                    simage.setWidth(50);
                    //将图片的本地路径导入进去
                    simage.setUrl(realImagePath);
                    //将simage对象的类型设置为URL类型。
                    //该图像实体表示的是一个通过URL链接获取的远程图像,而不是一个本地存储的图像。
                    simage.setType(ImageEntity.URL);
//                    ByteArrayOutputStream out = new ByteArrayOutputStream();
//                    simage.setData(out.toByteArray()); //字节流读取
                    //将图片添加进去
                    alarm.put("img", simage);
                    //alarms是一个里面元素都是map的list集合
                    alarms.add(alarm);
                    order = order + 1;
                }

                //Map集合params,将jobs(元素为map的list集合添加进去)
                params.put("alarms", alarms);
                //定义了一个表示模板文件夹路径的字符串变量temDir,用于存储模板文件所在的文件夹的路径。
                // 在这个例子中,temDir指向E:/template/file/word/路径。表示文件路径分隔符,可以是\或者/,具体取决于操作系统
                String temDir="E:/template/" + File.separator + "file/word/"; ;//生成临时文件存放地址
                //生成文件名
                Long time = new Date().getTime();
                // 生成的word格式
                String formatSuffix = ".docx";
                // 拼接后的文件名
                String fileName = time + formatSuffix;//文件名  带后缀
                //导出word
                WordUtil.exportWord(templatePath, temDir, fileName, params, request, response);
//                WordUtil.exportWord(templatePath, PATH, fileName, params, request, response);
                code = 1;
            }else{
                msg = "token无效";
            }
        }catch (Exception e){
            msg = "操作失败";
        }
        return Result.success(code, msg,null);
    }

3.导出的效果

1.固定信息部分:

 2.循环表格和循环图片部分 

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值