導入Excel用戶表,調用存儲過程

花了一天半的時間學習了一下導入Excel用戶表,調用存儲過程,主要是學習存儲過程。由於以前沒有具體在項目中應用過。html

   這裏咱們採用導入Excel到臨時表,而後存儲過程當中讀取臨時表判斷數據類型和數據格式,而後保存到正式表。java

   導入Excel採用spring 的POI技術。spring


本文內容較多,請選擇性閱讀。sql


controller裏面的代碼:jsp

	/**
	 * Excel導入用戶表,調用存儲過程,先導入臨時表,再在存儲過程當中判斷,判斷經過後導入正式表,錯誤的則記錄錯誤日誌表中。 lijianbo
	 * 
	 * @param request
	 * @param respnse
	 * @throws Exception
	 */
	public void excelImport(HttpServletRequest request, HttpServletResponse response, UpLoadFile upLoadFile)
			throws Exception {
		ExcelImportResult excelToUserTemp = new ExcelImportResult();

		try {
			response.setCharacterEncoding("GBK");
			if (upLoadFile == null || upLoadFile.isEmpty()) {
				response.getWriter().println("<script>parent.uploadCallback('0','請選擇導入的文件');</script>");
				return;
			}
			/**
			 * 清空臨時表
                            <select id="truncate" >
                              truncate table USERTEMP
                    	    </select>
                	*/
			excelImportManager.truncate();
			/**
			 * 讀取Excel數據封裝爲List
			 */
			excelToUserTemp = saveExcelToUserTemp(request, response, upLoadFile);

			if (excelToUserTemp.getResultFlag() == 0) {
				response.setCharacterEncoding("UTF-8");
				response.getWriter().println(
						"<script>parent.uploadCallback('0','" + excelToUserTemp.getErrorMsg() + "');</script>");
				return;
			} else {// 保存數據到臨時表
				@SuppressWarnings("unchecked")
				List<String> resultList = (List<String>) excelToUserTemp.getResultList();
				if (resultList != null && resultList.size() > 0) {
					for (String sqlStr : resultList) {
						this.excelImportManager.excuteInsertSql(sqlStr);
					}
				}
			}
			HashMap<String, String> parmMap = new HashMap<String, String>();
			parmMap.put("totalCount", "");
			// 調用存儲過程,判斷數據格式,保存數據到正式表,記錄錯誤日誌
			userManager.batchImportUser(parmMap);
			String totalCount = parmMap.get("totalCount");
			System.out.println("保存的總記錄數爲:" + totalCount);

			response.setCharacterEncoding("UTF-8");
			response.getWriter().println("<script>parent.uploadCallback('0','導入成功!共導入" + totalCount + "條');</script>");
		} catch (Exception e) {
			response.setCharacterEncoding("UTF-8");
			response.getWriter().println(
					"<script>parent.uploadCallback('0','導入失敗!'" + excelToUserTemp.getErrorMsg() + ");</script>");
			e.printStackTrace();
		}
	}

	/**
	 * 導入Excel到臨時表
	 * 
	 * @throws IOException
	 */
	public ExcelImportResult saveExcelToUserTemp(HttpServletRequest request, HttpServletResponse response,
			UpLoadFile upLoadFile) throws Exception {
		String result = "";
		ExcelImportResult excelImportResult = new ExcelImportResult();
		List<String> dataList = new ArrayList<String>();
		// 建立工做簿
		Workbook wb = WorkbookFactory.create(upLoadFile.getFile().getInputStream());
		// 取得第一個sheets
		Sheet sheet = wb.getSheetAt(0);
		// 最大的行數
		int lastRowNum = sheet.getLastRowNum();
		// 檢查表的列數是否和模板一致
		result = excelLineCheck(sheet);
		if ("true".equals(result)) {
			// 讀取excel內容
			for (int i = 1; i <= lastRowNum; i++) {
				Row row = sheet.getRow(i); // 獲取行(row)對象
				if (row == null) {
					// row爲空的話,不處理
					continue;
				}
				String sqlvalue = "";
				for (int j = 0; j < 4; j++) {
					Cell cell = row.getCell(j); // 得到單元格(cell)對象
					// 將單元格的數據添加至一個對象 在sql中
					sqlvalue = sqlvalue + "'" + cell.toString() + "',";
				}
				sqlvalue = sqlvalue.substring(0, sqlvalue.length() - 1);
				String sql = "insert into USERTEMP(ID,NAME,CARDTYPE,CARDNO,STATUS) values(SEQ_USERTEMP.NEXTVAL,"
						+ sqlvalue + ")";
				System.out.println("sql:" + sql);
				dataList.add(sql);
				excelImportResult.setResultList(dataList);
				excelImportResult.setResultFlag(1);
			}
		} else {
			excelImportResult.setErrorMsg(result);
			excelImportResult.setResultFlag(0);
		}
		return excelImportResult;
	}
	/**
	 * 檢查Excel的列是否與模板一致
	 * @param sheet
	 * @return
	 */
	private String excelLineCheck(Sheet sheet) {
		/**
		 * getPhysicalNumberOfRows()獲取的是物理行數,也就是不包括那些空行(隔行)的狀況。
		 * getLastRowNum()獲取的是最後一行的編號(編號從0開始)
		 */
		// 物理行數(不包括隔行)
		int rowNumbers = sheet.getPhysicalNumberOfRows();
		if (rowNumbers == 0) {
			return "excel中數據爲空!";
		}
		Row excelRow = sheet.getRow(0);
		int excelFirstRow = excelRow.getFirstCellNum();
		int excelLastRow = excelRow.getLastCellNum();
		if (4 != (excelLastRow - excelFirstRow)) {
			System.out.println("模版列數與excel列數不相符,請檢查");
			return "模版列數與excel列數不相符,請檢查";
		} else {
			return "true";
		}
	}


