poi批量匯入匯出Excel(三、通過模板匯出Excel並能實現匯入多個sheet表)
阿新 • • 發佈:2019-01-27
本專案基於SSM框架,簡單封裝了Excel批量匯入匯出功能,不用建資料庫表一鍵匯入匯出Excel,不過這樣只適用於對匯入的Excel表進行轉換,通過模板匯出Excel並且能實現匯入多個sheet表。上一篇介紹了建表匯入匯出Excel(點選跳轉)
一、下載poi jar包:
點這裡下載:poi 3.8/3.9/3.10三個版本下載
poi 3.17最新版本下載
二、基本操作步驟:
首先,理解一下一個Excel的檔案的組織形式,一個Excel檔案對應於一個workbook(HSSFWorkbook),一個workbook可以有多個sheet(頁/表)(HSSFSheet)組成,一個sheet是由多個row(行)(HSSFRow)組成,一個row是由多個cell(單元格)(HSSFCell)組成。
1、用HSSFWorkbook開啟或者建立“Excel檔案物件”
2、用HSSFWorkbook物件返回或者建立Sheet物件
3、用Sheet物件返回行物件,用行物件得到Cell物件
4、對Cell物件讀寫。
然後需要先新建一個Excel檔案,格式樣式表頭標題編輯好,放入到專案中,下面是我的路徑。
WEB-INF/jsp/purchasing/orderExcel/Excel.xls
三、控制層Controller按照模板匯出Excel
/** * 匯出銷售訂單資料 * @param myFile * @param respon * @return * @throws IOException */ @RequestMapping(value = "export", method=RequestMethod.POST) public ModelAndView exportFile(@RequestParam(value="file",required=false)MultipartFile myFile,HttpServletResponse response,HttpServletRequest request)throws IOException { ModelAndView mv = this.getModelAndView(); try { ImportExcelUtil util = new ImportExcelUtil(); InputStream input = null; List<List<Object>> lists = null; if (myFile.isEmpty()) { logBefore(logger, "匯入檔案為空,請先新增Excel檔案!"); } else { String fileName = myFile.getOriginalFilename(); input = myFile.getInputStream(); //實現多sheet頁批量匯入Excel讀取資料存入lists lists = util.getBankListByExcel(input, fileName); input.close(); //引入匯出Excel路徑 File fi = new File(request.getSession().getServletContext().getRealPath("/") + "WEB-INF/jsp/purchasing/orderExcel/Excel.xls"); POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(fi)); //讀取excel模板 HSSFWorkbook wb = new HSSFWorkbook(fs); //讀取了模板內所有sheet內容 HSSFSheet sheet = wb.getSheetAt(0); //如果這行沒有了,整個公式都不會有自動計算的效果的 sheet.setForceFormulaRecalculation(true); // 迴圈將excel中的資料存入庫 for (int i = 1; i < lists.size(); i++) { List<Object> list = lists.get(i); HSSFRow dataRow = sheet.createRow((int) i + 1); dataRow.createCell(0).setCellValue(util.getFormat(String.valueOf(list.get(0))));//單據日期 dataRow.createCell(1).setCellValue(util.getFormat(String.valueOf(list.get(1))));//單據編號(內部單號) dataRow.createCell(2).setCellValue(util.getFormat(String.valueOf(list.get(19))));//往來單位編碼(客戶編碼)(結算客戶編碼) dataRow.createCell(3).setCellValue("");//客戶 dataRow.createCell(4).setCellValue(util.getFormat(String.valueOf(list.get(19))));//結算客戶編碼 dataRow.createCell(5).setCellValue("");//結算客戶 dataRow.createCell(6).setCellValue(util.getFormat(String.valueOf(list.get(21))));//部門編碼 dataRow.createCell(7).setCellValue("");//部門 dataRow.createCell(8).setCellValue(util.getFormat(String.valueOf(list.get(17))));//業務員編碼 dataRow.createCell(9).setCellValue(util.getFormat(String.valueOf(list.get(18))));//業務員 dataRow.createCell(10).setCellValue(util.getFormat(String.valueOf(list.get(12))));//幣種程式碼 dataRow.createCell(11).setCellValue("");//幣種 dataRow.createCell(12).setCellValue(util.getFormat(String.valueOf(list.get(22))));//匯率 dataRow.createCell(13).setCellValue("");//運輸方式 dataRow.createCell(14).setCellValue("");//送貨地址 dataRow.createCell(15).setCellValue("");//聯絡人 dataRow.createCell(16).setCellValue("");//聯絡電話 dataRow.createCell(17).setCellValue("");//客戶手機號 dataRow.createCell(18).setCellValue("");//合同號 dataRow.createCell(19).setCellValue("其它");//收款方式 dataRow.createCell(20).setCellValue("");//外部單據號 dataRow.createCell(21).setCellValue("");//按倉庫拆單出庫 dataRow.createCell(22).setCellValue("");//國際單號 dataRow.createCell(23).setCellValue(util.getFormat(String.valueOf(list.get(4))));//內部單號 dataRow.createCell(24).setCellValue(util.getFormat(String.valueOf(list.get(6))));//備註 dataRow.createCell(25).setCellValue(util.getFormat(String.valueOf(list.get(23))));//倉庫編碼 dataRow.createCell(26).setCellValue("");//倉庫 dataRow.createCell(27).setCellValue("");//專案編碼 dataRow.createCell(28).setCellValue("");//專案 dataRow.createCell(29).setCellValue(util.getFormat(String.valueOf(list.get(8))));//存貨編碼 dataRow.createCell(30).setCellValue("");//存貨名稱 dataRow.createCell(31).setCellValue("個");//銷售單位 dataRow.createCell(32).setCellValue(util.getFormat(String.valueOf(list.get(9))));//數量 dataRow.createCell(33).setCellValue("");//報價 dataRow.createCell(34).setCellValue("");//折扣% dataRow.createCell(35).setCellValue("0");//稅率% dataRow.createCell(36).setCellValue(util.getFormat(String.valueOf(list.get(10))));//含稅單價 dataRow.createCell(37).setCellValue(util.getFormat(String.valueOf(list.get(11))));//含稅金額 dataRow.createCell(38).setCellValue(util.getFormat(String.valueOf(list.get(13))));//國家 dataRow.createCell(39).setCellValue(util.getFormat(String.valueOf(list.get(15))));//貨代?國際 dataRow.createCell(40).setCellValue(util.getFormat(String.valueOf(list.get(5))));//客戶單號 dataRow.createCell(41).setCellValue("");//預計交貨日期 dataRow.createCell(42).setCellValue("");//贈品 dataRow.createCell(43).setCellValue("");//備註 } // 設定Excel檔名,並以中文進行編碼 String codedFileName = new String("銷售訂單".getBytes("gbk"), "iso-8859-1"); response.setHeader("Content-Disposition", "attachment;filename=" + codedFileName + DateUtil.sdfDaym() +".xlsx"); // 響應型別,編碼 response.setContentType("application/octet-stream;charset=UTF-8"); // 形成輸出流 OutputStream osOut = response.getOutputStream(); // 將指定的位元組寫入此輸出流 wb.write(osOut); // 重新整理此輸出流並強制將所有緩衝的輸出位元組被寫出 osOut.flush(); // 關閉流 osOut.close(); } } catch (Exception e) { e.printStackTrace(); System.out.println("異常資訊: " + e.getMessage() ); mv.addObject("msg","error"); mv.setViewName("purchasing/orderExcel/orderExcelList"); return mv; } mv.addObject("msg","success"); return mv; }
四、封裝Excel工具類ImportExcelUtil實現匯入多個sheet表
匯入多個sheet表-->如果就一個sheet那麼就讀取所有行,如果有多個sheet就在第二頁開始跳過標題行只讀取資料,不然會出現標題重複。
package com.fh.util; import java.io.InputStream; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ImportExcelUtil { private final static String Excel_2003 = ".xls"; //2003 版本的excel private final static String Excel_2007 = ".xlsx"; //2007 版本的excel public List<List<Object>> getBankListByExcel(InputStream in,String fileName) throws Exception{ List<List<Object>> list = null; //建立Excel工作簿 Workbook work = this.getWorkbook(in, fileName); if(work == null) { throw new Exception("建立Excel工作簿為空!"); } Sheet sheet = null; Row row = null; Cell cell = null; list = new ArrayList<List<Object>>(); //遍歷Excel中的所有sheet for(int i = 0; i<work.getNumberOfSheets(); i++) { //如果Excel就一頁一個sheet則i=0 if(i==0){ sheet = work.getSheetAt(i); if(sheet == null) {continue;} //遍歷當前sheet中的所有行 //int totalRow = sheet.getPhysicalNumberOfRows();//如果excel有格式,這種方式取值不準確 int totalRow = sheet.getPhysicalNumberOfRows(); for(int j = sheet.getFirstRowNum(); j<totalRow; j++) { row = sheet.getRow(j); if(!isRowEmpty(row)) { //if(row != null && !"".equals(row)) { //獲取第一個單元格的資料是否存在 Cell fristCell=row.getCell(0); if(fristCell!=null){ //遍歷所有的列 List<Object> li = new ArrayList<Object>(); //int totalColum = row.getLastCellNum(); for(int y = row.getFirstCellNum(); y<row.getLastCellNum(); y++) { cell = row.getCell(y); if(cell == null){ String callCal =""; li.add(callCal); }else{ String callCal = this.getCellValue(cell)+""; li.add(callCal); } } list.add(li); } }else if(isRowEmpty(row)){ continue; } } }else{ //如果是第二頁sheet要從第二行遍歷資料去掉標題行即i>0 sheet = work.getSheetAt(i); if(sheet == null) {continue;} //遍歷當前sheet中的所有行 int totalRow = sheet.getPhysicalNumberOfRows(); //j從第二行讀取資料即j=1跳過標題行 for(int j = 1; j<totalRow; j++) { row = sheet.getRow(j); if(!isRowEmpty(row)) { //if(row != null && !"".equals(row)) { //獲取第一個單元格的資料是否存在 Cell fristCell=row.getCell(0); if(fristCell!=null){ //遍歷所有的列 List<Object> li = new ArrayList<Object>(); //int totalColum = row.getLastCellNum(); for(int y = row.getFirstCellNum(); y<row.getLastCellNum(); y++) { cell = row.getCell(y); if(cell == null){ String callCal =""; li.add(callCal); }else{ String callCal = this.getCellValue(cell)+""; li.add(callCal); } } list.add(li); } }else if(isRowEmpty(row)){ continue; } } } } in.close(); return list; } /** * 判斷行是否為空 * @param row * @return */ public static boolean isRowEmpty(Row row) { for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) { Cell cell = row.getCell(c); if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) return false; } return true; } /** * 描述:根據檔案字尾,自動適應上傳檔案的版本 * @param inStr,fileName * @return * @throws Exception * */ public Workbook getWorkbook(InputStream inStr,String fileName) throws Exception { Workbook work = null; String fileType = fileName.substring(fileName.lastIndexOf(".")); if(Excel_2003.equals(fileType)){ work=new HSSFWorkbook(inStr);//2003 版本的excel }else if(Excel_2007.equals(fileType)) { work=new XSSFWorkbook(inStr);//2007 版本的excel }else { throw new Exception("解析檔案格式有誤!"); } return work; } /** * 描述:對錶格中數值進行格式化 * @param cell * @return * */ public Object getCellValue(Cell cell) { String result = new String(); switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_FORMULA: //Excel公式 try { result = String.valueOf(cell.getNumericCellValue()); } catch (IllegalStateException e) { result = String.valueOf(cell.getRichStringCellValue()); } break; case HSSFCell.CELL_TYPE_NUMERIC:// 數字型別 if (HSSFDateUtil.isCellDateFormatted(cell)) {// 處理日期格式、時間格式 SimpleDateFormat sdf; if (cell.getCellStyle().getDataFormat() == HSSFDataFormat .getBuiltinFormat("h:mm")) { sdf = new SimpleDateFormat("HH:mm"); } else {// 日期 sdf = new SimpleDateFormat("yyyy-MM-dd"); } Date date = cell.getDateCellValue(); result = sdf.format(date); } else if (cell.getCellStyle().getDataFormat() == 58) { //如果匯出格式是yyyy/MM/dd那麼如下 //SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); //如果匯出格式是例如:9月10日那麼如下 SimpleDateFormat sdf = new SimpleDateFormat("M月d日"); double value = cell.getNumericCellValue(); Date date = org.apache.poi.ss.usermodel.DateUtil .getJavaDate(value); result = sdf.format(date); } else { double value = cell.getNumericCellValue(); CellStyle style = cell.getCellStyle(); DecimalFormat format = new DecimalFormat(); String temp = style.getDataFormatString(); // 單元格設定成常規 if (temp.equals("General")) { format.applyPattern("#.##"); } result = format.format(value); } break; case HSSFCell.CELL_TYPE_STRING:// String型別 result = cell.getRichStringCellValue().toString(); break; case HSSFCell.CELL_TYPE_BLANK: result = ""; default: result = ""; break; } return result; } public String getFormat(String str) { if(str.equals("null")) { str=""; return str; }else{ return str; } } public Integer getFormats(Integer str) { if(str==null) { str=0; return str; }else{ return str; } } /** * 獲取字串中的數字訂單號、數字金額等,如從"USD 374.69"中獲取到374.69、從“交易單號:66666666666”獲取到66666666666 * @param receiptAmountString * @return */ public static String getFormatNumber(String str){ str = str.trim(); Pattern p = Pattern.compile("[0-9]"); int indexNum = 0; int lenght = str.length(); String num = ""; for(int i=0;i<lenght;i++){ num += str.charAt(i); Matcher m = p.matcher(num); if(m.find()){ indexNum = i; break; } } String formatNumber = str.substring(indexNum,lenght); return formatNumber; } }
五、jsp頁面
<form action="orderExcel/export.do" name="Form" id="Form" method="post" enctype="multipart/form-data">
<table id="table_report" class="table table-striped table-bordered table-hover">
<tr>
<td style="width:70px;text-align: right;padding-top: 13px;">選擇Excel:</td>
<td><input id="uploadFile" name="file" type="file" style="width:330px" onchange="fileType(this)"/><br/><br/>
</td>
</tr>
<tr>
<td style="text-align: center;" colspan="10">
<input id="btnImportSubmit" class="btn btn-small btn-success" type="submit" value="Excel轉換"/>
</td>
</tr>
</table>
</form>
<script type="text/javascript">
var msg = '${msg}';
if(msg == 'error'){
alert("匯出檔案失敗!請檢查Excel檔案!")
}
$(top.hangge());
//檢索
function search(){
top.jzts();
$("#Form").submit();
}
//過濾型別
function fileType(obj){
var fileType=obj.value.substr(obj.value.lastIndexOf(".")).toLowerCase();//獲得檔案字尾名
if(fileType != '.xls' && fileType != '.xlsx'){
$("#uploadFile").tips({
side:3,
msg:'請選擇正確的Excel檔案',
bg:'#AE81FF',
time:3
});
$("#uploadFile").val('');
}
}
</script>