【SpringBoot+poi实现excel文档导出(三)】

【SpringBoot+poi实现excel文档导出(三)】,第1张

【SpringBoot+poi实现excel文档导出(三)】 SpringBoot+poi实现excel文档导出(三)

使用SpringBoot+poi实现excel文档导出,打算分为三篇书写,第一篇基于if-else导出,第二篇提取部分方法作为抽象方法导出,第三篇为全抽象导出。

三、全抽象导出

本篇将用三个模板导出三个不同样式的excel表格。
首先理一下思路 (可以类比一个两头和中间有开口的物体,按照基本的三种颜色的流体往下灌,中间的口不动的情况下,灌红色的流体出红色,灌绿色的流体出绿色;如果上口灌红色的流体,中间灌绿色的流体,出来的颜色就是黄色。把开口的物体作为抽象层的业务代码,流体作为参数,传不同的参数,出不同的结果,但是物体不变):

  1. 将第二章Service层的业务层代码全部抽取出来作为抽象方法,使用工厂生产impl层和不同类型数据处理结果;
  2. 使用“T”“V”“B”三个泛型分别代表实体(业务中暂时用不到,但是使用baseService查询肯定会用到)、导出表的Vo、查询条件。
1. 接口工厂
import javax.servlet.http.HttpServletResponse;
import java.util.List;


public interface IExportServiceFactory {

    
    void exportExcel(B b, HttpServletResponse response) throws Exception;

    
    List findScheduleByConditions(B b);
2.1. 实现类1(用户)
import com.example.export.dispose.ExcelDispose;
import com.example.export.dispose.IDispose;
import com.example.export.dispose.datadispose.UserExport;
import com.example.export.service.IExportServiceFactory;
import com.example.export.vo.UserVo;
import com.example.export.vo.ScheduleVo;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

@Service
public class UserExportServiceImpl implements IExportServiceFactory {
    @Override
    public void exportExcel(ScheduleVo vo, HttpServletResponse response) throws Exception {
        // 新行的索引
        int i = 1;
        // 表头索引
        int j = 0;
        List cellNameList = new ArrayList<>();
        Integer width = null;
        IDispose dispose = new UserExport();
        ExcelDispose zhqJtsyjcExcelDispose = new UserExport();
//        vo.setYljgLb(DicYljgUtils.findByOrganId(UserUtils.getUser(vo.getUserId()).getOrganId()).getYljgLb());
//        导出excel模板根据传入的参数置空list,1:模板导出;2:全量导出
//        List users = vo.getMb().equals("1") ? new ArrayList<>() : query(vo);
        List scheduleByConditions = findScheduleByConditions(vo);
        String path = "excel/user.xlsx";
        zhqJtsyjcExcelDispose.excelPathDispose(path, scheduleByConditions, cellNameList, i, j, response, width, dispose);
    }

    
    public List findScheduleByConditions(ScheduleVo vo) {
        UserVo userVo1 = new UserVo();
        UserVo userVo2 = new UserVo();
        UserVo userVo3 = new UserVo();
        UserVo userVo4 = new UserVo();
        UserVo userVo5 = new UserVo();
        List userVos = new ArrayList<>();
        userVo1.setName("账伞").setAge("17").setSex("男").setAddress("北京市朝阳区上雕刻技法").setContactInformation("2342893472374");
        userVo2.setName("里斯").setAge("43").setSex("女").setAddress("上海市黄浦区的发射点").setContactInformation("34534453");
        userVo3.setName("汪芜").setAge("23").setSex("男").setAddress("陕西省西安市瓦基尔克").setContactInformation("3131231");
        userVo4.setName("马尔扎哈").setAge("534").setSex("男").setAddress("山西省太原市昆仑山地方").setContactInformation("23544343");
        userVo5.setName("古力娜扎").setAge("43").setSex("女").setAddress("广东省广州市的快速减肥").setContactInformation("1213124242");
        userVos.add(userVo1);
        userVos.add(userVo2);
        userVos.add(userVo3);
        userVos.add(userVo4);
        userVos.add(userVo5);
        return userVos;
    }

}
2.2. 实现类2(汽车)
import com.example.export.dispose.ExcelDispose;
import com.example.export.dispose.IDispose;
import com.example.export.dispose.datadispose.CarExport;
import com.example.export.service.IExportServiceFactory;
import com.example.export.vo.CarVo;
import com.example.export.vo.ScheduleVo;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

@Service
public class CarExportServiceImpl implements IExportServiceFactory {

