使用POI插件实现Excel含有合并行的导入

一、要导入的Excel样式如下图  红色是合并行的单元格  紫色是正常单元格

  需要实现的功能是作业类型存一张表  作业步骤另一张表 后面未合并的部分在第三张表中

二、EXCEL解析工具类

package com.xxx.xxx.commons.utils;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFSheet;
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.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * EXCEL解析工具类
 *
 * @author ZP
 * @ClassName: ExcelUtils
 * @Description: TODO(EXCEL解析工具类)
 * @date 2016年4月29日 上午10:49:44
 */
public class ExcelUtils {
    private static Logger logger = Logger.getLogger(ExcelUtils.class);

    /**
     * 解析EXCEL数据
     * @author ZP
     * @Title: inputDataInfo
     * @Description: TODO(解析EXCEL数据)
     * @param stream
     * @param fileType
     * @return    设定文件
     * @return List<Map<Integer,String>>    返回类型
     * @throws
     */
    public static List<Map<Integer, String>> inputDataInfo(InputStream stream, String fileType) {
        List<Map<Integer, String>> resultList = null;
        if ("xls".equals(fileType)) {
            resultList = read2003Excel(stream, fileType);
        } else if ("xlsx".equals(fileType)) {
            resultList = read2007Excel(stream, fileType);
        }
        return resultList;
    }

