1. 程式人生 > >SSM學習筆記(三)——excel匯入匯出

SSM學習筆記(三)——excel匯入匯出

非專門的軟體企業用的比較多的便是excel的匯入和匯出的功能,本次對近日實現的匯入和匯出功能做下記錄。

首先是工具類,這裡參考了CSDN  “如果海豚會飛” 的文章,但由於其文章內容有些殘缺,且與QB個人開發的現狀不符合,所以做了一定的修改。

參考的文章:http://blog.csdn.net/hsf15768615284/article/details/73136029

注意的導包:poi的幾個包,xmlbeans這個包(因為這個包沒匯入QB除錯了6個多小時才找到錯誤,感覺虧了一個億)

工具類:

建立一個ExcelBean實現資料的封裝

ExcelBean.java

package cn.gsp.common.utils.excel;

import org.apache.poi.xssf.usermodel.XSSFCellStyle;

/**
 * @Description: 建立一個ExcelBean實現資料的封裝
 * @author QB
 * @date 2017年10月17日 上午9:19:00
 */
public class ExcelBean implements java.io.Serializable {
	/**
	 * @Fields serialVersionUID : TODO(用一句話描述這個變量表示什麼)
	 */
	private static final long serialVersionUID = 1L;
	private String headTextName;// 列頭(標題)名
	private String propertyName;// 對應欄位名
	private Integer cols;// 合併單元格數
	private XSSFCellStyle cellStyle;

	public ExcelBean() {

	}

	public ExcelBean(String headTextName, String propertyName) {
		this.headTextName = headTextName;
		this.propertyName = propertyName;
	}

	public ExcelBean(String headTextName, String propertyName, Integer cols) {
		super();
		this.headTextName = headTextName;
		this.propertyName = propertyName;
		this.cols = cols;
	}

	public String getHeadTextName() {
		return headTextName;
	}

	public void setHeadTextName(String headTextName) {
		this.headTextName = headTextName;
	}

	public String getPropertyName() {
		return propertyName;
	}

	public void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}

	public Integer getCols() {
		return cols;
	}

	public void setCols(Integer cols) {
		this.cols = cols;
	}

	public XSSFCellStyle getCellStyle() {
		return cellStyle;
	}

	public void setCellStyle(XSSFCellStyle cellStyle) {
		this.cellStyle = cellStyle;
	}

}

excel的匯入工具類(這裡QB只採用了原博主的匯入工具類,同時也進行了一些符合自己現狀的修改)

ExcelUtil.java

package cn.gsp.common.utils.excel;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
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.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.sun.org.apache.xerces.internal.impl.xpath.regex.ParseException;

public class ExcelUtil {
	private final static String excel2003L = ".xls"; // 2003- 版本的excel
	private final static String excel2007U = ".xlsx"; // 2007+ 版本的excel

