最近公司新增功能要求導入excel,並讀取其中數據批量寫入數據庫。於是就開始了這個事情,之前的文章,記錄了上傳文件,本篇記錄如何通過POI讀取excel數據並封裝為對象上傳。
上代碼:
1、首先這是一個依賴第三方的事情,故而需要導入jar包
1 <!-- read excel start --> 2 <dependency> 3 <groupId>org.apache.poi</groupId> 4 <artifactId>poi</artifactId> 5 <version>3.17</version> 6 </dependency> 7 <dependency> 8 <groupId>org.apache.poi</groupId> 9 <artifactId>poi-ooxml</artifactId> 10 <version>3.17</version> 11 </dependency> 12 <!-- read excel start -->
切記下面的那個包不可忘記,否則報錯RETURN_NULL_AND_BLANK
之前我們已經上傳含有數據的excel模板,返回的是一個url,本博主對應的url的excel表內容如下:
那么我們傳入導入的excel的url來進行讀取。不做過多解釋,該有的解釋代碼注釋里面均有
1 package com.topband.sweepmachine.utils; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.text.DecimalFormat; 8 import java.util.ArrayList; 9 import java.util.List; 10 11 import org.apache.commons.io.FileUtils; 12 import org.apache.poi.hssf.usermodel.HSSFDateUtil; 13 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 14 import org.apache.poi.ss.usermodel.Cell; 15 import org.apache.poi.ss.usermodel.CellType; 16 import org.apache.poi.ss.usermodel.Row; 17 import org.apache.poi.ss.usermodel.Sheet; 18 import org.apache.poi.ss.usermodel.Workbook; 19 import org.apache.poi.ss.usermodel.WorkbookFactory; 20 import org.apache.poi.xssf.usermodel.XSSFWorkbook; 21 import org.slf4j.Logger; 22 import org.slf4j.LoggerFactory; 23 24 import com.topband.cloud.common.utils.DateFormatUtil; 25 import com.topband.cloud.common.utils.StringUtil; 26 27 public class ReadExcelUtil { 28 29 private Logger logger = LoggerFactory.getLogger(this.getClass()); 30 private static final String EXCEL_XLS = ".xls"; 31 private static final String EXCEL_XLSX = ".xlsx"; 32 33 /** 34 *讀取excel數據 35 * @throws Exception 36 * 37 */ 38 public static List<List<String>> readExcelInfo(String url) throws Exception{ 39 /* 40 * workbook:工作簿,就是整個Excel文檔 41 * sheet:工作表 42 * row:行 43 * cell:單元格 44 */ 45 46 // BufferedWriter bw = new BufferedWriter(new FileWriter(new File(url))); 47 // 支持excel2003、2007 48 File excelFile = new File(url);//創建excel文件對象 49 InputStream is = new FileInputStream(excelFile);//創建輸入流對象 50 checkExcelVaild(excelFile); 51 Workbook workbook = getWorkBook(is, excelFile); 52 // Workbook workbook = WorkbookFactory.create(is);//同時支持2003、2007、2010 53 // 獲取Sheet數量 54 int sheetNum = workbook.getNumberOfSheets(); 55 // 創建二維數組保存所有讀取到的行列數據,外層存行數據,內層存單元格數據 56 List<List<String>> dataList = new ArrayList<List<String>>(); 57 // FormulaEvaluator formulaEvaluator = null; 58 // 遍歷工作簿中的sheet,第一層循環所有sheet表 59 for(int index = 0;index<sheetNum;index++){ 60 Sheet sheet = workbook.getSheetAt(index); 61 if(sheet==null){ 62 continue; 63 } 64 System.out.println("表單行數:"+sheet.getLastRowNum()); 65 // 如果當前行沒有數據跳出循環,第二層循環單sheet表中所有行 66 for(int rowIndex=0;rowIndex<=sheet.getLastRowNum();rowIndex++){ 67 Row row = sheet.getRow(rowIndex); 68 // 根據文件頭可以控制從哪一行讀取,在下面if中進行控制 69 if(row==null){ 70 continue; 71 } 72 // 遍歷每一行的每一列,第三層循環行中所有單元格 73 List<String> cellList = new ArrayList<String>(); 74 for(int cellIndex=0;cellIndex<row.getLastCellNum();cellIndex++){ 75 Cell cell = row.getCell(cellIndex); 76 System.out.println("遍歷行中cell數據:"+getCellValue(cell)); 77 cellList.add(getCellValue(cell)); 78 System.out.println("第"+cellIndex+"個: cell個數:"+cellList.size()); 79 } 80 dataList.add(cellList); 81 System.out.println("第"+rowIndex+"行: 共幾行:"+dataList.size()); 82 } 83 84 } 85 is.close(); 86 return dataList; 87 } 88 /** 89 *獲取單元格的數據,暫時不支持公式 90 * 91 * 92 */ 93 public static String getCellValue(Cell cell){ 94 CellType cellType = cell.getCellTypeEnum(); 95 String cellValue = ""; 96 if(cell==null || cell.toString().trim().equals("")){ 97 return null; 98 } 99 100 if(cellType==CellType.STRING){ 101 cellValue = cell.getStringCellValue().trim(); 102 return cellValue = StringUtil.isEmpty(cellValue)?"":cellValue; 103 } 104 if(cellType==CellType.NUMERIC){ 105 if (HSSFDateUtil.isCellDateFormatted(cell)) { //判斷日期類型 106 cellValue = DateFormatUtil.formatDurationYMD(cell.getDateCellValue().getTime()); 107 } else { //否 108 cellValue = new DecimalFormat("#.######").format(cell.getNumericCellValue()); 109 } 110 return cellValue; 111 } 112 if(cellType==CellType.BOOLEAN){ 113 cellValue = String.valueOf(cell.getBooleanCellValue()); 114 return cellValue; 115 } 116 return null; 117 118 } 119 /** 120 *判斷excel的版本,並根據文件流數據獲取workbook 121 * @throws IOException 122 * 123 */ 124 public static Workbook getWorkBook(InputStream is,File file) throws Exception{ 125 126 Workbook workbook = null; 127 if(file.getName().endsWith(EXCEL_XLS)){ 128 workbook = new HSSFWorkbook(is); 129 }else if(file.getName().endsWith(EXCEL_XLSX)){ 130 workbook = new XSSFWorkbook(is); 131 } 132 133 return workbook; 134 } 135 /** 136 *校驗文件是否為excel 137 * @throws Exception 138 * 139 * 140 */ 141 public static void checkExcelVaild(File file) throws Exception { 142 String message = "該文件是EXCEL文件!"; 143 if(!file.exists()){ 144 message = "文件不存在!"; 145 throw new Exception(message); 146 } 147 if(!file.isFile()||((!file.getName().endsWith(EXCEL_XLS)&&!file.getName().endsWith(EXCEL_XLSX)))){ 148 System.out.println(file.isFile()+"==="+file.getName().endsWith(EXCEL_XLS)+"==="+file.getName().endsWith(EXCEL_XLSX)); 149 System.out.println(file.getName()); 150 message = "文件不是Excel"; 151 throw new Exception(message); 152 } 153 } 154 /* public static void main(String[] args) throws Exception { 155 readExcelInfo("g://批量新增設備表.xlsx"); 156 }*/ 157 }
封裝為對象,插入數據庫,這里本博主不放入公司業務對象,刪掉了
1 @PostMapping("/addBatchDevice") 2 public ResponseObj addBatchDevice(@RequestBody JSONObject jsonObject){ 3 ResponseObj response = new ResponseObj(); 4 response.setData(Defined.STATUS_SUCCESS); 5 response.setMessage("插入成功!"); 6 String url = jsonObject.getString("url"); 7 // 存放封裝的設備 8 List<Device> devices = new ArrayList<Device>(); 9 try { 10 List<List<String>> list = ReadExcelUtil.readExcelInfo(url); 11 for(int i=0;i<list.size();i++){ 12 // new一個對象按照相應的字段設置進去就可以了,這里省略對象設置值,字段如下: 13 System.out.println("封裝成對象后:"+"\t"+"設備名稱--->"+list.get(i).get(0)+"型號--->"+list.get(i).get(1)+"數量---> "+list.get(i).get(2)); 14 } 15 } catch (Exception e) { 16 // TODO Auto-generated catch block 17 e.printStackTrace(); 18 } 19 // 插入數據庫 20 // 調用相關插入方法,可以批量也可單條插入循環實現,看具體業務需要選擇 21 return response; 22 }
調用接口運行效果如下:
OK,成功運行!