需要用到的的类

主控制器

package io.jboot.admin.controller.ImportController;import java.util.ArrayList;
import java.util.List;import javax.validation.ConstraintViolationException;import org.apache.commons.lang3.StringUtils;import com.jfinal.plugin.activerecord.Page;
import com.jfinal.upload.UploadFile;import io.jboot.admin.base.web.base.BaseController;
import io.jboot.admin.excelutils.ExportExcel;
import io.jboot.admin.excelutils.ImportExcel;
import io.jboot.admin.service.api.UserService;
import io.jboot.admin.service.entity.model.User;
import io.jboot.core.rpc.annotation.JbootrpcService;
import io.jboot.web.controller.annotation.RequestMapping;/*** Excel 导入 Demo * @author Rlax**/
@RequestMapping("/url")
public class DemoController extends BaseController {@JbootrpcServiceprivate UserService userService;public void downloadTemplate() {try {String fileName = "测试管理导入模板.xlsx";List<User> list = new ArrayList<User>();User param = new User();list.add(param);ExportExcel exportExcel = new ExportExcel("信息数据", User.class, 1);ExportExcel dataList = exportExcel.setDataList(list);dataList.write(getResponse(), fileName).dispose();renderNull();} catch (Exception e) {System.err.print("导入模板下载失败!失败信息:"+e.getMessage());e.printStackTrace();}}public void exportFile() {try {String fileName = "测试标题" + ".xlsx";int pageNumber = getParaToInt("pageNumber", 1);int pageSize = getParaToInt("pageSize", 30);User sysUser = new User();sysUser.setName(getPara("name"));sysUser.setPhone(getPara("phone"));sysUser.setOffice(getParaToLong("office"));Page<User> userPage = userService.findPage(sysUser, pageNumber, pageSize);new ExportExcel("学员信息", User.class).setDataList(userPage.getList()).write(getResponse(), fileName).dispose();renderNull();} catch (Exception e) {System.err.println("导出信息记录失败!失败信息:" + e.getMessage());}}/*** 导入Excel数据* */public void importFile() {UploadFile file = getFile();try {int successNum = 0;int failureNum = 0;StringBuilder failureMsg = new StringBuilder();ImportExcel ei = new ImportExcel(file.getFile(), 1, 0);List<User> dataList = ei.getDataList(User.class);//Long office = AuthUtils.getLoginUser().getOffice();for (User u : dataList) {try {if (StringUtils.isBlank(u.getName()) && StringUtils.isBlank(u.getEmail())&& StringUtils.isBlank(u.getPhone())) {continue;}//如果存在该条数据,执行修改操作,否则保存successNum++;} catch (ConstraintViolationException ex) {failureNum++;} catch (Exception ex) {ex.printStackTrace();failureNum++;}}if (failureNum > 0) {failureMsg.insert(0, ",失败 " + failureNum + " 条信息记录。");}setAttr("ok", "已成功导入 " + successNum + " 条信息记录" + failureMsg);} catch (Exception e) {setAttr("flag", "导入信息失败!失败信息:" + e.getMessage());e.printStackTrace();}renderJson("/导入完成,开始重定向");}
}

excelutils

ExcelField.java

package io.jboot.admin.excelutils;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Excel注解定义*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelField {/*** 导出字段名(默认调用当前字段的“get”方法,如指定导出字段为对象,请填写“对象名.对象属性”,例:“area.name”、“office.name”)*/String value() default "";/*** 导出字段标题(需要添加批注请用“**”分隔,标题**批注,仅对导出模板有效)*/String title();/*** 字段类型(0:导出导入;1:仅导出;2:仅导入)*/int type() default 0;/*** 导出字段对齐方式(0:自动;1:靠左;2:居中;3:靠右)*/int align() default 0;/*** 导出字段字段排序(升序)*/int sort() default 0;/*** 如果是字典类型,请设置字典的type值*/String dictType() default "";/*** 反射类型*/Class<?> fieldType() default Class.class;/*** 字段归属组(根据分组导出导入)*/int[] groups() default {};
}

Exceptions.java

package io.jboot.admin.excelutils;
import java.io.PrintWriter;
import java.io.StringWriter;import javax.servlet.http.HttpServletRequest;/*** 关于异常的工具类.*/
public class Exceptions {/*** 将CheckedException转换为UncheckedException.*/public static RuntimeException unchecked(Exception e) {if (e instanceof RuntimeException) {return (RuntimeException) e;} else {return new RuntimeException(e);}}/*** 将ErrorStack转化为String.*/public static String getStackTraceAsString(Throwable e) {if (e == null){return "";}StringWriter stringWriter = new StringWriter();e.printStackTrace(new PrintWriter(stringWriter));return stringWriter.toString();}/*** 判断异常是否由某些底层的异常引起.*/@SuppressWarnings("unchecked")public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {Throwable cause = ex.getCause();while (cause != null) {for (Class<? extends Exception> causeClass : causeExceptionClasses) {if (causeClass.isInstance(cause)) {return true;}}cause = cause.getCause();}return false;}/*** 在request中获取异常类* @param request* @return */public static Throwable getThrowable(HttpServletRequest request){Throwable ex = null;if (request.getAttribute("exception") != null) {ex = (Throwable) request.getAttribute("exception");} else if (request.getAttribute("javax.servlet.error.exception") != null) {ex = (Throwable) request.getAttribute("javax.servlet.error.exception");}return ex;}}

ExportExcel.java

package io.jboot.admin.excelutils;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 导出Excel文件(导出“XLSX”格式,支持大数据量导出   @see org.apache.poi.ss.SpreadsheetVersion)*/
public class ExportExcel {private static Logger log = LoggerFactory.getLogger(ExportExcel.class);/*** 工作薄对象*/private SXSSFWorkbook wb;/*** 工作表对象*/private SXSSFSheet sheet;/*** 样式列表*/private Map<String, CellStyle> styles;/*** 当前行号*/private int rownum;/*** 注解列表(Object[]{ ExcelField, Field/Method })*/List<Object[]> annotationList = new ArrayList<Object[]>();/*** 构造函数* @param title 表格标题,传“空值”,表示无标题* @param cls 实体对象,通过annotation.ExportField获取标题*/public ExportExcel(String title, Class<?> cls){this(title, cls, 1);}/*** 构造函数* @param title 表格标题,传“空值”,表示无标题* @param cls 实体对象,通过annotation.ExportField获取标题* @param type 导出类型(1:导出数据;2:导出模板)* @param groups 导入分组*/public ExportExcel(String title, Class<?> cls, int type, int... groups){// Get annotation field Field[] fs = cls.getDeclaredFields();for (Field f : fs){ExcelField ef = f.getAnnotation(ExcelField.class);if (ef != null && (ef.type()==0 || ef.type()==type)){if (groups!=null && groups.length>0){boolean inGroup = false;for (int g : groups){if (inGroup){break;}for (int efg : ef.groups()){if (g == efg){inGroup = true;annotationList.add(new Object[]{ef, f});break;}}}}else{annotationList.add(new Object[]{ef, f});}}}// Get annotation methodMethod[] ms = cls.getDeclaredMethods();for (Method m : ms){ExcelField ef = m.getAnnotation(ExcelField.class);if (ef != null && (ef.type()==0 || ef.type()==type)){if (groups!=null && groups.length>0){boolean inGroup = false;for (int g : groups){if (inGroup){break;}for (int efg : ef.groups()){if (g == efg){inGroup = true;annotationList.add(new Object[]{ef, m});break;}}}}else{annotationList.add(new Object[]{ef, m});}}}// Field sortingCollections.sort(annotationList, new Comparator<Object[]>() {public int compare(Object[] o1, Object[] o2) {return new Integer(((ExcelField)o1[0]).sort()).compareTo(new Integer(((ExcelField)o2[0]).sort()));};});// InitializeList<String> headerList = new ArrayList<String>();for (Object[] os : annotationList){String t = ((ExcelField)os[0]).title();// 如果是导出,则去掉注释if (type==1){String[] ss = StringUtils.split(t, "**", 2);if (ss.length==2){t = ss[0];}}headerList.add(t);}initialize(title, headerList);}/*** 构造函数* @param title 表格标题,传“空值”,表示无标题* @param headers 表头数组*/public ExportExcel(String title, String[] headers) {initialize(title, Arrays.asList(headers));}/*** 构造函数* @param title 表格标题,传“空值”,表示无标题* @param headerList 表头列表*/public ExportExcel(String title, List<String> headerList) {initialize(title, headerList);}/*** 初始化函数* @param title 表格标题,传“空值”,表示无标题* @param headerList 表头列表*/private void initialize(String title, List<String> headerList) {this.wb = new SXSSFWorkbook(500);this.sheet = (SXSSFSheet) wb.createSheet("Export");this.styles = createStyles(wb);// Create titleif (StringUtils.isNotBlank(title)){Row titleRow = sheet.createRow(rownum++);titleRow.setHeightInPoints(30);Cell titleCell = titleRow.createCell(0);titleCell.setCellStyle(styles.get("title"));titleCell.setCellValue(title);sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(),titleRow.getRowNum(), titleRow.getRowNum(), headerList.size()-1));}// Create headerif (headerList == null){throw new RuntimeException("headerList not null!");}Row headerRow = sheet.createRow(rownum++);headerRow.setHeightInPoints(16);//sheet.trackAllColumnsForAutoSizing();for (int i = 0; i < headerList.size(); i++) {Cell cell = headerRow.createCell(i);cell.setCellStyle(styles.get("header"));String[] ss = StringUtils.split(headerList.get(i), "**", 2);if (ss.length==2){cell.setCellValue(ss[0]);Comment comment = this.sheet.createDrawingPatriarch().createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 3, 3, (short) 5, 6));comment.setString(new XSSFRichTextString(ss[1]));cell.setCellComment(comment);}else{cell.setCellValue(headerList.get(i));}sheet.autoSizeColumn(i);}for (int i = 0; i < headerList.size(); i++) {  int colWidth = sheet.getColumnWidth(i)*2;sheet.setColumnWidth(i, colWidth < 3000 ? 3000 : colWidth);  }log.debug("Initialize success.");}/*** 创建表格样式* @param wb 工作薄对象* @return 样式列表*/private Map<String, CellStyle> createStyles(Workbook wb) {Map<String, CellStyle> styles = new HashMap<String, CellStyle>();CellStyle style = wb.createCellStyle();style.setAlignment(CellStyle.ALIGN_CENTER);//style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);Font titleFont = wb.createFont();titleFont.setFontName("Arial");titleFont.setFontHeightInPoints((short) 16);titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);style.setFont(titleFont);styles.put("title", style);style = wb.createCellStyle();style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);style.setBorderRight(CellStyle.BORDER_THIN);style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderLeft(CellStyle.BORDER_THIN);style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderTop(CellStyle.BORDER_THIN);style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderBottom(CellStyle.BORDER_THIN);style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());Font dataFont = wb.createFont();dataFont.setFontName("Arial");dataFont.setFontHeightInPoints((short) 10);style.setFont(dataFont);styles.put("data", style);style = wb.createCellStyle();style.cloneStyleFrom(styles.get("data"));style.setAlignment(CellStyle.ALIGN_LEFT);styles.put("data1", style);style = wb.createCellStyle();style.cloneStyleFrom(styles.get("data"));style.setAlignment(CellStyle.ALIGN_CENTER);styles.put("data2", style);style = wb.createCellStyle();style.cloneStyleFrom(styles.get("data"));style.setAlignment(CellStyle.ALIGN_RIGHT);styles.put("data3", style);style = wb.createCellStyle();style.cloneStyleFrom(styles.get("data"));
//      style.setWrapText(true);style.setAlignment(CellStyle.ALIGN_CENTER);style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setFillPattern(CellStyle.SOLID_FOREGROUND);Font headerFont = wb.createFont();headerFont.setFontName("Arial");headerFont.setFontHeightInPoints((short) 10);headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);headerFont.setColor(IndexedColors.WHITE.getIndex());style.setFont(headerFont);styles.put("header", style);return styles;}/*** 添加一行* @return 行对象*/public Row addRow(){return sheet.createRow(rownum++);}/*** 添加一个单元格* @param row 添加的行* @param column 添加列号* @param val 添加值* @return 单元格对象*/public Cell addCell(Row row, int column, Object val){return this.addCell(row, column, val, 0, Class.class);}/*** 添加一个单元格* @param row 添加的行* @param column 添加列号* @param val 添加值* @param align 对齐方式(1:靠左;2:居中;3:靠右)* @return 单元格对象*/public Cell addCell(Row row, int column, Object val, int align, Class<?> fieldType){Cell cell = row.createCell(column);String cellFormatString = "@";try {if(val == null){cell.setCellValue("");}else if(fieldType != Class.class){cell.setCellValue((String)fieldType.getMethod("setValue", Object.class).invoke(null, val));}else{if(val instanceof String) {cell.setCellValue((String) val);}else if(val instanceof Integer) {cell.setCellValue((Integer) val);cellFormatString = "0";}else if(val instanceof Long) {cell.setCellValue((Long) val);cellFormatString = "0";}else if(val instanceof Double) {cell.setCellValue((Double) val);cellFormatString = "0.00";}else if(val instanceof Float) {cell.setCellValue((Float) val);cellFormatString = "0.00";}else if(val instanceof Date) {cell.setCellValue((Date) val);cellFormatString = "yyyy-MM-dd HH:mm";}else {cell.setCellValue((String)Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), "fieldtype."+val.getClass().getSimpleName()+"Type")).getMethod("setValue", Object.class).invoke(null, val));}}if (val != null){CellStyle style = styles.get("data_column_"+column);if (style == null){style = wb.createCellStyle();style.cloneStyleFrom(styles.get("data"+(align>=1&&align<=3?align:"")));style.setDataFormat(wb.createDataFormat().getFormat(cellFormatString));styles.put("data_column_" + column, style);}cell.setCellStyle(style);}} catch (Exception ex) {log.info("Set cell value ["+row.getRowNum()+","+column+"] error: " + ex.toString());cell.setCellValue(val.toString());}return cell;}/*** 添加数据(通过annotation.ExportField添加数据)* @return list 数据列表*/public <E> ExportExcel setDataList(List<E> list){for (E e : list){int colunm = 0;Row row = this.addRow();StringBuilder sb = new StringBuilder();for (Object[] os : annotationList){ExcelField ef = (ExcelField)os[0];Object val = null;// Get entity valuetry{if (StringUtils.isNotBlank(ef.value())){val = Reflections.invokeGetter(e, ef.value());}else{if (os[1] instanceof Field){val = Reflections.invokeGetter(e, ((Field)os[1]).getName());}else if (os[1] instanceof Method){val = Reflections.invokeMethod(e, ((Method)os[1]).getName(), new Class[] {}, new Object[] {});}}// If is dict, get dict label
//                  if (StringUtils.isNotBlank(ef.dictType())){
//                      val = DictUtils.getDictLabel(val==null?"":val.toString(), ef.dictType(), "");
//                  }}catch(Exception ex) {// Failure to ignorelog.info(ex.toString());val = "";}this.addCell(row, colunm++, val, ef.align(), ef.fieldType());sb.append(val + ", ");}log.debug("Write success: ["+row.getRowNum()+"] "+sb.toString());}return this;}/*** 输出数据流* @param os 输出数据流*/public ExportExcel write(OutputStream os) throws IOException{wb.write(os);return this;}/*** 输出到客户端* @param fileName 输出文件名*/public ExportExcel write(HttpServletResponse response, String fileName) throws IOException{response.reset();response.setContentType("application/octet-stream; charset=utf-8");response.setHeader("Content-Disposition", "attachment; filename="+Encodes.urlEncode(fileName));write(response.getOutputStream());return this;}/*** 输出到文件* @param fileName 输出文件名*/public ExportExcel writeFile(String name) throws FileNotFoundException, IOException{FileOutputStream os = new FileOutputStream(name);this.write(os);return this;}/*** 清理临时文件*/public ExportExcel dispose(){wb.dispose();return this;}// /**
//   * 导出测试
//   */
//  public static void main(String[] args) throws Throwable {
//
//      List<String> headerList = new ArrayList()();
//      for (int i = 1; i <= 10; i++) {
//          headerList.add("表头"+i);
//      }
//
//      List<String> dataRowList = new ArrayList()();
//      for (int i = 1; i <= headerList.size(); i++) {
//          dataRowList.add("数据"+i);
//      }
//
//      List<List<String>> dataList = new ArrayList()();
//      for (int i = 1; i <=1000000; i++) {
//          dataList.add(dataRowList);
//      }
//
//      ExportExcel ee = new ExportExcel("表格标题", headerList);
//
//      for (int i = 0; i < dataList.size(); i++) {
//          Row row = ee.addRow();
//          for (int j = 0; j < dataList.get(i).size(); j++) {
//              ee.addCell(row, j, dataList.get(i).get(j));
//          }
//      }
//
//      ee.writeFile("target/export.xlsx");
//
//      ee.dispose();
//
//      log.debug("Export success.");
//
//  }}

ImportExcel.java

package io.jboot.admin.excelutils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 导入Excel文件(支持“XLS”和“XLSX”格式)*/
public class ImportExcel {private static Logger log = LoggerFactory.getLogger(ImportExcel.class);/*** 工作薄对象*/private Workbook wb;/*** 工作表对象*/private Sheet sheet;/*** 标题行号*/private int headerNum;/*** 构造函数* @param path 导入文件,读取第一个工作表* @param headerNum 标题行号,数据行号=标题行号+1* @throws InvalidFormatException * @throws IOException */public ImportExcel(String fileName, int headerNum) throws InvalidFormatException, IOException {this(new File(fileName), headerNum);}/*** 构造函数* @param path 导入文件对象,读取第一个工作表* @param headerNum 标题行号,数据行号=标题行号+1* @throws InvalidFormatException * @throws IOException */public ImportExcel(File file, int headerNum) throws InvalidFormatException, IOException {this(file, headerNum, 0);}/*** 构造函数* @param path 导入文件* @param headerNum 标题行号,数据行号=标题行号+1* @param sheetIndex 工作表编号* @throws InvalidFormatException * @throws IOException */public ImportExcel(String fileName, int headerNum, int sheetIndex) throws InvalidFormatException, IOException {this(new File(fileName), headerNum, sheetIndex);}/*** 构造函数* @param path 导入文件对象* @param headerNum 标题行号,数据行号=标题行号+1* @param sheetIndex 工作表编号* @throws InvalidFormatException * @throws IOException */public ImportExcel(File file, int headerNum, int sheetIndex) throws InvalidFormatException, IOException {this(file.getName(), new FileInputStream(file), headerNum, sheetIndex);}/*** 构造函数* @param file 导入文件对象* @param headerNum 标题行号,数据行号=标题行号+1* @param sheetIndex 工作表编号* @throws InvalidFormatException * @throws IOException *//*public ImportExcel(MultipartFile multipartFile, int headerNum, int sheetIndex) throws InvalidFormatException, IOException {this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);}*//*** 构造函数* @param path 导入文件对象* @param headerNum 标题行号,数据行号=标题行号+1* @param sheetIndex 工作表编号* @throws InvalidFormatException * @throws IOException */public ImportExcel(String fileName, InputStream is, int headerNum, int sheetIndex) throws InvalidFormatException, IOException {if (StringUtils.isBlank(fileName)){throw new RuntimeException("导入文档为空!");}else if(fileName.toLowerCase().endsWith("xls")){   this.wb = new HSSFWorkbook(is);    }else if(fileName.toLowerCase().endsWith("xlsx")){  this.wb = new XSSFWorkbook(is);}else{  throw new RuntimeException("文档格式不正确!");}  if (this.wb.getNumberOfSheets()<sheetIndex){throw new RuntimeException("文档中没有工作表!");}this.sheet = this.wb.getSheetAt(sheetIndex);this.headerNum = headerNum;log.debug("Initialize success.");}/*** 获取行对象* @param rownum* @return*/public Row getRow(int rownum){return this.sheet.getRow(rownum);}/*** 获取数据行号* @return*/public int getDataRowNum(){return headerNum+1;}/*** 获取最后一个数据行号* @return*/public int getLastDataRowNum(){return this.sheet.getLastRowNum()+headerNum;}/*** 获取最后一个列号* @return*/public int getLastCellNum(){return this.getRow(headerNum).getLastCellNum();}/*** 获取单元格值* @param row 获取的行* @param column 获取单元格列号* @return 单元格值*/public Object getCellValue(Row row, int column){Object val = "";try{Cell cell = row.getCell(column);if (cell != null){if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
//                  val = cell.getNumericCellValue();DecimalFormat df = new DecimalFormat("0");     // 去掉科学计数法val = df.format(cell.getNumericCellValue());  }else if (cell.getCellType() == Cell.CELL_TYPE_STRING){val = cell.getStringCellValue();}else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA){val = cell.getCellFormula();}else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN){val = cell.getBooleanCellValue();}else if (cell.getCellType() == Cell.CELL_TYPE_ERROR){val = cell.getErrorCellValue();}}}catch (Exception e) {return val;}return val;}/*** 获取导入数据列表* @param cls 导入对象类型* @param groups 导入分组*/public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{List<Object[]> annotationList = new ArrayList<Object[]>();// Get annotation field Field[] fs = cls.getDeclaredFields();for (Field f : fs){ExcelField ef = f.getAnnotation(ExcelField.class);if (ef != null && (ef.type()==0 || ef.type()==2)){if (groups!=null && groups.length>0){boolean inGroup = false;for (int g : groups){if (inGroup){break;}for (int efg : ef.groups()){if (g == efg){inGroup = true;annotationList.add(new Object[]{ef, f});break;}}}}else{annotationList.add(new Object[]{ef, f});}}}// Get annotation methodMethod[] ms = cls.getDeclaredMethods();for (Method m : ms){ExcelField ef = m.getAnnotation(ExcelField.class);if (ef != null && (ef.type()==0 || ef.type()==2)){if (groups!=null && groups.length>0){boolean inGroup = false;for (int g : groups){if (inGroup){break;}for (int efg : ef.groups()){if (g == efg){inGroup = true;annotationList.add(new Object[]{ef, m});break;}}}}else{annotationList.add(new Object[]{ef, m});}}}// Field sortingCollections.sort(annotationList, new Comparator<Object[]>() {public int compare(Object[] o1, Object[] o2) {return new Integer(((ExcelField)o1[0]).sort()).compareTo(new Integer(((ExcelField)o2[0]).sort()));};});//log.debug("Import column count:"+annotationList.size());// Get excel dataList<E> dataList = new ArrayList<E>();for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) {E e = (E)cls.newInstance();int column = 0;Row row = this.getRow(i);StringBuilder sb = new StringBuilder();for (Object[] os : annotationList){Object val = this.getCellValue(row, column++);if (val != null){ExcelField ef = (ExcelField)os[0];// If is dict type, get dict valueif (StringUtils.isNotBlank(ef.dictType())){
//                      val = DictUtils.getDictValue(val.toString(), ef.dictType(), "");//log.debug("Dictionary type value: ["+i+","+colunm+"] " + val);}// Get param type and type castClass<?> valType = Class.class;if (os[1] instanceof Field){valType = ((Field)os[1]).getType();}else if (os[1] instanceof Method){Method method = ((Method)os[1]);if ("get".equals(method.getName().substring(0, 3))){valType = method.getReturnType();}else if("set".equals(method.getName().substring(0, 3))){valType = ((Method)os[1]).getParameterTypes()[0];}}//log.debug("Import value type: ["+i+","+column+"] " + valType);try {if (valType == String.class){String s = String.valueOf(val.toString());if(StringUtils.endsWith(s, ".0")){val = StringUtils.substringBefore(s, ".0");}else{val = String.valueOf(val.toString());}}else if (valType == Integer.class){val = Double.valueOf(val.toString()).intValue();}else if (valType == Long.class){val = Double.valueOf(val.toString()).longValue();}else if (valType == Double.class){val = Double.valueOf(val.toString());}else if (valType == Float.class){val = Float.valueOf(val.toString());}else if (valType == Date.class){val = DateUtil.getJavaDate((Double)val);}else{if (ef.fieldType() != Class.class){val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());}else{val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), "fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());}}} catch (Exception ex) {log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());val = null;}// set entity valueif (os[1] instanceof Field){Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);}else if (os[1] instanceof Method){String mthodName = ((Method)os[1]).getName();if ("get".equals(mthodName.substring(0, 3))){mthodName = "set"+StringUtils.substringAfter(mthodName, "get");}Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});}}sb.append(val+", ");}dataList.add(e);log.debug("Read success: ["+i+"] "+sb.toString());}return dataList;}//    /**
//   * 导入测试
//   */
//  public static void main(String[] args) throws Throwable {
//
//      ImportExcel ei = new ImportExcel("target/export.xlsx", 1);
//
//      for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
//          Row row = ei.getRow(i);
//          for (int j = 0; j < ei.getLastCellNum(); j++) {
//              Object val = ei.getCellValue(row, j);
//              System.out.print(val+", ");
//          }
//          System.out.print("\n");
//      }
//
//  }}

Reflections.java

package io.jboot.admin.excelutils;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 反射工具类.* 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.*/
@SuppressWarnings("rawtypes")
public class Reflections {private static final String SETTER_PREFIX = "set";private static final String GETTER_PREFIX = "get";private static final String CGLIB_CLASS_SEPARATOR = "$$";private static Logger logger = LoggerFactory.getLogger(Reflections.class);/*** 调用Getter方法.* 支持多级,如:对象名.对象名.方法*/public static Object invokeGetter(Object obj, String propertyName) {Object object = obj;for (String name : StringUtils.split(propertyName, ".")){String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});}return object;}/*** 调用Setter方法, 仅匹配方法名。* 支持多级,如:对象名.对象名.方法*/public static void invokeSetter(Object obj, String propertyName, Object value) {Object object = obj;String[] names = StringUtils.split(propertyName, ".");for (int i=0; i<names.length; i++){if(i<names.length-1){String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});}else{String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);invokeMethodByName(object, setterMethodName, new Object[] { value });}}}/*** 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.*/public static Object getFieldValue(final Object obj, final String fieldName) {Field field = getAccessibleField(obj, fieldName);if (field == null) {throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");}Object result = null;try {result = field.get(obj);} catch (IllegalAccessException e) {logger.error("不可能抛出的异常{}", e.getMessage());}return result;}/*** 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.*/public static void setFieldValue(final Object obj, final String fieldName, final Object value) {Field field = getAccessibleField(obj, fieldName);if (field == null) {throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");}try {field.set(obj, value);} catch (IllegalAccessException e) {logger.error("不可能抛出的异常:{}", e.getMessage());}}/*** 直接调用对象方法, 无视private/protected修饰符.* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.* 同时匹配方法名+参数类型,*/public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,final Object[] args) {Method method = getAccessibleMethod(obj, methodName, parameterTypes);if (method == null) {throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");}try {return method.invoke(obj, args);} catch (Exception e) {throw convertReflectionExceptionToUnchecked(e);}}/*** 直接调用对象方法, 无视private/protected修饰符,* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.* 只匹配函数名,如果有多个同名函数调用第一个。*/public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {Method method = getAccessibleMethodByName(obj, methodName);if (method == null) {throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");}try {return method.invoke(obj, args);} catch (Exception e) {throw convertReflectionExceptionToUnchecked(e);}}/*** 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.* * 如向上转型到Object仍无法找到, 返回null.*/public static Field getAccessibleField(final Object obj, final String fieldName) {Validate.notNull(obj, "object can't be null");Validate.notBlank(fieldName, "fieldName can't be blank");for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {try {Field field = superClass.getDeclaredField(fieldName);makeAccessible(field);return field;} catch (NoSuchFieldException e) {//NOSONAR// Field不在当前类定义,继续向上转型continue;// new add}}return null;}/*** 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.* 如向上转型到Object仍无法找到, 返回null.* 匹配函数名+参数类型。* * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)*/public static Method getAccessibleMethod(final Object obj, final String methodName,final Class<?>... parameterTypes) {Validate.notNull(obj, "object can't be null");Validate.notBlank(methodName, "methodName can't be blank");for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {try {Method method = searchType.getDeclaredMethod(methodName, parameterTypes);makeAccessible(method);return method;} catch (NoSuchMethodException e) {// Method不在当前类定义,继续向上转型continue;// new add}}return null;}/*** 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.* 如向上转型到Object仍无法找到, 返回null.* 只匹配函数名。* * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)*/public static Method getAccessibleMethodByName(final Object obj, final String methodName) {Validate.notNull(obj, "object can't be null");Validate.notBlank(methodName, "methodName can't be blank");for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {Method[] methods = searchType.getDeclaredMethods();for (Method method : methods) {if (method.getName().equals(methodName)) {makeAccessible(method);return method;}}}return null;}/*** 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。*/public static void makeAccessible(Method method) {if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))&& !method.isAccessible()) {method.setAccessible(true);}}/*** 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。*/public static void makeAccessible(Field field) {if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {field.setAccessible(true);}}/*** 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处* 如无法找到, 返回Object.class.* eg.* public UserDao extends HibernateDao<User>** @param clazz The class to introspect* @return the first generic declaration, or Object.class if cannot be determined*/@SuppressWarnings("unchecked")public static <T> Class<T> getClassGenricType(final Class clazz) {return getClassGenricType(clazz, 0);}/*** 通过反射, 获得Class定义中声明的父类的泛型参数的类型.* 如无法找到, 返回Object.class.* * 如public UserDao extends HibernateDao<User,Long>** @param clazz clazz The class to introspect* @param index the Index of the generic ddeclaration,start from 0.* @return the index generic declaration, or Object.class if cannot be determined*/public static Class getClassGenricType(final Class clazz, final int index) {Type genType = clazz.getGenericSuperclass();if (!(genType instanceof ParameterizedType)) {logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");return Object.class;}Type[] params = ((ParameterizedType) genType).getActualTypeArguments();if (index >= params.length || index < 0) {logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "+ params.length);return Object.class;}if (!(params[index] instanceof Class)) {logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");return Object.class;}return (Class) params[index];}public static Class<?> getUserClass(Object instance) {Class clazz = instance.getClass();if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {Class<?> superClass = clazz.getSuperclass();if (superClass != null && !Object.class.equals(superClass)) {return superClass;}}return clazz;}/*** 将反射时的checked exception转换为unchecked exception.*/public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException|| e instanceof NoSuchMethodException) {return new IllegalArgumentException(e);} else if (e instanceof InvocationTargetException) {return new RuntimeException(((InvocationTargetException) e).getTargetException());} else if (e instanceof RuntimeException) {return (RuntimeException) e;}return new RuntimeException("Unexpected Checked Exception.", e);}
}

Encodes.java

package io.jboot.admin.excelutils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;/*** 封装各种格式的编码解码工具类.* 1.Commons-Codec的 hex/base64 编码* 2.自制的base62 编码* 3.Commons-Lang的xml/html escape* 4.JDK提供的URLEncoder*/
public class Encodes {private static final String DEFAULT_URL_ENCODING = "UTF-8";private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();/*** Hex编码.*/public static String encodeHex(byte[] input) {return new String(Hex.encodeHex(input));}/*** Hex解码.*/public static byte[] decodeHex(String input) {try {return Hex.decodeHex(input.toCharArray());} catch (DecoderException e) {throw Exceptions.unchecked(e);}}/*** Base64编码.*/public static String encodeBase64(byte[] input) {return new String(Base64.encodeBase64(input));}/*** Base64编码.*/public static String encodeBase64(String input) {try {return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING)));} catch (UnsupportedEncodingException e) {return "";}}//    /**
//   * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
//   */
//  public static String encodeUrlSafeBase64(byte[] input) {
//      return Base64.encodeBase64URLSafe(input);
//  }/*** Base64解码.*/public static byte[] decodeBase64(String input) {return Base64.decodeBase64(input.getBytes());}/*** Base64解码.*/public static String decodeBase64String(String input) {try {return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING);} catch (UnsupportedEncodingException e) {return "";}}/*** Base62编码。*/public static String encodeBase62(byte[] input) {char[] chars = new char[input.length];for (int i = 0; i < input.length; i++) {chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];}return new String(chars);}/*** Html 转码.*/public static String escapeHtml(String html) {return StringEscapeUtils.escapeHtml4(html);}/*** Html 解码.*/public static String unescapeHtml(String htmlEscaped) {return StringEscapeUtils.unescapeHtml4(htmlEscaped);}/*** Xml 转码.*/public static String escapeXml(String xml) {return StringEscapeUtils.escapeXml10(xml);}/*** Xml 解码.*/public static String unescapeXml(String xmlEscaped) {return StringEscapeUtils.unescapeXml(xmlEscaped);}/*** URL 编码, Encode默认为UTF-8. */public static String urlEncode(String part) {try {return URLEncoder.encode(part, DEFAULT_URL_ENCODING);} catch (UnsupportedEncodingException e) {throw Exceptions.unchecked(e);}}/*** URL 解码, Encode默认为UTF-8. */public static String urlDecode(String part) {try {return URLDecoder.decode(part, DEFAULT_URL_ENCODING);} catch (UnsupportedEncodingException e) {throw Exceptions.unchecked(e);}}
}

