• 手把手教你springboot中导出数据到excel中


    手把手教你springboot中导出数据到excel中

    问题来源:

    前一段时间公司的项目有个导出数据的需求,要求能够实现全部导出也可以多选批量导出(虽然不是我负责的,我自己研究了研究),我们的项目是xboot前后端分离系统,后端的核心为SpringBoot 2.2.6.RELEASE,因此今天我主要讲述后端的操作实现,为了简化需求,我将需要导出的十几个字段简化为5个字段,导出的样式模板如下:

    实现步骤:

    打开一个你平时练习使用的springboot的demo,开始按照以下步骤加入代码进行操作。

    1.添加maven依赖

            <!--Excel-->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.11</version>
            </dependency>    
    

     poi-ooxml是一个excel表格的操作工具包,处理的单页数据量也是百万级别的,因此我们选择的是poi-ooxml.

    2.编写excel工具类

    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.util.List;
    
    public class ExcelUtil {
        /**
         * 用户信息导出类
         * @param response 响应
         * @param fileName 文件名
         * @param columnList 每列的标题名
         * @param dataList 导出的数据
         */
        public static void uploadExcelAboutUser(HttpServletResponse response,String fileName,List<String> columnList,
    List<List<String>> dataList){ //声明输出流 OutputStream os = null; //设置响应头 setResponseHeader(response,fileName); try { //获取输出流 os = response.getOutputStream(); //内存中保留1000条数据,以免内存溢出,其余写入硬盘 SXSSFWorkbook wb = new SXSSFWorkbook(1000); //获取该工作区的第一个sheet Sheet sheet1 = wb.createSheet("sheet1"); int excelRow = 0; //创建标题行 Row titleRow = sheet1.createRow(excelRow++); for(int i = 0;i<columnList.size();i++){ //创建该行下的每一列,并写入标题数据 Cell cell = titleRow.createCell(i); cell.setCellValue(columnList.get(i)); } //设置内容行 if(dataList!=null && dataList.size()>0){ //序号是从1开始的 int count = 1; //外层for循环创建行 for(int i = 0;i<dataList.size();i++){ Row dataRow = sheet1.createRow(excelRow++); //内层for循环创建每行对应的列,并赋值 for(int j = -1;j<dataList.get(0).size();j++){//由于多了一列序号列所以内层循环从-1开始 Cell cell = dataRow.createCell(j+1); if(j==-1){//第一列是序号列,不是在数据库中读取的数据,因此手动递增赋值 cell.setCellValue(count++); }else{//其余列是数据列,将数据库中读取到的数据依次赋值 cell.setCellValue(dataList.get(i).get(j)); } } } } //将整理好的excel数据写入流中 wb.write(os); } catch (IOException e) { e.printStackTrace(); } finally { try { // 关闭输出流 if (os != null) { os.close(); } } catch (IOException e) { e.printStackTrace(); } } } /* 设置浏览器下载响应头 */ private static void setResponseHeader(HttpServletResponse response, String fileName) { try { try { fileName = new String(fileName.getBytes(),"ISO8859-1"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } response.setContentType("application/octet-stream;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment;filename="+ fileName); response.addHeader("Pargam", "no-cache"); response.addHeader("Cache-Control", "no-cache"); } catch (Exception ex) { ex.printStackTrace(); } } }

     网上的excel的工具类有很多,但很多并不是你复制过来就能直接使用的,因此需要我们深究其原理,这样可以应对不同的场景写出属于我们自己的合适的代码,这里就不一一解释了,代码中注释加的很清楚,有不懂的可以留言评论。

    3.编写controller,service,serviceImpl,dao,entity

    3.1 entity

    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    import org.hibernate.annotations.Where;
    import javax.persistence.*;
    import java.math.BigDecimal;
    
    @Data
    @Entity
    @Where(clause = "del_flag = 0")
    @Table(name = "t_scf_item_data")
    public class ItemData{
        private static final long serialVersionUID = 1L;
    
        @Id
        @TableId
        @ApiModelProperty(value = "唯一标识")
        private String id = String.valueOf(SnowFlakeUtil.getFlowIdInstance().nextId());
    
        @ApiModelProperty(value = "创建者")
        @CreatedBy
        private String createBy;
    
        @CreatedDate
        @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        @ApiModelProperty(value = "创建时间")
        private Date createTime;
       
        @ApiModelProperty(value = "项目编号")
        private String itemNo;
        @ApiModelProperty(value = "项目名称")
        private String itemName;
        
        @ApiModelProperty(value = "删除标志 默认0")
        private Integer delFlag = 0;    
    }
    

     3.2 dao

    import cn.exrick.xboot.modules.item.entity.ItemData;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.stereotype.Repository;
    import java.util.List;
    
    @Repository
    public interface ItemDataDao{
      @Query(value = "select a.item_no,a.item_name,concat(a.create_time),a.create_by from t_scf_item_data a where a.del_flag = 0 limit 5",nativeQuery = true)
        List<List<String>> findAllObject();
        @Query(value = "select a.item_no,a.item_name,concat(a.create_time),a.create_by  from t_scf_item_data a where a.del_flag = 0 and a.id in ?1 limit 5",nativeQuery = true)
        List<List<String>> findByIds(List<String> idList);
    }
    

     3.3 service

    import javax.servlet.http.HttpServletResponse;
    import java.util.List;
    
    public interface TestService {
        void exportExcel(List<String> idList, HttpServletResponse response);
    }
    

     3.4 serviceImpl

    import cn.exrick.xboot.common.utils.ExcelUtil;
    import cn.exrick.xboot.modules.item.dao.ItemDataDao;
    import cn.exrick.xboot.modules.item.service.TestService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import javax.servlet.http.HttpServletResponse;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    @Transactional
    @Service
    public class TestServiceImpl implements TestService {
    
        @Autowired
        private ItemDataDao itemDataDao;
        @Override
        public void exportExcel(List<String> idList, HttpServletResponse response) {
            List<List<String>> dataList = new ArrayList<>();
            if(idList == null || idList.size() == 0){
                  dataList = itemDataDao.findAllObject();
            }else{
                  dataList = itemDataDao.findByIds(idList);
            }
            List<String> titleList = Arrays.asList("序号","项目编码", "项目名称", "创建时间", "创建人");
            ExcelUtil.uploadExcelAboutUser(response,"项目信息.xlsx",titleList,dataList);
        }
    }
    

     3.5 controller

    import cn.exrick.xboot.modules.item.service.TestService;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletResponse;
    import java.util.List;
    import java.util.Map;
    @Slf4j
    @RestController
    @RequestMapping("/test")
    public class TestController {
    
        @Autowired
        private TestService testService;
    
        @RequestMapping(value = "/exportExcel", method = RequestMethod.POST)
        @ApiOperation(value = "导出excel",produces="application/octet-stream")
        public void exportCorpLoanDemand(@RequestBody Map<String,List<String>> map, HttpServletResponse response){ ;
            log.info("测试:{}",map);
            testService.exportExcel(map.get("list"),response);
        }
    }
    

    4.测试

    测试的话可以使用swagger或者postman,甚至你前端技术足够ok的话也可以写个简单的页面进行测试,我是用的是swaager进行的测试,下面就是我测试的结果了:

     

     

     如果你觉得这篇博客有用,请点个赞再走吧。

  • 相关阅读:
    Vue的响应式
    让html上两个元素在一行显示
    linux的<<命令
    http-only,withCredentials
    axios跨域请求时 withCredentials:true 表示request携带cookie
    异步代码async await阻塞进程的误区——await的是Promise的resolve而不是语句块的执行结束
    理解状态机
    关于express返回值的问题
    axios基本的get/post请求使用方法
    【转】 前端笔记之Vue(四)UI组件库&amp;Vuex&amp;虚拟服务器初识
  • 原文地址:https://www.cnblogs.com/zaevn00001/p/13353744.html
Copyright © 2020-2023  润新知