天天看點

el-upload + springboot + apache poi 實作解析固定excel模闆資料導入資料庫

前端代碼

<template>
  <div>
    <el-upload
      class="upload"
      ref="doUpload"
      :action="uploadUrl"
      :on-preview="beforeUploadHandle"
      :on-success="successHandle"
      :limit="1"
      accept=".xls, .xlsx"
      :file-list="fileList">
      <el-button slot="trigger" size="small" type="primary" @click="submitUpload">導入</el-button>
      <div slot="tip" class="el-upload__tip">隻能上傳excel檔案</div>
    </el-upload>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        uploadUrl: '',
        fileList: []
      }
    },
    methods: {
      // 上傳之前
      beforeUploadHandle (file) {
        console.log('fileType', file.type)
      },
      // 上傳成功
      successHandle (response, file, fileList) {
        this.fileList = fileList
      },
      // 上傳檔案
      submitUpload () {
      	// storeType [1, 4, 5, 6, 7] [标準庫, 實驗庫, 動态庫, 競品庫, 仿真庫]
        let storeType = '1'
        this.uploadUrl = this.$http.BASE_URL + `/doImport/importAll?token=${this.$cookie.get('token')}&storeType=${storeType}`
        this.$nextTick(() => {
          this.$refs.doUpload.submit()
        })
      }
    }
  }
</script>


           

後端代碼

依賴
<!-- Apache POI -->
  <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>4.0.1</version>
  </dependency>
  <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>4.0.1</version>
  </dependency>
           
DoImportController
@RestController
@RequestMapping("doImport")
public class DoImportController extends AbstractController {
	@Autowired
    private WcmsBaseInfoService wcmsBaseInfoService;
    @Autowired
    private WcmsChemicalCompositionService wcmsChemicalCompositionService;

    @RequestMapping("/importAll")
    @Transactional
    public RestResponse importAll(@RequestParam(value = "file", required = false) MultipartFile file, @RequestParam(value = "storeType", required = false) String storeType) {
        if (file != null) {
            // 讀取Excel檔案中主表内容
            List<WcmsBaseInfo> wcmsMaterialInfoList = ExcelReader.readExcelToGetWcmsMaterialInfo(file);
            // 讀取Excel檔案中所有化學元素内容
            List<ChemicalComposition> chemicalCompositionList = ExcelReader.readExcelToGetChemicalComposition(file);
            // 擷取到資料後執行相應插入資料庫操作
            ......
            }
            return RestResponse.success().put("message", "上傳成功");
        } else {
            return RestResponse.error("檔案上傳失敗");
        }
    }
 }
           
ExcelReader
/**
 * @ClassName ExcelReader
 * @Description 讀取Excel檔案中的各個實體資訊
 * @Author F
 * @Version 1.0
 */
public class ExcelReader {

    private final static Logger logger = LoggerFactory.getLogger(ExcelReader.class);

    private static final String XLS = "xls";
    private static final String XLSX = "xlsx";

    /**
     * @param file 檔案
     * @return 讀取結果清單,讀取失敗時傳回null
     * @description 讀取Excel檔案中主表資訊
     */
    public static List<WcmsMaterialInfo> readExcelToGetWcmsMaterialInfo(MultipartFile file){
        List<WcmsMaterialInfo> wcmsMaterialInfoList;

        Workbook workbook = null;
        FileInputStream inputStream = null;
        String fileName = file.getOriginalFilename();

        try {
            // 擷取Excel字尾名
            String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);

            // 擷取Excel檔案
            File excelFile = transferToFile(file);
            if (!excelFile.exists()) {
                logger.info("指定的Excel檔案不存在!");
                return null;
            }

            // 擷取Excel工作簿
            inputStream = new FileInputStream(excelFile);
            workbook = getWorkbook(inputStream, fileType);

            // 讀取Excel第五行之後的合并行數
            List<Integer> mergeRowNumList = ExcelReader.getMergeRowNumList(file);
            // 讀取excel中主表的資料
            wcmsMaterialInfoList = parseExcelToGetMaterialInfo(workbook, 1, mergeRowNumList);

            return wcmsMaterialInfoList;

        } catch (Exception e) {
            logger.info("解析Excel失敗,檔案名:" + fileName + " 錯誤資訊:" + e.getMessage());
            return null;
        } finally {
            try {
                if (null != workbook) {
                    workbook.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e) {
                logger.info("關閉資料流出錯!錯誤資訊:" + e.getMessage());
                return null;
            }
        }
    }

    /**
     * @param file 檔案
     * @return 讀取結果清單,讀取失敗時傳回null
     * @description 讀取Excel檔案中化學成分資訊
     */
    public static List<ChemicalComposition> readExcelToGetChemicalComposition(MultipartFile file) {
        List<ChemicalComposition> chemicalCompositionList;

        Workbook workbook = null;
        FileInputStream inputStream = null;
        String fileName = file.getOriginalFilename();

        try {
            // 擷取Excel字尾名
            String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);

            // 擷取Excel檔案
            File excelFile = transferToFile(file);
            if (!excelFile.exists()) {
                logger.info("指定的Excel檔案不存在!");
                return null;
            }

            // 擷取Excel工作簿
            inputStream = new FileInputStream(excelFile);
            workbook = getWorkbook(inputStream, fileType);

            // 讀取excel中化學成分資料
            chemicalCompositionList = parseExcelToGetChemicalComposition(workbook, 50);

            return chemicalCompositionList;

        } catch (Exception e) {
            logger.info("解析Excel失敗,檔案名:" + fileName + " 錯誤資訊:" + e.getMessage());
            return null;
        } finally {
            try {
                if (null != workbook) {
                    workbook.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e) {
                logger.info("關閉資料流出錯!錯誤資訊:" + e.getMessage());
                return null;
            }
        }
    }

    /**
     * @param row 行資料
     * @return 解析後的行資料對象,行資料錯誤時傳回null
     * @description 提取每一行中主表的資料,構造成為一個結果資料對象
     * @note 當該行中有單元格的資料為空或不合法時,忽略該行的資料
     * @note 主表資料1-3列
     **/
    private static WcmsMaterialInfo convertRowDataToMaterialInfo(Row row, int startCellNum) {
        WcmsMaterialInfo wcmsMaterialInfo = new WcmsMaterialInfo();

        Cell cell;
        // 從1開始 去掉excel開始的序号
        int cellNum = startCellNum;

        // 材料名稱(中文)
        cell = row.getCell(cellNum++);
        String materialCategoryC = convertCellValueToString(cell);
        wcmsMaterialInfo.setMaterialCategoryC(materialCategoryC);

        // 材料名稱(英文)
        cell = row.getCell(cellNum++);
        String mMaterialCategoryE = convertCellValueToString(cell);
        wcmsMaterialInfo.setMaterialCategoryE(mMaterialCategoryE);

        // 材料牌号
        cell = row.getCell(cellNum++);
        String mMaterialNum = convertCellValueToString(cell);
        wcmsMaterialInfo.setMaterialNum(mMaterialNum);

        return wcmsMaterialInfo;
    }

    /**
     * @param row 行資料
     * @return 解析後的行資料對象,行資料錯誤時傳回null
     * @Description 提取每一行中化學成分資料,構造成為一個結果資料對象
     * @note 化學成分資料偶從4-7列
     */
    private static ChemicalComposition convertRowDataToChemicalComposition(Row row, int startCellNum) {
        ChemicalComposition chemicalComposition = new ChemicalComposition();

        Cell cell;
        // 從 4開始 模闆設定4以後是化學成分資料
        int cellNum = startCellNum;

        // C 碳
        cell = row.getCell(cellNum++);
        String c = convertCellValueToString(cell);
        chemicalComposition.setC(c);

        // N 氮
        cell = row.getCell(cellNum++);
        String n = convertCellValueToString(cell);
        chemicalComposition.setN(n);

        // O 氧
        cell = row.getCell(cellNum++);
        String o = convertCellValueToString(cell);
        chemicalComposition.setO(o);
        
        return chemicalComposition;
    }
    /**
     * @param cell 單元格
     * @return 内容
     * @description 将單元格内容轉換為字元串
     */
    private static String convertCellValueToString(Cell cell) {
        if (cell == null) {
            return null;
        }

        String returnValue = null;
        switch (cell.getCellType()) {
            // 數字
            case NUMERIC:
                Double doubleValue = cell.getNumericCellValue();
                returnValue = doubleValue.toString();
                break;
            // 字元串
            case STRING:
                returnValue = cell.getStringCellValue();
                break;
            // 布爾
            case BOOLEAN:
                Boolean booleanValue = cell.getBooleanCellValue();
                returnValue = booleanValue.toString();
                break;
            // 空值
            case BLANK:
                break;
            // 公式
            case FORMULA:
                returnValue = cell.getCellFormula();
                break;
            // 故障
            case ERROR:
                break;
            default:
                break;
        }
        return returnValue;
    }

    /**
     * @param multipartFile 原本檔案類型
     * @return File
     * @description 轉換檔案類型
     */
    private static File transferToFile(MultipartFile multipartFile) {
        // 選擇用緩沖區來實作這個轉換即使用java 建立的臨時檔案 使用 MultipartFile.transferto()方法 。
        File resultFile = null;
        try {
            String originalFileName = multipartFile.getOriginalFilename();
            
            String[] fileName = originalFileName.split("\\.");
            if (fileName.length > 1) {
                resultFile = File.createTempFile(fileName[0], fileName[1]);
                multipartFile.transferTo(resultFile);
                resultFile.deleteOnExit();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultFile;
    }

    /**
     * @param inputStream 讀取檔案的輸入流
     * @param fileType    檔案字尾名類型(xls或xlsx)
     * @return 包含檔案資料的工作簿對象
     * @throws IOException
     * @description 根據檔案字尾名類型擷取對應的工作簿對象
     */
    private static Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException {
        Workbook workbook = null;
        if (fileType.equalsIgnoreCase(XLS)) {
            workbook = new HSSFWorkbook(inputStream);
        } else if (fileType.equalsIgnoreCase(XLSX)) {
            workbook = new XSSFWorkbook(inputStream);
        }
        return workbook;
    }
    /**
     * @param cell  目前單元格
     * @param sheet 工作sheet
     * @return 合并的行數
     * @decription 擷取合并行數
     */
    public static int getMergeRowNum(Cell cell, Sheet sheet) {
        int mergeSize = 1;
        List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
        for (CellRangeAddress cellRangeAddress : mergedRegions) {
            if (cellRangeAddress.isInRange(cell)) {
                //擷取合并的行數
                mergeSize = cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow() + 1;
                break;
            }
        }
        return mergeSize;
    }

    /**
     * @param file 檔案
     * @return 傳回合并行數清單
     * @decription 擷取合并行數清單
     */
    public static List<Integer> getMergeRowNumList(MultipartFile file) {
        // 解析sheet workbook.getNumberOfSheets()擷取sheet頁數 隻有一個sheet頁
        List<Integer> result = new ArrayList<>();

        Workbook workbook = null;
        FileInputStream inputStream = null;
        String fileName = file.getOriginalFilename();

        try {
            // 擷取Excel字尾名
            String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);

            // 擷取Excel檔案
            File excelFile = transferToFile(file);
            if (!excelFile.exists()) {
                logger.info("指定的Excel檔案不存在!");
                return null;
            }

            // 擷取Excel工作簿
            inputStream = new FileInputStream(excelFile);
            workbook = getWorkbook(inputStream, fileType);
            Sheet sheet = workbook.getSheetAt(0);
            if (sheet == null) {
                return result;
            }
            // 模闆設定從第五行資料
            int rowStart = sheet.getFirstRowNum() + 5;
            int rowEnd = sheet.getPhysicalNumberOfRows();
            for (int rowNum = rowStart; rowNum < rowEnd; ) {
                Row row = sheet.getRow(rowNum);
                int physicalNumberOfRows = getMergeRowNum(row.getCell(0), sheet);
                // 合并行數
                result.add(physicalNumberOfRows);
                rowNum += physicalNumberOfRows;
            }
            return result;
        } catch (Exception e) {
            logger.info("解析Excel失敗,檔案名:" + fileName + " 錯誤資訊:" + e.getMessage());
            return null;
        } finally {
            try {
                if (null != workbook) {
                    workbook.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e) {
                logger.info("關閉資料流出錯!錯誤資訊:" + e.getMessage());
                return null;
            }
        }
    }
}
           

繼續閱讀