问题:

在Java读取Excel导入操作时, sheet.getLastRowNum()会统计带有格式的空白行,导致获取的最大行数不准确,数据导入失败。

java 删除表格行 java excel删除行_合并单元格

java 删除表格行 java excel删除行_java 删除表格行_02


解决:

在操作过程中删除存在样式的空白行

可通过将空白行(内容为空,但是存在样式)进行sheet.removeRow删除后

再调用getLastRowNum()进行行数统计,getAccuracyContextNum()方法中。

@Transactional(rollbackFor =  Exception.class)
	public Map<String,Object> importWeb(Workbook wb,String skillName,String skilltype,String office) {
		StringBuilder msg = new StringBuilder();
		Map<String, Object> reMap = new HashMap<>();
		Sheet sheet = wb.getSheetAt(0);
		Row titleRow = sheet.getRow(0);
		if (titleRow.getLastCellNum() != 3 || !"项目名称".equals(getCellValue(titleRow.getCell(0)))
				|| !"操作要点".equals(getCellValue(titleRow.getCell(1))) || !"总分".equals(getCellValue(titleRow.getCell(2)))){
			reMap.put("flag",false);
			reMap.put("msg","模板错误");
			return reMap;
		}

		//获取合并单元格信息的hashmap
		Map<String,Integer[]> mergedRegionMap = getMergedRegionMap(sheet);

		//拿到excel的最后一行的索引
//		int lastRowNum = sheet.getLastRowNum();
		sheet=getAccuracyContextNum(wb,mergedRegionMap);
		int lastRowNum=sheet.getLastRowNum();
		List<Map<String, Object>> projectNameList = new ArrayList<>();
		List<Map<String, Object>> mainPointsList = new ArrayList<>();
		//nursetrain_skill_oper表主键id
		String operId = IdGen.uuid();
		BigDecimal totalScore = new BigDecimal(0);
		//从excel的第二行索行开始,遍历到最后一行(第一行是标题,直接跳过不读取)
		for(int i = 1; i<=lastRowNum ; i++) {
			//拿到excel的行对象
			Row row = sheet.getRow(i);
			//获取excel的行中有多个列
			int cellNum = row.getLastCellNum();

			if (cellNum > 3){
				reMap.put("flag",false);
				reMap.put("msg","数据列超出标题范围");
				return reMap;
			}

			Map<String, Object> projectMap = new LinkedHashMap<>();
			Map<String, Object> mainPointsMap = new LinkedHashMap<>();
			//对每行进行列遍历,即一列一列的进行解析
			for(int j=0; j < cellNum; j++) {
				//拿到了excel的列对象
				Cell cell = row.getCell(j);

				//将列对象的行号和列号+下划线组成key去hashmap中查询,不为空说明当前的cell是合并单元列
				Integer[] firstRowNumberAndCellNumber = mergedRegionMap.get(i+"_"+j);

				//如果是合并单元列,就取合并单元格的首行和首列所在位置读数据,否则就是直接读数据
				if(firstRowNumberAndCellNumber != null) {
					Row rowTmp = sheet.getRow(firstRowNumberAndCellNumber[0]);
					Cell cellTmp = rowTmp.getCell(firstRowNumberAndCellNumber[1]);
					if (j == 0 ){
						projectMap.put("NAME", getCellValue(cellTmp));
						if(StringUtils.isEmpty(getCellValue(cellTmp))) {
							msg.append("第").append(i + 1).append("行项目名称不能为空").append("<br>");
						}
					}
					if (j == 1){
						mainPointsMap.put("NAME", getCellValue(cellTmp));
						if(StringUtils.isEmpty(getCellValue(cellTmp))) {
							msg.append("第").append(i + 1).append("行操作要点不能为空").append("<br>");
						}
					}
					if (j == 2){
						mainPointsMap.put("SCORE", getCellValue(cellTmp));
						if(StringUtils.isEmpty(getCellValue(cellTmp))) {
							msg.append("第").append(i + 1).append("行总分不能为空").append("<br>");
						}else{
							try{
								BigDecimal score = new BigDecimal(getCellValue(cellTmp)).setScale(2,RoundingMode.DOWN);
								totalScore = totalScore.add(score);
							}catch (Exception e){
								msg.append("第").append(i + 1).append("行总分只能为数字").append("<br>");
							}
						}
					}
					mainPointsMap.put("order", i);
				}else{
					if (j == 0 ){
						projectMap.put("NAME", getCellValue(cell));
						if(StringUtils.isEmpty(getCellValue(cell))) {
							msg.append("第").append(i + 1).append("行项目名称不能为空").append("<br>");
						}
					}
					if (j == 1){
						mainPointsMap.put("NAME", getCellValue(cell));
						if(StringUtils.isEmpty(getCellValue(cell))) {
							msg.append("第").append(i + 1).append("行操作要点不能为空").append("<br>");
						}
					}
					if (j == 2){
						mainPointsMap.put("SCORE", getCellValue(cell));
						if(StringUtils.isEmpty(getCellValue(cell))) {
							msg.append("第").append(i + 1).append("行总分不能为空").append("<br>");
						}else {
							try{
								BigDecimal score = new BigDecimal(String.valueOf(getCellValue(cell))).setScale(2,RoundingMode.UP);
								totalScore = totalScore.add(score);
							}catch (Exception e){
								msg.append("第").append(i + 1).append("行总分只能为数字").append("<br>");
							}
						}
					}
					mainPointsMap.put("order", i);
				}
			}
			``````
		try {
			//插入nursetrain_skill_oper表
			//插入nursetrain_skill_oper_item表
			//插入nursetrain_skill_oper_item_step表
			reMap.put("flag",true);
			reMap.put("msg","导入成功");
		}catch (Exception e){
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			reMap.put("flag",false);
			reMap.put("msg","导入失败,请联系系统管理员");
		}
		return reMap;
	}
//获取准确的文件行数
	public Sheet getAccuracyContextNum(Workbook workbook,Map<String,Integer[]> mergedRegionMap) {
		// 取第一个sheet
		Sheet sheet = workbook.getSheetAt(0);
		// 删除空行
		for (int i = 0; i <= sheet.getLastRowNum(); i++) {
			Row row = sheet.getRow(i);
			int cellNum = row.getLastCellNum();
			boolean flag=false;
			for(int j=0; j < cellNum; j++) {
				Integer[] firstRowNumberAndCellNumber = mergedRegionMap.get(i+"_"+j);
				if(firstRowNumberAndCellNumber != null){
					flag=true;
				}
			}
			if (this.isRowEmpty(row) && !flag) {
			// 删除空行
			if (this.isRowEmpty(row)) {
				int lastRowNum = sheet.getLastRowNum();
				if (i >= 0 && i < lastRowNum) {
					sheet.shiftRows(i + 1, lastRowNum, -1);// 将行号为i+1一直到行号为lastRowNum的单元格全部上移一行,以便删除i行
				}
				if (i == lastRowNum) {
					if (row != null) {
						sheet.removeRow(row);
					}
				}
				i--;
			}
		}
		return sheet;
	}
	/**
	 * 判断是否有空行
	 * @param row
	 * @return
	 */
	private  boolean isRowEmpty(Row row) {
		for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
			Cell cell = row.getCell(c);
			if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) {
				return false;
			}
		}
		return true;
	}
	//将存在合并单元格的列记录入put进hashmap并返回
	public Map<String,Integer[]> getMergedRegionMap(Sheet sheet){

		Map<String,Integer[]> result = new HashMap<String,Integer[]>();

		//获取excel中的所有合并单元格信息
		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();

			//构造一个开始行和开始列组成的数组
			Integer[] firstRowNumberAndCellNumber = new Integer[]{firstRow,firstColumn};

			//遍历,将单元格中的所有行和所有列处理成由行号和下划线和列号组成的key,然后放在hashmap中
			for(int currentRowNumber = firstRow; currentRowNumber <= lastRow; currentRowNumber++) {

				for(int currentCellNumber = firstColumn; currentCellNumber <= lastColumn; currentCellNumber ++) {
					result.put(currentRowNumber+"_"+currentCellNumber, firstRowNumberAndCellNumber);
				}
			}
		}
		return result;
	}