user.xml裏面調用存儲過程。參數咱們只有一個返回參數count,即成功導入的條數。ide

<!-- 存儲過程 -->
  	<parameterMap id="map_batchImportUser" type="java.util.HashMap">  
	    <parameter property="totalCount" jdbcType="VARCHAR" javaType="java.lang.String" mode="OUT" />  
	</parameterMap>  
	<select id="batchImportUser" parameterMap="map_batchImportUser" statementType="CALLABLE" >
	  <![CDATA[
	           {call BATCHIMPORTUSER(?)}
	        ]]> 
  </select>

存儲過程BATCHIMPORTUSER爲:oop

CREATE OR REPLACE 
procedure "BATCHIMPORTUSER"(TOTALCOUNT  out VARCHAR2) is
v_sql varchar2(2000);
excellogid NUMBER;
userId NUMBER;
totalCount1 NUMBER;
cardtype varchar2(255);
status varchar2(125);
cardNo varchar2(255);
flag NUMBER;

Cursor cursor is select * from USERTEMP;-- 顯性遊標,cursor 存儲了全部數據
begin
dbms_output.put_line('start--BATCHIMPORTUSER');
-- 讀取臨時表,驗證數據。
totalCount1:=0;
TOTALCOUNT:=0;
for us in cursor LOOP
if us.CARDTYPE ='×××' then 
  cardtype:=1;
else if us.CARDTYPE ='護照' then 
	cardtype:=2;
else if us.CARDTYPE ='駕駛證' then 
	cardtype:=3;
else 
-- 保存錯誤日誌,證件類型錯誤
v_sql := 'SELECT SEQ_EXCEL_LOG.NEXTVAL FROM dual';
execute immediate v_sql into excellogid;
 INSERT INTO EXCEL_LOG(ID,ROW_NO,CODE,ERROR_FIELD,TYPE,CREATE_TIME,BATCH_NO,BATCH_NAME,REMARK ) VALUES
   (excellogid,'','','cardtype','1',sysdate,'',us.name,'證件類型錯誤');
flag:=0;
end if;
end if;
end if;
if us.STATUS ='正常' then 
	status:=2;
else if us.STATUS ='異常' then 
	status:=1;
else -- 保存錯誤日誌,狀態錯誤
v_sql := 'SELECT SEQ_EXCEL_LOG.NEXTVAL FROM dual';
execute immediate v_sql into excellogid;
 INSERT INTO EXCEL_LOG( ID,ROW_NO,CODE,ERROR_FIELD,TYPE,CREATE_TIME,BATCH_NO,BATCH_NAME,REMARK ) VALUES
   (excellogid,'','','status','2',sysdate,'',us.name,'狀態錯誤,只能填正常、異常');
flag:=0;
end if;
end if;
--判斷是否爲數字
if  translate(replace(us.CARDNO,'0',''), '0123456789', '$') is not null then
	-- 保存錯誤日誌,證件號格式錯誤。
v_sql := 'SELECT SEQ_EXCEL_LOG.NEXTVAL FROM dual';
execute immediate v_sql into excellogid;
 INSERT INTO EXCEL_LOG( ID,ROW_NO,CODE,ERROR_FIELD,TYPE,CREATE_TIME,BATCH_NO,BATCH_NAME,REMARK ) VALUES
   (excellogid,'','','cardNo','3',sysdate,'',us.name,'證件號格式錯誤,必須爲字母數字格式');
flag:=0;
else 
	cardNo:=us.CARDNO;
end if;
v_sql := 'SELECT	SEQ_USERS.NEXTVAL AS id FROM dual';
execute immediate v_sql into userId;
--用戶數據導入
if flag=0 then 
	null;