    @Override
    public void exportExcel(ScheduleVo vo, HttpServletResponse response) throws Exception {
        // 新行的索引
        int i = 1;
        // 表头索引
        int j = 0;
        List cellNameList = new ArrayList<>();
        Integer width = null;
        IDispose dispose = new CarExport();
        ExcelDispose zhqJtsyjcExcelDispose = new CarExport();
//        vo.setYljgLb(DicYljgUtils.findByOrganId(UserUtils.getUser(vo.getUserId()).getOrganId()).getYljgLb());
//        导出excel模板根据传入的参数置空list,1:模板导出;2:全量导出
//        List users = vo.getMb().equals("1") ? new ArrayList<>() : query(vo);
        List scheduleByConditions = findScheduleByConditions(vo);
        String path = "excel/car.xlsx";
        zhqJtsyjcExcelDispose.excelPathDispose(path, scheduleByConditions, cellNameList, i, j, response, width, dispose);
    }

    @Override
    public List findScheduleByConditions(ScheduleVo vo) {
        CarVo carVo1 = new CarVo();
        CarVo carVo2 = new CarVo();
        CarVo carVo3 = new CarVo();
        CarVo carVo4 = new CarVo();
        CarVo carVo5 = new CarVo();
        CarVo carVo6 = new CarVo();
        CarVo carVo7 = new CarVo();
        List carVos = new ArrayList<>();
        carVo1.setBrand("奥迪").setColor("红色").setLength("6.2").setWidth("2.4").setKilometre("600公里").setSpeed("150km/h").setLifetime("3年");
        carVo2.setBrand("宝马").setColor("蓝色").setLength("6.3").setWidth("2.5").setKilometre("700公里").setSpeed("160km/h").setLifetime("4年");
        carVo3.setBrand("比亚迪").setColor("黑色").setLength("6.4").setWidth("2.6").setKilometre("800公里").setSpeed("170km/h").setLifetime("5年");
        carVo4.setBrand("长安").setColor("橙色").setLength("6.5").setWidth("2.7").setKilometre("900公里").setSpeed("180km/h").setLifetime("6年");
        carVo5.setBrand("长城").setColor("渐变红").setLength("6.6").setWidth("2.8").setKilometre("1000公里").setSpeed("190km/h").setLifetime("7年");
        carVo6.setBrand("五菱之光").setColor("青色").setLength("6.7").setWidth("2.9").setKilometre("1100公里").setSpeed("200km/h").setLifetime("8年");
        carVo7.setBrand("奥托").setColor("玫瑰红").setLength("6.8").setWidth("2.0").setKilometre("11200公里").setSpeed("140km/h").setLifetime("9年");
        carVos.add(carVo1);
        carVos.add(carVo2);
        carVos.add(carVo3);
        carVos.add(carVo4);
        carVos.add(carVo5);
        carVos.add(carVo6);
        carVos.add(carVo7);
        return carVos;
    }
}
2.3. 实现类3(公司)
import com.example.export.dispose.ExcelDispose;
import com.example.export.dispose.IDispose;
import com.example.export.dispose.datadispose.CompanyExport;
import com.example.export.service.IExportServiceFactory;
import com.example.export.vo.CompanyVo;
import com.example.export.vo.ScheduleVo;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

@Service
public class CompanyExportServiceImpl implements IExportServiceFactory {

    @Override
    public void exportExcel(ScheduleVo vo, HttpServletResponse response) throws Exception {
        // 新行的索引
        int i = 2;
        // 表头索引
        int j = 1;
        List cellNameList = new ArrayList<>();
        Integer width = null;
        IDispose dispose = new CompanyExport();
        ExcelDispose zhqJtsyjcExcelDispose = new CompanyExport();
//        vo.setYljgLb(DicYljgUtils.findByOrganId(UserUtils.getUser(vo.getUserId()).getOrganId()).getYljgLb());
//        导出excel模板根据传入的参数置空list,1:模板导出;2:全量导出
//        List users = vo.getMb().equals("1") ? new ArrayList<>() : query(vo);
        List scheduleByConditions = findScheduleByConditions(vo);
        String path = "excel/company.xlsx";
        zhqJtsyjcExcelDispose.excelPathDispose(path, scheduleByConditions, cellNameList, i, j, response, width, dispose);
    }

