You are on page 1of 34

3-1 事 件 內 容 及 順 序

本 章 重 點 是 表 單 、 報 表 、 控 制 項 等 可 使 用 之 事 件 ,「 事 件 」 是 物
件 導 向 設 計 的 中 心 觀 念 , 且 事 件 是 Access 應 用 系 統 的 核 心 , 大 部 份
的細部處理,使用事件會方便許多,所以事件是設計人員不可不知的
部份。

3-1-1 何 謂 事 件

「 事 件 」 之 英 文 原 名 為 Event , 也 是 物 件 導 向 設 計 不 可 缺 少 的 重
要工具,它是系統定義的自發性動作,如讀者在表單上建立一個按
鈕,目的是讓使用者在按下此鈕執行指定功能,則在此按鈕按下左鍵
的 動 作 , 可 啟 動 該 按 鈕 的 「 Click 」 事 件 。 啟 動 此 事 件 後 , 系 統 會 至
此 事 件 相 對 應 的 屬 性 , 即 「 OnClick」 內 尋 找 有 無 定 義 巨 集 或 程 序 ,
若有則執行之,無則略過。

在 以 上 的 例 子 中 ,「 C l i c k 」 是 事 件 , 而 「 OnClick」 則 可 謂 之 「 事
件 屬 性 」。 二 者 是 相 對 應 的 , 但 也 有 事 件 及 事 件 屬 性 同 名 , 如
AfterUpdate 或 BeforeUpdate 等 。
所以每一事件皆對應至一個屬性,讀者可在屬性表內找到這些屬
性 , 所 有 以 「 O n」、「 After」、「 Before」 開 頭 者 , 皆 為 事 件 屬 性 , 這 些
屬性都代表一個事件,而每一事件之啟動時機皆不同。藉由這些屬
性,讀者可為使用者在不 同情況時,定義所需之控制及執行動作。

以較專業的說法而言,只要是物件,就會有事件。而在表單或報
表設計視窗中,可以被滑鼠選取者,如細部、表單本身、文字方塊或
每一控制項等皆可被選取,故以上所述皆為物件,各自又有不同之事
件。

<<說 明 > >


以下是事件與事件屬性之特色:

l 三 種 事 件 內 容 : 即 讀 者 可 使 用 巨 集 、 VBA( 程 式 碼 )、 運 算 式 等 建 立
事 件 發 生 時 , 執 行 之 動 作 , 如 圖 3- 1 :
圖 3- 1 定 義 事 件 內 容
除了三點按鈕外,箭頭按鈕則可開啟現用資料庫所有巨集的清
單 , 可 在 此 指 定 事 件 發 生 時 執 行 之 巨 集 。「 運 算 式 建 立 幫 手 」 則 表 示
可 使 用 所 有 Access 提 供 之 所 有 函 數 , 或 任 何 可 求 得 結 果 的 運 算 式 ,
但須在運算式前加上等號。

所以若事件屬性已使用程式碼,會顯示「事件程序」四字,若使
用巨集,則顯示巨集名稱。

l 各 事 件 之 順 序 :由於各事件之發生時機不同,且彼此間只有些許
差異,如表單有「 Open」及「 Load 」 事 件 , 皆 發 生 於 表 單 開 啟 時 ,
但順序不同。加上表單、報表、不同型態的控制項皆有各自的事
件,所以一個操作動作,由開始至結束,系統背後可能有多個事
件連續發生,這也是讀者定義事件內容的重點。

l 無 法 自 訂 事 件 :如前所述,各事件之名稱、發生時機等均為系統
定義,設計人員 無法定義事件,但可自訂使用於表單或報表的程
序 , 如 同 在 標 準 模 組 內 自 訂 Sub 或 Funtion 程 序 。

3-1-2 使 用 事 件 屬 性

在筆者的設計經驗中,幾乎針對表單及報表的控制功能,均寫在
事件程序內。此類程序除了其位置是在表單、報表、控制項內之外,
其 可 用 語 法 均 與 在 標 準 模 組 內 之 Sub 或 F u n t i o n 程 序 相 同 , 但 仍 有 下
列差異及注意事項:

l 不 可 更 改 名 稱:事件程序的名稱即為事件名稱,此名稱不可更改,
否 則 將 無 法 正 常 作 業 , 唯 一 可 更 改 的 是 刪 除 名 稱 前 的 「 Private」
字元,也就是將預設為私用的事件程序改為公用。

l 參 照 內 容 :由於事件程序是儲存在表單或報表內,且執行事件程
序時,該程序所在的表單或報表必定為執行中狀態,故參照至本
身 之 表 單 或 報 表 時 , 可 使 用 「 Me」。 但 在 標 準 模 組 的 程 序 內 , 則 不
可 使 用 M e,須由 Forms 或 Reports 群 體 取 出 Form 或 Report 物件,
再取出所需控制項。此點差異是因為執行程式時,外在環境不同
所致。

除了上述差異外,其他如語法、編輯視窗均相同。事實上,每一
表 單 或 報 表 均 可 視 為 一 個 模 組 , 型 態 為 類 別 模 組 , VisualBasic 編 輯 器
之專案總管視窗會顯示資料庫的兩類模組,分別是標準及類別,後者
指 的 就 是 已 使 用 VBA 的 表 單 及 報 表 。
表單及報表之類別模組之內又有多個程序,也就是對應於各事件
屬性的程序,只不過這些程序是固定的,無法如同標準模組,由讀者
自行定義須要多少程序。

在 Access 2000 中 , 撰 寫 程 式 均 在 Visual Basic 編 輯 器 內 , 讀 者 可


按 下 表 單 或 報 表 設 計 視 窗 工 具 列 之 按鈕、使用「檢視」→「程式碼」
選 項 及 在 屬 性 表 內 按 下 已 定 義 事 件 程 序 之 屬 性 右 方 的 按鈕等,皆可
進 入 Visual Basic 編 輯 器 , 如 圖 3- 2 :

圖 3- 2 在 Visaul Basic 編 輯 器 顯 示 物 件 及 事 件

圖 3- 2 的 狀 態 是 開 啟 「 Form_People 」 類 別 模 組 , 此 模 組 也 就 是
「 People 」 表 單 之 模 組 , 而 在 此 模 組 中 , 就 是 所 有 已 使 用 VBA 程 式
碼的事件程序。
圖 3- 2 顯 示 兩 個 下 拉 式 清 單 , 此 圖 是 合 成 圖 , 因 為 兩 個 下 拉 式 清
單不可能同時顯示,筆者目的是便於說明這兩個清單在模組中的作
用。左方清單的內容是表單或報表中的所有物件,也就是控制項,包
含 表 單 (Form) 及 報 表 (Report) 本 身 , 在 此 選 擇 任 一 物 件 後 , 右 方 清 單
會立即切換為該物件的所有可用事件名稱,任選一個事件後,即會顯
示該事件程序,表示可開始輸入程式。若一個事件已含有程式,其所
屬事件名稱在清單中會顯示為粗體,讀 者可依此原則判斷,那一事件
已輸入程式。

3-1-3 啟 動 時 機

這是使用事件的重點,首先說明各事件之發生時機及可使用之物
件 , 即 表 單 、 報 表 、 控 制 項 、 區 段 等 , 如 表 3- 1 :

事 件 (屬 性 ) 發生時機 使用位置

AfterDelConfirm 使用者在確認刪除之 表單
對話方塊內完成操作
時,不論是否真的刪除

AfterInsert 新增記錄後 表單
AfterUpdate 更新記錄後 表單及在表單上的結合
物件框、核取方塊、組合
方塊方塊、清單方塊、選
項按鈕、選項群組、文字
方塊、切換按鈕

BeforeUpdate 更新記錄前 同上
BeforeDelConfirm 刪 除 記 錄 時 , ACCESS 表 單
顯示對話方塊確認是
否 刪 除 前 ( 在 Delete 事
件前 )
BeforeInsert 輸入新記錄的第一字 表單
元時

OnActivate 表單或報表切換為作 表單、報表


用中視窗時

OnApplyFilter 使用篩選或移除篩選 表單
時(除 表 單 篩 選)
事 件 (屬 性 ) 發生時機 使用位置

OnChange 更改記錄內容時 在表單的組合方塊方


塊、文字方塊

OnClick 按下左鍵時 表單、表單區段、在表單


的結合物件框、圖表、核
取方塊、組合方塊方塊、
命令按鈕、標籤、清單方
塊 、 選 項按 鈕 、 選 項 群
組、矩形、文字方塊、切
換按鈕、非結合物件框
OnDblClick 按兩下左鍵時 同上

OnClose 關閉表單或報表並由 表單、報表


螢幕消失後

OnCurrent 切換至另一筆記錄或 表單
開啟表單時
OnDeactivate 當表單或報表由作用 表單、報表
中視窗切換至背景時

OnError 發生執行中錯誤時 表單、報表


OnDirty 在表單更改記錄時 表單
OnEnter 由同表單的另一控制 在表單的結合物件框、圖
項 獲 得 焦 點 前 (在 表、核取方塊、組合方塊
GotFocus 前 ) 方塊、命 令按鈕、清單方
塊、選項按鈕、選項群
組、子表單、文字方塊、
切換按鈕、非結合物件框

OnExit 焦點移至同表單的另 同上
一 控 制 項 ( 在 LostFocus
前)

OnDelete 刪除記錄前 表單
OnFilter 使用表單篩選時 表單

OnFormat 為區段內容設定列印 報表區段


格式前
事 件 (屬 性 ) 發生時機 使用位置

OnGotFocus 表單或控制項獲得焦 表單及在表單的結合物


點 件框、核取方塊、組合方
塊方塊、命令按鈕、清單
方塊、選項按鈕、文字方
塊、切換按鈕、非結合物
件框

OnLostFocus 表單或控制項失去焦 同上

OnKeyDown 按下某按鍵時 同上

OnKeyPress 按 下 可 轉 換 為 ANSI 碼 同 上
的按鍵時

OnKeyUp 放開某按鍵時 同上
OnLoad 開啟表單及顯示第一 表單
筆記錄後

OnOpen 表單或報表開啟後,第 表單、報表


一筆記錄顯示前

OnResize 開啟表單及改變視窗 表單
大小時
OnTimer 在指定時間之間隔重 表單
覆發生

OnUnload 關閉表單及由螢幕消 表單
失前

OnUpdated 更新 OLE 物 件 時 在表單的結合物件框、非


結合物件框
OnMouseDown 按下滑鼠任 意鍵 表單、表單區段、在表單
的結合物件框、圖表、核
取方塊、組合方塊方塊、
命令按鈕、標籤、清單方
塊、選項按鈕、選項群
組、矩形、文字方塊、切
換按鈕、非結合物件框

OnMouseMove 移動滑鼠至某控制項 同上

事 件 (屬 性 ) 發生時機 使用位置

OnMouseUp 放開滑鼠任意鍵 同上
OnNoData 列印報表前,某頁無資 報表
料可印時
OnNotInList 在組合方塊輸入資 表單的組合方塊
料,但此資料不在清單
內時

OnPage 格式化完成某頁報表 報表
及列印前

OnPrint 格式化完成某頁報表 報表區段


及 列 印 前 ( 在 Page 事 件
前)
OnRetreat 當區段無法列印於目 報表區段
前格式化的位置時,
ACCESS 會 將 其 向 前 移
動,尋找合宜的列印位
置,此一移動過程經過
的每一報表區段,均會
發生此事件

表 3- 1 各 事 件 啟 動 時 機

上 表 包 含 所 有 在 Access 2000 內 可 使 用 之 事 件 屬 性 , 僅 較 舊 版 新
增 OnDirty 事 件 , 多 數 均 使 用 於 表 單 及 其 控 制 項 , 以 下 是 不 同 操 作 動
作時,各事件的先後順序:

l 開 啟 表 單:O p e n (表 單 ) → L o a d (表 單 ) → Resize( 表 單 ) → Activate(表 單 )


→ Current( 表 單 ) → Enter( 第 一 個 擁 有 焦 點 的 控 制 項 ) → GotFocus( 第
一 個 擁 有 焦 點 的 控 制 項)

l 關 閉 表 單 : Exit(控 制 項 ) → LostFocus(控 制 項 ) → Unload( 表 單 ) →


Deactivate( 表 單 )→ Close(表 單 )

l 切 換 至 另 一 表 單 : Deactivate( 表 單 A )→ Activate( 表 單 B) → Click( 在


表單 B 的記錄選取器按一下左鍵 )

l 在 表 單 A 的 按 鈕 開 啟 表 單 B : Click( 表 單 A 的 按 鈕 )→ Open( 表 單
B)→ Load( 表 單 B )→ Current( 表 單 B )→ Click( 表 單 A 的 按 鈕 )

l 由 表 單 A 的 控 制 項 切 換 至 表 單 B 的 控 制 項:Exit( 表 單 A 之 控 制 項 )
→ LostFocus(表 單 A 之 控 制 項 )→ Deactivate( 表 單 A )→ Activate( 表
單 B) → Enter( 表 單 B 第 一 個 擁 有 焦 點 之 之 控 制 項 ) →
MouseMove( 表 單 B 第 一 個 擁 有 焦 點 之 控 制 項 ) → GotFocus( 表 單 B
第 一 個 擁 有 焦 點 之 控 制 項 )→ MouseDown( 表 單 B 第 一 個 擁 有 焦 點
之 控 制 項 ) → MouseUp(表 單 B 第 一 個 擁 有 焦 點 之 控 制 項 )→
Click(表 單 B 第 一 個 擁 有 焦 點 之 控 制 項 )

l 儲 存 更 改 後 記 錄 或 新 記 錄 : BeforUpdate( 控 制 項 )→ AfterUpdate(控
制 項 )→ BeforUpdate( 表 單 )→ AfterUpdate(表 單 )

l 儲 存 更 改 後 記 錄 或 新 記 錄 及 切 換 至 另 一 控 制 項: BeforUpdate(控 制
項 A) → AfterUpdate(控 制 項 A) → Exit( 控 制 項 A )→ LostFocus( 控 制
項 A) → Enter( 控 制 項 B )→ GotFocus(控 制 項 B)

l 儲 存 更 改 後 記 錄 或 新 記 錄 及 切 換 至 另 一 筆 記 錄: BeforUpdate(控 制
項 A) → AfterUpdate(控 制 項 A) → Exit( 控 制 項 A )→ LostFocus( 控 制
項 A) → Current( 表 單 ) → GotFocus( 另 一 記 錄 之 控 制 項 )

l 在 文 字 方 塊 更 改 資 料 : KeyDown → KeyPress → Change→ KeyUp

l 在 組 合 方 塊 輸 入 清 單 沒 有 的 資 料:KeyDown( 控 制 項 ) → KeyPress( 控
制 項 )→ Change(控 制 項 ) → KeyUp( 控 制 項 )→ NotInList( 控 制 項 ) →
Error(表 單 )

l 切 換 至 新 記 錄 及 輸 入 資 料 : Current( 表 單 ) → Enter( 控 制 項 )→
GotFocus ( 控 制 項 ) → OnDirty( 表 單 )→ BeforeInsert(表 單 ) →
AfterInsert( 表 單 )

l 刪 除 記 錄 : Delete → BeforDelConfirm→ AfterDelConfirm

l 在 控 制 項 上 按 兩 下 左 鍵 : MouseDown → MouseUp→ Click→ DblClick


→ MouseUp

l 使 用 選 取 篩 選 或 移 除 篩 選 : ApplyFilter

l 使 用 表 單 篩 選 : Filter → ApplyFilter

l 開 啟 、 預 覽 及 關 閉 報 表 : Page( 報 表 ) → Open( 報 表 )→ Activate( 報 表 )


→ Format( 報 表 區 段 )→ Print( 報 表 區 段 ) → Close( 報 表 ) →
Deactivate( 報 表 )

<<結 論 > >


所以一個操作動作在系統背後,是不斷啟動事件的過程,設計人
員開發所需功能時,須先設想使用者的操作動作,會引發那 些 事 件 ,
再 於 適 當 的 事 件 使 用 巨 集 或 VBA。
3-2 事 件 詳 解
各事件皆有其發生時機,讀者可在需要的事件內定義欲執行的動
作,但有些事件除了系統已定義的程序名稱外,尚有該事件發生時,
一併傳回至該事件程序的引數,這些引數在不同程序內亦有不同意
義,以下將以事件特性為分類,說明各事件程序之使用方式。

3-2-1 鍵 盤

與 鍵 盤 有 關 的 事 件 共 有 KeyPress、KeyUp、KeyDown 等 三 者 , 可
使用在表單及多數控制項,但以使用於控制項之情況居多。功能為判
斷 使 用 者 按 下 之 按 鍵 為 何 , 其 中 KeyPress 只 可 判 斷 ASCII 碼 , 餘 二
者 皆 為 以 按 鍵 傳回 之 常 數 為 判 斷 依 據 。

檢查使用者按下之按鍵
KeyDown 及 KeyUp 事 件 皆 有 一 個 KeyCode 引 數 , 讀 者 可 使 用 此
引 數 , 判 斷 使 用 者 按 之 按 鍵 為 何 , 如 圖 3- 3 :

圖 3- 3 使 用 KeyCode 引 數

圖 3- 3 是 Ch3 \3- 2\Key.mdb 檔 案 中 的 「 客 戶 」 表 單 , 在 此 圖 的


KeyDown 事 件 中 , 筆 者 以 KeyCode 引 數 傳 回 值 , 判 斷 使 用 者 按 下 之
按鍵,再分別執行不同程式。

但須注意的是每一控制項及表單本身皆有三個與鍵盤有關的事
件 , 預 設 值 只 會 啟 動 控 制 項 的 鍵 盤 事 件 。 而 在 圖 3- 3 的 例 子 中 , 筆 者
目 的 是 在 表 單 攔 截 使 用 者 按 下 的 功 能 鍵, 此 時 可 將 表 單 的 KeyPreview
屬 性 設 為 「 是 」, 即 可 在 表 單 的 鍵 盤 事 件 進 行 攔 截 。

所 以 使 用 KeyCode 引 數 之 目 的 是 判 斷 使 用 者 按 下 之 按 鍵 為 何 , 各
常 用 按 鍵 之 傳 回 值 如 表 3- 2:

按鍵 傳回值 按鍵 傳回值

0至 9 48- 57 Enter 13
A至 Z 56- 90 PageUp 及 33、 34
PageDown
F1 至 F12 112- 123 空白鍵 32
左右上下 37、 39 、 38 、 4 0 Tab 9
等方向鍵

Del 46 Home 及 End 36、 35

Esc 27 Insert 45

表 3- 2 常 用 按 鍵 之 KeyCode 引 數 傳 回 值

除 如 上 表 之 數 字 外 , 讀 者 也 可 使 用 常 數 , 均 以 「 vbKey」 開 頭 ,
如 A 鍵 的 常 數 為 「 vbKeyA」 、F1 鍵之常數為「 vbKeyF1 」等,但 Enter
鍵 的 常 數 為 「 vbKeyReturn」, 不 是 「 vbKeyEnter」, 讀 者 可 使 用 「 檢
視」→「物件瀏覽 」選項,在此查看上述之鍵盤常數。

<<說 明 > >

故 每 次 按 下 按 鍵 時 , 系 統 都 會 啟 動 KeyDown 及 KeyUp 事 件 , 筆
者 通 常 會 在 這 兩 個 事 件 的 第 一 行 使 用 KeyCode 引 數 , 判 斷 按 下 之 按
鍵 為 何 , 只 有 按 下 某 按 鍵 時 , 方 執 行 判 斷 式 以 下 的內 容 , 否 則 若 未 判
斷 KeyCode, 則 每 次 按 下 按 鍵 後 , 均 將 執 行 事 件 程 序 之 內 容 。 讀 者 可
依 此 角 度 , 在 KeyDown 及 KeyUp 事 件 設 計 所 需 功 能 。

在 文 字 方 塊 的 KeyUp 篩 選 清 單 方 塊
在 筆 者 的 多 數 經 驗 中 , 均 使 用 KeyDown 事 件 , 較 少 使 用 KeyUp ,
二 者 差 別 是 KeyDown 會 發 生 在 每 次 按 下 按 鍵 時 , KeyUp 則 發 生 在 按
下 及 放 開 按 鍵 後 。 所 以 在 KeyDown 事 件 中 無 法 取 得 輸 入 之 字 元 ,
KeyUp 則 可 , 如 圖 3- 4 :
圖 3- 4 使 用 KeyUp 事 件

圖 3- 4 是 Ch3 \3- 2\Key.mdb 之 「 員 工 」 表 單 中 ,「 城 市 」 文 字 方 塊


的 KeyUp 事 件 , 筆 者 目 的 是 在 此 方 塊 輸 入 文 字 後 , 立 即 在 此 方 塊 下
方的清單方塊中選取最接近的選項。由於必須「抓到」使用者輸入的
文 字 , 且 是 中 文 , 故 此 功 能 必 須 寫 在 KeyUp 事 件 中 。

以鍵盤事件使用快速鍵
除 KeyCode 引 數 外 ,KeyDown 及 KeyUp 事 件 尚 有 Shift 引數,可
判 斷 使 用 者 是 否 按 下 Ctrl、 Shift 、 Alt 等 鍵 , 如 圖 3- 5:
圖 3- 5 在 KeyDown 事 件 判 斷 是 否 按 下 Ctrl 鍵

圖 3- 6 是 Ch3 \3- 2\K e y.mdb 之 「 廠 商 」 表 單 的 KeyDown 事 件 , 筆


者 目 的 是 在 新 記 錄 時 按 下 Ctrl+L 鍵 , 可 複 製 最 末 一 筆 記 錄 , 首 先 須
宣 告 一 個 變 數 (intCtrlDown) , 並 在 行 號 1002 加 總 Shift 及
acCtrlMask , 二 者 之 和 若 不 等 於 0 , 表 示 已 按 住 Ctrl 鍵 , 之 後 再 判 斷
KeyCode 引 數 是 否 等 於 76 , 若 是 則 執 行 行 號 1005 至 1026 之 程 式 ,
在 此 段 程 式 中 , 複 製 及 新 增 是 在 行 號 1012, 原 理 是 先 切 換 至 最 末 一
筆記錄、暫時更改主索引、複製、回復主索引、新增、儲存、切換至
新增之記錄等。暫時更改主索引的原因是由於主索引不可重覆,故以
亂數做為新記錄之主索引。

<<說 明 > >

圖 3- 5 的 例 子 是 以 C t r l 為 例 , 若 要 判 斷 是 否 按 下 S hift 或 Alt 鍵 ,
原 理 皆 同 行 號 1001 至 1003 , 唯 一 差 別 是 行 號 1002 的 acCtrlMask 須
改 為 acShiftMask 或 acAltMask 。

以 上 例 子 為 KeyDown 及 KeyUp , 另 尚 有 KeyPress, 此 事 件 會 發


生 在 KeyDown 之 後 及 KeyUp 之 前 。 但 在 筆 者 經 驗 中 , KeyPress 事 件
甚 少 使 用 , 此 事 件 提 供 KeyAscii 引 數 , 會 傳 回 使 用 者 按 下 按 鍵 的
ASCII 值 , 但 只 有 部 份 按 鍵 , 包 括 英 文 字 母 及 數 字 鍵 , 會 傳 回 其 ASCII
值。

三個鍵盤事件的重點是攔截使用者按下之按鍵,也就是使用
KeyCode 及 KeyAsc i i 等 引 數 。 反 過 來 說 , 讀 者 也 可 將 前 述 兩 個 引 數
設為 0, 即 可 取 消 使 用 者 按 下 之 按 鍵 。

3-2-2 滑 鼠

與 滑 鼠 有 關 的 事 件 共 有 MouseMove 、 MouseDown、 MouseUp 、


Click 、 DbClick 等 五 項 , 前 三 項 可 判 斷 使 用 者 按 下 滑 鼠 的 左 或 右 鍵 ,
後二者只對左鍵有效,此為上述事件的主要差異。另這五項事件可使
用 在 表 單 、 區 段 及 多 數 控 制 項 。 如 按 鈕 控 制 項 常 使 用 Click 事 件 定 義
其 功 能 , DbClick 事 件 常 用 於 子 表 單 內 。
在表單中,表單及控制項均有上述五項事件,差別為只有在捲軸
列 、 左 方 記 錄 選 取 器 按 下 滑 鼠 任 意 鍵 , 方 可 發 生 表 單 的 上 述事 件 。

以 DoubleClick 顯 示 及 切 換 相 關 記 錄
讀 者 可 開 啟 Ch3 \3- 2 \Mouse.mdb 檔 案 的 「 訂 單 」 表 單 , 筆 者 在 此
表 單 上 方 製 作 一 個 組 合 方 塊 , 以 便 切 換 記 錄 , 切 換 依 據 是「 訂 單 編 號 」

欄位。也可按下此方塊右方的 ,按下此鈕後,可開啟另一顯示所

有 訂 單 基 本 資 料 之 表 單 , 此 表 單 名 稱 為 「 速 查 訂 單 」, 在 此 表 單 的 任
一欄位按兩下左鍵,即可再切換回「訂單」表單,並顯示按兩下左鍵
時 , 所 指 之 記 錄 , 如 圖 3- 6:
圖 3- 6 在 速 查 訂 單 按 兩 下 左 鍵

此 功 能 的 程 式 是 在 「 速 查 訂 單 」 的 表 單 及 四 個 欄 位 之 DblClick 事
件 中 , 如 圖 3- 7 :

圖 3- 7 使 用 DblClick 事 件

筆 者 在 圖 3- 7 共 使 用 五 個 DblClick 事件,但均指向 Form_DblClick


事件程序,此處目的是更改「訂單」表單之組合方塊值,並執行組合
方 塊 之 AfterUpdate 事 件 , 也 就 是 切 換 記 錄 。
動態更改快顯功能表及字型顏色
這 兩 項 功 能 須 使 用 MouseUp 及 MouseMove 等 事 件 , 讀 者 可 開 啟
Ch3\3- 2 \Mouse.mdb 之 「 訂 單 」 表 單 , 讀 者 將 滑 鼠 移 至 此 表 單 的 「 發
票 日 期 」、「 送 貨 日 期 」、「 發 票 號 碼 」 等 文 字 方 塊 時 , 其 內 文 字 會 顯 示
為 紅 色 , 移 至 細 部 時 , 又 回 復 正 常 , 此 段 程 式 如 圖 3- 8 :

圖 3- 8 以 滑 鼠 更 改 文 字 顏 色

筆 者 在 圖 3- 8 首 先 宣 告 一 個 公 用 變 數 , 名 稱 為 lastControl, 目 的
是記錄上一個更改文字為紅色的控制項名稱,以便回復。由於有多個
須 更 改 顏 色 的 文 字 方 塊 , 為 節 省 程 式 所 佔 空 間 , 故 筆 者 建 立 chcolor
程序,並使用一個引數,內容即為將更改文字顏色的文字方塊,再於
每 個 文 字 方 塊 的 MouseMove 事 件 執 行 此 程 序 。
滑鼠移至細部後,就須將上個更改為紅色的文字方塊予以回復,
筆 者 使 用 lastControl 變 數 值 做 為 依 據 。 在 以 上 的 設 計 中 , 所 有 程 式 均
圍 繞 著 變 數 lastControl, 因 為 若 未 記 錄 上 一 更 改 顏 色 的 文 字 方 塊 名
稱,會多寫許多程式,處理所有可能已更改顏色的文字方塊。

另在「訂單」表單中,筆者尚在「訂單編號」之 MouseUp 事 件 中 ,
判 斷 是 否 按 下 右 鍵 , 再 於 不 同 情 況 開 啟 及 關 閉 快 顯 功 能 表 , 如 圖 3- 9:
圖 3- 9 使 用 MouseUp 事 件
筆者目的是當「訂單編號」文字方塊內若無資料,則按下右鍵後,
不顯示快顯功能表。反之,僅在有資料時,方顯示快顯功能。故筆者
在 圖 3- 9 先 以 Button 引 數 判 斷 是 否 等 於 2( 按 下 右 鍵 ), 再 以 IsNull 函
數判斷「訂單編號」文字方塊是否有資料,再分別更改表單的
ShortcutMenu( 快 顯 功 能 表 列 ) 屬 性 值 。

<<說 明 > >

以 上 範 例 使 用 MouseUp 及 MouseMove 事 件 , 包 括 未 使 用 的
MouseDown 事 件 , 此 三 者 皆 提 供 四 個 引 數 , 分 別 是 Button( 傳 回 按 下
之 按 鍵 )、Shift(判 斷 是 否 按 住 C t r l、Shift 及 Alt 等 鍵 )及 X、 Y(判 斷 按
下 按 鍵 的 位 置 ), 其 中 Button 引 數 會 傳 回 1( 左 鍵 ) 或 2 (右 鍵 ), Shift 引
數 之 使 用 方 式 同 圖 3- 5 , X 及 Y 為 座 標 值 , 單 位 為 Twips 。

3-2-3 記 錄 處 理

這是在表單內使用事件的重點,因為在輸入式表單中,會因為使
用者針對記錄的不同處理動作,而引發各種事件,請見以下說明。

儲存前檢查
這 是 最 常 見 的 處 理 , 因 為 Access 是 自 動 儲 存 , 只 要 游 標 離 開 目 前
記錄,即儲存完畢,故使用者可能會有「到底存了沒?」的疑問,加
上避免誤打造成的錯誤資料,故建議最好加上儲存前檢查的處理,也
就 是 表 單 的 BeforeUpdate 事 件 , 如 圖 3- 10 :
圖 3- 10 在 BeforeUpdate 事 件 攔 截 儲 存 動 作

BeforeUpdate 事 件 會 在 每 次 儲 存 記 錄 前 自 動 啟 動 , 不 論 儲 存 動 作
的操作原點為何,包括移至另一記錄、使用「記錄」→「儲存記錄」
選 項 、 自 訂 按 鈕 等 , 皆 可 儲 存 記 錄 , 同 時 會 發 生 Be foreUpdate 及
AfterUpdate 事 件 。 但 在 BeforeUpdate 事 件 中 , 設 計 人 員 無 法 確 知 攔
截到的儲存動作來自何方?如使用「記錄」→「儲存記錄」選項的操
作,此一儲存動作即不應攔截,應攔截的是切換記錄引起的儲存動
作 , 故 須 如 圖 3- 10 , 使 用 公 用 變 數 做 為 指 標 。

此 圖 在 Ch3 \3- 2\Record.mdb 檔 案 之 「 訂 單 」 表 單 中 , 筆 者 在 此 表


單之表單首製作「儲存記錄」按鈕,以便儲存作業。而在程式中,首
先 宣 告 savePrompt 變 數 , 做 為 判 斷 是 否 要 顯 示 對 話 方 塊 之 指 標 , 若
此 指 標 為 True 且 發 生 BeforeUpda te 事 件 , 即 詢 問 是 否 要 先 儲 存 。 換
言 之 , 按 下 「 儲 存 記 錄 」 按 鈕 時 , 指 標 即 設 為 F a l s e。

<<說 明 > >

BeforeUpdate 事 件 常 用 於 儲 存 前 的 必 要 處 理 , 此 時 表 示 即 將 儲 存
記 錄 , 若 要 中 止 儲 存 動 作 , 請 將 Cancel 設 為 True(Cancel=True) 即 可 。

在新記錄輸入後立即處理
也 就 是 BeforeInsert 事 件 , 此 事 件 會 發 生 在 新 記 錄 輸 入 第 一 個 字
元 時 , 筆 者 常 用 來 在 新 記 錄 產 生 自 動 編 號 , 如 圖 3- 11 :
圖 3- 11 使 用 BeforeInsert 事 件

圖 3- 11 也 在 Ch3 \3- 2 \Record.mdb 檔 案 之 「 訂 單 」表 單 中 , 筆 者 目


的 是 為 訂 單 編 號 欄 位 自 動 輸 入 如 「 890316- 0 0 1」 的 內 容 , 也 就 是 民 國
日期加上流水號。由於「訂單編號」欄位是主索引,故建議只有在新
記錄輸入第一個字元時,方以程式設定,因為此時已確定使用者正在
輸入資料。

同 時 筆 者 為 配 合 前 例 , 將 此 表 單 的 BeforeUpdate 事 件 由 圖 3- 10
改 為 圖 3- 11, 仍 使 用 savePrompt 變 數 做 為 判 斷 是 否 詢 問 儲 存 的 指 標 ,
在流程上,筆者以「編號」資料表做為自動編號的判斷,此表有
「產生日期」及「訂單數」等兩個欄位,分別記錄每日的訂單數。所
以 在 BeforeInsert 事 件 中 , 首 先 至 此 資 料 表 尋 找 今 日 的 訂 單 數 欄 位 ,
若 無 則 新 增 ( 行 號 1002 至 1007) , 取 得 編 號 則 是 行 號 1010, 但 此 僅 是
取得編號,並未將目前正在輸入的新編號回存至「編號」資料表。

因 為 回 存 的 動 作 必 須 寫 在 BeforeUpdate 事 件 中 , 因 為 此 時 方 確 定
使用者將儲存新記錄,在此事件中,主要動作是判斷「編號」資料表
中,今天的訂單數是否等於「訂單編號」欄位減 1, 若 不 是 , 則 表 示
已有網路上另一位使用者更改過,此時再依新值加 1 後,顯示在「訂
單編號」欄位,並以此值回存至「編號」資料表之「訂單數」欄位,
這是為了網路應用,而加入的設計。

<<說 明 > >

所 以 BeforeInsert 事 件 常 用 於 「 確 定 使 用 者 已 開 始 輸 入 資 料 」 之
後,所需的設計,因為在輸入式表單中,任何以程式更改欄位值、手
動 輸 入 等 動 作 , 皆 會 造 成 Access 認 為 已 更 改 記 錄 , 故 必 須 確 定 使 用
者的動作,再進行必要設計。

更新後執行公式
最 常 見 的 是 小 計 = 數 量 *單 價 , 此 一 小 計 即 必 須 計 算 而 來 , 同 時 若
小 計 是 來 自 資 料 表 的 欄 位 , 設 計 人 員 就 須 在 VBA 中 執 行 計 算 , 如 圖
3- 12:

圖 3- 12 在 程 式 中 使 用 公 式

圖 3- 12 是 Ch3 \3- 2 \Record.mdb 檔 案 之 「 訂 單 」 表 單 中 的 子 表 單 ,


子表單內有單價、數量、 總 價 等 欄 位 , 而 總 價 欄 位 等 於 前 二 者 之 乘 積 。

兩 個 程 序 分 別 是 單 價 及 數 量 的 AfterUpdate 事 件 , 筆 者 在 程 式 內
首 先 以 IsNull 及 IsNumeric 等 函 數 判 斷 欄 位 內 之 值 是 否 正 確 , 若 是 方
進行計算。

在 單 價 的 AfterUpdate 事 件 中 , 筆 者 尚 有 使 用 Format 函 數 , 目 的
是四捨五入至整數,若要使用小數點,語法是:

Me![ 總 價 ] = Format(Me![數 量 ] * Me![單 價 ], "###.00")

但 在 Ch3\3- 2 \Record.mdb 檔 案 中 , 總 價 欄 位 之 「 欄 位 大 小 」 屬 性
為 「 長 整 數 」, 故 會 自 動 四 捨 五 入 , 亦 不 須 使 用 Format 函 數 。 筆 者 目
的 僅 在 說 明 在 程 式 內 若 要 四 捨 五 入 , 可 使 用 Format 函 數 。
另 在 數 量 的 AfterUpdate 事 件 中 , 筆 者 在 計 算 前 , 尚 先 檢 查 「 總
價」之值是否已等於單價及數量之乘積,若是則不做計算。如此設計
的 目 的 是 因 為 不 論 計 算 後 之 值 是 否 等 於 「 總 價 」, 若 直 接 將 值 傳 遞 至
「 總 價 」, 皆 會 造 成 記 錄 已 更 改 , 也 就 是 會 發 生 儲 存 記 錄 的 動 作 , 為
減少可能的磁碟存取動作,筆者皆為如是設計。

<<說 明 > >

以 上 是 使 用 欄 位 的 AfterUpdate 事 件 , 此 事 件 會 發 生 在 欄 位 資 料
已 更 改 , 且 插 入 點 離 開 此 欄 時 , 故 可 確 定 的 是 此 時 資 料 已 更 改, 必 須
重新計算。而本例的處理範圍是更改目前記錄中,另一欄位之值。若
要 更 改 其 他 欄 位 , 必 須 先 取 得 Recordset 物 件 之 記 錄 , 再 執 行 計 算 。

載入時最大化及讀取標題
也 就 是 使 用 Load 事 件 , 表 單 開 啟 時 , 會 持 續 發 生 O p e n→ Load →
Current 等 事 件 , 其 中 O p e n 表 示 表 單 已 開 啟 , 但 尚 未 取 得 記 錄 , Load
表 示 已 取 得 記 錄 , Current 表 示 取 得 並 已 顯 示 第 一 筆 記 錄 在 表 單 中 。
除 了 以 上 差 別 外 , O p e n 事 件 尚 可 取 消 開 啟 表 單 (Cancel=True), Load
事件則無法取消。

在 設 計 上 , 有 關 表 單 載 入 處 理 均 會 寫 在 Load 事 件 , 因 為 此 時 已
取 得 記 錄 。 若 有 可 能 取 消 開 啟 之 動 作 , 請 使 用 O p e n 事 件 。 如 圖 3- 13
是載入時最大化及讀取標題之例:

圖 3- 13 使 用 Load 事 件

圖 3- 13 在 Ch3 \3- 2 \Record.mdb 檔 案 之 「 訂 單 」 表 單 中 , 也 是 由 圖


3- 10 改 良 而 來 , 筆 者 在 Load 事 件 使 用 Dlookup 函 數 在 「 我 的 公 司 資
訊 」 資 料 表 內 取 得 公 司 名 稱 , 再 置 於 名 為 「 Label70」 之 標 籤 中 。 最
大 化 的 設 定 則 是 使 用 Maximize 巨 集 指 令 , 由 於 這 是 巨 集 指 令 , 故 須
在 之 前 加 上 Docmd 。

<<說 明 > >

Dlookup 函 數 相 當 好 用 , 其 功 能 是 在 資 料 表 或 查 詢 中 取 得 一 筆 記
錄的某一欄位值,關鍵是一筆記錄,若會找到多筆記錄,則須使用
Recordset 物 件 。 此 函 數 的 三 個 引 數 分 別 是 欄 位 名 稱 、 資 料 表 或 查 詢
名稱、準則等。

Docmd 表 示 將 在 程 式 中 使 用 巨 集 指 令 , 所 有 巨 集 指 令 均 會 顯 示 在
輸 入 「 Docmd. 」 之 後 的 清 單 中 。 最 大 化 及 最 小 化 的 設 定 皆 須 使 用 巨
集 指 令 , 如 「 DoCmd.Maximize 」 或 「 DoCmd. Minimize 」, 因 為 表 單
沒有控制大小的屬性。

復原處理
復原之意是記錄已更改,但不想儲存,同時回復至上次儲存的內
容,復原的單位可以是整筆記錄或一個欄位。

在 資 料 表 及 表 單 中 , 使 用 者 可 持 續 按 下 「 ESC 」 按 鍵 , 執 行 回 復 ,
此鍵功能是逐一回復,先回復目前插入點所在欄位,再回復同記錄其
他已被更改的欄位,另也可持續使用「編輯」→「回復」選項。

除 此 之 外 , Access 2000 的 表 單 新 增 Dirty 事 件 , 此 事 件 會 發 生 在


更 改 記 錄 時 , 若 將 此 事 件 的 Cancel 引 數 設 為 True , 可 以 整 筆 記 錄 為
單 位 , 進 行 回 復 。 另 一 回 復 的 設 計 是 「 DoCmd.RunCommand
acCmdUndo」,如圖 3- 10,此圖是在 BeforeUpdate 事 件 攔 截 儲 存 動 作 ,
並在必要時執行回復。

<<說 明 > >

以 上 是 有 關 復 原 處 理 之 說 明 , 讀 者 也 可 在 VBA 內 使 用 表 單 的
Dirty 屬 性 , 判 斷 目 前 記 錄 是 否 已 更 改 , 如 :

If Me.Dirty=True Then

End If

若 Dirty 屬 性 為 True, 表 示 記 錄 已 更 改 , 反 之 為 False, 但 此 屬 性


為唯讀,也就是讀者只可以此屬性值做為判斷記錄是否已更改的依
據,但不可更改此屬性值。

自訂刪除處理
刪除的設計可使用巨集指令,也可以自訂之對話方塊,詢問使用
者 是 否 真 的 要 刪 除 記 錄 , 因 為 Access 雖 然 預 設 會 要 求 確 認 , 但 此 項
預 設 值 若 被 更 改 ( 在 「 工 具 」 功 能 表 的 「 選 項 」 中 ), 則 不 會 顯 示 確 認
訊息,故筆者通常會製作 刪除按鈕,以供操作。

讀 者 可 開 啟 Ch3 \3- 2 \Record.mdb 檔 案 的 「 訂 單 」 表 單 , 其 表 單 首


有「刪除」按鈕,圖 3- 14 是 此 按 鈕 的 Click 事 件 及 其 他 有 關 刪 除 處 理
的事件程序:

圖 3- 14 自 訂 刪 除 處 理

圖 3- 14 共 有 三 個 程 序 , 首 先 是 「 刪 除 」 按 鈕 之 Click 事 件 , 執 行
刪除的語法是:

DoCmd.RunCommand acCmdDeleteRecord

RunCommand 是 巨 集 指 令 , 其 後 是 Access 2000 提 供 的 所 有 功 能 ,


共 有 數 百 項 之 多 , 均 以 acCmd 為 開 頭 的 引 數 。 另 在 刪 除 之 前 , 筆 者
加 上 「 On Error Resume Next」, 表 示 若 發 生 錯 誤 , 即 予 略 過 。 因 為 在
預 設 情 況 下 , 使 用 者 若 於 確 認 是 否 刪 除 之 對 話 方 塊 中 按 下 「 否 」, 表
示中斷巨集指令,會因此而發生錯誤,故以此行避開。

執 行 刪 除 後 , 會 連 續 發 生 Delete、 BeforeDelConfirm 及
AfterDelConfirm 等 事 件 , 刪 除 處 理 必 須 寫 在 後 二 者 。 在 圖 3- 14 中 ,
筆 者 在 BeforeDelConfirm 事 件 中 以 MsgBox 函 數 詢 問 是 否 要 刪 除 , 若
按 下 否 , 則 會 傳 回 vbNo, 即 執 行 Cancel=True, 也 就 是 中 止 刪 除 之 動
作 ,「 Response = acDa taErrContinue 」 則 表 示 不 顯 示 系 統 預 設 之 對 話
方 塊 。 反 之 若 按 下 「 是 」, 則 會 傳 回 vbYes , 同 時 不 處 理 。

不 論 在 BeforeDelConfirm 事 件 中 有 無 將 Cancel 引 數 設 為 True ,


均 會 再 發 生 AfterDelConfirm 事 件 , 處 理 情 況 可 使 用 此 事 件 的 Status
引 數 進 行 判 斷 , 圖 3- 14 的 AfterDelConfirm 事 件 分 別 在 兩 種 情 況 , 顯
示相關訊息。

<<說 明 > >


以上就是刪除處理的基本設計,包括啟動刪除、顯示確認刪除之
對話方塊及後續處理等。但在實際環境中,可能會因刪除一筆記錄之
後,連帶須更新其他資料表的記錄,如刪除一筆訂單後,該筆訂單原
有的訂單細明仍存在,但已無意義,這些明細是否也應一併以程式刪
除?視各環境而定。

若 須 刪 除 相 關 記 錄 , 筆 者 的 建 議 是 使 用 刪 除 查 詢 , 以 圖 3- 14 為
例 , 若 在 刪 除 訂 單 記 錄 後 , 一 併 刪 除 明 細 , 程 式 更 改 如 圖 3- 15 :

圖 3- 15 以 程 式 執 行 刪 除 查 詢

筆 者 在 圖 3- 15 的 目 的 是 刪 除 訂 單 後 , 立 即 至 「 詳 細 訂 單 」 資 料 表
刪除明細。在流程上,首先必須「記住」即將刪除的訂單編號,因為
刪 除 時 , 記 錄 將 暫 時 由 表 單 清 除 , 無 法 直 接 抓 取 , 故 筆 者 以 DeleteID
變數記住訂單編號,同時此變數為共用。先在刪除按鈕中取得訂單編
號 , 再 於 BeforeDelConfirm 事 件 取 得 「 刪 除 _ 訂 單 明 細 」 查 詢 , 此 查
詢 內 含 一 個 參 數 , 將 參 數 值 設 為 變 數 DeleteID 後 , 再 以 Execute 方 法
執 行 之 。 如 圖 3- 16 是 「 刪 除 _ 訂 單 明 細 」 查 詢 :
圖 3- 16 含 有 參 數 的 刪 除 查 詢

如 圖 3- 16 所 示 , 在 刪 除 查 詢 中 , From 表 示 刪 除 的 範 圍 , 通 常 就
是 含 有 「 * 」 符 號 的 敘 述 , 表 示 將 刪 除 整 筆 記 錄 , Where 就 是 準 則 ,
結果是只有符合準則的記錄,方會被刪除。

組合方塊
組 合 方 塊 有 一 較 特 殊 的 事 件 , 即 NotInList, 若 要 使 用 此 事 件 , 首
先 須 將 「 限 制 在 清 單 內 」 屬 性 設 為 「 是 」。 此 事 件 會 發 生 在 當 使 用 者
輸入不存在於方塊內之名稱時,此時因為僅允許使用方塊內之選項,
因而發生錯誤,啟動此一事件。

所以此事件在實際應用上,常做為輸入找不到的名稱時,立即新
增 , 也 就 是 在 NotInList 事 件 中 詢 問 是 否 要 立 即 輸 入 新 資 料 。 讀 者 可
開 啟 Ch3\3- 2 \Record.mdb 檔 案 的 「 訂 單 」 表 單 , 本 例 操 作 如 下 :

l 在 「 客 戶 名 稱 」 組 合 方 塊 中 輸 入 不 存 在 的 名 稱 , 再 按 下 Tab 鍵 。
l 在詢問是否要立即新增客戶之對話方塊中按下「是」後,可開啟
「 客 戶 」表 單 , 並 將 原 輸 入 之 客 戶 名 稱 , 置 於「 客 戶 」表 單 之「 客
戶 名 稱 」 欄 位 中 。 至 此 之 程 式 處 理 如 圖 3- 1 7 :
圖 3- 17 使 用 NotInList 事 件

在 圖 3- 17 之 NotInList 事 件 中 , 若 按 下 「 是 」 按 鈕 , 會 立 即 開 啟
「客戶」表單,並將輸入的新客戶編號置於「客戶名稱」欄位內,此
處 的 關 鍵 是 使 用 如 「 Me![ 客 戶 編 號 ].Text」, 也 就 是 Text 屬 性 , 此 屬
性會傳回目前正在輸入的文字,但只有控制項擁有焦點或插入點時,
方可使用此屬性。

l 在「客戶」表單中輸入完新客戶資料後,按下「回至訂單」按鈕,
可 儲 存 新 客 戶 及 回 至 「 訂 單 」 表 單 , 如 圖 3- 1 8:

圖 3- 18 處 理 完 成 之 後

圖 3- 18 是 由 「 客 戶 」 回 至 「 訂 單 」 之 處 理 , 在 此 分 別 儲 存 記 錄 、
還原、重新查詢、傳遞客戶編號等,重要的是後三者,還原的目的是
使組合方塊之值回復至未輸入前之資料,因為此時組合方塊仍是限制
在 清 單 內 , 若 直 接 處 理 , 仍 會 發 生 錯 誤 , 故 須 先 還 原 , 再 以 Requry
方法重新查詢,目的是將新輸入的客戶資料,顯示在組合方塊內,最
後再傳遞客戶編號。

<<說 明 > >

NotInList 是 組 合 方 塊 的 專 用 屬 性 , 若 使 用 者 只 會 在 方 塊 中 以 滑 鼠
選取,則永遠不須使用此事件,因為不會發生輸入不存在資料的可
能 , 所 以 NotInList 事 件 只 使 用 在 必 須 使 用 鍵 盤 在 組 合 方 塊 中 輸 入 資
料時。
計時器
任 何 程 式 設 計 工 具 皆 有 計 時 器 的 功 能 , 在 Access 中 , 可 使 用 表 單
的 Timer 事 件 , 但 此 事 件 須 搭 配 TimerInterval 屬 性 , 此 屬 性 預 設 值 為
0, 若 設 為 1000 , 表 示 每 一 秒 發 生 一 次 Timer 事 件 , 故 單 位 為 毫 秒 。

讀 者 可 開 啟 Ch3 \3- 2 \Record.mdb 檔 案 的 「 產 品 」 表 單 , 筆 者 在 此


表單製作兩個有關計時器的設計,一是在表單首顯示目前時間,且會
每 秒 更 新 一 次 , 因 為 此 表 單 的 TimerInterval 屬 性 為 1000 。 另 是 若 使
用者清除「產品名稱」欄位之值,會顯示警示對話方塊,而此對話方
塊 會 在 顯 示 三 秒 鐘 後 , 自 動 退 出 , 這 兩 項 功 能 均 寫 在 Timer 事 件 中 ,
如 圖 3- 1 9:

圖 3- 19 使 用 Timer 事 件

筆 者 在 圖 3- 19 宣 告 兩 個 公 用 變 數 , 分 別 做 為 累 計 秒 數 及 顯 示 對 話
方 塊 的 指 標 。 兩 個 程 序 分 別 是 「 產 品 名 稱 」 欄 位 的 AfterUpdate 事 件
及 表 單 之 Timer 事 件 。 若 在 行 號 1001 發 現 「 產 品 名 稱 」 欄 位 沒 有 資
料,即顯示對話方塊,並將變數 ShowD 設 為 True, 以 便 在 表 單 之 Timer
事 件 之 行 號 1008 累 計 對 話 方 塊 之 顯 示 秒 數 , 若 此 一 累 計 數 等 於 3,
即 在 行 號 1010 退 出 對 話 方 塊 , 原 理 是 使 用 SendKeys 指 令 , 傳 遞 ESC
按鍵,最後再予以 歸零。

故以上處理的方式是藉由兩個公用變數在數個程序間的傳遞,達
到所需功能。

<<說 明 > >


如 上 所 述 , Timer 事 件 的 發 生 頻 率 須 視 TimerInterval 屬 性 值 之 設
定 , 讀 者 也 可 在 程 式 中 更 改 此 一 屬 性 值 , 如 改 為 0, 就 不 會 發 生 Timer
事 件 , 可 視 需 求 隨 時 在 程 式 中 開 啟 或 關 閉 Timer 事 件 。

3-2-4 報 表

報表的事件不多,大致分為兩類,分別是報表本身及各區段的事
件 , 大 多 使 用 後 者 , 即 各 區 段 的 Format、 Print 及 Retreat 等 , 其 中 又
以前二者之使用率較高,請見以下說明。

每五筆增加間隔
在報表中,每筆記錄的間隔視細部高 度而定,亦即細部即等於一
筆記錄的高度,此一高度可在列印前以程式更改,即可達到增加或減
間 隔 的 目 的 , 讀 者 可 開 啟 Ch3 \3- 2\Rpt.mdb 檔 案 之「 列 印 間 隔 」 表 單 ,
此表單只有一個按鈕及兩個文字方塊,後二者的功能是分別輸入每隔
多 少 筆 , 列 印 之 間 隔 , 如 圖 3- 20 :

圖 3- 20 列 印 產 生 間 隔 之 報 表

在 圖 3- 20 分 別 輸 入 兩 個 數 字 後 , 再 按 下「 預 覽 」按鈕,可開啟「產
品 」 報 表 , 此 報 表 的 處 理 如 圖 3- 21 :

圖 3- 21 在 報 表 中 處 理 細 部 高 度

更 改 高 度 的 設 計 只 可 寫 在 Format 事 件 中 , 不 可 寫 在 Print 事 件 ,
因 為 Format 事 件 正 在 準 備 列 印 , 而 Print 事 件 表 示 已 準 備 完 畢 , 所 有
資料皆已就位,故不可更改大小、位置等。

在 圖 3- 21 中 , 筆 者 是 以 「 產 品 編 號 」 欄 位 的 最 右 方 兩 位 數 做 為 判
斷 依 據 , 此 欄 之 值 是 如 「 1001 」 的 數 字 , 取 得 個 位 及 十 位 數 後 , 再 以
MOD 運 算 子 (功 能 為 求 餘 數 ) 除 以 在 圖 3- 20 輸 入 的 數 字 , 若 結 果 為 0,
表示將更改間隔,也就是調整細部的高度,新高度是原高度加上在圖
3- 22 輸 入 之 數 字 , 此 處 的 重 點 是 單 位 , 在 細 部 區 段 的 屬 性 表 中 ,「 高
度 」 屬 性 的 單 位 是 公 分 , 但 在 程 式 中 , 單 位 是 twips, 567 twips 等 於
1 公 分 , 所 以 在 行 號 1002 須 乘 以 567, 如 此 即 可 達 成 更 改 間 隔 的 目 的。

<<說 明 > >

圖 3- 21 的 例 子 是 使 用 「 產 品 編 號 」 欄 位 值 做 為 判 斷 是 否 應 該 加 大
間 隔 的 依 據 , 若 沒 有 此 欄 , 另 一 方 法 是 使 用 公 用 變 數 , 在 每 次 Format
事 件 中 進 行 累 計 , 以 此 值 除 以 筆 數 , 再 更 改 高 度 , 如 圖 3- 2 2:

圖 3- 22 以 公 用 變 數 更 改 細 部 高 度

圖 3- 22 是 Ch3 \3- 2 \Rpt.mdb 檔 案 之 「 產 品 1 」 報 表 , 筆 者 在 此 使


用 公 用 變 數 p , 做 為 在 行 號 1001 除 以 筆 數 的 依 據 。 但 重 點 是 須 在 報
表 的 Page 及 頁 首 的 Format 事 件 , 將 公 用 變 數 予 以 歸 零 。 在 報 表 _Page
中 歸 零 之 原 因 是 由 預 覽 至 報 表 時,Access 會 重 新 執 行 報 表 , 故 所 有 公
用 變 數 均 須 先 歸 零 , 否 則 公 用 變 數 會 持 續 累 計 ; 在 頁 首 區 段 _Format
內歸零的原因是每頁均可重新累計。

如何在報表顯示如民國八十九年一月一日的日期
Access 中 有 關 民 國 年 的 設 定 有 兩 種 , 一 是 控 制 台 的「 國 別 設 定 」,
另 是 使 用 如 「 e/mm/dd」 的 格 式 , 但 二 者 均 只 可 產 生 如 「 民 國 89 年 3
月 26 日 」 之 日 期 , 若 要 將 數 字 轉 換 為 國 字 , 即 非 自 行 撰 寫 不 可 。 讀
者 可 開 啟 Ch3 \3- 2 \Rpt.mdb 檔 案 之 「 產 品 」 報 表 , 筆 者 在 此 報 表 之 頁
尾 左 方 使 用 「 convertdate 」 函 數 , 將 日 期 轉 換 為 國 字 , 如 圖 3- 23 :

圖 3- 23 將 日 期 轉 換 為 國 字

「 convertdate 」不 是 Access 提 供 的 函 數 , 而 是 在 Ch3 \3- 2 \Rpt.mdb


檔 案 之 「 Module1」 模 組 內 , 如 圖 3- 24 :

圖 3- 24 轉 換 為 民 國 大 寫 日 期 之 程 式

圖 3- 24 有 兩 個 函 數 , 圖 3- 23 使 用 的 是 convertDate, 此 函 數 又 呼
叫 下 方 的 convertToText 函 數 , 此 函 數 目 的 是 轉 換 為 大 寫 , 再 回 傳 至
上 方 的 convertDate 函 數 , yy、 mm、 dd 分 別 代 表 年 、 月 及 日 等 不 同
單位。

<<說 明 > >


本例未使用報表的任何事件,而是使用自訂函數,在
Ch3\3- 2 \Rpt.mdb 檔 案 中 , 圖 3- 24 的 函 數 可 使 用 在 任 何 位 置 , 包 括 查
詢、表單、報表等之屬性表。

列印空白表格線
Access 報 表 的 列 印 原 理 是 忠 實 反 應 資 料 來 源 , 如 資 料 來 源 共 有 五
筆記錄,報表即只會列印五筆,衍伸的問題是每次列印同一份報表,
可能會因筆數不同,造成最末一頁的空白區域大小不一,故筆者曾發
展出數種不同的方法,以便在最末一頁列印空白表格。

讀 者 可 開 啟 Ch3 \3- 2 \Rpt.mdb 檔 案 之 「 訂 單 」 表 單 , 再 按 下 表 單


首之「列印出貨單」按鈕,此按鈕可瀏覽「出貨單」報表,此報表之
來 源 是 「 出 貨 單_來 源 」 資 料 表 , 但 此 資 料 表 僅 是 做 為 列 印 之 用 , 筆
者 是 在 「 出 貨 單 」 報 表 之 Open 事 件 中 , 以 程 式 判 斷 目 前 將 列 印 的 出
貨 單 共 有 多 少 筆 記 錄 , 假 設 報 表 一 頁 可 印 26 筆 記 錄 , 即 以 26 筆 減 去
目 前 記 錄 筆 數 , 再 新 增 空 白 記 錄 至「 出 貨 單 _來 源 」資料表,如圖 3- 2 5:
圖 3- 25 以 程 式 新 增 空 白 記 錄

圖 3- 25 是 報 表 的 O p e n 事 件 , 筆 者 首 先 於 行 號 1002 執 行 「 刪 除 _
出 貨 單 」 查 詢 , 這 是 刪 除 查 詢 , 目 的 是 刪 除 「 出 貨 單_來 源 」 資 料 表
的 所 有 記 錄 , 以 便 在 行 號 1003 至 1005 新 增 本 次 將 列 印 的 記 錄 , 此 處
執行的「出貨單」查詢,此為新增查詢,且其內使用一個參數,參照
至「訂單」表單的「訂單編號」欄位,目的是以訂單編號為依據,列
印此訂單的出貨單。

行 號 1011 至 1023 即 為 新 增 記 錄 的 程 式 , 筆 者 使 用 26 及 3 1 等 兩
種 數 字 , 26 表 示 有 報 表 尾 時 , 一 頁 列 印 之 記 錄 總 數 , 31 表 示 沒 有 報
表尾之記錄總數,這是因為「出貨單」報表有報表尾,而報表尾又只
列印在最末一頁,其他頁面則沒有報表尾,乃有此差別。

<<說 明 > >

本 例 是 使 用 報 表 的 Open 事 件 , 此 事 件 表 示 報 表 已 啟 動 , 但 尚 未
載入資料來源,一切準備動作均尚未開始,故本例可在此事件更改報
表資料來源的內容,再進行列印。

另 在 圖 3- 25 中 尚 有 報 表 的 Pa ge 事 件 , 其 內 只 有 一 行 程 式 , 此 行
目 的 是 在 報 表 四 週 繪 製 線 條 , 形 成 矩 形 , Line 是 只 可 使 用 在 報 表 的 語
法,功能是繪製線條或矩形,其後共可使用三個參數,分別是起迄點
座標、線條顏色及是否為矩形,最後一個參數若為 B 表示繪製矩形;
若 為 BF 表 示 繪 製 矩 形 及 矩 形 內 部 填 滿 顏 色 (ForeColor 屬 性 值 ) 。

在頁尾計算合計
報表之頁首及頁尾區段不可使用公式,若在此位置使用公式,將
在 列 印 時 顯 示 「 錯 誤 」 二 字 , 這 是 因 為 Access 無 法 針 對 一 頁 進 行 計
算,只可針對一整份報表或群組執行計算。

若 要 在 頁 尾 使 用 公 式 , 可 使 用 巨 集 或 VBA, 原 理 仍 是 以 公 用 變 數
進 行 累 計 , 如 圖 3- 26 :

圖 3- 26 在 頁 尾 使 用 公 式

圖 3- 26 是 Ch3 \3- 2 \Rpt.mdb 檔 案 之 「 銷 貨 明 細 」 報 表 的 程 式 , 讀


者 可 先 開 啟 此 檔 的 「 報 表 日 期 」表 單 , 輸 入 起 迄 日 期 後 再 按 下「 預 覽 」
按鈕,可開啟「銷貨明細」報表。此報表的頁尾有兩個文字方塊,分
別可顯示本頁的數量及總價之和。

兩 個 和 又 分 別 來 自 圖 3- 26 之 兩 個 公 用 變 數 , 在 細 部 的 Print 事 件
中 進 行 累 計 、 在 頁 尾 放 入 兩 個 文 字 方 塊 、 在 頁 首 的 Print 事 件 中 歸 零
等 , 處 理 流 程 與 圖 3- 22 類 似 。

<<說 明 > >

以 上 說 明 多 集 中 於 報 表 各 區 段 的 Format 及 Pr int 事 件 , 筆 者 建 議
程 式 儘 量 寫 在 Print 事 件 中 , 因 為 此 事 件 最 「 接 近 」 實 際 列 印 成 果 ,
但 也 因 如 此 , 所 以 此 事 件 可 調 整 的 範 圍 亦 最 小 , 如 圖 3- 22 就 必 須 使
用 Format 事 件 。 所 以 讀 者 若 不 確 應 寫 在 何 處 , 可 先 試 用 Print 事 件 ,
不 行 再 換 至 Format, 再 不 行 就 使 用 Open 事 件 , 但 以 使 用 前 二 者 居 多 。
3-2-5 事 件 行 為

如上所述,事件皆是系統所定義,讀者無法新增或更改事件名
稱,同時會在不同操作下,連續發生數個事件。設計人員在事件行為
上,可以有如下的兩種處理。

呼叫事件
事件均是被動地等待執行,但也可在任何地方以程式呼叫事件,
有如將事件程序當做副程式。讀者只須在程式中輸入另一事件程序名
稱 即 可 , 如 圖 3- 27 :

圖 3- 27 執 行 另 一 事 件

圖 3- 27 是 Ch3 \3- 2 \Record.mdb 檔 案 的 「 訂 單 子 表 單 」 表 單 , 此 表


單 是 置 於 「 訂 單 」 之 子 表 單 , 筆 者 在 AfterUpdate 事 件 計 算 「 金 額 」
欄位的合計,並傳遞至主表單的「合計」欄位。並更新主表單的「未
稅價」及「稅額」欄位,即每次儲存後,因為資料已變更,故主表單
相關欄位亦須更新。

但更新的動作不止是在儲存之後,刪除後亦須更新,所以
AfterDelConfirm 亦 須 更 新 , 筆 者 在 此 事 件 判 斷 Status 若 等 於
acDeleteOK(刪 除 完 成 ) , 則 執 行 AfterUpdate 事 件 , 只 要 輸 入 程 序 名
稱即可,好處是同樣的程式內容,不須撰寫多次,也達到精簡程式的
目的。

<<說 明 > >

圖 3- 27 是 在 同 一 模 組 內 呼 叫 各 個 程 序 之 例 , 若 要 呼 叫 另 一 表 單 、
報 表 、 模 組 內 之 程 序 , 讀 者 須 先 刪 除 被 呼 叫 程 序 之「 Private」 關 鍵 字 ,
每一事件預設皆會加上此關鍵字,其意是該程序只可被同模組另一程
序 所 呼 叫 。刪 除 之 字 後 , 即 可 在 資 料 庫 的 任 一 模 組 , 對 之 進 行 呼 叫 ,
但 須 加 上 模 組 名 稱 , 如 現 有 一 個 名 為「 客 戶 」之 表 單 , 呼 叫 此 表 單 之
AfterUpdate 事 件 的 語 法 如 下 :

Form_ 訂 單 .AfterUpdate

中止事件
有 些 事 件 是 可 被 中 止 的, 此 類 事 件 均 會 提 供 Cancel 引 數, 將 此 引
數 設 為 True 即 可 中 止 事 件 , 如 在 一 般 情 況 下 , BeforeUpdate 之 後 是
AfterUpdate, 若 在 BeforeUpdate 事 件 中 將 Cancel 設 為 True , 即 不 會
發 生 AfterUpdate。 另 一 中 止 事 件 的 語 法 是 使 用 巨 集 , 如 :

Docmd.CancelEvent

也 就 是 CancelEvent 巨 集 指 令 , 同 樣 可 達 到 中 止 事 件 的 效 果 , 但
不 是 每 一 事 件 皆 可 中 止 , 只 有 提 供 Cancel 引 數 的 事 件 , 方 可 使 用 上
述語 法 。

<<結 論 > >


本節 說 明多 個 實例 及 兩種 事 件行 為,事 件 的重 點 是讓 設 計 人員 可
在 正 確 位 置 定 義 所 需 功 能 , 筆 者 在 Access 2000 實 戰 問 答 及 Access
2000 專 案 開 發 等 書 中 , 有 更 多 的 事 件 實 例 , 請 參 考 。

You might also like