else
	INSERT INTO USERS(ID,COMPANY_ID,NAME,EMAIL,STATUS,PHONE,GMT_UPDATE_PWD,CONTACT_TYPE,MOBILE,IDX_NUM,
	ID_TYPE,ID_NO,ID_EXPIRE_DATE,ID_TYPE2,ID_NO2,SEX,ETHNICITY,NATION,POST_ADDRESS,RESIDENCE_ADDRESS,HOMETOWN,
	BIRTHDAY,BANK,BANK_ACCOUNT_NO,MARITAL_STATUS,FINGER_PRINT ,BLOOD_TYPE,HOBBY,WEI_XIN_ID,QQ,CHANGE_BY,
	CHANGE_AT,CREATE_BY,CREATE_AT,PROVIDER_ID, LOGIN_ID,PASSWORD ) VALUES (userId,'',
	us.NAME,'',status,'','','','','',cardtype,cardNo,'','','','','','','','','','','','','','','','','','','','','',sysdate,'','','');
	totalCount1:=totalCount1+1;
end if;
end LOOP;
totalCount:=totalCount1;
end ;


總結:學習


①能夠直接在sql中用SEQ_USERTEMP.NEXTVAL 表示自增的主鍵ID(前提是已經建立了序列  SEQ_USERTEMP)this

 這裏還要注意zhangs等字符串要加單引號,不然會報錯。日誌

  INSERT INTO USERTEMP(id,name,cardtype,cardno,status)
  VALUES(SEQ_USERTEMP.NEXTVAL,'zhangs','1','511322','2');

②邏輯判斷時,若是隻是須要判讀是否成功,則通常返回TRUE或FALSE。

 若是要根據不一樣的狀況處理,則須要封裝到一個類或map中,根據不一樣的flag處理。

 若是是最後返回頁面了,則一般爲成功或失敗,這裏則用try--catch。

③POI技術:

*主要就是建立工做簿workbook

*建立表sheets

*獲取最大行,循環,

*對每一行數據循環,取單元格。

*處理具體的單元格。


	/**
	 * 導入Excel到臨時表
	 * 
	 * @throws IOException
	 */
	public ExcelImportResult saveExcelToUserTemp(HttpServletRequest request, HttpServletResponse response,
			UpLoadFile upLoadFile) throws Exception {
		String result = "";
		ExcelImportResult excelImportResult = new ExcelImportResult();
		List<String> dataList = new ArrayList<String>();
		// 建立工做簿
		Workbook wb = WorkbookFactory.create(upLoadFile.getFile().getInputStream());
		// 取得第一個sheets
		Sheet sheet = wb.getSheetAt(0);
		// 最大的行數
		int lastRowNum = sheet.getLastRowNum();
		// 檢查表的列數是否和模板一致
		result = excelLineCheck(sheet);
		if ("true".equals(result)) {
			// 讀取excel內容
			for (int i = 1; i <= lastRowNum; i++) {
				Row row = sheet.getRow(i); // 獲取行(row)對象
				if (row == null) {
					// row爲空的話,不處理
					continue;
				}
				String sqlvalue = "";
				for (int j = 0; j < 4; j++) {
					Cell cell = row.getCell(j); // 得到單元格(cell)對象
					// 將單元格的數據添加至一個對象 在sql中
					sqlvalue = sqlvalue + "'" + cell.toString() + "',";
				}
				sqlvalue = sqlvalue.substring(0, sqlvalue.length() - 1);
				String sql = "insert into USERTEMP(ID,NAME,CARDTYPE,CARDNO,STATUS) values(SEQ_USERTEMP.NEXTVAL,"
						+ sqlvalue + ")";
				dataList.add(sql);
				excelImportResult.setResultList(dataList);
				excelImportResult.setResultFlag(1);
			}
		} else {
			excelImportResult.setErrorMsg(result);
			excelImportResult.setResultFlag(0);
		}
		return excelImportResult;
	}

④存儲過程當中的,在loop循環中繼續下一次循環,怎麼作?至關於Java中的continue。

?????


⑤獲取Excel文件:

jsp頁面上傳文件:

                        <tr>
	                   <td>
	                	<div class="file_down">
	                	    <input name="file" type="file" id="file" style="width:90%"/>
	                	</div>
	                   </td>
			</tr>

後臺能獲取到一個:

UpLoadFile upLoadFile

public class UpLoadFile{
	//文件  二進制
	protected MultipartFile	file;
	protected String		busiAlias;
	protected Long			busiId;
	protected String		description;
	protected Long			categoryId;
	protected Long			upLoadStaffId;
	protected String		ifDown;
}

這樣就能獲得Excel文件MultipartFile。

相關文章
相關標籤/搜索