当前位置: 首页 > article >正文

poi处理多选框进行勾选操作下载word以及多word文件压缩

一、场景

将数据导出word后且实现动态勾选复选框操作
eg: word模板
在这里插入图片描述
导出后效果(根据数据动态勾选复选框)
在这里插入图片描述

二、解决方案及涉及技术

① 使用poi提供的库进行处理(poi官方文档)
② 涉及依赖

 <!-- excel工具 -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>${poi.version}</version>
            </dependency>
  <!-- pio处理word文件操作复选框-->
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.4</version>
        </dependency>

三、代码实现

word单个/批量下载工具类
在操作模板时,我们需先将写入word模板的数据构建为Map
① 数据封装处理(TrafficBlock 对象)

public Map buildTrafficDataForm(TrafficBlock trafficBlock){
    BlockDownLoadDataForm dataForm = new BlockDownLoadDataForm();
    BeanUtils.copyProperties(trafficBlock, dataForm);
    dataForm.setDirection(EventInfoDirection.getDirection(trafficBlock.getDirection()).getMessage());
    // 涉桥/涉隧
    dataForm.setInvolveNo(String.valueOf(trafficBlock.getInvolveNumber()));
    // 模板数据处理
    dataForm.setStartToEndPile("K"+trafficBlock.getStartKilometersPile()+"+"+trafficBlock.getStartHectometerPile()+"至"+trafficBlock.getEndKilometersPile()+"+"+trafficBlock.getEndHectometerPile());
    dataForm.setAffectedStartToEndPile("K"+trafficBlock.getAffectedStartKilometersPile()+"+"+trafficBlock.getAffectedStartHectometerPile()+"至"+trafficBlock.getAffectedEndKilometersPile()+"+"+trafficBlock.getAffectedEndHectometerPile());
    // 阻断类别(突发类才会有)
    String blockCategory = String.valueOf(trafficBlock.getBlockCategory());
    // checkBox处理
    if("1".equals(trafficBlock.getBlockNature())){
        // 计划类
        dataForm.setPlanCheckBox(String.valueOf(trafficBlock.getBlockType()));
    }else{ //突发类
        if("1".equals(blockCategory)){
            // 地质灾害
            dataForm.setGeologyCheckBox(String.valueOf(trafficBlock.getBlockType()));
        }else if("2".equals(blockCategory)){
            // 重大灾害
            dataForm.setGreatCheckBox(String.valueOf(trafficBlock.getBlockType()));
        }else if("3".equals(blockCategory)){
            // 气象灾害
            dataForm.setWeatherCheckBox(String.valueOf(trafficBlock.getBlockType()));
        }else if("4".equals(blockCategory)){
            // 事故灾害
            dataForm.setAccidentCheckBox(String.valueOf(trafficBlock.getBlockType()));
        }else if("5".equals(blockCategory)){
            // 其他
            dataForm.setOtherCheckBox(String.valueOf(trafficBlock.getBlockType()));
        }
    }
    return convertTrafficBlockToMap(dataForm);
}

② dataMap构建工具