    /**
     * 读取07版EXCEL
     * @author ZP
     * @Title: read2007Excel
     * @Description: TODO(读取07版EXCEL)
     * @param stream
     * @param fileType
     * @return    设定文件
     * @return List<Map<Integer,String>>    返回类型
     * @throws
     */
    private static List<Map<Integer, String>> read2007Excel(InputStream stream, String fileType) {
        try {
            XSSFWorkbook xwb = new XSSFWorkbook(stream);
            // 定义Excel中对象集合接收读取到的文件
            List<Map<Integer, String>> list = new ArrayList<Map<Integer, String>>();

            // 得到Excel工作表对象
            XSSFSheet xSheet = xwb.getSheetAt(0);
            for (int j = 1; j < xSheet.getLastRowNum() + 1; j++) {
                // 获取当前行对象
                Row row = xSheet.getRow(j);
                if (row == null) {
                    continue;
                }
                // 迭代列
                Map<Integer, String> map = new HashMap<Integer, String>();
                // 列的迭代器
                Iterator<Cell> cellIterator = (Iterator<Cell>) row.cellIterator();
                int i = 0;
                while (cellIterator.hasNext()) {
                    // 当前列对象
                    Cell cell = cellIterator.next();
                    if (null != cell) {
                        switch (cell.getCellType()) {
                        case HSSFCell.CELL_TYPE_STRING:
                            map.put(i, cell.getStringCellValue().trim());
                            break;
                        case HSSFCell.CELL_TYPE_NUMERIC:
                            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                String date = sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
                                map.put(i, date);
                                break;
                            } else {
                                HSSFDataFormatter dataFormatter = new HSSFDataFormatter();
                                String cellFormatted = dataFormatter.formatCellValue(cell);
                                map.put(i, cellFormatted);
                                break;
                            }
                        case HSSFCell.CELL_TYPE_FORMULA:
                            map.put(i, cell.getCellFormula());
                            break;
                        case HSSFCell.CELL_TYPE_BLANK:
                            map.put(i, null);
                            break;
                        default:
                            map.put(i, null);
                            break;
                        }
                    } else {
                        map.put(i, null);
                    }
                    i++;
                }

                if (map != null && !map.isEmpty()) {
                    list.add(map);
                }
            }

            return list;
        } catch (Exception e) {
            logger.error("服务器解析出错!");
        }
        return null;
    }

    /**
     * 读取03版EXCEL
     * @author ZP
     * @Title: read2007Excel
     * @Description: TODO(读取07版EXCEL)
     * @param stream
     * @param fileType
     * @return    设定文件
     * @return List<Map<Integer,String>>    返回类型
     * @throws
     */
    private static List<Map<Integer, String>> read2003Excel(InputStream stream, String fileType) {
        try {
            HSSFWorkbook wb = new HSSFWorkbook(stream);
            // 定义Excel中对象集合接收读取到的文件
            List<Map<Integer, String>> list = new ArrayList<Map<Integer, String>>();

            // 得到Excel工作表对象
            HSSFSheet sheet = wb.getSheetAt(0);
            for (int j = 1; j < sheet.getLastRowNum() + 1; j++) {
                // 获取当前行对象
                Row row = sheet.getRow(j);
                if (row == null) {
                    continue;
                }
                // 迭代列
                Map<Integer, String> map = new HashMap<Integer, String>();
                // 列的迭代器
                Iterator<Cell> cellIterator = (Iterator<Cell>) row.cellIterator();
                int i = 0;
                while (cellIterator.hasNext()) {
                    // 当前列对象
                    Cell cell = cellIterator.next();
                    if (null != cell) {
                        switch (cell.getCellType()) {
                        case HSSFCell.CELL_TYPE_STRING:
                            map.put(i, cell.getStringCellValue().trim());
                            break;
                        case HSSFCell.CELL_TYPE_NUMERIC:
                            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                                String date = sdf.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
                                map.put(i, date);
                                break;
                            } else {
                                HSSFDataFormatter dataFormatter = new HSSFDataFormatter();
                                String cellFormatted = dataFormatter.formatCellValue(cell);
                                map.put(i, cellFormatted);
                                break;
                            }
                        case HSSFCell.CELL_TYPE_FORMULA:
                            map.put(i, cell.getCellFormula());
                            break;
                        case HSSFCell.CELL_TYPE_BLANK:
                            map.put(i, null);
                            break;
                        default:
                            map.put(i, null);
                            break;
                        }
                    } else {
                        map.put(i, null);
                    }
                    i++;
                }

                if (map != null && !map.isEmpty()) {
                    list.add(map);
                }
            }

            return list;
        } catch (Exception e) {
            logger.error("服务器解析出错!");
        }
        return null;
    }

    /**   
    * 获取单元格的值   
    * @param cell   
    * @return   
    */
    public static String getCellValue(Cell cell) {
        if (cell == null)
            return "";
        if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
            return cell.getStringCellValue();
        } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
            return String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
            return cell.getCellFormula();
        } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
            return String.valueOf(cell.getNumericCellValue());
        }
        return "";
    }

    /** 
    * 合并单元格处理,获取合并行 
    * @param sheet 
    * @return List<CellRangeAddress> 
    */
    public static List<CellRangeAddress> getCombineCell(Sheet sheet) {
        List<CellRangeAddress> list = new ArrayList<CellRangeAddress>();
        // 获得一个 sheet 中合并单元格的数量
        int sheetmergerCount = sheet.getNumMergedRegions();
        // 遍历所有的合并单元格
        for (int i = 0; i < sheetmergerCount; i++) {
            // 获得合并单元格保存进list中
            CellRangeAddress ca = sheet.getMergedRegion(i);
            list.add(ca);
        }
        return list;
    }

    // 获取合并行的最后一行的下标
    public static int getRowNum(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet) {
        int xr = 0;
        int firstC = 0;
        int lastC = 0;
        int firstR = 0;
        int lastR = 0;
        for (CellRangeAddress ca : listCombineCell) {
            // 获得合并单元格的起始行, 结束行, 起始列, 结束列
            firstC = ca.getFirstColumn();
            lastC = ca.getLastColumn();
            firstR = ca.getFirstRow();
            lastR = ca.getLastRow();
            if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
                if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
                    xr = lastR;
                }
            }

        }
        return xr;

    }

    /** 
     * 判断单元格是否为合并单元格,是的话则将单元格的值返回 
     * @param listCombineCell 存放合并单元格的list 
     * @param cell 需要判断的单元格 
     * @param sheet sheet 
     * @return 
     */
    public static String isCombineCell(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet)
            throws Exception {
        int firstC = 0;
        int lastC = 0;
        int firstR = 0;
        int lastR = 0;
        String cellValue = null;
        for (CellRangeAddress ca : listCombineCell) {
            // 获得合并单元格的起始行, 结束行, 起始列, 结束列
            firstC = ca.getFirstColumn();
            lastC = ca.getLastColumn();
            firstR = ca.getFirstRow();
            lastR = ca.getLastRow();
            if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
                if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
                    Row fRow = sheet.getRow(firstR);
                    Cell fCell = fRow.getCell(firstC);
                    cellValue = getCellValue(fCell);
                    break;
                }
            } else {
                cellValue = "";
            }
        }
        return cellValue;
    }

    /**   
    * 获取合并单元格的值   
    * @param sheet   
    * @param row   
    * @param column   
    * @return   
    */
    public static String getMergedRegionValue(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();

        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress ca = sheet.getMergedRegion(i);
            int firstColumn = ca.getFirstColumn();
            int lastColumn = ca.getLastColumn();
            int firstRow = ca.getFirstRow();
            int lastRow = ca.getLastRow();

            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    Row fRow = sheet.getRow(firstRow);
                    Cell fCell = fRow.getCell(firstColumn);
                    return getCellValue(fCell);
                }
            }
        }

        return null;
    }

    /**  
    * 判断指定的单元格是否是合并单元格  
    * @param sheet   
    * @param row 行下标  
    * @param column 列下标  
    * @return  
    */
    public static boolean isMergedRegion(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return true;
                }
            }
        }
        return false;
    }
}

