excel導入導出工具類

Excel導入功能

導入功能是將excel中的數據轉換成對應的javaBean。

實現思路

  1. 使用poi讀取excel表格
  2. 獲取每行表格中的單元格信息,將單元格中的數據存入到對應的javaBean中。
  3. 寫一個註解類來標註javaBean中的那個屬性要與Excel中的數據進行對應。
  4. 運用java反射來獲取javaBean中的註解屬性。

代碼實現

 public class ImportExcelUtil {
    private final Logger logger = LoggerFactory.getLogger(ImportExcelUtil.class);
    private static final int DEFAULT_COUNT=20000;
    private static final int DEFAULT_START_LINE=0;
    public static <T> List<T> convertSheetToList(InputStream in,Class<T> clazz, boolean isExcel2003,
                                                 int startLine,int maxCount) throws Exception {
       List<T> list = new ArrayList<>();
        /** 根據版本選擇創建Workbook的方式 */
        Workbook wb;
        if (isExcel2003) {
            wb = new HSSFWorkbook(in);
        } else {
            wb = new XSSFWorkbook(in);
        }
        if(null != wb){
            //獲取第0個工作表格
            Sheet sheet = wb.getSheetAt(0);
            int count = sheet.getLastRowNum();
            if(maxCount == 0){
                maxCount = DEFAULT_COUNT;
            }
            if(count > maxCount){
                throw new Exception("導入失敗,excel數據控制在"+maxCount+"條之內!");
            }
            //遍歷excel表格並將每一行中的數據轉換成對象
            if(startLine < 0){
                startLine = DEFAULT_START_LINE;
            }
            for(int i=startLine;i<=count;i++){
                Row row = sheet.getRow(i);
                if(row==null){
                    continue;
                }
                T obj = convertLineToObj(clazz,row);
                if(obj==null){
                    continue;
                }
                list.add(obj);
            }
        }
        return list;
    }
    //行遍歷
    private static <T> T convertLineToObj(Class<T> clazz, Row row) throws Exception {
        T obj = clazz.newInstance();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields){
            ExcelImport annotation = field.getAnnotation(ExcelImport.class);
            if(annotation!=null && row.getLastCellNum() >= annotation.columnIndex()){
                //每行對應的單元格遍歷
                Cell cell = row.getCell(annotation.columnIndex());
                if(cell==null)
                    throw new Exception("請使用正確的excel模板");
                field.setAccessible(true);
                field.set(obj,getCellValue(cell));
            }
        }
        return obj;
    }
    private static Object getCellValue(Cell cell) {
        if(cell.getCellType() == Cell.CELL_TYPE_BOOLEAN){
            return String.valueOf(cell.getBooleanCellValue());
        }else if(cell.getCellType()==Cell.CELL_TYPE_NUMERIC){
            DecimalFormat df = new DecimalFormat("0.00");
            String str = df.format(cell.getNumericCellValue());
            return str;
        }
        return String.valueOf(cell.getStringCellValue());
    }

    public static void main(String[] args) {
        try {
            FileInputStream in = new FileInputStream("/Users/vobile_lzl/Downloads/tvids(2).xlsx");
//            List<TvIdPresent> list = convertSheetToList(in, TvIdPresent.class,false,1);
//            System.out.println("list = " + list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

註解類()

該類主要用來識別excel字段中對應那個javaBean的屬性。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface ExcelImport {
    int columnIndex() default 0;
}
  • 例子
public class ShopResourceExcelBo {
    @ExcelImport(columnIndex = 0)
    private String resourceId;
    @ExcelImport(columnIndex = 1)
    private String resourceName;
    @ExcelImport(columnIndex = 2)
    private String priceStr;
    @ExcelImport(columnIndex = 3)
    private String inventoryNumStr;
   }
   ...省去set和get方法

   調用方法
    List<ShopResourceExcelBo> excelList = ImportExcelUtil.convertSheetToList(inputStream, 
    ShopResourceExcelBo.class,isExcel2003,1,500);

導出Excel

將List集合中的對象轉換過成excel單元格數據

  • 同樣是利用poi的導出功能來實現。
  • 利用註解來說明javaBean的屬性對應excel的單元格信息。
  • 利用java反射將註解類的屬性描述寫入到excel的頭信息上。
  • 利用java反射將註解類中的屬性值寫入到excel對應的單元格。

代碼實現

public class ExportExcelUtil {
    private final Logger logger = LoggerFactory.getLogger(ExportExcelUtil.class);
    private OutputStream outputStream;
    private Workbook workbook;
    private HSSFSheet sheet;
    private int index;

    public ExportExcelUtil(String fileName){
        try {
            this.init(new FileOutputStream(fileName));
        } catch (FileNotFoundException e) {
            logger.error("導出excel出錯");
            e.printStackTrace();
        }
    }
    public ExportExcelUtil(OutputStream outputStream){
        try {
            this.init(outputStream);
        } catch (Exception e) {
            logger.error("導出excel出錯");
            e.printStackTrace();
        }
    }
    private void init(OutputStream fileOutputStream) {
        this.outputStream = fileOutputStream;
        this.workbook = new HSSFWorkbook();
        this.index = 0;
    }

    public ExportExcelUtil writeHead(Class<?> tClass){
        if (tClass==null){
            return this;
        }
        List<String> list = new ArrayList<>();
        for (Field filed : getFields(tClass)) {
           ExcelExport excelExport = filed.getAnnotation(ExcelExport.class);
           list.add(excelExport.columnName());
        }
        createData(list);
        return this;
    }

    /**
     * 獲取帶有ExcelExport註解的屬性
     * @param tClass
     * @return
     */
    private List<Field> getFields(Class<?> tClass){
        Field[] fields = tClass.getDeclaredFields();
        List<Field> list = new ArrayList<>(fields.length);
        for (Field f: fields) { //遍歷tClass中的屬性
            if(f.isAnnotationPresent(ExcelExport.class)){ //有ExcelExport註解的信息屬性保留
                list.add(f);
            }
        }
        return list;
    }
    /**
     * 行列填充數據
     * @param list
     */
    private void createData(List<String> list) {
        if(sheet == null){
            sheet = (HSSFSheet) workbook.createSheet();
        }
        HSSFRow row = sheet.createRow(index++);
        HSSFCell[] cells = new HSSFCell[list.size()];
        for(int i=0;i<cells.length;i++) {
            cells[i] = row.createCell(i);
            cells[i].setCellValue(list.get(i));
        }
    }
    public <T> ExportExcelUtil writeList(List<T> list){
        if(list!=null && list.size()>0){
            for ( Object obj: list) {
                writeObject(obj);
            }
        }
        return this;
    }

    private void writeObject(Object obj) {
        Class clazz = obj.getClass();
        List<String> list = new ArrayList<>();
        for (Field f: getFields(clazz)) {
            f.setAccessible(true);
            try {
                Object o = f.get(obj);
                if(o instanceof Date){
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    list.add(sdf.format(o));
                }else if(o instanceof BigDecimal){
                    list.add(String.valueOf(((BigDecimal) o).setScale(2,BigDecimal.ROUND_CEILING)));
                }else{
                    list.add(String.valueOf(o));
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                logger.error("格式化obj失敗");
            }
        }
        if(!list.isEmpty()){
            createData(list);
        }
    }
    public void exportData(){
        try {
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("創建excel失敗");
        }
    }
}

註解類

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface ExcelExport {
    String columnName() default "";
}
  • 例子
public class OperationRecordVO{

    @ExcelExport(columnName = "用戶名")
    private String username;

    @ExcelExport(columnName = "角色")
    private String roleName;

    @ExcelExport(columnName = "IP地址")
    private String ip;

    @ExcelExport(columnName = "操作內容")
    private String context;

    private Integer type;

    @ExcelExport(columnName = "操作類型")
    private String typeStr;

    private String objectType;

    private String objectId;

    @ExcelExport(columnName = "操作時間")
    @JsonSerialize(converter = JacksonDateConverter.BacklashDateTimeConverter.class)
    private Date createTime;
    }

    ...省去get和set方法

    //調用實例
 public void exportRecords(String startTime,String endTime,HttpServletResponse response){
        List<OperationRecordVO> list = operationRecordService.exportRecordsByDate(startTime,endTime);
        //導出excel
        String fileName = "操作日誌.xls";
        try {
            response.setContentType("application/octet-stream;");
            response.setHeader("Content-disposition",
                    "attachment; filename=" + new String(fileName.getBytes("UTF-8"), "iso8859-1"));
            ExcelExportUtil excelExportUtil = new ExcelExportUtil(response.getOutputStream());
            //excel第一列表頭信息
            excelExportUtil.writeHeader(OperationRecordVO.class);
            //寫入每一行信息
            excelExportUtil.writeObjects(list);
            excelExportUtil.exportData();
        } catch (IOException e) {
            logger.error("導出excel失敗...");
            e.printStackTrace();
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章