引入jar包

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.9</version><!-- 3.9 --></dependency><!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>3.9</version></dependency>

注意点:jboot框架内 Bean对象的get set 方法是  return get(‘xxx’)和set(‘xxx’, xxx),spring框架的话是return xxx和this.xxx=xxx

所以在ExportExcel.java中的 添加一个单元格addCell()内的反射赋值做对应处理。

Jboot框架内Bean里方法上的注解不能写到基类内,否则不生效(具体没明白为什么);

    public void setName(java.lang.String name) {set("name", name);}@ExcelField(title="姓名", align=2, sort=20)public java.lang.String getName() {return getStr("name");}

导出效果

下载模板效果

Jboot框架excel导入导出模板下载的简单封装相关推荐

  1. 一个基于POI的通用excel导入导出工具类的简单实现及使用方法

    前言: 最近PM来了一个需求,简单来说就是在录入数据时一条一条插入到系统显得非常麻烦,让我实现一个直接通过excel导入的方法一次性录入所有数据.网上关于excel导入导出的例子很多,但大多相互借鉴. ...

  2. easyexcel 设置标题_EasyExcel,让 excel 导入导出更加简单

    做积极的人,而不是积极废人! 来源:jianshu.com/p/8f3defdc76d4EasyExcelGitHub上的官方说明快速开始maven仓库地址导入导出总结 EasyExcel 在做exc ...

  3. easypoi 多sheet导入_程序员接私活利器 玩转excel导入导出

    为什么会写Easypoi 以前的以前(岁月真TMD的快)我虽然写了不少代码但还是很少写poi,然后跳到一家公司之后就和业务人员聊上了,来这个需要个报表,这个报表样式是这样的,这个表头是这样的,就这样我 ...

  4. SpringBoot集成EasyPoi实现Excel导入导出

    作者介绍: 本人Java特工,代号:Cris Li : 中文名:克瑞斯理 简书地址: 消失的码农 - 简书 CSDN地址: https://blog.csdn.net/jianli95 个人纯洁版博客 ...

  5. SpringBoot实现Excel导入导出,好用到爆,POI可以扔掉了!

    在我们平时工作中经常会遇到要操作Excel的功能,比如导出个用户信息或者订单信息的Excel报表.你肯定听说过POI这个东西,可以实现.但是POI实现的API确实很麻烦,它需要写那种逐行解析的代码(类 ...

  6. 基于 POI 封装 ExcelUtil 精简的 Excel 导入导出

    由于 poi 本身只是针对于 excel 等office软件的一个工具包,在一些常规的 excel 导入导出时,还需要再做一次精简的封装,简化代码耦合. 一.现状 本人经历过几家公司的代码封装,导入导 ...

  7. easyexcel 在 设置标题_EasyExcel,让excel导入导出更加简单

    EasyExcel 在做excel导入导出的时候,发现项目中封装的工具类及其难用,于是去gitHub上找了一些相关的框架,最终选定了EasyExcel.之前早有听闻该框架,但是一直没有去了解,这次借此 ...

  8. Java操作大数据量Excel导入导出万能工具类(完整版)

    Java操作大数据量Excel导入导出万能工具类(完整版) 转载自:https://blog.csdn.net/JavaWebRookie/article/details/80843653 更新日志: ...

  9. Java实现Excel导入导出操作详解

    前言 本次封装是基于 POI 的二次开发,最终使用只需要调用一个工具类中的方法,就能满足业务中绝大部门的导入和导出需求. 1. 功能测试 1.1 测试准备 在做测试前,我们需要將[2. 环境准备]中的 ...

最新文章

  1. oracle表空间压缩
  2. 历经8年双11流量洗礼,淘宝开放平台如何攻克技术难关?--转
  3. 2018第九届蓝桥杯C/C++ B国赛 —— 第三题:格雷码
  4. 【工业控制】What is a Waveform
  5. 数据挖掘: 频繁项集挖掘(购物篮问题)
  6. 附加作业:源自刘乾老师的问题
  7. Linux运维系统工程师系列---13
  8. html5点击按钮出现弹窗 怎么实现_HTML5游戏开发过程中的二三事
  9. Nutanix公布财报数据 准备IPO前表现抢眼
  10. 【蓝桥杯官网试题 - 基础练习】 矩形面积交 (几何)
  11. Google SVN托管和使用学习笔记
  12. STM32 的RAM跑到哪里去了
  13. 修复老相片_将老相片数码化
  14. 一、数据库应用系统分析及规划
  15. hp1015驱动64位_惠普1015打印机驱动下载
  16. 子慕谈设计模式系列(三)
  17. Vitis开发笔记:使用分区工具Gparted将SD卡分为BOOT和RoofFS
  18. 关闭Window 10 Ctrl+Shift+B(表情包)快捷键冲突
  19. python的mapl画图y轴排_Python三维绘图之Matplotlib库的使用方法
  20. C++ 类的静态成员及静态成员函数

热门文章

  1. 大数据时代的时序数据 陈超-互联网技术联盟-专题视频课程
  2. Angular.js前端简单微服务架构设计
  3. 2021年中国防潮垫市场趋势报告、技术动态创新及2027年市场预测
  4. 从外行的视角尝试讲解为什么这回丰田栽了
  5. 多态Class对象注册工厂反射动态代理
  6. java基础之面向对象的运用
  7. LeetCode每日一题——380. O(1) 时间插入、删除和获取随机元素
  8. 例9003 火星上的加法
  9. Python之模块增加到site-packages
  10. 自制一个USB2.0拓展坞