1. 程式人生 > >poi處理excel遇到的坑

poi處理excel遇到的坑

做poi匯入匯出:

匯出功能還好比較簡單,只需要指定好相應模板,對於日期格式的資料來說,同理模板需要設定日期,然後模板中大致的格式是

<jx:forEach items="${itsmciList}" var="itsmci">
${itsmci.name} ${itsmci.categoryvalue} ${itsmci.version} ${itsmci.sn} ${itsmci.assetNumber}
</jx:forEach>
類似這樣的格式:這裡的itsmciList是List<Entity>這樣的資料,學JAVA都知道把。

poi從資料庫------到excel:原理是,先讀模板,往模板注入資料,形成Workbook,workbooke經ServletOutputStream,流到瀏覽器端。

直接上程式碼:

		匯出
		@RequestMapping("/itsmciExport.do")  
		public void itsmciExport(HttpServletRequest request,HttpServletResponse response) throws IOException, ParsePropertyException, InvalidFormatException
		{
		QueryParameter paramMap = new QueryParameter();
		
			paramMap.addEquals("companyid", getUser().getCompanyId());

		List<Itsm_ci> list = itsm_ciService.findListByParam(paramMap);
		
		if(CollectionUtils.isNotEmpty(list)){
			String companyId = list.get(0).getCompanyid();
			Itsm_ci.formatList(companyId, list);//翻譯
		}
		itsmCiFeatureproService.getFeatureproInfor(list);          //加進特徵資訊
		String fileName = getUser().getCompanyName()+"的配置項.xls";
		String filePath = this.getClass().getClassLoader().getResource("//templates//itsmciList.xls").getPath();

		Map<String, Object> beans = new HashMap<String, Object>();
		beans.put("itsmciList", list);

		InputStream is = new BufferedInputStream(new FileInputStream(filePath));

		XLSTransformer transformer = new XLSTransformer();
		Workbook resultWorkbook = transformer.transformXLS(is, beans);
		is.close();

		super.responseDownloadWorkbook(request, response, fileName, resultWorkbook);
		}

/**
	 * workbook檔案下載方法
	 * 
	 * @param response
	 * @param fileName
	 *            檔名
	 * @param workbook
	 *            檔案
	 * @throws IOException
	 */
	public void responseDownloadWorkbook(HttpServletRequest request, HttpServletResponse response, String fileName, Workbook workbook) throws IOException {
		String agent = request.getHeader("User-Agent").toUpperCase();

		String encodedfileName = "";
		if (agent.indexOf("MSIE") != -1 || agent.indexOf("TRIDENT") != -1) { // IE
			encodedfileName = URLEncoder.encode(fileName, "utf-8");
		} else if (agent.indexOf("CHROME") != -1 || agent.indexOf("FIREFOX") != -1) { // 谷歌或火狐
			encodedfileName = new String(fileName.getBytes("utf-8"), "ISO8859-1");
		} else {
			encodedfileName = new String(fileName.getBytes("utf-8"), "ISO8859-1");
		}

		// 設定輸出的格式
		response.reset();
		response.setContentType("bin");
		response.addHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + "\"");

		// 取出流中的資料
		ServletOutputStream os = response.getOutputStream();
		workbook.write(os);
		os.write(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF });// UTF-8
		os.flush();
		os.close();
	}
匯出完畢;

匯入功能:我的需求比較複雜:需要根據      填寫欄位的名稱去找外來鍵 ,excel中填的是名稱,但是存到資料庫中是外來鍵(前提是該名稱在主表中已經存在),然後還需要分析excel填寫的資訊的合法性,並且將錯誤資訊返回給使用者(這裡需要判斷多個欄位唯一性,對資料庫中不存在的主表字段,也要報錯誤,這裡我是用List<>來存放錯誤)。

然後一個很特別的坑是日期格式的資料。(注意,excel匯入到資料庫的功能:一般情況下需要伺服器制定好模板讓使用者去下載,然後填寫。所以製作模板的時候將時間格式的資料設定為時間格式)

具體業務就不寫了,把那個坑獻上:

	/**
	 * 
	 *author:cwy
	 *說明:將excel表中的資料倒入到資料庫時要用到,將excel表中的資料轉換成List<Map<String,Object>>形式的資料
	 *引數:
	 * @param in  輸入流
	 * @param filename     檔案原始名字  
	 * @param startrow     從第幾行開始讀
	 * @param startcol     從第幾列開始讀
	 * @param sheetnum     第幾個sheet開始
	 * @return
	 * @throws IOException
	 */
	public   List<Map<String,Object>> readAllExcel(InputStream in, String filename, int startrow, int startcol, int sheetnum) throws IOException {
		List<Map<String,Object>> varList = new ArrayList<Map<String,Object>>();
		Workbook wb=null;
		try {
			if(filename.substring(filename.lastIndexOf(".")+1).equals("xlsx"))
			{
				wb = new XSSFWorkbook(in);
			}
			else
			{
				wb=new HSSFWorkbook(in);
				
			}
				Sheet sheet = wb.getSheetAt(sheetnum); // sheet 從0開始
			int rowNum = sheet.getLastRowNum() + 1; // 取得最後一行的行號

			for (int i = startrow; i < rowNum; i++) { // 行迴圈開始

			
				Row row =  sheet.getRow(i); // 行
				int cellNum = row.getLastCellNum(); // 每行的最後一個單元格位置
				Map<String,Object> map=new HashMap<String,Object>();
				for (int j = startcol; j < cellNum; j++) { // 列迴圈開始
					
					Cell cell = row.getCell(Short.parseShort(j + ""));
					String cellValue = null;
					if (null != cell) {
						switch (cell.getCellType()) { // 判斷excel單元格內容的格式,並對其進行轉換,以便插入資料庫
							case 0:                  //數字型別(包括純數字和時間)
								cellValue = String.valueOf((int) cell.getNumericCellValue());
								if(HSSFDateUtil.isCellDateFormatted(cell))          //如果是時間格式(萬能方法)
								{
									 short format = cell.getCellStyle().getDataFormat();  
									    SimpleDateFormat sdf = null;  
									    if(format == 14 || format == 31 || format == 57 || format == 58){  
									        //日期  
									        sdf = new SimpleDateFormat("yyyy-MM-dd");  
									    }else if (format == 20 || format == 32) {  
									        //時間  
									        sdf = new SimpleDateFormat("HH:mm");  
									    }  
									    double value = cell.getNumericCellValue();  
									    Date date = DateUtil.getJavaDate(value);  
									    cellValue = sdf.format(date);  
								}
								break;
							case 1:               //字串型別
								cellValue = cell.getStringCellValue();
								
								break;
							case 2:              //格式型別
								cellValue = cell.getNumericCellValue() + "";
								break;
							case 3:              //空
								cellValue = "";
								break;
							case 4:              //布林型別
								cellValue = String.valueOf(cell.getBooleanCellValue());
								break;
							case 5:             //錯誤
								cellValue = String.valueOf(cell.getErrorCellValue());
								break;
						}
					} else {
						cellValue = "";
					}

					map.put("var"+j,cellValue);
				}
				varList.add(map);
			}

		} catch (Exception e) {
			System.out.println(e);
		}
		finally{in.close();}

		return varList;
	}
List<Map<String,Object>>      excel的資料就全放到這裡了。後面是解析和儲存。