写在前面

前后端分离:前端VUE+ELEMENT,后端springboot。

excel上传至后端

设置后端接口

先不做处理,收到文件就回复一个导入成功。(RespBean是为了规范,自己封装的一个用于统一回复格式的类,这里改成String也是一样的)

    @PostMapping("/import")
    public  RespBean importExcel(MultipartFile file){
        System.out.println("收到文件");
        return RespBean.ok("导入成功");
    }

前端使用upload组件

上传时采用的是element的upload组件,不仅仅是element,只要是成熟的Vue组件库肯定都有upload组件,所以这个不所谓,使用对应upload组件即可。具体使用参照官网:element upload组件

<el-upload action="/api/order/import"
	      :show-file-list="false"
	       :on-success="hanleSuccess"
	       accept=".xls">
	<el-button type="primary">导入订单</el-button>
</el-upload>

action指定后端地址;accept指定允许的导入文件的格式;show-file-list置为false,那么成功导入后,页面上不会显示已导入的文件列表(跟代码逻辑无关,只是修改一下视觉效果);hanleSuccess是成功时回调方法,我用来展示后端返回的信息。当然,这几个属性最重要的还是action,其它根据自己开发需要,参照一下官网,自定义就好了。
至此就导入成功了,接下来时excel的解析

解析excel

使用POI:Apache POI提供API给Java对Microsoft Office格式档案读和写的功能。
导入依赖

<!--解析excel-->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>RELEASE</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>RELEASE</version>
</dependency>

创建一个解析excel的工具类,将前端得到的file作为参数:

//controller
    @PostMapping("/import")
    public  RespBean importExcel(MultipartFile file){
//        System.out.println("收到文件");
        List<Order> orders = ExcelUtils.excelToOrder(file);
        return RespBean.ok("导入成功");
    }

下面是工具类的代码:(注释写里面了,节省空间)
简单来说就是:先拿到整个表的对象,再拿到单张sheet的对象,再拿到每一行的对象,再分别取出一行中每一个单元格的值。

public class ExcelUtils {
    public static List<Order> excelToOrder(MultipartFile file){
    	// 新建一个list,用于存放解析结果
        List<Order> list=new ArrayList<>();
        try {
        	// 拿到对象
            HSSFWorkbook workbook = new HSSFWorkbook(file.getInputStream());
            // 一个excel可能有多个sheet,所以遍历sheet
            for (int i = 0; i <workbook.getNumberOfSheets() ; i++) {
            	// 拿到sheet对象
                HSSFSheet sheet = workbook.getSheetAt(i);
//                System.out.println("行数"+sheet.getPhysicalNumberOfRows());
				// 遍历每一行
                for (int j = 0; j <sheet.getPhysicalNumberOfRows() ; j++) {
                	//略过首行,即标题行
                    if(j==0){
                        continue;
                    }
                    // 拿到行的对象
                    HSSFRow row = sheet.getRow(j);
                    // 即使你的表格中没有空行,但也可能会被解析出一些空行,所以我们略过空行,否则会报错
                    if (row==null){
                        continue;
                    }
//                    System.out.println("列数"+row.getPhysicalNumberOfCells());
					// new一个自己的实体类的对象,方便一会儿将解析出来的值存放进去
                    Order order = new Order();
                    // 注意下面这种方法是最简单但是也最死板的方法,就是固定excel的表头
                    // 每一列只能是对应的字段。一旦excel的某两列相互替换一下位置
                    // 那么写入order的值就乱了

					// 遍历一行中的每一个单元格
                    for (int k = 0; k <row.getPhysicalNumberOfCells() ; k++) {
                        // 写固定了,每一列内容不能变
                        if(k==0){
                            //订单号
                            order.setOrdernumber(row.getCell(k).getStringCellValue());
                        }
                        else if(k==1){
                            //产线
                            order.setLinename(row.getCell(k).getStringCellValue());
                        }
                        else if(k==2){
                            // 订单时间
                            order.setSubmittime(row.getCell(k).getDateCellValue());
                        }
                        else if(k==3){
                            // 交货时间
                            order.setDelivertime(row.getCell(k).getDateCellValue());
                        }
                        else if(k==4){
                            // 规格
                            order.setGuige(row.getCell(k).getStringCellValue());
                        }
                        else if(k==5){
                            // 备注
                            order.setSpecification(row.getCell(k).getStringCellValue());
                        }
                        else ;
                    }
                    // 将order对象添加到list中
                    list.add(order);
//                    System.out.println(order);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }
}

至此,excel的解析就完成了,并且我们也得到了一个待存放入数据库的list。下一步就是常规的入库了。

写入数据库

这一步就常规了,就一个普通的insert操作,不详细写了。

    @PostMapping("/import")
    public  RespBean importExcel(MultipartFile file){
        List<Order> orders = ExcelUtils.excelToOrder(file);
        // 遍历list,导入数据库。
        for (Order order : orders) {
            orderService.save(order);
        }
        return RespBean.ok("导入成功");
    }

用的Mybatis。mapper、service什么的根据自己的情况写了就OK了。

写在后面

上述的excel解析方法,较为简单,要求导入的excel格式要严格规范。
要想通用性强一点的话,可以考虑以下思路:判断表头;判断单元格值的属性再进行枚举。
后续可能的问题:为了防止重复导入,在解析结果入库时,应该先判断数据库内是否已经有对应的数据了。可以根据某个唯一的字段进行查询(比如:身份证号、用户唯一id、订单号等等),有的话就不插入,没有的话则插入。
正在学习,欢迎交流,多多指教!

Logo

前往低代码交流专区

更多推荐