簡單的前後端分離的EXCEL上傳、解析、導入數據庫

寫在前面

前後端分離:前端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、訂單號等等),有的話就不插入,沒有的話則插入。
正在學習,歡迎交流,多多指教!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章