三 、controller层中导入的方法

  其中使用的 MultipartFile类可以去看一下他的api (别人的博客:https://www.cnblogs.com/chenhonggao/p/8994598.html)

@RequestMapping(value = "/import")
    @ResponseBody
    public Map<String, Object> importExcel(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        User user = (User) session.getAttribute(Constants.SESSION_KEY_LOGIN_INFO);
        String fileName = file.getOriginalFilename();// 返回原来的文件名在客户机的文件系统
        boolean isE2007 = false; // 判断是否是excel2007格式
        if (fileName.endsWith("xlsx")) {
            isE2007 = true;
        }
        int rowIndex = 0;
        int columnIndex = 0;
        try {
            InputStream input = file.getInputStream(); // 返回InputStream读取文件的内容。
            Workbook wb = null;
            // 根据文件格式(2003或者2007)来初始化
            if (isE2007) {
                wb = new XSSFWorkbook(input);
            } else {
                wb = new HSSFWorkbook(input);
            }
            Sheet sheet = wb.getSheetAt(0); // 获得第一个表单

            // System.out.println("总行数:"+sheet.getLastRowNum());

            List<CellRangeAddress> cras = ExcelUtils.getCombineCell(sheet);
            // isMergedRegion(Sheet sheet,int row ,int column);判断是不是合并单元格
            int count = sheet.getLastRowNum() + 1;// 总行数

            // 从第三行开始取值
            for (int i = 2; i < count; i++) {
                rowIndex = i;
                Row row = sheet.getRow(i);
                JSRManage jsr = new JSRManage();//风险管理实体
                jsr.setJsrdangerName(ExcelUtils.getCellValue(row.getCell(1)));
                jsr.setCreateTime(DateUtils.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
                jsr.setCreateName(user.getUsername());
                jsr.setCreator(user.getId());
                jsr.setJsrdangerCode(bussNumberService.getSerialNumber(Constants.JSR_CODE, null));
                int countJsr = jsrManageService.insertJSR(jsr);//风险管理id
                // 第i行第二列是否合并行
                if (ExcelUtils.isMergedRegion(sheet, i, 1)) {
                    int lastRow = ExcelUtils.getRowNum(cras, sheet.getRow(i).getCell(1), sheet);
                    for (; i <= lastRow; i++) {
                        row = sheet.getRow(i);
                        WorkStep workStep = new WorkStep();//作业步骤实体类
                        workStep.setJsrdangerId(countJsr);
                        workStep.setJsrdangerStepName(ExcelUtils.getCellValue(row.getCell(2)));
                        workStep.setCreator(user.getId());
                        workStep.setCreateName(user.getUsername());
                        workStep.setCreateTime(DateUtils.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
                        workStep.setLevel(i);
                        int countWork = workStepService.insertWorkStep(workStep);// 步骤id
                        SystemLogger.info(countWork > 0 ? "工作步骤新增成功!" : "工作步骤新增失败!");
                        // 第i行第三列是否合并行
                        if (ExcelUtils.isMergedRegion(sheet, i, 2)) {
                            int lastRow3 = ExcelUtils.getRowNum(cras, sheet.getRow(i).getCell(2), sheet);
                            List<FewRisk> riskList = new ArrayList<FewRisk>();
                            for (; i <= lastRow3; i++) {
                                row = sheet.getRow(i);
                                FewRisk fewRisk = new FewRisk();//风险实体类
                                fewRisk.setJsrdangerStepId(countWork);
                                fewRisk.setCreator(user.getId());
                                fewRisk.setCreateName(user.getUsername());
                                fewRisk.setCreateTime(DateUtils.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
                                fewRisk.setRiskName(ExcelUtils.getCellValue(row.getCell(3)));
                                fewRisk.setPreventtName(ExcelUtils.getCellValue(row.getCell(4)));
                                fewRisk.seteFrenqucy(Double.valueOf(ExcelUtils.getCellValue(row.getCell(5))));
                                fewRisk.setSeverity(Double.valueOf(ExcelUtils.getCellValue(row.getCell(6))));
                                fewRisk.setPossible(Double.valueOf(ExcelUtils.getCellValue(row.getCell(7))));
                                Double frenqucy = Double.valueOf(ExcelUtils.getCellValue(row.getCell(5)));
                                Double severity = Double.valueOf(ExcelUtils.getCellValue(row.getCell(6)));
                                Double possible = Double.valueOf(ExcelUtils.getCellValue(row.getCell(7)));
                                Double riskLevelTemp = frenqucy*severity*possible;
                                if (riskLevelTemp>=320) {
                                    fewRisk.setRiskLevel(Double.valueOf(5));
                                } else if(riskLevelTemp>=160){
                                    fewRisk.setRiskLevel(Double.valueOf(4));
                                }else if(riskLevelTemp>=70){
                                    fewRisk.setRiskLevel(Double.valueOf(3));
                                }else if(riskLevelTemp>=20){
                                    fewRisk.setRiskLevel(Double.valueOf(2));
                                }else{
                                    fewRisk.setRiskLevel(Double.valueOf(1));
                                }
                                fewRisk.setLevel(i);
                                riskList.add(fewRisk);
                            }
                            int total = fewRiskService.insertRiskList(riskList);
                            SystemLogger.info(total > 0 ? "风险新增成功!" : "风险新增失败!");
                            i--;
                        } else {
                            List<FewRisk> riskList = new ArrayList<FewRisk>();
                            row = sheet.getRow(i);
                            FewRisk fewRisk = new FewRisk();
                            fewRisk.setJsrdangerStepId(countWork);
                            fewRisk.setCreator(user.getId());
                            fewRisk.setCreateName(user.getUsername());
                            fewRisk.setCreateTime(DateUtils.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
                            fewRisk.setRiskName(ExcelUtils.getCellValue(row.getCell(3)));
                            fewRisk.setPreventtName(ExcelUtils.getCellValue(row.getCell(4)));
                            fewRisk.seteFrenqucy(Double.valueOf(ExcelUtils.getCellValue(row.getCell(5))));
                            fewRisk.setSeverity(Double.valueOf(ExcelUtils.getCellValue(row.getCell(6))));
                            fewRisk.setPossible(Double.valueOf(ExcelUtils.getCellValue(row.getCell(7))));
                            Double frenqucy = Double.valueOf(ExcelUtils.getCellValue(row.getCell(5)));
                            Double severity = Double.valueOf(ExcelUtils.getCellValue(row.getCell(6)));
                            Double possible = Double.valueOf(ExcelUtils.getCellValue(row.getCell(7)));
                            Double riskLevelTemp = frenqucy*severity*possible;//计算风险等级
                            if (riskLevelTemp>=320) {
                                fewRisk.setRiskLevel(Double.valueOf(5));
                            } else if(riskLevelTemp>=160){
                                fewRisk.setRiskLevel(Double.valueOf(4));
                            }else if(riskLevelTemp>=70){
                                fewRisk.setRiskLevel(Double.valueOf(3));
                            }else if(riskLevelTemp>=20){
                                fewRisk.setRiskLevel(Double.valueOf(2));
                            }else{
                                fewRisk.setRiskLevel(Double.valueOf(1));
                            }
                            fewRisk.setLevel(i);
                            riskList.add(fewRisk);
                            int total = fewRiskService.insertRiskList(riskList);
                            SystemLogger.info(total > 0 ? "风险新增成功!" : "风险新增失败!");
                        }
                    }
                    i--;
                } else {
                    row = sheet.getRow(i);
                    WorkStep workStep = new WorkStep();
                    workStep.setJsrdangerId(count);
                    workStep.setJsrdangerStepName(ExcelUtils.getCellValue(row.getCell(2)));
                    workStep.setCreator(user.getId());
                    workStep.setCreateName(user.getUsername());
                    workStep.setCreateTime(DateUtils.getCurrentTime("yyyy-MM-dd HH:mm:ss"));
                    workStep.setLevel(i);
                    int countWork = workStepService.insertWorkStep(workStep);// 步骤id
                    SystemLogger.info(countWork > 0 ? "工作步骤新增成功!" : "工作步骤新增失败!");
                }

            }

        } catch (Exception ex) {

        }
        resultMap.put(STATUS, STATUS_TRUE);
        resultMap.put(MSG, "文件上传成功");
        return resultMap;
    }

四、html页面  和  js(用的angular js)

/**
         * @param file
         *                 上传文件
         */
        $scope.upload = function (file) {
           if(file != null && file != ""){
               Upload.upload({
               url: 'dangerJSRController/import',
               data: {"sourceName": file.name.substring(0, file.name.lastIndexOf(".")) + ""},
               file: file
           }).progress(function (evt) {
               //进度条
               var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
               console.log('progess:' + progressPercentage + '%' + evt.config.file.name);
           }).success(function (data, status, headers, config) {
               //上传成功
               // console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
               // console.info(data.path);
               if(data.code == '1001'){
                   zsAlert($ZSPLAT, $scope, "上传失败!");
               }else{
                   zsAlert($ZSPLAT, $scope, "上传成功!");
                   clearItme($scope);
               }
           }).error(function (data, status, headers, config) {
               //上传失败
               console.log('error status: ' + status);
               zsAlert($ZSPLAT, $scope, "上传失败!");
           });}
        };
<div style=" 100px;" class="btn btn-primary btn-sm" ngf-select="upload($file)">
      <span class="glyphicon glyphicon-cloud-upload"></span>
       <a style="color:#FFFFFF;text-decoration: none;" href="javascript:void(0);">导入风险</a>
 </div>

实现的效果

原文地址:https://www.cnblogs.com/zhou-pan/p/10037438.html