package com.zksy.utils; import com.zksy.common.exception.ServiceException; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.web.multipart.MultipartFile; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.text.DecimalFormat; import java.util.*; import java.util.regex.Pattern; public class MergeReadsExcelUtil { /** * 读取excel数据 * @param file */ public static List> readExcelToObj(MultipartFile file, int headerColumn, int number, int headerLine, Class classEntity) { Workbook wb = null; String fileName = file.getOriginalFilename();//获取文件名 List> result = null; try { if (!validateExcel(fileName)) {// 验证文件名是否合格 return null; } boolean isExcel2003 = true;// 根据文件名判断文件是2003版本还是2007版本 if (isExcel2007(fileName)) { isExcel2003 = false; } if (isExcel2003) {// 当excel是2003时,创建excel2003 wb = new HSSFWorkbook(file.getInputStream()); } else {// 当excel是2007时,创建excel2007 wb = new XSSFWorkbook(file.getInputStream()); } result = readExcel(wb, 0, 1, 0, headerColumn, number, headerLine,classEntity); } catch (IOException e) { e.printStackTrace(); } return result; } /** * 读取excel文件 * @param wb * @param sheetIndex sheet页下标:从0开始 * @param startReadLine 开始读取的行:从0开始 * @param tailLine 去除最后读取的行 */ private static List> readExcel(Workbook wb, int sheetIndex, int startReadLine, int tailLine,int headerColumn,int number,int headerLine,Class classEntity) { Sheet sheet = wb.getSheetAt(sheetIndex); Row row = null; List> result = new ArrayList>(); List stringList = getEntityProp(classEntity); List serialNumberColumn = new ArrayList<>(); /*if(sheet.getRow(sheet.getFirstRowNum()).getLastCellNum() != headerColumn){ throw new ServiceException("导入模板不正确"); }*/ for(int i=startReadLine; i map = new HashMap(); for(Cell c : row) { String returnStr = ""; boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex()); //判断是否具有合并单元格 if(isMerge) { String rs = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex()); returnStr = rs; }else { //设置单元格类型 returnStr = getCellValue(c); } //将值存进list serialNumberColumn.add(returnStr); if(serialNumberColumn.contains("序号")){ //去掉第一列数据 if(c.getColumnIndex() <= headerColumn && c.getColumnIndex() >= number && i > headerLine) { map.put(stringList.get(c.getColumnIndex() - 1), returnStr); } }else{ //不去第一列数据 if(c.getColumnIndex() < headerColumn && i > headerLine) { map.put(stringList.get(c.getColumnIndex()), returnStr); } } } if(map.size() > 0) { result.add(map); } } if(result.size() > 0 && result.get(0).size() != headerColumn){ throw new ServiceException("导入模板不正确"); } return result; } //错误信息接收器 private static String errorMsg; public static boolean validateExcel(String filePath) { if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) { errorMsg = "文件名不是excel格式"; return false; } return true; } // @描述:是否是2003的excel,返回true是2003 public static boolean isExcel2003(String filePath) { return filePath.matches("^.+\\.(?i)(xls)$"); } //@描述:是否是2007的excel,返回true是2007 public static boolean isExcel2007(String filePath) { return filePath.matches("^.+\\.(?i)(xlsx)$"); } public static List getEntityProp(Class clazz) { Field[] fields = clazz.getDeclaredFields(); List fieldNames = new ArrayList<>(); for (Field field : fields) { fieldNames.add(field.getName()); } fieldNames.remove("serialVersionUID"); fieldNames.remove("id"); return fieldNames; } /** * 获取合并单元格的值 * @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 */ private boolean isMergedRow(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; } /** * 判断指定的单元格是否是合并单元格 * @param sheet * @param row 行下标 * @param column 列下标 * @return */ private 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; } /** * 判断sheet页中是否含有合并单元格 * @param sheet * @return */ private boolean hasMerged(Sheet sheet) { return sheet.getNumMergedRegions() > 0 ? true : false; } /** * 合并单元格 * @param sheet * @param firstRow 开始行 * @param lastRow 结束行 * @param firstCol 开始列 * @param lastCol 结束列 */ private void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) { sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol)); } /** * 获取单元格的值 * @param cell * @return */ public static String getCellValue(Cell cell){ if(cell == null) { return ""; } if(cell.getCellType() == CellType.STRING){ return cell.getStringCellValue(); }else if(cell.getCellType() == CellType.BOOLEAN){ return String.valueOf(cell.getBooleanCellValue()); }else if(cell.getCellType() == CellType.FORMULA){ return convertToPercentage(cell); }else if(cell.getCellType() == CellType.NUMERIC){ double numericValue = cell.getNumericCellValue(); DecimalFormat df = new DecimalFormat("0"); // 设置格式化模式,保留小数点后的所有位数 // 判断是否为科学计数法 if(String.valueOf(numericValue).contains("E")) { DataFormatter dataFormatter = new DataFormatter(); String formattedValue = dataFormatter.formatCellValue(cell); // 使用 DataFormatter 获取格式化后的值 return formattedValue; }/*else if(String.valueOf(numericValue).contains("-")){ //时间格式 DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("d-LLL-yyyy", Locale.CHINESE); LocalDate date = LocalDate.parse(cell.toString(), inputFormatter); return date.toString(); } */else { String formattedValue = df.format(numericValue); // 格式化数值为完整形式 return formattedValue; } /* String s = cell.getNumericCellValue() + ""; // 去掉尾巴上的小数点0 if (Pattern.matches(".*\\.0*", s)) { return s.split("\\.")[0]; } else { return s; }*/ } return ""; } public static String convertToPercentage(Cell cell) { try { if (cell.getCellType() == CellType.FORMULA) { String s = cell.getNumericCellValue() + ""; // 去掉尾巴上的小数点0 if (Pattern.matches(".*\\.0*", s)) { return s.split("\\.")[0]; } else if(s.contains("E")){ DecimalFormat decimalFormat = new DecimalFormat("0"); String decimalNumber = decimalFormat.format(Double.parseDouble(s)); return decimalNumber; }else{ return s; } /*double value = cell.getNumericCellValue(); return String.format("%.2f%%", value * 100); // 保留两位小数*/ } }catch (Exception e){ //return "0%"; // 如果不是数字类型,返回"NaN%" } return null; } /** * 从excel读取内容 */ public static void readContent(String fileName) { boolean isE2007 = false; //判断是否是excel2007格式 if(fileName.endsWith("xlsx")) { isE2007 = true; } try { InputStream input = new FileInputStream(fileName); //建立输入流 Workbook wb = null; //根据文件格式(2003或者2007)来初始化 if(isE2007) { wb = new XSSFWorkbook(input); } else { wb = new HSSFWorkbook(input); } Sheet sheet = wb.getSheetAt(0); //获得第一个表单 Iterator rows = sheet.rowIterator(); //获得第一个表单的迭代器 while (rows.hasNext()) { Row row = rows.next(); //获得行数据 System.out.println("Row #" + row.getRowNum()); //获得行号从0开始 Iterator cells = row.cellIterator(); //获得第一行的迭代器 while (cells.hasNext()) { Cell cell = cells.next(); System.out.println("Cell #" + cell.getColumnIndex()); switch (cell.getCellType()) { //根据cell中的类型来输出数据 case NUMERIC: System.out.println(cell.getNumericCellValue()); break; case STRING: System.out.println(cell.getStringCellValue()); break; case BOOLEAN: System.out.println(cell.getBooleanCellValue()); break; case FORMULA: System.out.println(cell.getCellFormula()); break; default: System.out.println("unsuported sell type======="+cell.getCellType()); break; } } } } catch (IOException ex) { ex.printStackTrace(); } } }