	/**
	 * Excel匯入
	 */
	public static List<List<Object>> getBankListByExcel(InputStream in, String fileName) throws Exception {
		List<List<Object>> list = null;
		// 建立Excel工作薄
		Workbook work = getWorkbook(in,fileName);
		if ( null==work) {
			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++) {
			sheet = work.getSheetAt(i);
			if (sheet == null) {
				continue;
			}
			// 遍歷當前sheet中的所有行
			// 包涵頭部,所以要小於等於最後一列數,這裡也可以在初始值加上頭部行數,以便跳過頭部
			for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
				// 讀取一行
				row = sheet.getRow(j);
				// 去掉空行和表頭
				if (row == null || row.getFirstCellNum() == j) {
					continue;
				}
				// 遍歷所有的列
				List<Object> li = new ArrayList<Object>();
				for (int y = 0; y <3; y++) {  	//由於個人原因被明確規定了匯入資料只有三列,
					cell = row.getCell(y);	//且 考慮到匯入的excel單元格內可以不寫東西得情況
					if(cell==null)		//所以直接用 明確的數值來確定遍歷的次數
					{li.add(null);}		//這裡添加了單元格中空白的判斷,如果空白預設賦值為null,避免後面mybatis裡面出現錯誤
					else
					li.add(getCellValue(cell));
				}
				list.add(li);
			}
		}
		return list;
	}

	/**
	 * 描述:根據檔案字尾,自適應上傳檔案的版本
	 */
	public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
		Workbook wb = null;
		String fileType = fileName.substring(fileName.lastIndexOf("."));
		if (excel2003L.equals(fileType)) {
			wb = new HSSFWorkbook(inStr); // 2003-
		} else if (excel2007U.equals(fileType)) {
			wb = new XSSFWorkbook(inStr); // 2007+
		} else {
			throw new Exception("解析的檔案格式有誤!");
		}
		return wb;
	}

	/**
	 * 描述:對錶格中數值進行格式化
	 */
	public static Object getCellValue(Cell cell) {
		Object value = null;
		DecimalFormat df = new DecimalFormat("0"); // 格式化字元型別的數字
		SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd"); // 日期格式化
		DecimalFormat df2 = new DecimalFormat("0.00"); // 格式化數字
		switch (cell.getCellType()) {
		case Cell.CELL_TYPE_STRING:
			value = cell.getRichStringCellValue().getString();
			break;
		case Cell.CELL_TYPE_NUMERIC:
			if ("General".equals(cell.getCellStyle().getDataFormatString())) {
				value = df.format(cell.getNumericCellValue());
			} else if ("m/d/yy".equals(cell.getCellStyle().getDataFormatString())) {
				value = sdf.format(cell.getDateCellValue());
			} else {
				value = df2.format(cell.getNumericCellValue());
			}
			break;
		case Cell.CELL_TYPE_BOOLEAN:
			value = cell.getBooleanCellValue();
			break;
		case Cell.CELL_TYPE_BLANK:
			value = "";
			break;
		default:
			break;
		}
		return value;
	}
匯出的工具類

ViewExcel.java

package cn.gsp.common.utils;

import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.servlet.view.document.AbstractExcelView;

public class ViewExcel extends AbstractExcelView {

	private String[] titles;

	// 傳入指定的標題頭
	public ViewExcel(String[] titles) {
		this.titles = titles;
	}

	@Override
	protected void buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		// 獲取資料
		List<Map<String, String>> list = (List<Map<String, String>>) model.get("excelList");
		// 在workbook新增一個sheet
		HSSFSheet sheet = workbook.createSheet();
		sheet.setDefaultColumnWidth(15);
		HSSFCell cell = null;
		// 遍歷標題
		for (int i = 0; i < titles.length; i++) {
			// 獲取位置
			cell = getCell(sheet, 0, i);
			setText(cell, titles[i]);
		}
		// 資料寫出
		for (int i = 0; i < list.size(); i++) {
			// 獲取每一個map
			Map<String, String> map = list.get(i);
			// 一個map一行資料
			HSSFRow row = sheet.createRow(i + 1);
			for (int j = 0; j < titles.length; j++) {
				// 遍歷標題,把key與標題匹配
				String title = titles[j];
				// 判斷該內容存在mapzhong
				if (map.containsKey(title)) {
					row.createCell(j).setCellValue(map.get(title));
				}
			}
		}
		// 設定下載時客戶端Excel的名稱
		String filename = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls";
		response.setContentType("application/vnd.ms-excel");
		response.setHeader("Content-disposition", "attachment;filename=" + filename);
		OutputStream ouputStream = response.getOutputStream();
		workbook.write(ouputStream);
		ouputStream.flush();
		ouputStream.close();
	}

}

這裡的匯入指的是將excel檔案上傳,匯入到資料庫中,然後進行相應的規則應用(匯入匯出只是附帶功能,但這裡只記錄匯入匯出的部分)

匯出指的是將資料從資料庫中匯出,生成excel檔案(目前正在想是否直接匯出查詢結果會更好?但感覺好麻煩。。。)

匯入jsp部分

<form method="post" enctype="multipart/form-data"
				action="${pageContext.request.contextPath }/seorder/import.action">
				<table>
					<tr>
						<td>上傳檔案:</td>
						<td><input id="upfile" type="file" name="upfile"
							class="btn btn-blue"></td>
					</tr>
					<tr>
						<td><input class="btn btn-blue" type="submit" value="提交"
							onclick="return checkData()"></td>
					</tr>
				</table>
			</form>

