2012年8月9日 星期四

匯入 EDI 檔案到 DataStore

在台灣寫程式常常會需要使用到其他公司的資料交換,而大部份的合作夥伴都很多都會使用EDI檔案傳遞,因此處理EDI檔案就成了家常便飯,但有時候又不想要遇到一個專案就要再寫一次,所以幾乎都將它轉成PFC來使用。

上一次提到了 EDI 轉出 Function,所以這次來看看轉入EDI檔案的 Function怎麼做吧。

Function 名稱:f_edi2ds
回傳值:Long
傳遞參數:ads_dest[datastore][refrence]、as_file[string][readonly]、as_error[string][refrence]

/* 將ED文字檔(as_file)I匯入到 DataStore(ads_dest) EDI切割模式依照 dataObject 的 column.limit 訂定的長度 */ Integer li_ColCount,li_Pos,li_Col,li_file Long ll_collimit[],ll_rc,ll_totl,ll_cc,ll_new String ls_colname[],ls_coltype[],ls_data,ls_val,ls_date,ls_time Datetime ldt_1 boolean lb_fin //檔案存在否? IF not FileExists(as_file) THEN Return -1 //DataStore存在否? IF isnull(ads_dest) OR not isValid(ads_dest) THEN Return -1 END IF //欄位存在否? li_ColCount = integer(ads_dest.Describe("datawindow.column.count")) IF li_ColCount <= 0 THEN Return -1 ll_totl = 0 //取得欄位屬性 FOR li_Col=1 TO li_ColCount ls_colname[li_Col] = ads_dest.Describe("#" + string(li_Col) + ".Name") ll_collimit[li_Col] = Integer(ads_dest.Describe("#" + string(li_Col) + ".Edit.Limit")) //合計欄位總長度 ll_totl += ll_collimit[li_Col] ls_coltype[li_Col] = lower(ads_dest.Describe("#" + string(li_Col) + ".ColType")) //排除括弧字元 li_Pos = Pos(ls_coltype[li_Col] , "(") IF li_Pos > 0 THEN ls_coltype[li_Col] = Left(ls_coltype[li_Col] , li_Pos - 1) END IF NEXT //開啟檔案(以LinMode讀取) li_file = FileOpen(as_file , LineMode! , Read! ,LockReadWrite!) IF li_file <= 0 THEN Return -2 ll_cc = 0 //逐行讀取 do while fileRead(li_file , ls_data) >= 0 //行數計數 ll_cc ++ //筆對長度 IF len(ls_data) < ll_totl THEN as_error += "第" + String(ll_cc) + "行長度過少:" + String(len(ls_data)) +& "<" + String(ll_totl) + "~r~n" Continue END IF //新增一筆ROW到DataStore ll_new = ads_dest.InsertRow(0) li_pos = 1 //定位歸0 lb_fin = true //錯誤標記歸0 FOR li_col = 1 TO li_ColCount //讀取指定位置範圍字串 ls_val = MidA(ls_data ,li_pos , ll_collimit[li_Col]) //依照欄位類型轉換 Choose Case ls_coltype[li_Col] Case "char" //文字 IF trim(ls_val) = "" THEN SetNull(ls_val) ads_dest.SetItem(ll_new , li_col , ls_val) Case "datetime" //日期時間 IF trim(ls_val) <> "" THEN ls_date = left(ls_val,4)+"/"+mid(ls_val,5,2)+"/"+mid(ls_val,7,2) IF not isDate(ls_date) THEN as_error += "第"+String(ll_cc)+"行,位置:"+String(li_pos)+",長度:"+& String(ll_collimit[li_Col])+"無法轉換Datetime~r~n" lb_fin = false EXIT END IF ls_time = left(mida(ls_val , 9)+"000000",6) ls_time = left(ls_time,2)+":"+mid(ls_time,3,2)+":" +mid(ls_time,5,2) IF not isTime(ls_time) THEN as_error += "第"+String(ll_cc)+"行,位置:"+String(li_pos)+",長度:"+& String(ll_collimit[li_Col])+"無法轉換Datetime~r~n" lb_fin = false EXIT END IF ldt_1 = Datetime(date(ls_date),time(ls_time)) ELSE SetNull(ldt_1) END IF ads_dest.SetItem(ll_new , li_col , ldt_1) Case "date" //日期 IF trim(ls_val) <> "" THEN ls_date = left(ls_val,4)+"/"+mid(ls_val,5,2)+"/"+mid(ls_val,7,2) IF not isDate(ls_date) THEN as_error += "第"+String(ll_cc)+"行,位置:"+String(li_pos)+",長度:"+& String(ll_collimit[li_Col])+"無法轉換Date~r~n" lb_fin = false EXIT END IF ELSE SetNull(ls_date) END IF ads_dest.SetItem(ll_new , li_col , Date(ls_date)) Case "time" //時間 IF trim(ls_val) <> "" THEN ls_time = left(ls_val+"000000",6) ls_time = left(ls_time,2)+":"+mid(ls_time,3,2)+":"+mid(ls_time,5,2) IF not isTime(ls_time) THEN as_error += "第"+String(ll_cc)+"行,位置:"+String(li_pos)+",長度:"+& String(ll_collimit[li_Col])+"無法轉換Time~r~n" lb_fin = false EXIT END IF ELSE SetNull(ls_time) END IF ads_dest.SetItem(ll_new , li_col , Time(ls_time)) Case "long" ,"ulong" //整數 IF trim(ls_val) = "" THEN SetNull(ls_val) END IF ads_dest.SetItem(ll_new , li_col , long(ls_val)) Case "decimal" //數值 IF trim(ls_val) = "" THEN SetNull(ls_val) END IF ads_dest.SetItem(ll_new , li_col , dec(ls_val)) Case "real" //浮點數 IF trim(ls_val) = "" THEN SetNull(ls_val) END IF ads_dest.SetItem(ll_new , li_col , real(ls_val)) End Choose //定位點移到下一個指定位置 li_pos = li_pos + ll_collimit[li_Col] NEXT //處理錯誤跳出,未完成者取消此筆ROW IF lb_fin = false THEN ads_dest.rowsDisCard(ll_new , ll_new , Primary!) END IF loop //關閉檔案 FileClose(li_file) //回傳處理行數 Return ll_cc
與之前轉出EDI作法有點不一樣的地方,是在於取得 DataObject 的 DataWindow 欄位屬性時,我直接使用了幾個陣列(ll_collimit[]、ls_colname[]、ls_coltype[])來儲存,上次是使用一個structure來儲存,結果是相同,寫法不同,可以提供一個比較參考。

其次,這次轉入EDI檔案時欄位長度的參考,我是設計在每個欄位的 Edit.Limit 上,所以這個Function 使用時只要設計好 DataWindow 的模型就很好用了。

其次,使用上需要特別注意的地方是[日期時間]、[日期]、[時間]的轉換方式,我的設計上是假設EDI上的欄位日期是西元年的 YYYYMMDDHHMMSS 的格式的,所以 Datetime
欄位的 Limit 可以設定 8、10、14、16碼的,怎麼說呢?

假設日期欄來源資料為 YYMMDDHHMM的話,後面SS會自動補上00
例如:201208091325 -> 20120809132500 -> 2012/8/9 13:25:00
例如:2012080913 -> 20120809130000 -> 2012/8/9 13:00:00
如此可以簡化不少操作

倘偌需要更多格式的日期轉換就需要改寫轉換規則就可以了。

0 個回應: