一、添加需要用到的依赖
<!-- 实体类工具 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency><!-- excel工具 -->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency><!-- Alibaba Fastjson -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.74</version>
</dependency>
二、创建注解类
import java.lang.annotation.*;/*** excel注解** @author 胡晓波* @version V3.1.0* @copyright 微奇点网络工作室* @date 2022-11-03 17:00:03*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface Excel {/*** 导入导出数据的名称* @return*/String value();/*** 导出时每行数据是否有序号列(实体类上才有效)* @return*/boolean xh() default false;/*** 导出时列顺序* @return*/int sort() default 0;/*** 导出时需要格式化的数据* @return*/String format() default "";/*** 导出是否忽视* @return*/boolean hidden() default false;
}
三、异常类
/*** excel异常类** @author 胡晓波* @version V3.1.0* @copyright 微奇点网络工作室* @date 2022-11-03 14:58:32*/
public class ExcelException extends Exception {public ExcelException() {super();}public ExcelException(String message) {super(message);}
}
四、需要用到的时间工具类和json工具类
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;/*** 时间类型工具** @author 胡晓波* @version V3.1.0* @copyright 微奇点网络工作室* @date 2022-11-04 15:28:06*/
public class DateUtil {/*** Date类型转字符串* @param date* @param pattern* @return* @throws Exception*/public static String dateFormat (Date date, String pattern) throws Exception {if (StringUtil.isEmpty(pattern)) {throw new Exception("转换格式为空");}if (date == null) {date = new Date();}SimpleDateFormat formatter = new SimpleDateFormat(pattern);String dateString = formatter.format(date);return dateString;}/*** LocalDateTime类型进行格式化输出(返回类型:String)* @param date* @return*/public static String dateFormat(LocalDateTime date) {DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String localTime = df.format(date);return localTime;}/*** LocalDate类型进行格式化输出(返回类型:String)* @param date* @return*/public static String dateFormat(LocalDate date) {DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");String localTime = df.format(date);return localTime;}
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;import java.util.List;/*** json转换工具** @author 胡晓波* @version V3.1.0* @copyright 微奇点网络工作室* @date 2022-11-04 15:26:34*/
public class JsonUtil {/*** 功能描述:把java对象转换成JSON数据* @param object java对象* @return JSON数据*/public static String getObjectToString(Object object) {return JSON.toJSONString(object, SerializerFeature.WriteMapNullValue);}/*** 功能描述:把JSON数据转换成指定的java对象列表* @param dto dto对象* @param clazz 指定的java对象* @return List<T>*/public static <T> List<T> getJsonToList(Object dto, Class<T> clazz) {return JSON.parseArray(getObjectToString(dto), clazz);}}
五、导入导出excel工具类具体代码
import com.wx.annotation.Excel;
import com.wx.exception.ExcelException;
import lombok.Builder;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.InputStream;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;/*** excel导入导出工具** @author 胡晓波* @version V3.1.0* @copyright 微奇点网络工作室* @date 2022-11-04 09:43:27*/
public class DoExcel {/*** excel数据导入* @param is excel 导入数据* @param oc 实体类类型* @param sheetIndex 工作簿下标* @param titleRowIndex 标题行下标* @param <T>* @return 实体类集合* @throws Exception*/public static <T> List<T> importExcel (InputStream is, Class<T> oc, Integer sheetIndex, Integer titleRowIndex) throws Exception {XSSFWorkbook workbook = new XSSFWorkbook(is);XSSFSheet sheet = workbook.getSheetAt(sheetIndex);// 标题行XSSFRow row = sheet.getRow(titleRowIndex ++);List<String> titleText = new ArrayList<>();for (Cell cell : row) {titleText.add(cell.getStringCellValue());}Field[] fields = oc.getDeclaredFields();Map<String, ExpectExcelVo> titleMap = new HashMap<>(15);for (Field field : fields) {Excel _excel = field.getAnnotation(Excel.class);if (_excel == null) {continue;}titleMap.put(_excel.value(), ExpectExcelVo.builder().name(field.getName()).type(field.getType().getName()).build());}if (titleMap.size() == 0) {throw new ExcelException("类中没有@Excel注解");}List<Map<String, Object>> list = new ArrayList<>();for (int i = titleRowIndex; i <= sheet.getLastRowNum(); i++) {row = sheet.getRow(i);Map<String, Object> map = new HashMap<>(15);for (int j = 0; j < titleText.size(); j++) {String s = titleText.get(j);ExpectExcelVo expectExcelVo = titleMap.get(s);if (expectExcelVo == null) {continue;}XSSFCell cell = row.getCell(j);map.put(expectExcelVo.getName(), cell.getStringCellValue());}list.add(map);}return JsonUtil.getJsonToList(list, oc);}/*** 导出数据为excel* @param list* @param oc* @return excel流* @throws Exception*/public static XSSFWorkbook expectExcel (List<Object> list, Class<?> oc) throws Exception {XSSFWorkbook workbook = new XSSFWorkbook();XSSFSheet sheet = workbook.createSheet("import");Integer rowIndex = 0;Integer cellIndex = 0;Integer header = header(oc, sheet, rowIndex);if (header == 1) {rowIndex ++;}else if (header == 2) {rowIndex ++;cellIndex ++;}ArrayList<String> fieldNames = title(oc, sheet, rowIndex, cellIndex);rowIndex ++;content(list, fieldNames, sheet, rowIndex, cellIndex);return workbook;}/*** 生成表的头部* @param oc* @param sheet* @param rowIndex*/private static Integer header (Class<?> oc, XSSFSheet sheet, Integer rowIndex) {Excel header = oc.getAnnotation(Excel.class);if (header != null) {XSSFRow row = sheet.createRow(rowIndex++);XSSFCell cell = row.createCell(0);cell.setCellValue(header.value());if (header.xh()) {return 2;}return 1;}return 0;}/*** 生成标题* @param oc* @param sheet* @param rowIndex* @param cellIndex* @return* @throws Exception*/private static ArrayList<String> title (Class<?> oc, XSSFSheet sheet, Integer rowIndex, Integer cellIndex) throws Exception {ArrayList<String> fieldNames = new ArrayList<>();Field[] fields = oc.getDeclaredFields();if (fields.length > 0) {for (Field field : fields) {field.setAccessible(true);Excel title = field.getAnnotation(Excel.class);if (title == null || title.hidden()) {continue;}fieldNames.add(field.getName() + "~" + title.sort() + "~" + title.value());}fieldNames.sort((o1, o2) -> {int $1 = Integer.parseInt(o1.split("~")[1]);int $2 = Integer.parseInt(o2.split("~")[1]);return $1 - $2;});}if (fieldNames.size() == 0) {throw new ExcelException("实体类中属性没有@Excel注解");}else {XSSFRow row = sheet.createRow(rowIndex++);XSSFCell xh = row.createCell(0);xh.setCellValue("序号");for (int i = 0; i < fieldNames.size(); i++) {String[] split = fieldNames.get(i).split("~");XSSFCell cell = row.createCell(i+cellIndex);cell.setCellValue(split[2]);fieldNames.set(i, split[0]);}}return fieldNames;}/*** 生成数据内容* @param list* @param fieldNames* @param sheet* @param rowIndex* @param cellIndex* @throws Exception*/private static void content (List<Object> list, ArrayList<String> fieldNames, XSSFSheet sheet, Integer rowIndex, Integer cellIndex) throws Exception {for (int i = 0; i < list.size(); i++) {Object o = list.get(i);Class<?> ec = o.getClass();XSSFRow row = sheet.createRow(rowIndex++);XSSFCell xh = row.createCell(0);xh.setCellValue((i + 1) + "");int colIndex = cellIndex;for (String fieldName : fieldNames) {Field field = ec.getDeclaredField(fieldName);field.setAccessible(true);Excel column = field.getAnnotation(Excel.class);XSSFCell cell = row.createCell(colIndex++);String typeName = field.getType().getName();String[] split = typeName.split("\\.");switch (split[split.length - 1]) {case "Date":cell.setCellValue(DateUtil.dateFormat((Date) field.get(o), column.format()));break;case "LocalDateTime":cell.setCellValue(DateUtil.dateFormat((LocalDateTime) field.get(o)));break;case "LocalDate":cell.setCellValue(DateUtil.dateFormat((LocalDate) field.get(o)));break;default: cell.setCellValue(field.get(o).toString());}}}}
}@Data
@Builder
class ExpectExcelVo {private String type;private String name;
}
六、测试类及测试实体
import com.wx.annotation.Excel;
import com.wx.utils.DoExcel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** 测试类** @author 胡晓波* @version V3.1.0* @copyright 微奇点网络工作室* @date 2022-11-04 15:30:34*/
public class TestMain {public static void main(String[] args) throws Exception {List<Object> list = new ArrayList<Object>(){{add(ExcelTestVo.builder().no(9527).name("唐白虎").sex('男').birthday(new Date()).grad("一年级").school("加州大学").createTime(new Date()).build());add(ExcelTestVo.builder().no(9528).name("秋雅").sex('女').birthday(new Date()).grad("一年级").school("加州大学").createTime(new Date()).build());}};XSSFWorkbook workbook = DoExcel.expectExcel(list, ExcelTestVo.class);// 创建文件 或者直接用相应输出流输出结果(需要配置请求头)File file = new File("D://out/tmp.xlsx");file.createNewFile();FileOutputStream fos = new FileOutputStream(file);workbook.write(fos);workbook.close();fos.close();FileInputStream fis = new FileInputStream(file);List<ExcelTestVo> result = DoExcel.importExcel(fis, ExcelTestVo.class, 0, 1);System.out.println(result);}
}@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Excel(value = "excel导入导出测试实体", xh = true)
class ExcelTestVo {@Excel(value = "编号", sort = 1)private Integer no;@Excel(value = "姓名", sort = 2)private String name;@Excel(value = "性别", sort = 3)private Character sex;@Excel(value = "生日", sort = 4, hidden = true, format = "yyyy-MM-dd")private Date birthday;@Excel(value = "年级", sort = 5)private String grad;@Excel(value = "学校", sort = 6)private String school;@Excel(value = "创建时间", sort = 7, format = "yyyy-MM-dd HH:mm:ss")private Date createTime;}
七、测试结果
导入结果
导出结果