controller部分
/**
	 * excel表的匯入
	 */
	@RequestMapping("/import")
	public String impotr(HttpServletRequest request, Model model) throws Exception {

		// 獲取上傳的檔案
		MultipartHttpServletRequest multipart = (MultipartHttpServletRequest) request;
		MultipartFile file = multipart.getFile("upfile");
		if (file.isEmpty()) {
			JOptionPane.showMessageDialog(null, "上傳檔案為空!", "錯誤", JOptionPane.ERROR_MESSAGE);
			return "redirect:/seorder/list.action";
		} // 對上傳檔案是否為空做了一個判斷,如果excel不存在彈出錯誤提示框頁面重定向,存在匯入excel

		InputStream in = file.getInputStream();

		// 資料匯入
		seorderService.importExcelInfo(in, file);

		return "redirect:/seorder/pipei.action";
	}
service部分
/**
	 * 匯入excel
	 */
	public void importExcelInfo(InputStream in, MultipartFile file) throws Exception {
		List<List<Object>> listob = ExcelUtil.getBankListByExcel(in, file.getOriginalFilename());
		List<SeorderK> seorderList = new ArrayList<SeorderK>();
		
		// 遍歷listob資料,把資料放到List中
		for (int i = 0; i < listob.size(); i++) {
			List<Object> ob = listob.get(i);
			SeorderK seorderK = new SeorderK();
			
			// 通過遍歷實現把每一列封裝成一個model中,再把所有的model用List集合裝載

			seorderK.setFBillNo(String.valueOf(ob.get(0)));
			seorderK.setFMapNumber(String.valueOf(ob.get(1)));
			seorderK.setFEntrySelfS0164(String.valueOf(ob.get(2)));
//			seorderK.setFNumber(String.valueOf(ob.get(3))); 考慮到實際的情況讓使用者只用匯入三個欄位中的兩個就可以了
//			seorderK.setFShortNumber(String.valueOf(ob.get(4)));
//			seorderK.setFName(String.valueOf(ob.get(5)));
			
			seorderList.add(seorderK);
			
		}
		// 批量插入
		seorderkDao.insertInfoBatch(seorderList);
	}

dao部分
/**
	 * 匯入資料
	 * @param seorderkList
	 */
	public void insertInfoBatch(List<SeorderK> seorderkList);

dao的實現類xml
<!-- 匯入資料 -->
	<insert id="insertInfoBatch" parameterType="java.util.List">
		insert into gsp_seorderk_t (FBillNo, FMapNumber,FEntrySelfS0164)
		values
			<foreach collection="list" item="item" index="index"
				separator="," >
				(#{item.FBillNo}, #{item.FMapNumber}, #{item.FEntrySelfS0164})
			</foreach>
	</insert>

匯入部分到此為止,接下來是匯出的部分

匯出jsp部分

<form
				action="${pageContext.request.contextPath }/seorder/export.action">
				<button id="btnExport" type="submit" class="btn btn-blue">匯出</button>
			</form>

controller部分
/**
	 * 匯出excel2
	 * 
	 * @param map
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/export")
	public ModelAndView export(ModelMap map) throws Exception {
		List<Map<String, String>> list = seorderService.exportExcelInfo();
		String[] titles = { "訂單編號", "客戶程式碼", "新編碼", "GSP長程式碼", "GSP短程式碼", "GSP名稱" };
		ViewExcel excel = new ViewExcel(titles);
		map.put("excelList", list);
		return new ModelAndView(excel, map);
	}
service部分
/**
	 * 匯出excel2
	 * 
	 * @throws Exception
	 */
	public List<Map<String, String>> exportExcelInfo() throws Exception {
		List<SeorderK> list = seorderkDao.pipei(null);
		List<Map<String, String>> mapList = new ArrayList<Map<String, String>>();
		for (SeorderK sk : list) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("訂單編號", sk.getFBillNo());
			map.put("客戶程式碼", sk.getFMapNumber());
			map.put("新編碼", sk.getFEntrySelfS0164());
			map.put("GSP長程式碼", sk.getFNumber());
			map.put("GSP短程式碼", sk.getFShortNumber());
			map.put("GSP名稱", sk.getFName());
			mapList.add(map);
		}
		return mapList;
	}

dao部分
/**
	 * 匯出excel
	 * @param seorderkDate
	 * @return
	 */
	public List<SeorderK> selectApartInfo(String seorderkDate);
dao對應的實現類xml

依據個人情況來寫