1. 程式人生 > >poi批量匯入匯出Excel(三、通過模板匯出Excel並能實現匯入多個sheet表)

poi批量匯入匯出Excel(三、通過模板匯出Excel並能實現匯入多個sheet表)

本專案基於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>