public static Map<String, String> convertTrafficBlockToMap(BlockDownLoadDataForm downLoadDataForm) {
        Map<String, String> valueMap = new HashMap<>();
        Class<?> clazz = downLoadDataForm.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            try {
                Object fieldValue = field.get(downLoadDataForm);
                if (fieldValue == null) {
                    valueMap.put(field.getName(), "");
                } else {
                    valueMap.put(field.getName(), String.valueOf(fieldValue));
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return valueMap;
    }

此处需要注意在多个文件下载时,每次向ZipOutputStream 写入字节流时,需要为每个生成的 Word 文件提供一个唯一的名称(写入的文件名必须不一致)否则会导致每次写入的流覆盖之前的,导致浏览器不能正确解析,进而下载失败!!!

// *****(Word单个/批量下载)
    public void generateTrafficWordForm(HttpServletResponse response, List<Long> ids) throws IOException {
        List<TrafficBlock> trafficBlocks = trafficBlockMapper.selectList(new LambdaQueryWrapper<TrafficBlock>().in(TrafficBlock::getId, ids));
        if (ids.size() == 1){
            // 单个下载
            Map dataMap = buildTrafficDataForm(trafficBlocks.get(0));
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=***记录表.docx");
            response.setContentType(String.valueOf(MediaType.APPLICATION_OCTET_STREAM));
            try (OutputStream out = response.getOutputStream()) {
                writeTrafficWordForm(dataMap, out);
            }
        }else if (ids.size()  > 1) {
            // 多个文件压缩下载
            response.setContentType("application/zip");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("交通阻断.zip", "UTF-8"));
            try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
                for (TrafficBlock trafficBlock : trafficBlocks) {
                    Map dataMap = buildTrafficDataForm(trafficBlock);
                    ByteArrayOutputStream wordStream = new ByteArrayOutputStream();
                    writeTrafficWordForm(dataMap, wordStream);
                    // 为每个文件生成唯一的名称
                    String uniqueFileName = "*****_" + trafficBlock.getId() + ".docx";
                    zipOut.putNextEntry(new ZipEntry(uniqueFileName));
                    zipOut.write(wordStream.toByteArray());
                    zipOut.closeEntry();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

poi工具类读取模板处理数据工具:

public void writeTrafficWordForm(Map<String, String> dataMap,OutputStream outputStream) {
        /**
         *  复选框
         * */
        //需要循环的表单数据
        dataMap.put("dataTable", String.valueOf(new ArrayList<>()));

        ConfigureBuilder configureBuilder = Configure.builder().useSpringEL().bind("dataTable", new HackLoopTableRenderPolicy());
        Configure config = configureBuilder.build();
        InputStream is = null;
        try {
            // 读取Word模板文件,获取输入流
            is = new ClassPathResource("template/profile/交通阻断记录表.docx").getInputStream();
            XWPFTemplate template = XWPFTemplate.compile(is, config).render(dataMap);
            template.write(outputStream);
            outputStream.flush();
            PoitlIOUtils.closeQuietlyMulti(template, outputStream);
        } catch (IOException e) {
            log.error("失败!!!!!!", e);
        } finally {
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    log.error("关闭流失败!", e);
                }
            }
        }
    }

http://www.kler.cn/a/488287.html

相关文章:

  • 深度学习笔记11-优化器对比实验(Tensorflow)
  • 信息系统项目管理-采购管理-采购清单示例
  • WEB攻防-通用漏洞_文件上传_黑白盒审计流程
  • Three.js教程015:全面讲解Three.js的UV与应用
  • web服务器快速目录搜索遍历工具推荐:Dirsearch
  • 之前手写的两个好用开源组件优化升级
  • Cognitive architecture 又是个什么东东?
  • 【Rust自学】11.7. 按测试的名称运行测试
  • 记录一个移动端表格布局,就是一行标题,下面一列是对应的数据,一条一条的数据,还有点击数据进入详情的图标,还可以给一列加input输入框,还可以一对多
  • dubbo3 负载均衡
  • js迭代器模式
  • python+camelot库:提取pdf中的表格数据
  • 工厂人员定位管理系统方案(二)人员精确定位系统架构设计,适用于工厂智能管理
  • 《零基础Go语言算法实战》【题目 2-1】使用一个函数比较两个整数
  • iOS - 数组的真实类型
  • .NET 终止或结束进程
  • [SAP ABAP] 使用LOOP AT...ASSIGNING FIELD-SYMBOL 直接更新内表数据
  • Unity3D使用GaussianSplatting加载高斯泼溅模型
  • React Error Boundary 错误边界限制
  • Java Web开发进阶——Spring Security基础与应用
  • 华为C语言编程规范总结
  • 用户界面的UML建模11
  • MIT 6.S081 Lab9 File System
  • jeecg-boot 表单选择一条数据保存
  • 深入学习Headers Exchange交换机
  • 打桩机:灾害救援中的 “应急尖兵”,稳固支撑的保障|鼎跃安全