淺論 Excel VBA 的 MVC 框架

撰寫即時性的看盤資料分析,最簡單與方便的莫過於利用 Excel 了。工作表 (Worksheet)內的儲存格 (Cell)既可以當成如 DDE or RTD 的資料源,又能做計算邏輯與資料的呈現。而若牽涉到較複雜,如多個儲存格甚或多個工作表、多個工作簿 (Workbook)之間的資料處理,則可利用 Excel 內建的 VBE (Visual Basic Editor)程式開發編輯器來撰寫一般開發人員所認知的「巨集 (Macro)」程式。

VBE 編輯器會為每一個 Excel 檔案配置一個 VBA 專案 (VBAProject),每一個 VBAProject 可以有四種不同類型的資料夾 (Folder)-「Excel 物件」、「模組 (Module)」、「表單 (Form)」、「物件類別模組 (Class Module)」。其中「Excel 物件」資料夾是預設其內並預設了四個「This Workbook」、「工作表1」、「工作表2」、「工作表3」物件。
Excel VBA Project 組成

這裡帶出一個問題:VBA 程式碼該寫在這四種類型的哪一個資料夾 (或應該稱為哪一種類型的模組)?

或直接把其中最常見的問題更白話:不同工作表之間的資料篩選、處理與搬移等,VBA 程式碼的控制 (Control)與運算邏輯部分,該寫在「Excel 物件」還是「模組 (Module)」?

為了一次性解決 Excel VBA 程式碼結構議題,個人花了兩天的時間思考,先從這四種類型的物件 (可以把這四種資料夾想成四大物件類型)運用物件導向分析思維 (object-oriented analysis thinking)的「責任分派樣式 (responsibility assign pattern)」,先釐清這四大類物件的主要責任。

我這裡先利用 UML 類別圖 (class diagram),來表達出「VBAProject」與這四種類型的物件結構關係。
Excel VBA Project 的結構關係


其中,「Form」與「Class Module」比較容易釐清責任-「Form」提供視覺化 (visually)的表單操作;而「Class Module」在 VBA 環境被簡化為資料結構,例如「cls加權」類別有「成交價」、「開盤價」、「最高/最低價」、「成交量/預估量」...等屬性。(當然也可以包括該類別的操作方法,如「calc振幅()」、「get預估量()」等。)

最關鍵也最容易混淆的就是「Excel 物件」與「Module」這兩類型物件的責任區分了。

先直接給建議的解答:工作單/工作表 的事件處理 (Event-Handle),交給「Excel 物件」;控制/運算 邏輯,交給「模組 (Module)」。

基於「事件處理 (event-handle)」的考量,有關於該工作單或工作表 (Workbook/Worksheet)的事件 (Event)處理,建議就是寫在「Excel 物件」內的「ThisWorkbook」與「工作表」物件內。這倒也容易解釋:「Excel 物件」因有擔負「UI 的呈現 (present)」的責任,而 UI 元件 (如儲存格)很容易因有各類的操作而會觸發不同種類的事件。這些事件若有值得被捕捉 (capture)而需要處理,則落實在該事件的「Event Handler」內。

而至於不同工作表、甚或不同工作單 (每個工作單視為個別的檔案)的控制與運算邏輯,則應該是實現 (realize)在「模組 (Module)」內的程式碼。所以當工作表/工作單 捕捉到事件 (event)之後,即會委派 (delegate)給「Module」來實作。

這樣也就能導出關於 Excel 的「MVC (Model-View-Control」框架了。

View → 「表單 (Form)」、「Excel 物件」。
Control → 「模組 (Module)」。
Model → 「物件類別模組」。

由於 Excel VBA 並不如 C#/VB.NET 這類 OOP (object-oriented programming)來得嚴謹,且為了便利性,所以在上述的 MVC 框架上,責任會有些重疊,封裝 (encapsulate)也沒太過講究。

所以,「Excel 物件」如不考量跨工作單 (多個檔案)與連結外部資料源,且工作表本身即為 UI (沒有另外設計表單),則控制與運算邏輯可以簡化實現在其內的「ThisWorkbook」物件內。

而「模組 (Module)」的角色其實相當多元化。它既是 UI (這裡泛指「Excel 物件]內的工作表/工作單,以及「表單 (Form)」)的「Form Controller」),也可以是邏輯運算處理的「Functional Controller」,甚而還擔負了邏輯運算 (business logic)與連結外部資料源的資料處理。

所以若為了讓其責任更為明確,則「Module」還可以再區分為「FormServlet」、「FuncControl」、「Model」與「DAO (Data Access Object」等模組物件了。不過若非企業層級或產品的系統開發,倒也不致於如此需要講究,同時也可能造成程式碼分散的維護性議題,以及喪失了 Excel VBA 的簡易開發性了。(事實上,若為產品或企業層級系統的開發,也不至於會使用 VBA 來開發的。)

將 Excel VBA 程式碼規劃了基本的 MVC 框架,最主要當然就是可以讓這四大類型的物件責任更為明確,造成的效果就是降低「耦合性 (coupling)」,讓程式碼更具彈性度 (flexibility)。

※ References
 o Code Module And Code Names
 o Getting Started with VBA in Excel 2010
 o Excel Object Model Overview

文章導覽

   

共有 2 則迴響

  1. 原來Excel VBA也可以用MVC的觀點來分析…真是長知識

    若Excel VBA也可以,那應該沒什麼程式碼不行了

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *