2020 聖誕快樂
DataWindow 在程式運行的時候還是可以調整的,就好像勾上了的就全行變顏色,或者在打印前調一下行高欄闊,又或者是更新哪個表、哪個欄位之類,所有東西都能在這裏查到:New\Tool\DataWindow Syntax。
2020 聖誕快樂
DataWindow 在程式運行的時候還是可以調整的,就好像勾上了的就全行變顏色,或者在打印前調一下行高欄闊,又或者是更新哪個表、哪個欄位之類,所有東西都能在這裏查到:New\Tool\DataWindow Syntax。
明天就是平安夜了,各位萬事小心,別一不小心就升級為父母1.0 哦~
OpenWithParm() 用於打開窗體的時候,把變量也傳給它,只能傳一個,但你可以把多個拼成一串的傳進去,例如「公司名|單號|SOXXXXXX」,然後在目的窗體的 open event 裏面做分拆處理。
// 用於一般窗體
Datawindow 可以讓你設定 retrieve argument,有多少個或類型是什麼都需要預先寫死,在retrieve 的時候一個都不能少,沒彈性可言,但有方法改變這現實嗎?當然有,不然我提這個幹嘛?
方法是這樣的:
還是圖比 SQL 好看,弄成圖了:
前一篇已經把檔案寫到數據庫中了,那要怎麼下載呢?這裏簡單說一說。
1. 在PB 中定義 Blob 變量
Blob lblob_file
2. 以 SelectBlob 把 Binary 存到 blob 中
有時候用戶會希望把文件例如 jpg、pdf 等等上傳到系統中,作為對電腦數據的依據,這次聊聊怎麼上傳檔案。
上傳檔案基本有兩種方式,一是以檔案模式上傳到 file server ,二是以 Binary 模式寫到數據庫中,各有長短。前者需要另建 file server,也就是需要額外的支出,但由於是以文件是以檔案格式儲存,後台直接用 Windows 的檔案總管就可以打開;後者則把文件寫到原有數據庫中,不必另購,但這會導致數據庫體積變大,增加了備份時間和對硬盤空間的要求,而且由於是以 binary 形式儲存,需要另外加工還原成檔案才能使用。沒有最好的方案,只有最適合的方案,各適其適。就個人經驗所限,這次只能聊聊怎麼寫到數據庫中了。
在 PB 裏,用以儲存 Binary 的變量類型叫 Blob(Binary Large Object),可以儲存 word, excel, email 和圖片之類的東西,把它們轉化成 Binary 後就可以寫到變量中,再更新到數據庫了。
上傳步驟如下:
為了連接多個數據庫,我們可能需要好幾個Transaction Object,但每一個都預先寫到代碼裏面嗎?這樣彈性就不夠大了,我們可以一開始就先把它們寫到緩存中,適時調用。注意要養成用完就斷開連接的好習慣。
思路大概如下:
這裏提供個另建 Transaction Object 的例子,PB 內使連接數據的話,一般都默認是使用 SQLCA 的,所以如果是另建的話呢,你都需要以「using <transaction>」或「DW.SetTransobject(<transaction>)」去指定 Transaction。什麼情況下需要另建呢?比方說連入權限管理數據庫檢查密碼、取得權限設定,或連上其他系統的數據作比較等等。
// 定義 Transaction
transaction ltr_obj
Transaction Object 保存所有連接數據庫的參數並用以連接數據庫。其實只要在開發環境把參數設好,PB 就已經替你把腳本拼出來了,只要在「Preview」中拷貝到你的程序中就可以使用了,連接時記得要加上 connect using sqlca 啊。
SPID 全稱Server Process ID,是當前連接 MS SQL Server 的唯一識別碼,每次連接都會分派一個新的 spid 給你,通過spid 就可以查到程序目前在數據庫的狀態了。
這句可以查到數據庫中當前的所有任務,找出死鎖,blocked > 0 的就是被鎖了:
select * from sysprocesses
在程序裏很多的動作或事件我們都會想記錄下來以作日後檢查之用,很多人一看到「時間」兩個字就會想起Windows 右下角的系統時間,並打算把這時間記到數據庫中,這想法是危險的,為什麼呢?因為每台電腦的系統時間基本都各不同,所以這時間在查案時並不可靠。
更有參考價值是更新數據庫那一刻的時間,所以取「數據庫」時間才是可靠而且統一的,就算你說它的時間也不一定對呀,但起碼它對事件發生的「時間順序」還是準確的。
除了在數據表中以 Trigger 填充日期外,你也可以在 PB 中這樣從數據庫取時間:
Datatime ldt_now
變量命名規範化是件很重要的事情,最好能在程序開發前就定好規範,往後不管是老同事還是新入職的新同事,大家都要遵從命名規範去做,這有助於同事間的溝通,也方便日後在編碼上互想支持,讓大家一看就知道它的特性和用途。在控件名命方面,PowerBuilder 已經有所建議了,你可以從 PB 裏打開下面的畫面以作參考。
PowerBuilder 裏的變量主要分成三類,Local Variable、Instance Variable、Global Variable,Local Variable 只能在當前頁的代碼中使用,Instance Variable 就是在當前視窗的所有 event、function 中都可用,Global Variable 就是在整個程序中都可用。對於這三類,我的命名習慣是這樣的,以 string 為例,ls_value 是 local string,is_value 是 instance string,你已經猜到了吧? gs_value 就是 global string 了,這樣就一目了然,方便易明了。
INI 就是設定檔,做設定用的,通常會保存數據庫設定,以下面為例,它保存了程序名、循環時間、是否自動啓動、讀寫路徑之類,你想放什麼都行。
------ 我是分隔線 ------
[MAIN]
NAME=File Distributor - SAP EDI migration
string ls_value -- 這能存一個值
string ls_array[] -- array,列陣、數組,這能存多個單一類型的值
Structure 是一個能存放多種類型的變量(variable) ,主要用於需要同時「傳遞」多個值時使用。如果只是在同一段代碼裏面需要用到多個值的話,直接用 select... into... 就可以了,Structure 主要用於「傳遞」,或者作為 instant 或 global variable 使用。
Function 的 output 只能選一個,沒什麼好說的,但 input 有 Pass by value 和 Pass by reference 兩種,我們就來說一下它們有什麼差異。
Pass by value 最簡單,你 'Hello' 傳給 Function ,Function 就會接收到 'Hello' ,並把它放進下圖的 as_string 中,是個「值」的傳遞,跟外部不關連。
Pass by reference 傳的是「指標」,是個指着某個變量的指標,與調用該 function() 的外部關連,外面必須有個相同類型的變量,用以保存它在 function() 內的變化。意思就是說,不管 as_array[] 在裏面變成怎麼樣,外面的 array 也會變成怎麼樣,因為它們根本是同一個東西,這就剛好解決了前面說只能有一個 output 的問題了。
PowerBuilder 裏面比較常接觸到的有兩種 Function ,讓你可以把代碼打包起來不斷重複調用,不必每次重寫差不多的代碼。Functions 又叫 User-defined function 就是通用的,在整個程式裏都可以調用,Window function 就是限於在當前 Window 裏可用。
Function 就是整個系統都可以調用的通用代碼,由於是希望儘量通用,所以在寫的時候就要考慮到未來的各種可能性,比方說 input 什麼,output 又是什麼之類的,例子有:
PowerBuilder 提供了最基本的信息盒,但如果都在代碼裏面直接使用的話,那就難以支持多語言、沒彈性、用字也不易統一,因為不同程式員會有不同的習慣,可能 A 程式員用「請問需要儲存嗎?」,B 程式員卻問「是否要保存?」,這讓用戶體驗不好,後續也難以維護。
為了改良以上的問題,我們可以在調用 MessageBox() 前多加點功夫。過程中需要:
既然在前面提過「繼承」,我還是先說一下繼承好了。「繼承」就是所有子孫都能繼承祖先的所有代碼,不需另外再寫,可以擴展,也可以停用。
以下圖為例,一個 Window,內含三個 datawindow control 加一堆按鈕,每個控件裏面都寫好一堆相應的代碼,以後從它繼承出來的新 Window 就可以直接使用所有的控件和代碼了。不止 Window ,其他如 datawindow、按鈕之類的控件也可以有同樣的做法,在開發前期先寫好「祖先」,而同一套「袓先」也可以套用到往後開發的其他系統,這可以為未來的開發省下很多的時間。
近來所開發的系統都需要面對來自五湖四海的用戶,所以系統都需要提供多語言的界面,讓用戶選擇他想要的。這裏我就簡單說個思路,讓大家考一下。
思路如下: