一、抽象基类,传入Excel文件,自动解析出实体类对象或者相应的Map对象
package com.taoche.im.utility.excel; import java.util.List; import java.util.Map; //F为Excel文件对象,本例中为spring MultipartFile //T为实体类,实体类的属性应该和Excel文件第一行的标题头相同 public abstract class AbstractExcelBeanWrapper{ protected F excelFile; protected List beanWrapper; protected T t; protected List
二、抽象类实现,采用具体的解析Excel对象的技术
package com.taoche.im.utility.excel; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class HssfExcelBeanWrapperextends AbstractExcelBeanWrapper { public HssfExcelBeanWrapper(F f, T t, int indexOfSheet) { super(f, t, indexOfSheet); } @Override protected void resolve(int indexOfSheet) { List > list = null; Workbook wb = null; Sheet sheet = null; Row row = null; String cellData = null; List keys = null; if (this.excelFile instanceof MultipartFile) { MultipartFile file = (MultipartFile) excelFile; wb = readExcel(file); if (wb != null) { list = new ArrayList<>(); sheet = wb.getSheetAt(1); int rownum = sheet.getPhysicalNumberOfRows(); row = sheet.getRow(0); int column = row.getPhysicalNumberOfCells(); keys = new ArrayList<>(); for (int i = 0; i < column; i++) { keys.add((String) getCellFormatValue(row.getCell(i))); } for (int i = 1; i < rownum; i++) { Map map = new LinkedHashMap<>(); row = sheet.getRow(i); if (row != null) { for (int j = 0; j < column; j++) { cellData = (String) getCellFormatValue(row.getCell(j)); map.put(keys.get(j), cellData); } } else { break; } list.add(map); } } } this.mapWrapper = list; } @Override protected void resolveT(int indexOfSheet) throws IllegalAccessException, InstantiationException { List list = null; Workbook wb = null; Sheet sheet = null; Row row = null; Object cellData = null; List keys = null; if (this.excelFile instanceof MultipartFile) { MultipartFile file = (MultipartFile) excelFile; wb = readExcel(file); if (wb != null) { list = new ArrayList<>(); sheet = wb.getSheetAt(indexOfSheet); int rownum = sheet.getPhysicalNumberOfRows(); row = sheet.getRow(0); int column = row.getPhysicalNumberOfCells(); keys = resolveKeys(row, column); for (int i = 1; i < rownum; i++) { T bean = (T) this.t.getClass().newInstance(); row = sheet.getRow(i); if (row != null) { for (int j = 0; j < column; j++) { cellData = getCellFormatValue(row.getCell(j)); keys.get(j).setAccessible(true); setValues(keys.get(j), bean, cellData); } } else { break; } list.add(bean); } } } this.beanWrapper = list; } private void setValues(Field field, T bean, Object cellData) throws IllegalAccessException { switch (field.getGenericType().getTypeName()) { case "java.lang.String": field.set(bean, cellData); break; case "java.lang.Boolean": case "boolean": field.set(bean, Boolean.valueOf(cellData.toString())); break; case "java.lang.Byte": case "byte": field.set(bean, Byte.valueOf((byte) (double) cellData)); break; case "java.lang.Long": case "long": field.set(bean, Long.valueOf((long) ((double) cellData))); break; case "java.lang.Short": case "short": field.set(bean, Short.valueOf((short) ((double) cellData))); break; case "java.lang.Integer": case "int": field.set(bean, Integer.valueOf((int) ((double) cellData))); break; case "java.lang.Double": case "double": field.set(bean, Double.valueOf(cellData.toString())); break; case "java.lang.Float": case "floag": field.set(bean, Float.valueOf(cellData.toString())); break; case "java.lang.Character": case "char": field.set(bean, Character.valueOf(cellData.toString().charAt(0))); break; default: break; } } private List resolveKeys(Row row, int column) { List keys = new ArrayList<>(); Class tClass = this.t.getClass(); Field[] fields = tClass.getDeclaredFields(); for (int i = 0; i < column; i++) { for (int j = 0; j < fields.length; j++) { if (fields[j].getName().equalsIgnoreCase((String) getCellFormatValue(row.getCell(i)))) { keys.add(fields[j]); break; } } } return keys; } // 读取Excel文件,根据后缀名不同,选择相应的技术 private static Workbook readExcel(MultipartFile excelFile) { Workbook wb = null; String fileName = excelFile.getOriginalFilename(); String extString = fileName.substring(fileName.lastIndexOf(".")); try { if (".xls".equals(extString)) { return wb = new HSSFWorkbook(excelFile.getInputStream()); } else if (".xlsx".equals(extString)) { return wb = new XSSFWorkbook(excelFile.getInputStream()); } else { return wb = null; } } catch (IOException e) { e.printStackTrace(); } return wb; } private static Object getCellFormatValue(Cell cell) { Object cellValue = null; if (cell != null) { switch (cell.getCellType()) { case NUMERIC: { cellValue = cell.getNumericCellValue(); break; } case FORMULA: { if (DateUtil.isCellDateFormatted(cell)) { cellValue = cell.getDateCellValue(); } else { cellValue = cell.getNumericCellValue(); } break; } case STRING: { cellValue = cell.getStringCellValue(); break; } default: cellValue = ""; break; } } else { cellValue = ""; } return cellValue; } }
三、Service类,根据传入的Excel文件,解析为具体的实体类,保存数据库
@Override public int batchImport(MultipartFile file, String otherParameters) throws IllegalAccessException, InstantiationException { XXXModel model = new XXXModel(); AbstractExcelBeanWrapperexcelBeanWrapper = new HssfExcelBeanWrapper<>(file, model, 0); List list = excelBeanWrapper.getBeanWrapper(); return this.XXXDao.batchInsert(list, otherParameters); }
四、controller层,判断是否为Excel文件,调用service层解析存储数据,返回插入成功的条数
@PostMapping("importer") public ResponseResult batchInsert(@RequestParam("file") MultipartFile file, String otherParameters) throws InstantiationException, IllegalAccessException { if (file == null || (file.getOriginalFilename().endsWith(".xls") && file.getOriginalFilename().endsWith(".xlsx"))) { return new ResponseResult().setCode(5000).setMessage("不是Excel文件"); } int cnt = this.messageModelService.batchImport(file, otherParameters); return new ResponseResult().setCode(200).setMessage("插入:" + cnt + "条"); }