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

2023-11-17

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.循环表格和循环图片部分 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • Java - 如何将特殊字符放入字符串中

    Java 似乎有很好的字符串处理能力 尽管如此 我还是遇到了最简单的问题 我需要动态字符串 它们在运行时更改 因此字符串类型不是一个好的选择 因为它们是不可变的 所以我使用字符数组 设置起来有点痛苦 但至少它们是可以修改的 我想创建一个字符
  • 在Java中使用命令行编译多个包

    您好 我一直在使用 IDE 但现在我需要从命令行运行和编译 问题是我有多个软件包 我试图找到答案 但没有任何效果 所以我有 src Support java files Me java files Wrapers java files 你知
  • 将 Hibernate 对象序列化为 JSON 时抛出异常

    好吧 我正在使用 Hibernate 将一个小型数据库加载到一些表示表的类并与数据库交互 一切都很好 我真的可以看到所有结果 而且我没有任何空字段 所有这些都已被使用 这里我展示了 主 类 表 import javax persistenc
  • MongoTemplate upsert - 从 pojo 进行更新的简单方法(哪个用户已编辑)?

    这是一个简单的 pojo public class Description private String code private String name private String norwegian private String en
  • jvm 次要版本与编译器次要版本

    当运行使用具有相同主要版本但次要版本高于 JVM 的 JDK 编译的类时 JVM 会抛出异常吗 JDK 版本并不重要 类文件格式版本 http blogs oracle com darcy entry source target class
  • RMI 中的引用传递问题? [复制]

    这个问题在这里已经有答案了 有人可以告诉我我错在哪里 为什么这个 RMI 聊天应用程序不起作用 目标是通过远程对象或序列化对象实现客户端 服务器和逻辑之间的解耦 import javax swing import java awt even
  • 字符串池可以包含两个具有相同值的字符串吗? [复制]

    这个问题在这里已经有答案了 字符串池可以包含两个具有相同值的字符串吗 String str abc String str1 new String abc Will the second statement with new operator
  • JTable 和 JScrollpane 大小的问题

    我有一个JScrollPane with a JTable在里面 在里面JTable我最初有 3 行 稍后添加行 默认JTable我的 3 行很难看 因为JScrollPane calls getPreferredScrollableVie
  • 从 @JsonProperty 值获取枚举常量

    我有一个标有 JsonProperty 的枚举 用于使用 Jackson 进行 JSON 序列化 反序列化 并且希望获取给定字符串 JsonProperty 的枚举值 public enum TimeBucket JsonProperty
  • Jenkins 的代码覆盖率 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何将 Observable>> 转换为 Observable>

    我陷入了如何将以下可观察类型转换 转换为我的目标类型的困境 我有以下类型的可观察值 Observable
  • 改变for循环的顺序?

    我遇到一种情况 我需要根据用户输入以不同的顺序循环遍历 xyz 坐标 所以我是 3D 空间中的一个区域 然后是一组像这样的 for 循环 for int x 0 x lt build getWidth x for int y 0 y lt
  • JavaFX - 为什么多次将节点添加到窗格或不同的窗格会导致错误?

    我现在正在学习基本的 JavaFX 我不明白我正在阅读的书中的这一说法 不 诸如文本字段之类的节点只能添加到一个窗格中一次 将节点添加到多次窗格或不同的窗格将导致运行时错误 我可以从书中提供的UML图看出它是一个组合 但我不明白为什么 库类
  • Android Gradle 同步失败:无法解析配置“:classpath”的所有工件

    错误如下 Caused by org gradle api internal artifacts ivyservice DefaultLenientConfiguration ArtifactResolveException Could n
  • 了解 Spark 中的 DAG

    问题是我有以下 DAG 我认为当需要洗牌时 火花将工作划分为不同的阶段 考虑阶段 0 和阶段 1 有些操作不需要洗牌 那么为什么 Spark 将它们分成不同的阶段呢 我认为跨分区的实际数据移动应该发生在第 2 阶段 因为这里我们需要cogr
  • 使用 JAD 反编译 java - 限制

    我正在尝试使用 Java 中的 JAD 反编译几个 jar 文件 我也尝试过 JD GUI 但运气更差 但出现了很多错误 一种类型 易于修复 似乎是内部类 但我也发现了这段代码 static int SWITCH TABLE atp com
  • 春季 CORS。在允许的来源中添加模式

    查看CORS的弹簧指南 以下代码启用所有允许的来源 public class MyWebMVCConfigurer extends WebMvcConfigurerAdapter Override public void addCorsMa
  • 摩尔斯电码 至 英语

    我现在的问题是让 摩尔斯电码转英语 正常工作 将英语转换为莫尔斯电码的第一部分工作正常 我知道以前已经有人问过这个问题 但我不知道我做错了什么 我知道我需要在某个地方进行拆分 但我只是不确定将其放在代码中的何处 现在 莫尔斯电码到英语的部分
  • Java:使用 Graph API 在线更新 Sharepoint 上的 docx 文件

    我在使用 Java 在线更新 Sharepoint 上的 docx 文件时遇到问题 首先 我检查了构建 PUT 请求的 URL 此处 并使用此请求 PUT drives drive id items item id content 我首先使
  • 为什么范围为“provided”的依赖项会隐藏 Maven 中的传递依赖项?

    我的 Maven 项目中有三个模块 这稍微简化了 model包含JPA注释的实体类 坚持实例化一个实体管理器并调用它的方法 应用创建类的实例model 设置一些值并将它们传递给坚持 model and 坚持显然取决于javax persis

随机推荐