宏名不能隨便起

從前在講面授課程時,經常有同學會遇到一些「匪夷所思」的錯誤:一個非常簡單的小程序,看上去語法完全正確,可是卻根本無法運行。總結一下,發現很多都是與「宏的命名規則」有關,於是寫了一個文章專門討論一下這個問題,也就是給宏命名時必須避免的三種情況(其中第三種情況尤為特殊,而且似乎現在講清楚這個問題的中文資料也很少,所以加大篇幅深入討論了一下):

1. 與VBA保留字相衝突

經過《全民其一VBA 之 基礎篇》的學習,我想大家已經能夠理解,所謂「宏」,其實就是一個VBA子過程。而在VBA(以及絕大多數編程語言)中,變數、常量、過程、函數等需要自己命名的元素,絕對不可以與系統保留字重名,比如IF、For等。大家現在可以試一下,新建一個Sub For() ... End Sub,VBE馬上就會彈出下面的錯誤警告:

2. 與VBA常用字衝突

除了IF、For等保留字外,宏名也盡量不要與其他一些我們經常用到的對象名、函數名相同。比如,我們講過一個字元串函數 Left(),現在假如我們自己也寫一個函數,名字也叫作 left,那麼雖然編寫時VBE不會像前面那樣提示錯誤,但是運行時卻可能發生問題。因為當你想在別的過程中調用系統提供的字元串 Left 函數時,VBA會認為你調用的是你自己寫的那個Left函數,結果或者發生編譯錯誤,或者發生邏輯錯誤(即運行正常,但結果不正確),如下圖所示:

再舉一個例子,假如我們自己定義了一個過程叫做 range,那麼後面想通過 Range("3C")等方式操作單元格對象的時候,就會遇到類似錯誤:

3. 與單元格地址相同

宏命名的第三個常見錯誤最讓人頭疼。那就是,我們自己起的宏名,恰巧也符合Excel單元格地址的格式規則。比如宏名叫做「A5」或者「AZ232」,大家知道,這兩個名字同樣可以理解為工作表中的兩個單元格。而這時,往往就會導致莫名其妙的錯誤。

我們現在試驗一下,請大家新建一個宏,名字叫做 a2,裡面隨便寫一個什麼語句。接下來馬上轉到工作表中新建一個按鈕,再嘗試將該按鈕關聯到這個a2宏上。此時,你很可能就會遇到下圖這個錯誤:

這個問題的原因就在於,當一個宏的名字可以被理解為一個單元格地址(比如本例中的「a2」)時,這種命名方式就與Excel中一個絕對的「神秘故老『』——宏表——的編輯方式發生了衝突。至於什麼是宏表,相信現在99.9%的Excel用戶都沒有聽說過,而且也永遠不會需要用到它。這裡楊老師只說兩句:

(1)宏表是Excel4.0中的技術(從這個樸素的版本名稱可以看出,那時小茨領導下的微軟還是很純潔的)。而Excel4.0的推出年代,是1992年。是的,你沒有看錯,1992年!那是楊老師剛剛開始學習編程序的年代,那時我學慣用的電腦型號叫做長城0520,內存512K,硬碟大小10M,兩個5英寸軟碟機,以及一台CRT單色顯示器(人格擔保,一個字元都沒有打錯)。至今我還記得那時第一次看到一台竟然擁有1M內存和40M硬碟的286時,那種高性能所帶來的震撼感。(下圖是從網路上找到的長城0520照片)

(2)在隨後的Excel5.0中,宏表就被VBA所取代,但為了保持不同版本的兼容性,宏表這個功能至今仍然保留在最新版的Excel中,只是幾乎無人會去使用它。換句話說,宏表就是VBA的前身,所以它才會與我們今天的VBA代碼發生衝突。或者準確的說,我們上面這段出錯的代碼,其實屬於返祖現象(我們在VBA中使用了單元格地址做宏名,而宏表的特點之一就是部分代碼直接寫在單元格中),所以才導致了這個莫名其妙的衝突。

不好意思,遇到了懷舊的話題,不知不覺講了不止兩句話。總之楊老師想說的就是:請不要用疑似單元格地址作為宏的名稱!至於原因,與一個VBA始祖級的殭屍老古董有關,我們就不必深究了(貌似這種級別的老古董都是超級大BUG,比如《變形金剛4》裡面的禁閉,還有《X戰警》裡面的天啟……)。

當然,我們也不建議用單元格地址來做自定義函數的名稱,道理請大家自己思考。(提示:在單元格中寫 「=a2」 和寫 「=a2()」 是否會讓Excel困惑?)

好,關於宏命名的話題先到這裡,請大家在編寫程序時格外小心。要記住,VBA是依託於Office的一門腳本語言,在很多方面不得受到Office這個商品軟體的制約,所以很多時候會因為與編程完全無關的事情引發問題。解決辦法,無非就是積累經驗,當然還有谷哥度娘。而楊老師也會儘可能通過視頻教學與在線平台,把大家常犯的錯誤整理出來、逐期發布。


推薦閱讀:

增長黑客們都在使用什麼編程語言?
Python 2 系列壽命還剩幾年?
王垠:如何掌握所有的程序語言
Python入門容易掉進的10個坑
編程中的庫(包)是具體怎麼實現的,庫對於一個語言而言是不是非常重要?

TAG:VBA | MicrosoftOffice | 编程语言 |