springboot实现简单的excel导入

前文其实已经实现了较为复杂的excel导入了,这篇博客就给大家介绍简单的excel表格导入方法

以下是我的excel表格:

以下是我的实体类:

java 复制代码
package com.datapojo.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.Date;

/**
 * <p>
 * 
 * </p>
 *
 * @author yinan
 * @since 2024-03-08
 */
@Getter
@Setter
@Builder
@TableName("data_standard_manage")
@ApiModel(value = "DataStandardManage对象", description = "")
public class DataStandardManage implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty("数据库标准id")
    @TableId(value = "data_id", type = IdType.AUTO)
    private Integer dataId;

    @ApiModelProperty("数据标准编号")
    @TableField("data_standard_code")
    private String dataStandardCode;

    @ApiModelProperty("中文名")
    @TableField("cn_name")
    private String cnName;

    @ApiModelProperty("英文名")
    @TableField("en_name")
    private String enName;

    @ApiModelProperty("数据标准说明")
    @TableField("data_standard_explain")
    private String dataStandardExplain;

    @ApiModelProperty("来源机构")
    @TableField("source_orgnization")
    private String sourceOrgnization;

    @ApiModelProperty("数据类型")
    @TableField("data_standard_type")
    private String dataStandardType;

    @ApiModelProperty("数据长度")
    @TableField("data_standard_length")
    private Double dataStandardLength;

    @ApiModelProperty("数据精度")
    @TableField("data_standard_accuracy")
    private Double dataStandardAccuracy;

    @ApiModelProperty("默认值")
    @TableField("data_standard_default")
    private String dataStandardDefault;

    @ApiModelProperty("取值范围的最大值")
    @TableField("data_standard_value_max")
    private String dataStandardValueMax;

    @ApiModelProperty("取值范围的最小值")
    @TableField("data_standard_value_min")
    private String dataStandardValueMin;

    @ApiModelProperty("枚举范围:字典组编码")
    @TableField("data_standard_enumeration_range")
    private String dataStandardEnumerationRange;

    @ApiModelProperty("标准状态(0:未发布  1:已发布 2:已停用)")
    @TableField("data_standard_status")
    private Integer dataStandardStatus;

    @ApiModelProperty("是否为空(0:可为空 1:不为空)")
    @TableField("data_standard_is_blank")
    private Integer dataStandardIsBlank;

    @ApiModelProperty("创建时间")
    @TableField("create_time")
    @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
    private Date createTime;

    @ApiModelProperty("修改数据")
    @TableField("update_time")
    @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
    private Date updateTime;


}
复制代码
FileUploadConfig工具类:
java 复制代码
public String objectNameFromUploadPath(String filepath) {
        // 假设filepath是一个完整的URL形式
        // 首先判断是否为空或者不是一个合法的HTTP/HTTPS URL
        if (filepath == null || !(filepath.startsWith("http://") || filepath.startsWith("https://"))) {
            throw new IllegalArgumentException("Invalid file path: " + filepath);
        }

        try {
            // 将文件路径转换成URL对象
            URL url = new URL(filepath);
            // 获取URL的路径部分
            String path = url.getPath();

            // 我们需要去掉路径前的"/",因为OSS object name是不带前导"/"的
            if (path.startsWith("/")) {
                path = path.substring(1);
            }

            // 返回"files/"之后的部分作为object name
            int filesIndex = path.indexOf("files/");
            if (filesIndex != -1) {
                // 返回 "files/" 后面的部分
                return path.substring(filesIndex);
            } else {
                // 如果路径中不含 "files/",直接使用路径作为object name,根据具体情况调整
                return path;
            }
        } catch (MalformedURLException e) {
            throw new IllegalArgumentException("Malformed file path URL: " + filepath, e);
        }
    }

这里的filepath路径我是将前端传给我的文件先上传到oss上面然后获取的链接,你也可以上传到自己本地然后获取文件,或者后台私信我给你具体的上传oss的代码。

接下来是具体的service里面的实现方法:

java 复制代码
  public R addDataStandardsByExcel(MultipartFile file) throws IOException {
//        String filepath = fileUploadConfig.upload(file);
        String filepath = "https://yinan-bucket.oss-cn-beijing.aliyuncs.com/files/33ae3fdb-7b9d-46f4-8227-62c0189c08d6.xlsx";
        String filename = fileUploadConfig.objectNameFromUploadPath(filepath);
        System.out.println("filepath:" + filepath + "  filename:" + filename);
        String fileName = file.getOriginalFilename();
//        if (Objects.equals(filepath, "文件上传失败")) {
//            return R.Failed("文件上传失败,无法进行数据导入");
//        }
//        初始化变量
        boolean notNull = false;
        List<DataStandardManage> dsmList = new ArrayList<>();
//        InputStream is = fileUploadConfig.download(filename);
        InputStream is = file.getInputStream();
//        检查文件格式是否正确
        if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
//            自定义异常处理
            throw new FileNotStandardException(MessageConstant.File_NOT_STANDARD);
        }
        Workbook workbook = null;
        try {
            // 判断文件是2003格式的Excel还是2007格式的Excel
            boolean isExcel2003 = true;
            if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
                isExcel2003 = false;
            }
//        创建workbook对象
            workbook = null;
            if (isExcel2003) {
                workbook = new HSSFWorkbook(is);
            } else {
                workbook = new XSSFWorkbook(is);
            }
//        获取第一个工作表
            Sheet sheet = workbook.getSheetAt(0);
//        判断是否为空
            if (sheet != null) {
                notNull = false;
            } else {
                throw new FileIsEmptyException(MessageConstant.FILE_IS_EMPTY);
            }
//        遍历工作表的每一行
            for (int i = 1; i <= Objects.requireNonNull(sheet).getLastRowNum(); i++) {
                Row row = sheet.getRow(i);
                // 检查行是否为空
                if (row == null) {
                    continue; // 如果为空,跳过该行
                }
                DataStandardManage dsm = null;
                String dsmCnName = row.getCell(0).getStringCellValue();
                String dsmEnName = row.getCell(1).getStringCellValue();
                String dsmExplain = row.getCell(2) == null ? null : row.getCell(2).getStringCellValue();
                Integer dsmIsBlank = Objects.equals(row.getCell(3).getStringCellValue(), "可为空") ? 0 : 1;
                String dsmSourceOrg = row.getCell(4).getStringCellValue();
                String dsmDefault = row.getCell(5) == null ? null : row.getCell(5).getStringCellValue();
                String dsmDataType = row.getCell(6).getStringCellValue();
                Double dsmLength = row.getCell(7) == null ? null : row.getCell(7).getNumericCellValue();

                // 格式化科学计数法,取一位整数,如取小数,值如0.0,取小数点后几位就写几个0
                DecimalFormat df = new DecimalFormat("0");

                Double dsmAccuracy = ObjectUtils.isEmpty(row.getCell(8).getNumericCellValue()) ? null : row.getCell(7).getNumericCellValue();
//                Integer dsmAccuracy = dsmAccuracyTemp == null ? null : Integer.parseInt(df.format(dsmAccuracyTemp));

                Double dsmMinTemp = ObjectUtils.isEmpty(row.getCell(9).getNumericCellValue()) ? null : row.getCell(8).getNumericCellValue();
                String dsmMin = dsmMinTemp == null ? null : df.format(dsmMinTemp);

//                String dsmMin=ObjectUtils.isEmpty(row.getCell(9))?null:String.valueOf(row.getCell(9).getNumericCellValue());//使用此方法也可以,但是转换后格式有点不对
                Double dsmMaxTemp = ObjectUtils.isEmpty(row.getCell(10).getNumericCellValue()) ? null : row.getCell(10).getNumericCellValue();
                String dsmMax = dsmMaxTemp == null ? null : df.format(dsmMaxTemp);
//                String dsmMax=ObjectUtils.isEmpty(row.getCell(10))?null:String.valueOf(row.getCell(10).getNumericCellValue());
                String dsmMaBiao = row.getCell(11) == null ? null : row.getCell(11).getStringCellValue();
                dsm = DataStandardManage.builder()
                        .dataStandardCode(RandomUtil.generateRandomNumber("BZ",2))
                        .cnName(dsmCnName)
                        .enName(dsmEnName)
                        .dataStandardExplain(dsmExplain)
                        .sourceOrgnization(dsmSourceOrg)
                        .dataStandardType(dsmDataType)
                        .dataStandardIsBlank(dsmIsBlank)
                        .dataStandardDefault(dsmDefault)
                        .dataStandardLength(dsmLength)
                        .dataStandardAccuracy(dsmAccuracy)
                        .dataStandardValueMin(dsmMin)
                        .dataStandardValueMax(dsmMax)
                        .dataStandardEnumerationRange(dsmMaBiao)
                        .createTime(dateConfig.getDate())
                        .updateTime(dateConfig.getDate())
                        .dataStandardStatus(0)
                        .build();
                dsmList.add(dsm);
            }
            for (DataStandardManage dsm : dsmList) {
                dataStandardManageDao.insert(dsm);
                System.out.println("插入:" + dsm);
            }
            is.close();
            return R.Success("导入成功");
        } catch (Exception e) {
            // 处理文件读取异常
            e.printStackTrace(); // 这里可以记录日志或者返回相应错误信息
            return R.Failed("文件读取异常,无法进行数据导入");
        } finally {
            // 确保关闭流
            if (workbook != null) {
                workbook.close();
            }
            is.close();
        }
    }

代码中均做有注释,不懂得可以在评论区进行留言~

相关推荐
骆晨学长7 分钟前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
AskHarries12 分钟前
利用反射实现动态代理
java·后端·reflect
bjzhang7513 分钟前
SpringBoot开发——整合SpringDoc实现在线接口文档
spring boot·springdoc
Flying_Fish_roe35 分钟前
Spring Boot-Session管理问题
java·spring boot·后端
赚钱给孩子买茅台喝37 分钟前
智能BI项目第四期
java·spring boot·spring cloud·aigc
hai405871 小时前
Spring Boot中的响应与分层解耦架构
spring boot·后端·架构
执键行天涯2 小时前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis
Adolf_19933 小时前
Flask-JWT-Extended登录验证, 不用自定义
后端·python·flask
叫我:松哥3 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
海里真的有鱼3 小时前
Spring Boot 项目中整合 RabbitMQ,使用死信队列(Dead Letter Exchange, DLX)实现延迟队列功能
开发语言·后端·rabbitmq