Applies ToMicrosoft 365 Access Access 2021 Access 2019

此處的內容可能適用於 Northwind 2.0 Developer Edition 和 Starter Edition。 

VBA (Visual Basic for Applications) 是所有 Office 產品中使用的程式設計語言。 學習 VBA 可讓您使用所有 Office 產品, (不只是 Access) 。搜尋「操作說明」時,請務必尋找 Access 的特定範例,並將 Microsoft Access 包含在搜尋中。 其他 Office 產品通常可以使用解決方案,但無法保證。 Microsoft Access 是一項成人產品;這表示這裡有很多範例;這非常適合您! 

這也表示 Access 程式設計上的舊版書籍仍可行供您查看。 許多舊版書籍仍以其原始成本的一小部分提供於已使用的書籍網站上。 請查看 Microsoft 網站以判斷哪些版本的 Access 仍受到支援,並使用這些版本。

Office 終止支持資源 - 部署 Office |Microsoft Learn  

以下是 Microsoft Access 檔的一些連結。

Microsoft Access 檔案是 Office 檔案。 Office 檔案必須位於「信任的位置」,或是已啟用其「內容」。 這些項目會因為您建立而被視為「安全」,或是它們來自值得信任的來源。 每次開啟任何 Office 檔案時,都會檢查是否發生信任的位置。 我們會從這裡將此稱為「信任/已啟用」。 注意:如果新版應用程式是從不受信任的位置發行並開啟,則啟用內容的程式將會重複。

深入瞭解信任的位置。: 

宏、函數和子函數是您在 Access 資料庫中實作商務邏輯的方式。 在開始之前,請務必先瞭解 範圍和可見度

事件 (像是按兩下窗體上控制件上的控件) (例如按鈕、文字框、標籤等,) 觸發其他程式,例如新增、刪除記錄或開啟表單。 這些程式可以使用宏或 VBA 來實作。 Northwind Starter Edition 主要使用宏,以及某些 VBA,其中宏無法執行所需的函數。 Northwind Developer Edition 主要使用 VBA。 

某些控制件類型有內建精靈可自動建立宏。 例如,將命令按鈕新增至窗體會開啟精靈,提供按鈕的多種功能選擇。 新增下拉式方塊會開啟精靈,可設定為尋找窗體上的特定記錄。 

[導航窗格] 是您檢視及存取所有資料庫物件的主要方式,預設會顯示在 Access 視窗的左側。 [北風導航窗格] 已自定義。 我們建立了一個名為 「北風入門 2.0」的自定義類別。 這可讓我們依功能區整理物件。

有時候,建立變數的物件超出範圍后,您會需要有變數存在。 請參閱上方 的範圍和可見度 。 有三個主要方法可以執行此動作:公用變數、TempVars 和將值儲存在本機數據表中。 許多開發人員會混合使用這些功能。 每個都有其優點和缺點。  在這裡深入瞭解每個專案: 

VBA 模組公用變數: 

TempVars: 

將值儲存在本機數據表中

  • 公用變數和 TempVars 存在於目前的作業階段,並在應用程式關閉時超出範圍。 但如果您想要讓使用者在會話之間保持特定變數呢? 您可以將這些類型的值儲存在本機數據表中。 在 Northwind 2.0 中,一個這樣的變數會儲存在稱為 SystemSettings 的數據表中。 數據表中的值為 ShowWelcome。 此值會告訴 Access 您是否要在每次登入時看到歡迎畫面。

開發人員通常需要將參數從一個窗體傳遞到另一個窗體,或從窗體傳遞至報表。 這些參數傳達重要資訊,稱為函數接著會用來設定本身。 第二個表單或報表有數種方式可以從第一個表單取得資訊。 以下是幾個方法: 

  1. 第二個表單可以「回頭看看」到第一個窗體,以挑選一些值,可能在可見或隱藏的控件中。  例如: lngCustomerID = Forms!FirstForm!cboCustomerID 

  2. 第一個表單可以將值儲存到全域變數或 TempVars。 例如: g_lngUserID = Me.cboUserID  TempVars.Add “UserID”, Me.cboUserID 

Northwind Developer Edition 和我們的專業生活常用的方法是使用 DoCmd.OpenForm 或 OpenReport 的 OpenArgs 自變數。 例如: DoCmd.OpenForm "frmCompanyDetail", OpenArgs:=StringFormat("CompanyID={0} &CompanyTypeID={1}", Me.VendorID, ctVendor)

我們在此結合了兩種技巧: (1) 使用 OpenArgs 在 VendorID 和 VendorType 中傳遞,而 (2) 使用 StringFormat () 函數建立,例如,此字符串: 

CompanyID=5&CompanyTypeID=2 

這個字串看起來很像瀏覽器中使用的查詢字串。 它包含一個或多個以音量和字元分隔的「名稱/值組」: 

name1=value1&name2=value2

這類字串的優點是每個值都有名稱。 比較一下您將 OpenArgs 設為 “5,2” 的簡單方法。  在這種情況下,您必須費力找出每一個值所代表的內容。 為每個值命名會讓查詢字串「自我描述」,這是良好的程序設計做法。

