1. 程式人生 > >使用POI外掛實現Excel含有合併行的匯入

使用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="width: 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>

實現的效果