上传模板文件批量插入数据库
作者:互联网
小编在实习的时候,遇到了一个比较常见的需求,就是用户上传一个模板文件,里面有很多条数据,而我们要根据传入的模板文件,将模板文件里面的数据插入到数据库中。
首先我先列举一下思路:
一.拿到文件的输入流;
二.拿到得到Excel文件的workbook和sheet,用for循环去读取数据,将每一行数据插入到数据库里面;
三.读取Excel不同单元格的数值用到工具类,这个可以自己写一个;
以下的testImport(),就是通过前端拿到一个file,也就是模板文件,我们通过这个文件得到的输入流,然后进入readExcel2007()或者readExcel2003(),这个方法就是通过我们得到的输入流,再去得到模板文件的工作表和工作簿(workbook和sheet),然后将模板文件里面的每一行数据存到一个map里面,再将map插入到数据库里面,这里用到了mybatis,(我们拿到service之后去调用insert()方法,具体的就是我们将map数据按照格式存到一个实体类里面,将实体类插入到数据库里面)
public String testImport(HttpServletRequest request, HttpServletResponse response,MultipartFile file) throws Exception{
if(file == null){ return "文件不见了^_^,请重新传入文件"; } String fileName = file.getName(); String suffix = file.getName().substring(fileName.lastIndexOf("."));//获取文件后缀 File targetFile = new File(fileName);//获取文件 //根据不同的excel版本,将数据插入到数据库中 //2003版的为HSSFWorkbook,2007版为XSSFWorkbook if ("xlsx".equals(suffix) || "XLSX".equals(suffix) ) { FileInputStream targetStream= new FileInputStream(targetFile); readExcel2007(targetStream); return "导入成功^_^"; }else if("xls".equals(suffix) || "XLS".equals(suffix) ){ FileInputStream targetStream= new FileInputStream(targetFile); readExcel2003(targetStream); return "导入成功^_^"; }else{ return "请传入格式正确的Excel文件^_^"; } }
这里我就举例readExcel2003方法,两个方法都写出来太长了,都是差不多的,区别就在于excel的版本导致的workbook和sheet的不同。这个方法确实有点复杂,但总的来说就是拿到输入字节流,根据字节流创建excel的工作簿,然后一个for循环去读这个excel表,读取到模板文件的第一行也就是数据库的字段,这里我们将这些字段放到一个Header的map里面,这里是为了后面我们读取到真正的数据的时候,放到map里面的key为数据库的字段
private String readExcel2003(InputStream inputStream) throws Exception { int sheetnum = 0, startrow = 0, startcol = 0, errorRow = 0; try { HSSFWorkbook workbook = new HSSFWorkbook(inputStream); HSSFSheet sheet = workbook.getSheetAt(sheetnum); // sheet 從0開始 int rowNum = sheet.getLastRowNum() + 1; // 取得最後一行的行號 Map<String, Object> Header = new HashMap<String, Object>(); // 表頭的下標和內容 for (int i = startrow; i < rowNum; i++) { // 行循環開始 Map<String, String> map = null;// 每一行數據的map HSSFRow row = sheet.getRow(i); // 行 if (row == null) break; // 中間如果有空行,則退出 int lastCellNum = row.getLastCellNum(); // 每行的最後一個單元格位置 if (i != 0) {// 記錄數據的行號 map = new HashMap<String, String>(); map.put("lineNumber", i + "1"); } for (int j = startcol; j < lastCellNum; j++) { // 列循環開始 HSSFCell cell2 = row.getCell(j); String cellValue = getCellValue2003(cell2); if (i == 0) { switch (cellValue){ case "id": Header.put(j + "", "id"); break; case "交易日期": Header.put(j + "", "tradeDate"); break; case "公司名称": Header.put(j + "", "companyName"); break; case "开户银行名称": Header.put(j + "", "bankAccountName"); break; case "开户银行账户": Header.put(j + "", "bankAccountNo"); break; case "唯一流水号": Header.put(j + "", "serialNumber"); break; case "对方账户名称": Header.put(j + "", "sideAccountName"); break; case "对方账户": Header.put(j + "", "sideAccount"); break; case "收入": Header.put(j + "", "income"); break; case "摘要": Header.put(j + "", "digest"); break; case "已核销额度": Header.put(j + "", "haveVerLines"); break; case "未核销额度": Header.put(j + "", "notVerLines"); break; case "退款": Header.put(j + "", "refund"); break; case "项目类别": Header.put(j + "", "projectCategory"); break; case "核销状态": Header.put(j + "", "verState"); break; case "代付标识": Header.put(j + "", "paidLogo"); break; case "新台账标识": Header.put(j + "", "newLedgerLogo"); break; } } else { map.put((String) Header.get(j + ""), cellValue); } } // 每一行數據的過濾,如果一行中所有列都爲null,則不生成該行數據, if (null != map) { Collection<String> values = map.values(); Set<String> keySet = map.keySet(); long count2 = keySet.stream().filter(o -> !o.equals("lineNumber")).count();// 總條數 long count = values.stream().filter(o -> null == o).count();// 爲空的條數 if (count < count2) { SubcarBankStatement subcarBankStatement = new SubcarBankStatement(); subcarBankStatement.setId(map.get("id"));//遇到日期格式,需要转换格式,不然插入数据库时会报错 String tradeDate =map.get("tradeDate"); DateFormat formater = new SimpleDateFormat("yyyy-MM-dd"); subcarBankStatement.setTradeDate(formater.parse(tradeDate)); subcarBankStatement.setCompanyName(map.get("companyName")); subcarBankStatement.setBankAccountName(map.get("bankAccountName")); subcarBankStatement.setBankAccountNo(map.get("bankAccountNo")); subcarBankStatement.setSerialNumber(map.get("serialNumber")); subcarBankStatement.setSideAccountName(map.get("sideAccountName")); subcarBankStatement.setSideAccount(map.get("sideAccount")); subcarBankStatement.setIncome(map.get("income")); subcarBankStatement.setDigest(map.get("digest")); subcarBankStatement.setHaveVerLines(map.get("haveVerLines")); subcarBankStatement.setNotVerLines(map.get("notVerLines")); subcarBankStatement.setRefund(map.get("refund")); subcarBankStatement.setProjectCategory(map.get("projectCategory")); subcarBankStatement.setVerState(map.get("verState")); subcarBankStatement.setPaidLogo(map.get("paidLogo")); subcarBankStatement.setNewLedgerLogo(map.get("newLedgerLogo")); subcarBankStatementService.insert(subcarBankStatement); } } } workbook.close(); } catch (Exception e) { throw e; } return "success"; }
下面的这个是根据excel的不同单元格格式拿到对应的数值,很简单的方法。
private String getCellValue2003(HSSFCell cell) { String cellvalue = null; if (cell != null) { // 判斷當前Cell的Type switch (cell.getCellType()) { // 如果當前Cell的Type爲NUMERIC case NUMERIC: { short format = cell.getCellStyle().getDataFormat(); if(format == 14 || format == 31 || format == 57 || format == 58){ //excel中的時間格式 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); double value = cell.getNumericCellValue(); Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value); cellvalue = sdf.format(date); } // 判斷當前的cell是否爲Date else if (HSSFDateUtil.isCellDateFormatted(cell)) { //先註釋日期類型的轉換,在實際測試中發現HSSFDateUtil.isCellDateFormatted(cell)只識別2014/02/02這種格式。 // 如果是Date類型則,取得該Cell的Date值 // 對2014-02-02格式識別不出是日期格式 Date date = cell.getDateCellValue(); DateFormat formater = new SimpleDateFormat("yyyy-MM-dd"); cellvalue= formater.format(date); } else { // 如果是純數字 // 取得當前Cell的數值 cellvalue = NumberToTextConverter.toText(cell.getNumericCellValue()); } break; } // 如果當前Cell的Type爲STRIN case STRING: // 取得當前的Cell字符串 cellvalue = cell.getStringCellValue().replaceAll("'", "''"); break; case BLANK: cellvalue = null; break; // 默認的Cell值 default:{ cellvalue = ""; } } } else { cellvalue = ""; } return cellvalue; }
上面的工程可能有点复杂,如果还有不懂的小兄弟可以加我qq联系我,或者直接发邮箱给我(674085128)
标签:case,map,break,Header,put,subcarBankStatement,文件批量,上传,模板 来源: https://www.cnblogs.com/carryup/p/13542180.html