使用POI外掛實現Excel含有合併行的匯入
阿新 • • 發佈:2018-11-29
一、要匯入的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>
實現的效果