package org.dcexam.cms.core.plugin; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; 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.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.dcexam.cms.module.entity.Question; /** * @author 王海明 * @createData 2017年8月15日 下午2:24:35 * @说明 : poi 导入 导出 */ public class PoiPlugin { public static void main(String[] args) throws Exception { // 每行的 逻辑。。。 // String path = "E:/test1.xlsx"; String path = "E:/question_1.xlsx"; InputStream input = new FileInputStream(new File(path)); Map<String, Function<Object, Object>> formaterMap = new HashMap<>(); formaterMap.put("difficulty", value -> { return Integer.valueOf((String) value); }); formaterMap.put("qtid", value -> { String typeStr = (String) value; int type = 0; if (typeStr.startsWith("单选")) type = 1; else if (typeStr.startsWith("多选")) type = 2; else if (typeStr.startsWith("判断")) type = 3; else if (typeStr.startsWith("排序")) type = 4; else if (typeStr.startsWith("填空")) type = 5; else if (typeStr.startsWith("简答")) type = 6; return type; }); @SuppressWarnings("serial") List<Object> listFromExcel = getListFromExcel(path, input, new HashMap<String, String>() { { put("题目类型", "qtid"); } }, Question.class, formaterMap); System.out.println(listFromExcel); } /** * @param filepath 文件名称(文件的全路径也可以) * @param in inputStream 流 * @param map 第一行 和 class 类 字段 对应规则 为null 则 默认对应 * @param clazz 对应的实体类的类 文件 * @param formater 格式化。。参数类型是 Map<Object,Function<Object,Object>> * @return * @说明 暂时 仅支持 xls,xlsx 格式 的导入 */ public static List<Object> getListFromExcel(String filepath, InputStream in, Map<String, String> map, @SuppressWarnings("rawtypes") Class clazz, Map<String, Function<Object, Object>> formater) { List<Object> list = null; // 创建Excel工作薄 Workbook work = getWorkBook(filepath, in); if (null == work) { throw new RuntimeException("创建Excel工作薄为空!"); } Sheet sheet = null; Row row = null; // Cell cell = null; list = new ArrayList<>(); // 遍历Excel中所有的sheet for (int i = 0; i < work.getNumberOfSheets(); i++) { sheet = work.getSheetAt(i); if (sheet == null) { continue; } Row firstRow = sheet.getRow(0); // 遍历当前sheet中的所有行,rowNum 从 0 开始。。。以 长度 - 1 结尾。。 for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) { row = sheet.getRow(j); // 如果 row 为空。。。或者它是 第一行。。。 if (row == null || row.getRowNum() == 0) { continue; } /* * System.out.println(sheet.getFirstRowNum()); * System.out.println(sheet.getLastRowNum()); */ try { Object obj = null; if (clazz != null) { obj = clazz.newInstance(); } else { throw new RuntimeException("clazz 不能为空"); } // 遍历所有的列 // 从0 开始 。。。以长度 结尾。。。。也就是不用 <=.... for (int index = row.getFirstCellNum(); index < row.getLastCellNum(); index++) { // 第一列 应该全部是字符串。。。 String field = (String) getCellValue(firstRow.getCell(index)); Object cellValue = getCellValue(row.getCell(index)); buildObj(field, cellValue, map, clazz, obj, formater); } list.add(obj); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } try { if (in != null) in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; } private static void buildObj(String fieldstr, Object value, Map<String, String> map, @SuppressWarnings("rawtypes") Class clazz, Object obj, Map<String, Function<Object, Object>> formatter) throws Exception { Field field = null; if (map != null) { fieldstr = map.get(fieldstr) == null ? fieldstr : map.get(fieldstr); } try { field = clazz.getDeclaredField(fieldstr); } catch (NoSuchFieldException e) { //出现此异常,直接return return; } catch (Exception e) { //出现其它类型异常。。抛出 e.printStackTrace(); throw e; } field.setAccessible(true); Function<Object, Object> func = null; if (formatter != null) { func = formatter.get(fieldstr); } if (func != null) { Object apply = func.apply(value); field.set(obj, apply); } else { field.set(obj, value); } } /** * 此方法 应为 私有方法。。 * * @param path * @param input * @return */ private static Workbook getWorkBook(String path, InputStream input) { Workbook workbook = null; // File file = new File(path); if (path.endsWith(".xls")) try { workbook = new HSSFWorkbook(input); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } else if (path.endsWith(".xlsx")) { try { workbook = new XSSFWorkbook(input); } catch (Exception e) { // TODO: handle exception } } else { throw new RuntimeException("不支持的文档格式"); } return workbook; } @SuppressWarnings("deprecation") // 将要过时的方法 private static Object getCellValue(Cell cell) { Object value = null; DecimalFormat df = new DecimalFormat("0"); // 格式化number String字符 SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd"); // 日期格式化 DecimalFormat df2 = new DecimalFormat("0.00"); // 格式化数字 switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: value = cell.getRichStringCellValue().getString(); break; case Cell.CELL_TYPE_NUMERIC: if ("General".equals(cell.getCellStyle().getDataFormatString())) { value = df.format(cell.getNumericCellValue()); } else if ("m/d/yy".equals(cell.getCellStyle().getDataFormatString())) { value = sdf.format(cell.getDateCellValue()); } else { value = df2.format(cell.getNumericCellValue()); } break; case Cell.CELL_TYPE_BOOLEAN: value = cell.getBooleanCellValue(); break; case Cell.CELL_TYPE_BLANK: value = ""; break; default: break; } return value; } }