將Datawindow資料存出成EDI檔案
PowerBuilder 的 DataWindow 本身可以將資料存成許多種格式,但偏偏就是缺了一種格式--EDI (Eletronic Data Interchange)--
這種格式在台灣是早期非常普遍的格式,詳見維基百科、經建會-解釋「通關作業XML電子資料交換格式」與EDI格式,主要多是公家機關使用,舉凡報稅、金融皆是使用此一格,久而久之就變成了早期台灣電腦最普遍的資料交換檔案格式。
這個格式的特色是每個欄位呈現在文字檔案中都有指定的長度(位元數),各欄位資料之間無分隔符號。所以每個ROW DATA呈現成一串字串,每個ROW字串的長度完全一樣。當然,這種格式的優缺點並非這篇的重點,所以這裡就不討論。
例如:
假設 CSV 格式的資料如下
而轉成 EDI 格式就可能如此
所以若要將DataWindow的資料輸出成為EDI的格式,就需要一點技巧了
因此我們設計一個Function,讓它可以自動幫我們存成所需要的EDI格式
先定義一個 Function 名稱 f_ds2edi
迴傳一個 Long 值
參數兩個:ads_process[datastore][reference]、as_filename[string][value]
照此SCRIPT來實做,要注意的是傳入的 DataStore 設計,該 Function 輸出的欄位順序是 DataStore 的 SQL 裡面定義的欄位順序,並非 painter (設計版面)上設計的欄位排列順序。
另外,每個欄位輸出的長度是定義在每個欄位 properties 裡面 Edit屬性中的 Length ,數值型態的資料欄位輸出也是依照此長度產生,數值欄位特別要注意小數點,因為小數點佔用一個 byte 輸出。如果 length 設定成 0 則該欄位不會輸出任何資料(包含空白)。
這個 SCRIPT 能處理的欄位型態(Data Type)為三種: char、date(包含Date、DateTime)、Number(包含Lont、Integer、Decimal、UnsignedLong、UnsignedInteger......)。
如果需要增加處理資料型態的方式,就要自己增加程式規則了。這一部分可以依照個人資料庫特性結構去調整,你可以把它寫得很完備,並包入PFC中。不過,依照我的作法並不會這樣做,原因在於EDI接收對象的不同,你需要調整的輸出就很多。
就如日期這個欄位來比喻吧。
如果你輸出的資料是要給公家機關(政府機關),就有可能會是 yyy.mm.dd (這個yyy還是民國年!一般的 Convert Format 不會認得這個格式),年、月、日中間要有個『‧』,但是部分機關的格式就不可以有這個『‧』;然若是給銀行的就是標準的 yyyymmdd ,所以這樣輸出差異頗大的,若要做成 PFC 確實可用性就可議了。
另一個變化比較大的就是數值欄位了
例如有的程式接收數直欄位時必須是像 『0000123』 或也有像『 123』這樣的格式,或是『123 』這樣的格式,所以這種欄位也混因為需求不同而發生調整。
所以依照你要輸出對象單位的 EDI 檔案格式來調整這個 Function Script 才是比較實用的方式。
這種格式在台灣是早期非常普遍的格式,詳見維基百科、經建會-解釋「通關作業XML電子資料交換格式」與EDI格式,主要多是公家機關使用,舉凡報稅、金融皆是使用此一格,久而久之就變成了早期台灣電腦最普遍的資料交換檔案格式。
這個格式的特色是每個欄位呈現在文字檔案中都有指定的長度(位元數),各欄位資料之間無分隔符號。所以每個ROW DATA呈現成一串字串,每個ROW字串的長度完全一樣。當然,這種格式的優缺點並非這篇的重點,所以這裡就不討論。
例如:
假設 CSV 格式的資料如下
黃小明,1978/3/2,台中市中山路120號,0922-222-113,15 李大海,1970/12/14台北市忠孝東路三段41號8樓-5,02-12345678,23
而轉成 EDI 格式就可能如此
黃小明19780302台中市中山路120號 0922-222-113 SIMON 15 李大海19701214台北市忠孝東路三段41號8樓-5 02-12345678 DAVID CHAU 23
所以若要將DataWindow的資料輸出成為EDI的格式,就需要一點技巧了
因此我們設計一個Function,讓它可以自動幫我們存成所需要的EDI格式
先定義一個 Function 名稱 f_ds2edi
迴傳一個 Long 值
參數兩個:ads_process[datastore][reference]、as_filename[string][value]
//////////////////////////////////////////////////////////////////////////////
// Arguments:
// ads_process - datastore for processing
// as_filename - file name for exprot
//////////////////////////////////////////////////////////////////////////////
// Returns: Long
// -1 : failue
// ll_NumsRow : the adding rows
//////////////////////////////////////////////////////////////////////////////
st_Column lst_Column[]
Integer li_NumsColumn, li_Pos, li_no
Long ll_NumsRow, ll_Row
String ls_Value
Integer li_FileNum
String ls_LineWrite
Long ll_RecNum
// Open text file
li_FileNum = FileOpen(as_filename, LineMode!, Write!, LockWrite!, Replace!)
IF li_FileNum = -1 THEN
RETURN -1
END IF
// Set default column's expression
li_Pos = 1
li_NumsColumn = Integer(ads_Process.Object.Datawindow.Column.Count)
FOR li_no=1 TO li_NumsColumn
lst_Column[li_no].name = ads_Process.Describe("#" + string(li_no) + ".Name")
lst_Column[li_no].coltype = ads_Process.Describe("#" + string(li_no) + ".ColType")
lst_Column[li_no].pos = li_Pos
lst_Column[li_no].len = Integer(ads_Process.Describe("#" + string(li_no) + ".Edit.Limit"))
li_Pos += lst_Column[li_no].len
NEXT
// Read from text file
ll_NumsRow = ads_process.RowCount()
ll_RecNum = 0
FOR ll_Row = 1 TO ll_NumsRow
ls_LineWrite = ''
FOR li_no=1 TO li_NumsColumn
IF lst_Column[li_no].len > 0 THEN
IF left(lst_Column[li_no].coltype, 4) = 'char' THEN
ls_Value = ads_Process.GetItemString(ll_Row, lst_Column[li_no].name)
IF IsNull(ls_Value) THEN
ls_Value = Space(lst_Column[li_no].len)
ELSE
IF lst_Column[li_no].len > Len(ls_Value) THEN
ls_Value = ls_Value + Space(lst_Column[li_no].len - Len(ls_Value))
END IF
END IF
ELSEIF left(lst_Column[li_no].coltype, 4) = 'date' THEN
ls_Value = String(ads_Process.GetItemDateTime(ll_Row, lst_Column[li_no].name), 'yyyymmdd')
IF IsNull(ls_Value) THEN
ls_Value = Space(lst_Column[li_no].len)
ELSE
IF lst_Column[li_no].len > Len(ls_Value) THEN
ls_Value = Space(lst_Column[li_no].len - Len(ls_Value)) + ls_Value
END IF
END IF
ELSE
ls_Value = String(ads_Process.GetItemNumber(ll_Row, lst_Column[li_no].name))
IF IsNull(ls_Value) THEN
ls_Value = Space(lst_Column[li_no].len)
ELSE
IF lst_Column[li_no].len > Len(ls_Value) THEN
ls_Value = Space(lst_Column[li_no].len - Len(ls_Value)) + ls_Value
END IF
END IF
END IF
ls_LineWrite += ls_Value
END IF
NEXT
ll_RecNum++
FileWrite(li_FileNum, ls_LineWrite)
NEXT
// Close text file
FileClose(li_FileNum)
RETURN ll_RecNum
照此SCRIPT來實做,要注意的是傳入的 DataStore 設計,該 Function 輸出的欄位順序是 DataStore 的 SQL 裡面定義的欄位順序,並非 painter (設計版面)上設計的欄位排列順序。
另外,每個欄位輸出的長度是定義在每個欄位 properties 裡面 Edit屬性中的 Length ,數值型態的資料欄位輸出也是依照此長度產生,數值欄位特別要注意小數點,因為小數點佔用一個 byte 輸出。如果 length 設定成 0 則該欄位不會輸出任何資料(包含空白)。
這個 SCRIPT 能處理的欄位型態(Data Type)為三種: char、date(包含Date、DateTime)、Number(包含Lont、Integer、Decimal、UnsignedLong、UnsignedInteger......)。
如果需要增加處理資料型態的方式,就要自己增加程式規則了。這一部分可以依照個人資料庫特性結構去調整,你可以把它寫得很完備,並包入PFC中。不過,依照我的作法並不會這樣做,原因在於EDI接收對象的不同,你需要調整的輸出就很多。
就如日期這個欄位來比喻吧。
如果你輸出的資料是要給公家機關(政府機關),就有可能會是 yyy.mm.dd (這個yyy還是民國年!一般的 Convert Format 不會認得這個格式),年、月、日中間要有個『‧』,但是部分機關的格式就不可以有這個『‧』;然若是給銀行的就是標準的 yyyymmdd ,所以這樣輸出差異頗大的,若要做成 PFC 確實可用性就可議了。
另一個變化比較大的就是數值欄位了
例如有的程式接收數直欄位時必須是像 『0000123』 或也有像『 123』這樣的格式,或是『123 』這樣的格式,所以這種欄位也混因為需求不同而發生調整。
所以依照你要輸出對象單位的 EDI 檔案格式來調整這個 Function Script 才是比較實用的方式。
留言