    @Override
    public List findScheduleByConditions(ScheduleVo vo) {
        CompanyVo companyVo1 = new CompanyVo();
        CompanyVo companyVo2 = new CompanyVo();
        CompanyVo companyVo3 = new CompanyVo();
        CompanyVo companyVo4 = new CompanyVo();
        List companyVos = new ArrayList<>();
        companyVo1.setName("北京市律师事务所").setAddress("北京市朝阳区觉得还是开发").setPeopleNum("59").setAverageSalary("12300元").setBusiness("打官司").setScale("200平");
        companyVo2.setName("上海市美食加工厂").setAddress("上海市浦东新区登记是否").setPeopleNum("519").setAverageSalary("12400元").setBusiness("做食品").setScale("2000平");
        companyVo3.setName("上海市机械加工厂").setAddress("上海市闵行区健身房的和").setPeopleNum("5119").setAverageSalary("12500元").setBusiness("加工零件").setScale("20000平");
        companyVo4.setName("陕西旅游公司").setAddress("陕西省西安市扣税的风格").setPeopleNum("58").setAverageSalary("12600元").setBusiness("旅游推荐").setScale("200000平");
        companyVos.add(companyVo1);
        companyVos.add(companyVo2);
        companyVos.add(companyVo3);
        companyVos.add(companyVo4);
        return companyVos;
    }
}
3. 抽象数据处理
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.List;


public interface IDispose {

    
    V getType(List list, int k);

    
    void dataDispose(Row row, Sheet sheet, List cellNameList,
                            List valueList, CellStyle cellStyle, Integer width, int cells);
3.1. 数据处理实现1(用户,全样式)
import com.example.export.dispose.ExcelDispose;
import com.example.export.dispose.IDispose;
import com.example.export.util.DataExportUtils;
import com.example.export.vo.UserVo;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.List;


public class UserExport extends ExcelDispose implements IDispose {

    @Override
    public void dataDispose(Row row, Sheet sheet, List cellNameList,
                            List valueList, CellStyle cellStyle, Integer width, int cells) {
        for (int j = 0; j < cells; j++) {
            Cell cell = row.createCell(j);
            for (int z = 0; z < valueList.size(); z++) {
                if (j == z) {
                    if (j == 0) {
                        // 插入序号,并按照表头对序号进行列宽设置
                        width = DataExportUtils.checkNum(cellNameList.get(0).length());
                        sheet.setColumnWidth(j, width);
                        cell.setCellValue(valueList.get(z));
                        cell.setCellStyle(cellStyle);
                        break;
                    }
                    cell.setCellValue(valueList.get(z));
                    cell.setCellStyle(cellStyle);
                    break;
                }
            }
        }
    }

    @Override
    public UserVo getType(List list, int k) {
        // 对特定数据处理方法
        return list.get(k);
    }

    @Override
    public void valueListDispose(List valueList, UserVo userVo) {
//        例如:valueList.set(2, 调用翻译方法翻译字典项);
    }
}

3.2. 数据处理实现2(汽车,去掉所有样式)
import com.example.export.dispose.ExcelDispose;
import com.example.export.dispose.IDispose;
import com.example.export.util.DataExportUtils;
import com.example.export.vo.CarVo;
import com.example.export.vo.UserVo;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.List;


public class CarExport extends ExcelDispose implements IDispose {

    @Override
    public void dataDispose(Row row, Sheet sheet, List cellNameList,
                            List valueList, CellStyle cellStyle, Integer width, int cells) {
        for (int j = 0; j < cells; j++) {
            Cell cell = row.createCell(j);
            for (int z = 0; z < valueList.size(); z++) {
                if (j == z) {
                    if (j == 0) {
                        // 插入序号,并按照表头对序号进行列宽设置
                        // 删除样式和列宽设置
//                        width = DataExportUtils.checkNum(cellNameList.get(0).length());
//                        sheet.setColumnWidth(j, width);
                        cell.setCellValue(valueList.get(z));
//                        cell.setCellStyle(cellStyle);
                        break;
                    }
                    cell.setCellValue(valueList.get(z));
//                    cell.setCellStyle(cellStyle);
                    break;
                }
            }
        }
    }

    @Override
    public CarVo getType(List list, int k) {
        // 对特定数据处理方法
        return list.get(k);
    }

    @Override
    public void valueListDispose(List valueList, CarVo carVo) {
//        例如:valueList.set(2, 调用翻译方法翻译字典项);
//       给车长和车宽都加上单位
        valueList.set(3, valueList.get(3) + "米");
        valueList.set(4, valueList.get(4) + "米");
    }
}
3.3. 数据处理实现3(公司, 去掉样式,保留动态列宽设置)
import com.example.export.dispose.ExcelDispose;
import com.example.export.dispose.IDispose;
import com.example.export.util.DataExportUtils;
import com.example.export.vo.CompanyVo;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.List;


public class CompanyExport extends ExcelDispose implements IDispose {

    @Override
    public void dataDispose(Row row, Sheet sheet, List cellNameList,
                            List valueList, CellStyle cellStyle, Integer width, int cells) {
        for (int j = 0; j < cells; j++) {
            Cell cell = row.createCell(j);
            for (int z = 0; z < valueList.size(); z++) {
                if (j == z) {
                    if (j == 0) {
                        // 插入序号,并按照表头对序号进行列宽设置
                        // 删除样式但不删除格式
                        width = DataExportUtils.checkNum(cellNameList.get(0).length());
                        sheet.setColumnWidth(j, width);
                        cell.setCellValue(valueList.get(z));
//                        cell.setCellStyle(cellStyle);
                        break;
                    }
                    cell.setCellValue(valueList.get(z));
//                    cell.setCellStyle(cellStyle);
                    break;
                }
            }
        }
    }

    @Override
    public CompanyVo getType(List list, int k) {
        // 对特定数据处理方法
        return list.get(k);
    }

    @Override
    public void valueListDispose(List valueList, CompanyVo companyVo) {
//        例如:valueList.set(2, 调用翻译方法翻译字典项);
    }
}
4. 实体Vo 4.1. 用户
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class UserVo {

    private String id;
    private String name;
    private String age;
    private String sex;
    private String address;
    private String contactInformation;
}
4.2. 汽车
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class CarVo {

    private String id;
    private String brand;
    private String color;
    private String length;
    private String width;
    private String kilometre;
    private String speed;
    private String lifetime;
}
4.3. 公司
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class CompanyVo {

    private String id;
    private String name;
    private String address;
    private String peopleNum;
    private String scale;
    private String averageSalary;
    private String business;
}

5. 表格模板 5.1. 用户模板

5.2. 汽车模板

5.2. 公司模板

6. Controller层(其他两层参考如下用户层)
import com.example.export.service.IExportServiceFactory;
import com.example.export.vo.ScheduleVo;
import com.example.export.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IExportServiceFactory exportService;

    @GetMapping("/export")
    public void export(ScheduleVo scheduleVo, HttpServletResponse response) throws Exception {
        exportService.exportExcel(scheduleVo, response);
    }
}
7. 输出结果 7.1. 用户保留所有样式

7.2. 汽车删除所有样式

7.3. 公司除自适应列宽外样式全部删除

8. 项目层级


本章内容解决了项目内繁琐的if-else开发模式,并且抽取抽象方法,使用工厂模式自动生成对象,简单的静态代理模式增强代码块,强化各个类型的私有属性,这样就可以自定义一个通用的导出方法,无论业务怎么变,抽象方法自身不会发生改变,如果有需求需要强制改变所有类型的结构,我们只需要将抽象方法继承过来,使用简单的代理就可以达到要求,不会动原有的代码,符合设计模式的开闭原则,并且代码的灵动性非常高。
如果有新增其他类型的导出,我们只需要继承抽象类,实现抽象数据处理工厂的方法,就可以达到导出功能。
纯手打,技术有限,请各位大佬批评指正,谢谢!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5686157.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存