POI異步導入Excel兼容xsl和xlsx


項目架構:spring+struts2+hibernate4+oracle

需求:用戶導入excel文件,導入到相應的數據表中,要求提供導入模板,支持xls和xlsx文件

思路分析:

1、提供一個下載鏈接,點擊下載,可以使超鏈接,src直接是項目路徑加文件名。

2、通過上傳文件,服務器接收上傳,返回一個上傳后的服務器本地路徑,通過ajax異步賦值到jsp的路徑隱藏域。

3、ajax異步提交導入請求,后台處理,將路徑轉換成File,File轉換成MultipartFile,將文件讀取轉換成一個數組類型的集合。

4、循環集合這種的數據,每一行excel數據,是一個元素,將元素轉換成相應的java對象進行保存。

 

一、所需jar包

一共是6個jar包。

二、前端jsp代碼部分

<input type="hidden" id="excelFilePath" name="excelFilePath" value="" />
                <tr>
                    <td>選擇文件:</td>
                    <td><input type="file" name="uploadFile" id="excelFile"></input></input>
                    <span id="uploadMsg"></span></td>
                </tr>
                <tr>
                    <td></td>
                    <td> <input type="button" value="上傳" onclick="fileUpload()">
                    &nbsp;
                    <input type="button" value="導入" id="btnOk" disabled="true" onclick="importEmp()"/>
                    </td>
                </tr>

<script type="text/javascript">
    // 文件上傳
    function fileUpload(){
        $("#fileTypeError").html("");
        $("#btnOk").attr("disabled",true);
        var fileName = $("#excelFile").val();
        var fileType = fileName.substr(fileName.length-4,fileName.length);
        if(fileType == ".xls" || fileType == "xlsx"){
            
            var uploadFileUrl = "${basePath}/public/uploadFile.action";
            var formData = new FormData($("#mainForm")[0]);
            $.ajax({
                type: "POST",  
                url: uploadFileUrl, 
                data: formData,
                cache: false,
                processData: false,  
                contentType: false, 
                dataType : "json",
                success: function(data){
                    if(null != data){
                        if (data.dataStatus == "1") {
                            $("#uploadMsg").html("<font color='green'>上傳成功!</font>");
                            $("#btnOk").attr("disabled",false);
                            $("#excelFilePath").attr("value",data.dataMain);
                            //alert($("#excelFilePath").val());
                        } else {
                            if (data.errorMsg != null
                                    && data.errorMsg.length > 0) {
                                alert(data.errorMsg);
                                $("#uploadMsg").html("<font color='red'>" +data.errorMsg + "請仔細閱讀操作說明!</font>");
                            }
                        }
                    }
                },
                error : function(XMLHttpRequest, textStatus,
                        errorThrown) {
                    alert("系統異常[" + textStatus + "]:" + errorThrown);
                }
            });
        }else{
            $("#uploadMsg").html("<font color='red'>上傳文件類型錯誤,支持類型: .xls .xlsx</font>");
            
        }
    }
    //Excel文件導入到數據庫中       
    function importEmp(){  
        var importExcelURL = "${basePath}/public/importResultExaminee.action";
        var excelFilePath = $("#excelFilePath").val();
        $.ajax({
            type: "POST",  
            url: importExcelURL, 
            data: {"excelFilePath":excelFilePath},
            cache: false,
            dataType : "json",
            success: function(data){
                if(null != data){
                    if (data.dataStatus == "1") {
                        $("#btnOk").attr("disabled",false);
                        alert("本次成功導入數量:" + data.dataMain);
                    }else{
                        if (data.errorMsg != null
                                && data.errorMsg.length > 0) {
                            alert(data.errorMsg);
                        }
                    }
                }
            },
            error : function(XMLHttpRequest, textStatus,
                    errorThrown) {
                alert("系統異常[" + textStatus + "]:" + errorThrown);
            }
            
        })
    } 
</script>

 

三、核心處理類POIUtils代碼:

package com.sinotn.utils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

/**
 * excel導出導入工具類
 * Copyright (c) 2018 by Sinotn
 * @author Libin
 * @date 2018年4月8日 上午9:39:50
 */
public class POIUtils {

    private static Logger logger = Logger.getLogger(POIUtils.class);
    private final static String XLS = "xls";
    private final static String XLSX = "xlsx";
    /**
     * 讀取excel文件
     * @param formFile
     * @return
     * @throws IOException
     */
    public static List<String[]> readExcel(MultipartFile  formFile) throws IOException {
        // 檢查文件
        checkFile(formFile);
        //獲得Workbook工作薄對象
        Workbook workbook = getWorkBook(formFile);
        //創建返回對象,把每行中的值作為一個數組,所有行作為一個集合返回  
        List<String[]> list = new ArrayList<String[]>();
        if (null != workbook) {
            for (int sheetNum  = 0; sheetNum < workbook.getNumberOfSheets();sheetNum++) {
                //獲得當前sheet工作表  
                Sheet sheet = workbook.getSheetAt(sheetNum);
                if (null == sheet) {
                    continue;
                }
                //獲得當前sheet的開始行  
                int firstRowNum  = sheet.getFirstRowNum();  
                //獲得當前sheet的結束行  
                int lastRowNum = sheet.getLastRowNum();  
                //循環除了第一行的所有行 
                for (int rowNum = firstRowNum + 1;rowNum <= lastRowNum;rowNum++) {
                     //獲得當前行  
                    Row row = sheet.getRow(rowNum);  
                    if(row == null){  
                        continue;  
                    }  
                    //獲得當前行的開始列  
                    int firstCellNum = row.getFirstCellNum();  
                    //獲得當前行的列數  
                    int lastCellNum = row.getPhysicalNumberOfCells();  
                    String[] cells = new String[row.getPhysicalNumberOfCells()];  
                    //循環當前行  
                    for (int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++) {
                        Cell cell = row.getCell(cellNum);  
                        cells[cellNum] = getCellValue(cell);
                    }
                    list.add(cells);
                }
            }
             workbook.close();  
        }
        return list;

    }
    
