javascript
SpringBoot中使用POI实现Excel导入到数据库(图文教程已实践)
場景
IDEA中開發(fā)SpringBoot項(xiàng)目時(shí)需要將Excel模板中數(shù)據(jù)導(dǎo)入的到數(shù)據(jù)庫。
Excel模板如下
實(shí)現(xiàn)思想
首先將模板上傳到服務(wù)器中某路徑,并將當(dāng)前路徑存儲,然后使用POI自帶的
工具類獲取到sheet以及行數(shù)以及每個(gè)cell,然后分別給數(shù)據(jù)庫中對應(yīng)的對象的屬性賦值,然后插入到數(shù)據(jù)庫中并返回執(zhí)行結(jié)果。
實(shí)現(xiàn)
實(shí)現(xiàn)文件上傳
頁面代碼
實(shí)現(xiàn)點(diǎn)擊導(dǎo)入按鈕彈窗
<div class="modal inmodal" id="apImportModel" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog" id="apImportDiv" th:fragment="apImportDiv"><div class="modal-content animated fadeIn"><button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button><form class="dropzone" id="dropzoneForm" enctype="multipart/form-data"><div class="fallback"><input name="file" type="file" id="file_id" /></div></form><button id="uploladBtn" class="btn btn-info mt-2" type="button" onclick="return uploadExcel()"><i class="fa fa-reply"></i>上傳</button><button id="parseBtn" class="btn btn-info mt-2" type="button" onclick="return parseExcel()"><i class="fa fa-reply"></i>導(dǎo)入</button></div></div></div>因?yàn)檫@里使用的是thymeleaf模板
thymeleaf中文參考手冊下載:
https://download.csdn.net/download/badao_liumang_qizhi/11021427 ?
在當(dāng)前頁面需要引入js文件
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"th:replace="layout/layout(title='測試數(shù)據(jù)',cssPaths='/public/css/plugins/datapicker/datepicker3.css',jsPaths='/public/js/plugins/dataTables/datatables.min.js,/modular/receiveOrder/wmsReceiveOrder.js')"><!-- layout文件路徑-->?
來到/modular/receiveOrder/wmsReceiveOrder.js此目錄下的js文件
在js中實(shí)現(xiàn)點(diǎn)擊導(dǎo)入按鈕彈窗功能
//導(dǎo)入按鈕點(diǎn)擊事件$("#importBtn").click(function () {importExcel();});點(diǎn)擊事件調(diào)用下面的方法
?? function importExcel(){var url = "/wmsReceiveOrder/doExcelImport.html";$('#apImportDiv').load(url, function (response,status,xhr) {$("#apImportModel").modal('show');});}該方法按照url請求后臺,其中l(wèi)oad方法是讓隱藏的彈窗部分顯示 。
來到后臺url對應(yīng)的方法中
@Description("獲取收獲單信息列表頁面")@RequestMapping("/wmsReceiveOrder.html")public String page(Model model) {return "receiveOrder/wmsReceiveOrder.html";}返回當(dāng)前頁面并將彈窗顯示
開始設(shè)置文件上傳的點(diǎn)擊事件
在彈窗部分的代碼中
<div class="modal inmodal" id="apImportModel" tabindex="-1" role="dialog"? aria-hidden="true"><div class="modal-dialog" id="apImportDiv" th:fragment="apImportDiv"><div class="modal-content animated fadeIn"><button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button><form? class="dropzone"? id="dropzoneForm" enctype="multipart/form-data"><div class="fallback"><input name="file" type="file" id="file_id" /></div></form><button id="uploladBtn" class="btn btn-info mt-2" type="button" onclick="return uploadExcel()"><i class="fa fa-reply"></i>上傳</button><button id="parseBtn" class="btn btn-info mt-2" type="button" onclick="return parseExcel()"><i class="fa fa-reply"></i>導(dǎo)入</button></div></div></div>其中
<button id="uploladBtn" class="btn btn-info mt-2" type="button" onclick="return uploadExcel()"><i class="fa fa-reply"></i>上傳</button>
是調(diào)用js中對應(yīng)的方法uploadExcel()
?
選擇文件后,會上傳到url中對應(yīng)的位置
要實(shí)現(xiàn)文件上傳,需要引入commons-fileupload包
找到項(xiàng)目下的pom.xml
添加如下依賴
?<!--文件上傳--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3</version></dependency>來到url對應(yīng)的后臺方法
?@Description("獲取前端導(dǎo)入excel")@ResponseBody@RequestMapping(value = "/doImportExcel")public Map<String, Object> doUpload(HttpServletRequest request, @RequestParam("file") MultipartFile file) {Map<String, Object> result = new HashMap<String, Object>();String fileName = "";try {//將當(dāng)前上下文初始化給? CommonsMutipartResolver (多部分解析器)CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());//檢查form中是否有enctype="multipart/form-data"if (multipartResolver.isMultipart(request)) {//將request變成多部分requestMultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;//獲取multiRequest 中所有的文件名Iterator iter = multiRequest.getFileNames();while (iter.hasNext()) {//一次遍歷所有文件MultipartFile file1 = multiRequest.getFile(iter.next().toString());if (file != null) {//獲取上傳文件名fileName = file1.getOriginalFilename();//獲取后綴名String sname = fileName.substring(fileName.lastIndexOf("."));//時(shí)間格式化格式SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyyMMddHHmmssSSS");//獲取當(dāng)前時(shí)間并作為時(shí)間戳String timeStamp=simpleDateFormat.format(new Date());//拼接新的文件名String newName ="收貨單"+timeStamp+sname;//指定上傳文件的路徑String path = "F:\\" + newName;//上傳保存file.transferTo(new File(path));//保存當(dāng)前文件路徑request.getSession().setAttribute("currFilePath", path);}}}result.put("statusCode", "200");result.put("message", "上傳成功!");result.put("filename", fileName);} catch (Exception ex) {result.put("statusCode", "300");result.put("message", "上傳失敗:" + ex.getMessage());}return result;}實(shí)現(xiàn)效果
點(diǎn)擊選擇文件
選擇文件后
然后點(diǎn)擊上傳
這時(shí)在后臺controller打斷點(diǎn)查看,可以看到后臺已經(jīng)獲取到上傳的文件,并以當(dāng)前時(shí)間戳重名名存放在F盤下,將存放路徑存在當(dāng)前
session中。
可以看到F盤 下已經(jīng)有了剛才上傳的文件
?
解析并導(dǎo)入Excel實(shí)現(xiàn)
彈窗頁面的解析Excel按鈕代碼
<div class="modal inmodal" id="apImportModel" tabindex="-1" role="dialog"? aria-hidden="true"><div class="modal-dialog" id="apImportDiv" th:fragment="apImportDiv"><div class="modal-content animated fadeIn"><button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button><form? class="dropzone"? id="dropzoneForm" enctype="multipart/form-data"><div class="fallback"><input name="file" type="file" id="file_id" /></div></form><button id="uploladBtn" class="btn btn-info mt-2" type="button" onclick="return uploadExcel()"><i class="fa fa-reply"></i>上傳</button><button id="parseBtn" class="btn btn-info mt-2" type="button" onclick="return parseExcel()"><i class="fa fa-reply"></i>導(dǎo)入</button></div></div></div>點(diǎn)擊導(dǎo)入按鈕后調(diào)用js中的parseExcel()方法
//解析Excel操作 function parseExcel(){var url = "/wmsReceiveOrder/parseExcel";$.ajax({type: 'POST',url: url,cache: false,? //禁用緩存contentType: false,dataType: "json",processData:false,success: function (result) {debuggeralert(result.message)}})return false; }ajax請求后臺的url對應(yīng)的方法
前提要實(shí)現(xiàn)Excel的導(dǎo)入和導(dǎo)出需要引入POI的包
打開項(xiàng)目的pom.xml
<!--excel導(dǎo)入導(dǎo)出--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.9</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>3.9</version></dependency>剛才請求到后臺url對應(yīng)的方法
@ResponseBody@RequestMapping("/parseExcel")public Map<String, Object> parseExcel(HttpServletRequest request) {Map<String, Object> result = new HashMap<String, Object>();Workbook workbook = null;//獲取文件路徑String path = (String)request.getSession().getAttribute("currFilePath");//獲取文件格式String fileType = path.substring(path.lastIndexOf(".") + 1, path.length());try {InputStream stream = new FileInputStream(path);//如果后綴名為xls,使用HSSFif (fileType.equals("xls")) {workbook = new HSSFWorkbook(stream);//如果后綴名是xlsx,使用XSSF}else if (fileType.equals("xlsx")){workbook = new XSSFWorkbook(stream);}Sheet sheet= workbook.getSheet("sheet1");//獲取行數(shù)int rows=sheet.getPhysicalNumberOfRows();//List<WmsReceiveOrder> receiveOrderList =new ArrayList<WmsReceiveOrder>();WmsReceiveOrder receiveOrder =new WmsReceiveOrder();//獲取第一行數(shù)據(jù)Row row1 =sheet.getRow(0);if(row1!=null){//獲取采購訂單號row1.getCell(1).setCellType(Cell.CELL_TYPE_STRING);String purchaseCode =row1.getCell(1).getStringCellValue();receiveOrder.setPurchaseCode(purchaseCode);}//獲取第二行數(shù)據(jù)Row row2 =sheet.getRow(1);if(row2!=null){//獲取供應(yīng)商送貨單號row2.getCell(1).setCellType(Cell.CELL_TYPE_STRING);String deliveryCode =row2.getCell(1).getStringCellValue();receiveOrder.setDeliveryCode(deliveryCode);//獲取送貨日期Date deliveryTime =row2.getCell(3).getDateCellValue();receiveOrder.setDeliveryTime(deliveryTime);//獲取供應(yīng)商名稱row2.getCell(5).setCellType(Cell.CELL_TYPE_STRING);String supplierName =row2.getCell(5).getStringCellValue();receiveOrder.setSupplierName(supplierName);}//獲取第三行數(shù)據(jù)Row row3 =sheet.getRow(2);if(row3!=null){//獲取ERP入貨單號row3.getCell(1).setCellType(Cell.CELL_TYPE_STRING);String erpInCode =row3.getCell(1).getStringCellValue();receiveOrder.setErpInCod(erpInCode);//獲取入庫日期Date inTime =row3.getCell(3).getDateCellValue();receiveOrder.setInTime(inTime);}receiveOrder.setRemark("測試備注");receiveOrder.setType(1);receiveOrder.setStatus("1");//插入receiveOrder表數(shù)據(jù)boolean isSaveReceiveOrder =receiveOrderService.save(receiveOrder);List<WmsReceiveOrderDetails> receiveOrderDetailsList = new ArrayList<WmsReceiveOrderDetails>();if(isSaveReceiveOrder){//如果插入表頭成功,獲取插入數(shù)據(jù)的ID并插入詳情表Long receiveId=receiveOrder.getId();for (int currentRow=4;currentRow<rows;currentRow++) {WmsReceiveOrderDetails wmsReceiveOrderDetails =new WmsReceiveOrderDetails();wmsReceiveOrderDetails.setReceiveId(receiveId);//獲取物料編號sheet.getRow(currentRow).getCell(1).setCellType(Cell.CELL_TYPE_STRING);String materielId = sheet.getRow(currentRow).getCell(1).getStringCellValue();wmsReceiveOrderDetails.setMaterielId(materielId);//獲取物料名稱sheet.getRow(currentRow).getCell(2).setCellType(Cell.CELL_TYPE_STRING);String materielName = sheet.getRow(currentRow).getCell(2).getStringCellValue();wmsReceiveOrderDetails.setMaterielName(materielName);//獲取供應(yīng)商批次sheet.getRow(currentRow).getCell(3).setCellType(Cell.CELL_TYPE_STRING);String supplierBatch = sheet.getRow(currentRow).getCell(3).getStringCellValue();wmsReceiveOrderDetails.setSupplierBatch(supplierBatch);//獲取生產(chǎn)日期Date productDate = sheet.getRow(currentRow).getCell(4).getDateCellValue();wmsReceiveOrderDetails.setProductDate(productDate);//獲取數(shù)量sheet.getRow(currentRow).getCell(5).setCellType(Cell.CELL_TYPE_STRING);Long num =Long.parseLong(sheet.getRow(currentRow).getCell(5).getStringCellValue());wmsReceiveOrderDetails.setNum(num);//獲取托盤編號String salverCode = sheet.getRow(currentRow).getCell(6).getStringCellValue();wmsReceiveOrderDetails.setSalverCode(salverCode);wmsReceiveOrderDetails.setStatus("1");wmsReceiveOrderDetails.setRemark("測試備注");wmsReceiveOrderDetails.setDeletedFlag(false);receiveOrderDetailsList.add(wmsReceiveOrderDetails);}if(receiveOrderDetailsList!=null){for (WmsReceiveOrderDetails wmsReceiveOrderDetails:receiveOrderDetailsList) {boolean isSaveReceiveOrderDetails =receiveOrderDetailsService.save(wmsReceiveOrderDetails);if(!isSaveReceiveOrderDetails){result.put("statusCode", "300");result.put("message", "導(dǎo)入物料編號為:"+wmsReceiveOrderDetails.getMaterielId()+"出錯(cuò)了!");}else{result.put("statusCode", "200");result.put("message", "導(dǎo)入收貨單成功!");}}}}else{result.put("statusCode", "300");result.put("message", "導(dǎo)入收貨單失敗!");}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return result;}這里是結(jié)合具體的業(yè)務(wù)實(shí)現(xiàn)的Excel的導(dǎo)入,這里要導(dǎo)入的表是兩個(gè)關(guān)聯(lián)表。
基本思想就是通過行與列的坐標(biāo)定位獲取到cell中的值。
比如:
1.獲取sheet頁
Workbook workbook= null;?中間需要根據(jù)獲取的后綴名進(jìn)行初始化
?workbook = new HSSFWorkbook(stream);?或者
workbook = new XSSFWorkbook(stream);然后
?
這里的sheet1是sheet頁的名字
2.獲取行數(shù)
int rows=sheet.getPhysicalNumberOfRows();3.獲取第一行數(shù)據(jù)
Row row1 =sheet.getRow(0);4.獲取第一行的第2個(gè)Cell對象
row1.getCell(1)注意行與Cell都是從0開始的。
5.給第一行的第二個(gè)Cell設(shè)置值的類型
?row1.getCell(1).setCellType(Cell.CELL_TYPE_STRING);具體類型在IDEA代碼提示中會有。
6.獲取第一行第二個(gè)Cell的String類型的值。
String purchaseCode =row1.getCell(1).getStringCellValue();7.獲取日期格式的Cell的值
Date inTime =row3.getCell(3).getDateCellValue();?
實(shí)現(xiàn)效果
?
總結(jié)
以上是生活随笔為你收集整理的SpringBoot中使用POI实现Excel导入到数据库(图文教程已实践)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Eclipse中实现SpringBoot
- 下一篇: 一行Java代码判断文件夹是否存在,不存