1. 程式人生 > >excel匯入通用程式碼

excel匯入通用程式碼

匯入模板的樣式:

1:自定義註解

/**
 * 用於註解需要插入的物件
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Excel {
}

/**
 * 用於註解物件的屬性
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
    /**
     * 單元格對應的列號,必須指明,不能重複
     *
     * 
@return */ public int column() default -1; /** * 對應的名字、描述 * * @return */ public String description() default "no description"; /** * 單元格內容是否可為空 * true:可以為空,false:不能為空 * @return */ public boolean nullable() default true; }

2:使用註解

@Data
@Excel
public class CreateReservoirDto { @Column(column = 0,nullable = false,description = "測站名字") private String name; @Column(column = 1,nullable = false,description = "測站編碼") private String number; @Column(column = 2,nullable = false,description = "東經") private String lng; @Column(column
= 3,nullable = false,description = "北緯") private String lat; @Column(column = 4,description = "地區") private String address; @Column(column = 5,description = "壩頂高程") private Double damTop; @Column(column = 6,description = "堰頂高程") private Double weirTop; @Column(column = 7,description = "汛限水位") private Double floodWaterLevel; @Column(column = 8,description = "校核洪水位") private Double checkFloodWaterLevel; @Column(column = 9,description = "設計洪水位") private Double designFloodWaterLevel; @Column(column = 10,description = "正常蓄水位") private Double normalStoreWater; @Column(column = 11,description = "死水位") private Double deadWaterLevel; @Column(column = 12,description = "總庫容") private Double totalStorage; @Column(column = 13,description = "興利庫容") private Double utilizableCapacity; @Column(column = 14,description = "死庫容") private Double deadStorage; @Column(column = 15,description = "建立時間") private Long createdTime; }

3:匯入轉轉物件的工具類

import com.irrigation.icl.exception.ContextRuntimeException;
import com.irrigation.synthetic.annotation.Column;
import com.irrigation.synthetic.annotation.Excel;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;


@Slf4j
public class ExcelUtils {

    /**
     * 將excel資料轉換為javaBean
     *
     * @param file     excel檔案
     * @param startRow 匯入內容的開始行號(排除表頭)
     * @param clazz    要轉換的物件
     * @param <T>
     * @return
     */
    public static <T> List<T> getDataFromExcel(MultipartFile file, int startRow, Class<T> clazz) {
        List<T> list = new ArrayList<>();
        InputStream is = null;
        try {
            //建立工作簿
            is = file.getInputStream();
            String excelFileName = file.getOriginalFilename();
            Workbook workbook = createWorkbook(is, excelFileName);
            //建立工作表sheet
            Sheet sheet = getSheet(workbook, 0);
            //獲取sheet中資料的行數
            int rows = sheet.getPhysicalNumberOfRows();
            //獲取表頭單元格個數
            int cells = sheet.getRow(0).getPhysicalNumberOfCells();
            //判斷是否使用excel註解
            if (!clazz.isAnnotationPresent(Excel.class)) {
                log.error(clazz + "沒有使用@Excel註解");
                return null;
            }
            //利用反射,給JavaBean的屬性進行賦值
            Field[] fields = clazz.getDeclaredFields();
            Map<Integer, Field> fieldMap = new HashMap<>();
            if (null != fields && fields.length > 0) {
                for (Field field : fields) {
                    if (field.isAnnotationPresent(Column.class)) {
                        Column column = field.getAnnotation(Column.class);
                        int number = column.column();
                        if (number < 0) {
                            log.error(field.getName() + "沒有使用@column註解");
                            return null;
                        } else {
                            fieldMap.put(number, field);
                        }
                    }
                }
            }
            //包裝物件
            for (int i = startRow; i < rows; i++) {
                Row row = sheet.getRow(i);
                int index = 0;
                T instance = clazz.newInstance();
                while (index < cells) {
                    Field field = fieldMap.get(index);
                    if (null != field) {
                        //獲得單元格
                        Cell cell = row.getCell(index);
                        Column column = field.getAnnotation(Column.class);
                        Object value = null;
                        if (Integer.class.equals(field.getType()) || Double.class.equals(field.getType())) {
                            if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){
                                cell.setCellType(CellType.NUMERIC);
                                value =cell.getNumericCellValue();
                            }
                        } else if (String.class.equals(field.getType())) {
                            if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){
                                cell.setCellType(CellType.STRING);
                                value = cell.getStringCellValue();
                            }
                        } else if (Date.class.equals(field.getType())) {
                            if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){
                                cell.setCellType(CellType.STRING);
                                value = cell.getDateCellValue();
                            }
                        } else if (Boolean.class.equals(field.getType())) {
                            if(cell!=null&&cell.getCellTypeEnum()!=CellType.BLANK){
                                cell.setCellType(CellType.BOOLEAN);
                                value = cell.getBooleanCellValue();
                            }
                        } else {
                            log.error("單元格型別錯誤");
                            return null;
                        }
                        //不能為空
                        if (!column.nullable()) {
                            if (StringUtils.isEmpty(value)) {
                                throw new ContextRuntimeException("第" + i+1 + "行第" + index+1 + "列不能為空");
                            }
                        }
                        //設定屬性值
                        if(!StringUtils.isEmpty(value)){
                            String fieldName = field.getName();
                            String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                            //獲得set方法的名字
                            Method setMethod = clazz.getMethod(methodName, new Class[]{field.getType()});
                            setMethod.invoke(instance, new Object[]{value});
                        }
                    }
                    index++;
                }
                list.add(instance);
            }

        } catch (ContextRuntimeException e) {
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            try {
                if (null != is) {
                    is.close();//關閉流
                }
            } catch (Exception e2) {
                log.error(e2.getMessage());
            }
        }
        return list;
    }
    
    /**
     * 建立工作簿
     *
     * @param is
     * @param excelFileName
     * @return
     * @throws IOException
     */
    private static Workbook createWorkbook(InputStream is, String excelFileName) throws IOException {
        if (null != excelFileName) {
            if (excelFileName.endsWith(".xls")) {
                return new HSSFWorkbook(is);
            } else if (excelFileName.endsWith(".xlsx")) {
                return new XSSFWorkbook(is);
            }
        }
        return null;
    }

    /**
     * 建立工作表
     *
     * @param workbook
     * @param sheetIndex
     * @return
     */
    private static Sheet getSheet(Workbook workbook, int sheetIndex) {
        return workbook.getSheetAt(0);
    }
}

4:controller層

    @ApiOperation(value = "匯入excel", notes = "匯入excel")
    @ApiImplicitParam(name = "irriAreaId", value = "灌區id", paramType = "query", dataType = "int", required = true)
    @PostMapping("/import")
    public RestResult<String> importReservoir(@RequestParam("file") MultipartFile file, @RequestParam("irriAreaId") Integer irriAreaId) {
        try {
            reservoirService.importReservoir(file, irriAreaId);
            return RestResultGeneratorUtil.getSuccessResult();
        } catch (ContextRuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new ContextRuntimeException(ErrorEnum.IMPORT_DATA_ERROR.getMessage());
        }
    }

5:service層

    @Override
    public void importReservoir(MultipartFile file, Integer irriAreaId) {
        //excel表中每一列對應資料欄位的屬性
        List<CreateReservoirDto> createReservoirDtoList = ExcelUtils.getDataFromExcel(file,1, CreateReservoirDto.class);
        if (!CollectionUtils.isEmpty(createReservoirDtoList)) {
           createReservoirDtoList =  createReservoirDtoList.parallelStream().map(r -> {
                r.setIrriAreaId(irriAreaId);
                r.setCreatedTime(System.currentTimeMillis());
                return r;
            }).collect(Collectors.toList());    
           //批量寫入資料庫
           reservoirMapper.batchInsert(createReservoirDtoList);
        }
    }