    /**
     * 獲取當前行數據
     * @param cell
     * @return
     */
    @SuppressWarnings("deprecation")
    private static String getCellValue(Cell cell) {
        String cellValue = "";  
        if(cell == null){  
            return cellValue;  
        }  
        //把數字當成String來讀,避免出現1讀成1.0的情況  
        if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){  
            cell.setCellType(Cell.CELL_TYPE_STRING);  
        }  
      //判斷數據的類型  
        switch (cell.getCellType()){  
            case Cell.CELL_TYPE_NUMERIC: //數字  
                cellValue = String.valueOf(cell.getNumericCellValue());  
                break;  
            case Cell.CELL_TYPE_STRING: //字符串  
                cellValue = String.valueOf(cell.getStringCellValue());  
                break;  
            case Cell.CELL_TYPE_BOOLEAN: //Boolean  
                cellValue = String.valueOf(cell.getBooleanCellValue());  
                break;  
            case Cell.CELL_TYPE_FORMULA: //公式  
                cellValue = String.valueOf(cell.getCellFormula());  
                break;  
            case Cell.CELL_TYPE_BLANK: //空值   
                cellValue = "";  
                break;  
            case Cell.CELL_TYPE_ERROR: //故障  
                cellValue = "非法字符";  
                break;  
            default:  
                cellValue = "未知類型";  
                break;  
        }  
        return cellValue;  
    }
    
    /**
     * 獲得Workbook工作薄對象
     * @param formFile
     * @return
     */
    private static Workbook getWorkBook(MultipartFile  formFile) {
         //獲得文件名  
        String fileName = formFile.getName();
        //創建Workbook工作薄對象,表示整個excel  
        Workbook workbook = null;  
        try {  
            //獲取excel文件的io流  
            InputStream is = formFile.getInputStream();
            //根據文件后綴名不同(xls和xlsx)獲得不同的Workbook實現類對象  
            if(fileName.endsWith(XLS)){  
                //2003  
                workbook = new HSSFWorkbook(is);  
            }else if(fileName.endsWith(XLSX)){  
                //2007  
                workbook = new XSSFWorkbook(is);  
            }  
        } catch (IOException e) {  
            logger.info(e.getMessage());  
        }  
        return workbook;  
    }
    /**
     * 檢查文件
     * @param formFile
     * @throws IOException
     */
    private static void checkFile(MultipartFile  formFile) throws IOException {
        //判斷文件是否存在  
        if(null == formFile){  
            logger.error("文件不存在!");  
            throw new FileNotFoundException("文件不存在!");  
        }  
        //獲得文件名  
        String fileName = formFile.getName();
        //判斷文件是否是excel文件  
        if(!fileName.endsWith(XLS) && !fileName.endsWith(XLSX)){  
            logger.error(fileName + "不是excel文件");  
            throw new IOException(fileName + "不是excel文件");  
        }  
        
    }

}

四、action層代碼

POIUtil.readExcel方法讀取excel文件后,把一行中的值按先后順序組成一個數組,所有的行作為一個集合返回。我們可以在代碼中循環這個集合,把數組賦值到實體類對象中。

我在前台用form表單提交file文件,因為用的SpringMVC框架,后台用MultipartFile接收,代碼如下:

 

/**
 * 讀取excel文件中的用戶信息,保存在數據庫中
 * @param excelFile
 */
@RequestMapping("/readExcel")
public void readExcel(@RequestParam(value = "excelFile") MultipartFile excelFile,HttpServletRequest req,HttpServletResponse resp){
    Map<String, Object> param = new HashMap<String, Object>();
    List<User> allUsers = new ArrayList<User>();
    try {
        List<String[]> userList = POIUtil.readExcel(excelFile);
        for(int i = 0;i<userList.size();i++){
          String[] users = userList.get(i);
          User user = new User();
          user.setUserName(users[0]);
          user.setPassword(users[1]);
          user.setAge(Integer.parseInt(users[2]));
          allUsers.add(user);
         }
       } catch (IOException e) {
        logger.info("讀取excel文件失敗", e);
       }
     param.put("allUsers", allUsers);
     this.userService.insertUsers(param);
}

 

調用的service層方法就不貼代碼了,下面就是往數據庫插入數據了。

excel文件內容:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM