PowerBuilder 採用 **事件驅動** 模型:每個物件 (應用程式、視窗、控制項、DataWindow) 擁有預定義事件 (Open、Close、Clicked、ItemChanged...),開發者在對應事件中編寫 **腳本** (Script) 實作業務邏輯。
-- 1. 從 PB.INI 讀取資料庫連線參數
SQLCA.DBMS = ProfileString("PB.INI", "Database", "DBMS", "")
SQLCA.DBParm = ProfileString("PB.INI", "Database", "DBParm", "")
-- 2. 開啟登入視窗
Open(w_login)
**關鍵點**:`SQLCA` 為全域預設交易物件,`ProfileString` 讀取 INI 檔區段/鍵值,第三參數為預設值。
IF Upper(Trim(sle_1.Text)) = "MYPASSWORD" THEN
Open(w_main)
Close(w_login)
ELSE
sle_1.SetFocus()
END IF
**解析**:`Upper`/`Trim` 正規化輸入,硬編碼密碼僅供教學,實務應查詢資料庫驗證雜湊值。
CONNECT; -- 建立資料庫連線
dw_list.SetTransObject(SQLCA); -- 列表綁定交易物件
dw_list.Retrieve(); -- 執行關聯 SQL,填充資料
dw_detail.SetTransObject(SQLCA); -- 詳細綁定交易物件
INTEGER li_row, li_number
li_row = dw_list.GetClickedRow() -- 取得點擊列號
IF li_row = 0 THEN
MessageBox("提示", "非有效記錄列,請關閉後點選有效列")
ELSE
li_number = dw_list.GetItemNumber(li_row, 1) -- 第 1 欄為編號
dw_detail.Retrieve(li_number) -- 以編號為檢索參數
END IF
**深度解析**:`GetClickedRow()` 回傳 0 表示點擊非資料區 (標題/空白);`GetItemNumber(行, 列)` 取得數值欄位;`Retrieve(參數)` 對應 DataWindow 物件定義的檢索引數。
dw_detail.Reset() -- 清除現有資料/篩選/排序狀態
dw_detail.InsertRow(0) -- 在第 0 位置 (末尾) 插入新列,進入編輯模式
dw_detail.DeleteRow(0) -- 刪除當前列 (緩衝區),尚未寫入資料庫
IF dw_detail.Update() = 1 THEN
COMMIT; -- 提交交易,資料庫持久化
dw_list.Retrieve(); -- 重新查詢列表,保持雙邊同步
ELSE
ROLLBACK; -- 回滾,資料庫恢復更新前狀態
END IF
**關鍵**:`Update()` 回傳 1 表示成功;`COMMIT`/`ROLLBACK` 作用於 `SQLCA` 交易範圍。
Close(Parent) -- 關閉包含此按鈕的父視窗 (w_main),應用程式結束
| DataWindow 物件 | 來源類型 | 關鍵定義 | 腳本關聯點 |
|---|---|---|---|
| `d_list` | Quick Select (Grid) | 欄位:Number, Name, Phone 排序:Number 遞增 | `dw_list.Retrieve()` 無參數 |
| `d_detail` | SQL Select (Freeform) | 全欄位 + 檢索參數 `number_search` (Number 型別) WHERE `Number = :number_search` 排序:Number 遞增 | `dw_detail.Retrieve(li_number)` |
| 錯誤現象 | 可能原因 | 解決方案 |
|---|---|---|
| 執行時 `SQLCA` 連線失敗 | PB.INI 路徑錯誤、DBParm 格式不符、ODBC DSN 未建立 | MessageBox 列印 `SQLCA.DBMS`/`DBParm`,用 ISQL 測試連線 |
| `dw_list.Retrieve()` 無資料 | SQL 語法錯誤、表無資料、交易物件未 SetTransObject | DataWindow Painter → Preview 測試 SQL,檢查 `SQLCA.SqlCode` |
| 主從聯動不生效 | `GetClickedRow()` 邏輯錯、檢索參數名稱/型別不符 | 檢查 `d_detail` 參數定義:名稱 `number_search`、型別 Number |
| `Update()` 回傳 -1 | 主鍵衝突、外鍵違反、觸發器錯誤、資料型別不符 | 檢查 `SQLCA.Sqldbcode`、`SQLCA.Sqlerrtext`,啟用 SQL 追蹤 |
| 關閉應用程式殘留進程 | 未正確 `DISCONNECT` 或 `DESTROY SQLCA` | Application Close 事件加 `DISCONNECT; DESTROY SQLCA` |
-- 更新按鈕增強版:詳細錯誤回饋
IF dw_detail.Update() = 1 THEN
COMMIT;
dw_list.Retrieve();
MessageBox("成功", "資料已更新")
ELSE
ROLLBACK;
MessageBox("失敗", "錯誤碼: " + String(SQLCA.SqlCode) + "~n" + SQLCA.Sqlerrtext)
END IF
-- 刪除前確認對話框
IF MessageBox("確認", "確定刪除此記錄?", Question!, YesNo!) = 1 THEN
dw_detail.DeleteRow(0)
-- 此處不立即 Update,待使用者按更新按鈕統一提交
END IF
下一節 (2-5) 將講解第二個視窗物件建立完整流程:視窗設計、DataWindow 控制項佈局、屬性設定、物件關聯、預覽與儲存。