DoCmd.OpenForm 的接收端,我們通常會在 Form_Open 或 Form_Load 事件中,並想要將 OpenArgs 字串剖析為其元件。

在 Northwind 中,您可以使用 StringToDictionary 函數執行此動作。 它會採用類似 querystring 的函數,並將它剖析為其元件。 這些元件接著會儲存在 Scripting.Dictionary 物件中。 請注意,您必須使用 [工具] > 參照 ,並設定 Microsoft Scripting Runtime (scrrun.dll) 的參照。

字典物件的功能和優點包括:  

  • 元素的順序不重要

  • 新增及移除集合元素的簡單函數

  • 可在集合上循環的函數,讓您可以知道其中的內容

  • [存在] 函數,讓您可以測試特定元素是否可用

字典物件的使用會顯示在整個北風。 例如,frmGenericDialog 中的Form_Load事件。

在 Access 中使用控制精靈建立的宏很少包含錯誤處理;使用控制精靈建立的 VBA 可能僅限於一般 MsgBox Err.Description

在 Northwind 2.0 中,我們示範如何在使用 VBA 程序代碼時改善此功能。 我們已實作所謂的 全域錯誤處理程式。 任何程式中發生的錯誤會呼叫全域層級的函數以顯示錯誤。 這裡最大的優點是錯誤處理是一致的。 此外,如果郵件需要變更 (例如,若要額外顯示錯誤編號或將錯誤記錄到檔案) ,則必須只在單一位置完成。 

clsErrorHandler 是實作錯誤處理程式碼的類別模組。 類模組會將所有主要和幫手函數集中保存在一個單元中,因此會封裝程序代碼。

AutoExec 宏稱為 modStartup 中的 Startup 函數。 在 Starter Edition 中,函數會建立 clsErrorHandler 實例,並將它儲存為全域變數,可在整個應用程式中使用。 在 Dev 版本中會使用靜態類別,請參閱類模組頂端的批注。

事實上,程式中的錯誤處理程式代碼非常一致,因此我們可以在不到五分鐘內使用特定的 VBA 程式代碼建立所有程式,並以適當的錯誤處理程式來載入每個程式。 () 範本中未包含代碼。 Northwind 2.0 Starter 和 Developer 範本版本最初都是使用此錯誤處理方法進行裝回。  '

改良的錯誤處理方式

從 Northwind Developer Edition 版本 2.2 開始,由於 Access 社群的意見反應,錯誤處理程式已經改進。 Starter 版本保持不變。 

基本上,在2023年4月發行的舊版 (2.0中,錯誤處理程式) :

Public Sub HandleError(…)     MsgBox Err.DescriptionEnd Sub

在版本 2.2 中,它會升級至:

Public Sub HandleError (…, Optional ByVal IsEventProcedure As Boolean = False)     If Not IsEventProcedure Then         Err.Raise lngError, strErrSource     End If     MsgBox Err.DescriptionEnd Sub

若要瞭解為何要進行這項變更,讓我們先瞭解執行程式代碼的原因:

  • AutoExec 宏呼叫啟動程式,會在開啟第一個窗體之前執行一些縮寫。

  • 使用者會與應用程式互動,例如開啟表單擊按鈕,導致事件程序啟動 ,例如Form_LoadcmdPrintInvoice_Click '

除了事件程式之外,應用程式還具有子程式和函數,大部分在模組中,而且該程式代碼是從事件程式來稱呼。 這些程式稱為「標準」程式。

在 Northwind 版本 2.0 中,標準程式會處理自己的郵件錯誤,但不會不知何故通知通話事件過程發生錯誤。 如果事件過程有後續程式代碼應該執行,而不論上述錯誤是由稱為程式所處理,這可能會造成錯誤。 當然,我們可以以會傳回成功或失敗的函數取代子程式,並據此為事件過程進行程式代碼,但這不一定是一個選項。

在 Northwind 版本 2.2 中,標準程式不會處理錯誤訊息,而是使用 Err.Raise 將它們回報回通話事件過程。 通話事件過程接著會在 Exit_Handler顯示起號錯誤和繼續。 這會比較好,因為它可讓通話程式有寬限地結束。

若要使用 Northwind 版本 2.2 代碼,事件程式必須傳遞至 HandleError 第三個自變數,指出來電者是事件過程。 Northwind Dev Edition 已更新為執行此動作。

功能更強大的錯誤處理程式模組支援「堆疊」 (陣列) 上的「推入和彈出」程式。 第一個元素一定是事件過程,因此不需要額外的自變數。 這項實作超出 Northwind Dev Edition 的目標。

MRU[最近使用 ] 是最近使用的訂單和採購單清單。 您可能會想要經常回到這些位置,將它們放在下一個狀態。 MRU 清單通常會以最近使用的檔案清單的形式顯示在 Office 產品中,而您可能會想要重新開啟。

在 Northwind Dev 版本中,若要實作在 Starter 版本中不存在的 MRU 功能 () 您必須先建立下列專案: 

  1. 儲存 MRU 資訊的數據表。

  2. 當訂單或採購單 (PO) 開啟時更新數據表的代碼。

  3. 更新功能區中 MRU 下拉式清單的程式代碼。

  4. 從功能區選取 MRU 專案時載入專案的程式代碼。

讓我們更詳細地查看這些專案。 

1. 儲存 MRU 信息的數據表。

數據表 MRU 的設計值得檢閱,尤其是其索引。 請注意,有重複的索引 SortIdx 可協助快速排序功能區下拉式清單中的 MRU 專案,以及一個唯一的索引,以強制執行商務規則,讓每個使用者的專案只能發生一次。 例如,開啟相同訂單兩次並不會在 MRU 數據表中建立兩筆記錄。

數據表利用資料庫中所有與 MRU 相關的 PK (主鍵) 欄位為 [自動編號],因此長整數數據類型可用於 PKValue

2. 開啟訂單或 P.O 時更新資料表的程式代碼。

在 NW2 中,我們選擇只在建立新記錄時,而不是在現有記錄再次更新時,才新增到 MRU 清單。 我們當然可以將 AddToMRU 通話從 Form_AfterInsert 移至 Form_AfterUpdate ,以支援此功能。

AddToMRUDeleteFromMRU 程式是在 modGlobal 中實作,這是標準模組,其公開程式可從任何表單顯示。

AddToMRU (,因為名稱建議) 將新專案新增至 MRU 數據表,然後選擇性地將它修剪回來,刪除最舊的記錄,如果它已經超過最大大小 (MAX_MRU_COUNT) 。 Access 開發人員可能最不瞭解上一個步驟:功能區下拉式清單必須重新整理,並透過呼叫 InvalidateControl 來完成。 這是要求功能區重新執行初始化程序的訊號。 

3. 更新功能區中 MRU 下拉式清單的程式代碼。 

啟動時,在調用 InvalidateControl 之後,會執行一組複雜的函數來填入功能區。  這些程式是由表格 uSysRibbons 中的功能區 XML 稱為部分:

<group id="gCurrentStatus" label="MRU">
    <box id="bxMRU" boxStyle="vertical">
        <dropDown id="ddMRU"
                  getItemCount="ddMRU_GetItemCount"
                  getItemLabel="ddMRU_GetItemLabel"
                  getSelectedItemIndex="ddMRU_GetSelectedItemIndex"
                  getItemID="ddMRU_GetItemID"
                  onAction="ddMRU_OnAction"
                  screentip="Most Recently Used Objects">
        </dropDown>
    </box>
</group>

這四個回撥函數會填入下拉式清單。 請注意,這與標準下拉式方塊的概 念非常相同。

如果您在modRibbonCallback 中取消核准Debug.Print線並重新啟動應用程式,[立即存取視窗] 會呈現如下所示的順序: 

ddMRU_GetItemCount    ddMRU    6 
ddMRU_GetItemLabel    ddMRU    0      Order 60, Proseware, Inc.
ddMRU_GetItemID       ddMRU    0       2 
ddMRU_GetItemLabel    ddMRU    1      Order 62, Best For You Organics Company
ddMRU_GetItemID       ddMRU    1       4 
ddMRU_GetItemLabel    ddMRU    2      Order 63, Wide World Importers
ddMRU_GetItemID       ddMRU    2       5 
ddMRU_GetItemLabel    ddMRU    3      Order 66, Proseware, Inc.
ddMRU_GetItemID       ddMRU    3       8 
ddMRU_GetItemLabel    ddMRU    4      Order 67, Best For You Organics Company
ddMRU_GetItemID       ddMRU    4       9 
ddMRU_GetItemLabel    ddMRU    5      Order 68, Adatum Corporation
ddMRU_GetItemID       ddMRU    5       10 
ddMRU_GetSelectedItemIndex  ddMRU    0

我們在此處可以看到,Access 會先呼叫會傳回在 ddMRU_GetItemCount ByRef 自變數中載入項目的程式。 這也是我們在 MRU 數據表上開啟查詢並快取它的時候,因為它即將要使用數次。 

功能區接著重複呼叫兩個程式,以取得兩欄下拉式清單的 [標識符] 和 [卷標] 值。 

最後,呼叫停用應選取項目的程式。  (在我們的案例中,這是第一個 )  

4. 從功能區選取 MRU 專案時載入項目的程式代碼。

與任何其他功能區項目一樣,功能區 XML 中的 OnAction 屬性指定要用來執行動作的回撥函數:

onAction="ddMRU_OnAction"

此程式是在 modRibbonCallback中實作。 它會重新使用已開啟的 Recordset 來尋找含有所選項目的記錄,然後根據需要的 TableName 開啟對應的表單,並傳遞要載入的 PK 值。

需要更多協助嗎?

想要其他選項嗎?

探索訂閱權益、瀏覽訓練課程、瞭解如何保護您的裝置等等。

社群可協助您詢問並回答問題、提供意見反應,以及聆聽來自具有豐富知識的專家意見。