在Excel VBA中可以引用Excel工作表函數(shù),也可以引用Excel VBA函數(shù),還可以引用用戶自己定義的函數(shù)或過程。除此以外,還可以調(diào)用Windows API。
Windows API包括幾千個可調(diào)用的函數(shù),這些函數(shù)是Windows提供給應(yīng)用程序與操作系統(tǒng)的接口,他們猶如“積木塊”一樣,可以搭建出各種界面豐富,功能靈活的應(yīng)用程序。它們大致可以分為以下幾個大類:
基本服務(wù);
組件服務(wù);
用戶界面服務(wù);
圖形多媒體服務(wù);
消息和協(xié)作;
網(wǎng)絡(luò);
Web服務(wù)。
Windows API使用 .lib 文件。.lib 文件也就是庫文件,分為靜態(tài)庫文件和動態(tài)庫文件(DLL)
靜態(tài)鏈接就是把靜態(tài)鏈接庫中的函數(shù)直接復(fù)制到程序中,成為程序的一部分。
動態(tài)鏈接是指在程序運行時將已駐留在內(nèi)存中的動態(tài)鏈接庫中的函數(shù)在需要時鏈接起來一起運行。
API 的 dll 在 windows 系統(tǒng)的 system32 目錄下, 圖形界面相關(guān)的 API 在 USER32.dll 里,進程、文件之類的操作在 kernel32.dll 里。MSDN 的每個函數(shù)都會說明它在哪個頭文件, 哪個 lib, 哪個 dll 里的。
動態(tài)鏈接庫中的函數(shù)可以被VBA調(diào)用,下面就以一個實例來說明。
在kernel32.dll中有一個 GetSystemDirectory()函數(shù),可以到到Windows的系統(tǒng)路徑。以下就是通過一個過程來調(diào)用這個函數(shù)的實例:
Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" _
(ByVal lpBuffer As String, ByVal nSize As Long) As Long
Sub info()
Dim sPath As String * 260, lLen As Long
lLen = GetSystemDirectory(sPath, 260)
Text3 = Left(sPath, lLen)
VBA.MsgBox (Text3)
End Sub
效果如下:
1.1查詢?nèi)绾蝹鬟f參數(shù)到DLL函數(shù)的Declare語句格式
為了調(diào)用Windows API中的函數(shù),需要描述這些可用的函數(shù)的文檔規(guī)范,如何在VBA中聲明這些函數(shù),以及如何調(diào)用它們。下面是兩個有用的資源:
I 可以使用API Viewer加載宏查找和復(fù)制需要的Declare語句。可以在下面的站點下載API聲明查看器:
http://www.activevb.de/rubriken/apiviewer/index-apiviewereng.html
登錄以下頁面后在以下點擊下載:
安裝后打開需要的文件:
即可查看可以使用的API及聲明:
II Microsoft Platform SDK,包含復(fù)雜的Windows API文檔??梢栽谙旅娴牡刂分胁榭矗篽ttp://www.office-cn.net/t/api/index.html?apihelp.htm
可以使用的API函數(shù)類別:
1.2 使用Declare語句
在從VBA中調(diào)用DLL里的函數(shù)之前,必須為VBA提供在哪里找到函數(shù)以及如何調(diào)用該函數(shù)的信息:
Declare語句是一個定義,告訴VBA在哪里找到特定的DLL函數(shù)以及如何調(diào)用該函數(shù)。在代碼中添加Declare語句最簡單的辦法是使用API Viewer加載宏,其中包含Windows API中大多數(shù)函數(shù)的Declare語句,也包含一些函數(shù)所需要的常量和類型定義。
Declare語句聲明的形式如下:
[Public|Private]Declare Sub name Lib "libname" [Alias "aliasname"][([arglist])]
[Public|Private]Declare Function name Lib "libname" [Alias "aliasname"] [([arglist])] [As type]
下面是GetTempPath函數(shù)的Declare語句的示例,該函數(shù)返回Windows臨時文件夾的路徑(默認(rèn)為C:WindowsTemp):
Private Declare Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" (ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
I 關(guān)鍵字Declare告訴VBA在工程中要包含的DLL函數(shù)的定義。在標(biāo)準(zhǔn)模塊中的Declare語句可以是公共的或私有的,取決于你希望API函數(shù)僅用于單個模塊還是整個工程。在類模塊中,Declare語句必須是私有的。
II 在關(guān)鍵字Function之后是函數(shù)的名字,具體地說,是從VBA中調(diào)用該函數(shù)時使用的名字。這個名字可以與API函數(shù)本身的名字相同,也可以在Declare語句中使用關(guān)鍵字Alias指定打算在VBA中通過不同的名字(別名)調(diào)用該函數(shù)。
III 在上面的示例中,在DLL中API函數(shù)的名字是GetTempPathA,從VBA中調(diào)用該函數(shù)時使用的名字是GetTempPath。注意,DLL函數(shù)的實際名字出現(xiàn)在關(guān)鍵字Alias之后,同時也注意到GetTempPath是Win32API.txt文件用于該函數(shù)的別名(有充分必要使用別名),但你可以將其改變?yōu)槿魏文阆胍拿帧?/p>
IV 關(guān)鍵字Lib指定包含函數(shù)的DLL。
1.3 在過程中調(diào)用API函數(shù)。
有如下任務(wù):判斷一個文件框如果內(nèi)容為空,則顯示一個提示文本框進行提示,并在3秒后自動消息。
我們知道,VBA提供以下代碼的提示對話框,但它需要用戶自己點擊關(guān)閉按鈕才可以關(guān)閉,不能滿足我們的需要。
MsgBox ("提示:編號不能為空!")
2.1 插入用戶窗體,并添加兩個文本框,如下:
2.2 在VBE中插入模塊,并添加以下代碼:
Private Declare Function MsgBoxTimeout Lib "user32" _
Alias "MessageBoxTimeoutA" ( _
ByVal hwnd As Long, _
ByVal lpText As String, _
ByVal lpCaption As String, _
ByVal wType As VbMsgBoxStyle, _
ByVal wlange As Long, _
ByVal dwTimeout As Long) _
As Long
Sub PopupMsgbox(Optional prompt As String = "OK", Optional title As String = "友情提示", Optional seconds As Long = 300)
MsgBoxTimeOut 0, prompt, title, 64, 0, seconds
End Sub
2.3 為文本框添加事件代碼:
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox1.Value = "" Then
'MsgBox ("提示:編號不能為空!")
PopupMsgbox "編號不能為空!", "提示", 1500 '1.5秒后提示窗口自動關(guān)閉
End If
End Sub
2.4 當(dāng)文本框為空,鼠標(biāo)光標(biāo)點擊到文本框以外的其它位置時,就會彈出提示對話框,并在1.5秒后自動關(guān)閉,如下:
MsgBoxTimeout()是一個未公開的 API 函數(shù)。
此函數(shù)的參數(shù)如下:
hwnd:消息框擁有者窗口的句柄,可以設(shè)為 0
lpText:消息框顯示內(nèi)容,類似于 MsgBox 函數(shù)的第一個參數(shù) Prompt
lpCaption:消息框標(biāo)題,類似于 MsgBox 函數(shù)的第三個參數(shù) Caption
wType:消息框類型,類似于 MsgBox 函數(shù)的第二個參數(shù) Buttons
wlange:函數(shù)擴展,一般取 0
dwTimeout:消息框延遲關(guān)閉時間,單位為毫秒
總結(jié)上例使用API的流程:
I Declare MsgBoxTimeOut
II 定義PopupMsgbox過程,在此過程中調(diào)用了MsgBoxTimeOut
III 在其他過程中調(diào)用PopupMsgbox()
也可以聲明后直接調(diào)用:
Dim i As Long
i = MsgBoxTimeout(0, "編號不能為空!", "提示", vbYesNo, 0, 1500)
-End-