本文所有論述和觀點均是基于Excel平臺,更準確的說是MS Excel……如無特殊情況,文中將不再作特殊說明。對VBA無感或無基礎者,本章可跳過,并不影響之后的SQL學習。
1.
ADO (ActiveX Data Objects,ActiveX數(shù)據(jù)對象)是微軟提出的應用程序接口,用以實現(xiàn)訪問關(guān)系或非關(guān)系數(shù)據(jù)庫中的數(shù)據(jù)……更多概念信息請自行咨詢百度君,無賴臉。之所以要學習ADO,一個原因是ADO自身的一些屬性和方法對于數(shù)據(jù)處理是極其有益的;而首要原因是,在EXCEL VBA中,一般只有通過ADO,才可以使用強大的SQL查詢語言訪問外部數(shù)據(jù)源,進而查、改、增、刪外部數(shù)據(jù)源中的數(shù)據(jù)。后面這話延伸在具體編程操作上,就形成了四步走發(fā)展戰(zhàn)略……嗯,這就好比你先找個女(男)朋友,然后談戀愛,最后才能結(jié)婚…… 2.
所謂前期綁定,是指在VBE中手工勾選引用Microsoft ADO相關(guān)類庫。在Excel中,按<Alt+F11>快捷鍵打開VBA編輯窗口,依次單擊【工具】→【引用】,打開【引用-VBAProject】對話框。在【可使用的引用】列表框中,勾選“Microsoft ActiveX Data Objects 2.8 Library”庫,或“Microsoft ActiveX Data Objects 6.1 Library”庫,單擊【確定】按鈕關(guān)閉對話框。Sub 后期綁定()
Dim cnn As Object
Set cnn = CreateObject('adodb.connection')
End Sub
兩種方式的主要區(qū)別是,前期綁定后,在代碼編輯過程中,VBE的“自動列出成員”功能,可以提供ADO的屬性和方法,這便于代碼快捷、準確的編寫,但當他人的Excel工作簿并沒有手工前期綁定ADO類庫時,相關(guān)代碼將無法運行;因此后期代碼綁定ADO的通用性會更強些,它不需要手工綁定相關(guān)類庫。星光俺老油……老江湖的經(jīng)驗是,代碼編寫及調(diào)試時,使用前期綁定,代碼完善后,再修改為后期綁定發(fā)布使用。 3.
不論我們使用SQL語言對數(shù)據(jù)源作何操作,都得首先使用ADO創(chuàng)建并打開一個由VBA到數(shù)據(jù)源的鏈接;這就好比得先修路,才能使用汽車運輸貨物。在VBA中,我們通常使用ADO的Connection.Open語句來顯式建立一個到數(shù)據(jù)源的鏈接。connection.Open ConnectionString, UserID, Password, OptionsConnectionString可選,字符串,包含連接信息。UserID可選,字符串,包含建立連接時所使用用戶名。Password可選,字符串,包含建立連接時所使用密碼。Options可選,決定該方法是在連接建立之后(異步)還是連接建立之前(同步)返回,默認是同步,adAsyncConnect是異步。……語法看起來似乎很復雜?不必煩擾,現(xiàn)在,對我們而言,重點只是大體了解一下參數(shù)ConnectionString,也就是連接字符串。雖然不同的數(shù)據(jù)庫或文件有不同的連接字符串,但常用的數(shù)據(jù)庫或文件的連接字符串均是固定的。舉個例子,如果將代碼所在的Excel(2016版)作為一個外部數(shù)據(jù)源建立鏈接,代碼如下:
Sub Mycnn()
Dim cnn As Object
'定義變量
Set cnn = CreateObject('adodb.connection')
'后期綁定ADO
cnn.Open 'Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties='Excel 12.0;HDR=yes;IMEX=0';Data Source=' & ThisWorkbook.FullName
'建立鏈接
cnn.Close
'關(guān)閉鏈接
Set cnn = Nothing
'釋放內(nèi)存
End Sub
說一下上面代碼連接字符串中各關(guān)鍵字(字體加粗部分)的意思。Provider是Connection 對象提供者名稱的字符串值,03版Excel是“Microsoft.jet.OLEDB.4.0”,其它版本可以使用“Microsoft.ACE.OLEDB.12.0”;Extended Properties是Excel版本號及其它相關(guān)信息,03版本是Excel 8.0,其它版本可以使用Excel 12.0。其中HDR項是引用工作表是否有標題行,默認值HDR=Yes,意思是引用表的第一行是標題行,標題只能一行,不能多行,亦不能存在合并單元格。HDR=no,意思是引用表不存在標題行,也就是說第一行開始就是數(shù)據(jù)記錄了;此時,相關(guān)字段名在SQL語句中可以使用f加序列號表示,第1列字段名是f1,第2列字段名是f2,其余以此類推,f是英文field(字段)的縮寫。IMEX項是匯入模式,默認為0(只讀模式),1是只寫,2是可讀寫。當參數(shù)設置為1時,除了只寫,還有默認全部記錄數(shù)據(jù)類型為文本的用途,關(guān)于這一點及其限制前提我們以后再談。Data Source是數(shù)據(jù)來源工作薄的完整路徑。VBA代碼Application.Version可以獲取計算機的Excel版本號,因此以下代碼兼顧了03及各高級版本Excel的情況:
Sub Mycnn3()
Dim cnn As Object
Dim strPath As String
Dim str_cnn As String
Set cnn = CreateObject('adodb.connection')
strPath = ThisWorkbook.FullName
If Application.Version < 12 Then
str_cnn = 'Provider=Microsoft.jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=' & strPath
Else
str_cnn = 'Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0;Data Source=' & strPath
End If
cnn.Open str_cnn
cnn.Close
Set cnn = Nothing
End sub
最后,需要提醒大家的是,鏈接是一種昂貴的資源(官方語),因此在代碼運行完畢后,請養(yǎng)成關(guān)閉鏈接(cnn.Close)并釋放內(nèi)存(Set cnn = Nothing)的好習慣。
連接字符串中各關(guān)鍵字的對應值可能和大小寫有關(guān),這是因為不同數(shù)據(jù)庫的要求可能不一樣,但通常來說,關(guān)鍵字和大小寫無關(guān),例如Provider,可以寫成provider或者PROVIDER。不過,雖然關(guān)鍵字和大小寫無關(guān),但和拼寫正確與否……當然是有關(guān)的?。ㄏ肷赌馗鐐儯浚┊斒执虻倪B接字符串代碼運行出錯時,建議先復制正確的運行,再仔細核對個人錯漏之處。連接字符串中各關(guān)鍵字之間使用英文分號(;)間隔,例如(關(guān)鍵字1=值1;關(guān)鍵字2=值2;關(guān)鍵字3=值3……),另外,任何包含分號、單引號或雙引號的值必須用雙引號引起來,由于在VBA中連接字符串的外層已經(jīng)存在了一個雙引號,因此通常使用英文單引號進行轉(zhuǎn)義,例如上例中的Extended Properties='Excel 12.0;HDR=yes;IMEX=2',抄寫時,千萬別漏了英文單引號哦。星光俺掐指一算,算出相當一部分童鞋英語水平堪憂,想來拼寫這段英文連接字符串錯漏百出是很有可能的,因此特呈上錦囊一份,參見下圖。別問我這圖是哪來的,如果不幾道,佛山無銀腳,出門右拐重看第一章吧~如果這錦囊您也不想用——其實收藏本帖,用到時打開帖子復制粘貼相關(guān)代碼就可以了——嘿嘿,木錯,這才是最常用的一招。聊完了如何綁定ADO以及建立與數(shù)據(jù)源的鏈接……我們可以使用ADO的Connection對象或Recordset、Commannd執(zhí)行SQL語句;詳細內(nèi)容我們放到ADO部分再講;這里大家只需要先了解Connection對象的Execute方法就可以了。這是一個最常用的VBA+ADO+SQL套路化查詢代碼,通常,我們只需要修改SQL語言以及放置查詢結(jié)果的單元格位置。
Sub DoSql_Execute1()
Dim cnn As Object, rst As Object
Dim strPath As String, str_cnn As String, strSQL As String
Dim i As Long
Set cnn = CreateObject('adodb.connection')
'以上是第一步,后期綁定ADO
'
strPath = ThisWorkbook.FullName
If Application.Version < 12 Then
str_cnn = 'Provider=Microsoft.jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=' & strPath
Else
str_cnn = 'Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0;Data Source=' & strPath
End If
cnn.Open str_cnn
'以上是第二步,建立鏈接
'
strSQL = 'SELECT 姓名,成績 FROM [Sheet1$] WHERE 成績>=80'
'SQL語句,查詢Sheet1表成績大于80……姓名和成績的記錄
Set rst = cnn.Execute(strSQL)
'cnn.Execute()執(zhí)行SQL語句,始終得到一個新的記錄集rst
'以上是第三步,編寫并使用SQL語句
'
[d:e].ClearContents
'清空[d:e]區(qū)域的值
For i = 0 To rst.Fields.Count - 1
'利用fields屬性獲取所有字段名,fields包含了當前記錄有關(guān)的所有字段,fields.count得到字段的數(shù)量
'由于Fields.Count下標為0,又從0開始遍歷,因此總數(shù)-1
Cells(1, i + 4) = rst.Fields(i).Name
Next
Range('d2').CopyFromRecordset rst
'使用單元格對象的CopyFromRecordset方法將rst內(nèi)容復制到D2單元格為左上角的單元格區(qū)域
'以上是第四步,將SQL查詢結(jié)果和字段名寫入表格指定區(qū)域
'
cnn.Close
'關(guān)閉鏈接
Set cnn = Nothing
'釋放內(nèi)存
End Sub
對于新手而言,本章的重點是了解VBA執(zhí)行SQL的操作過程,以及懂得復制第4節(jié)的代碼執(zhí)行SQL語句,僅此而已,其它?看過就算,大概過一眼,留個印象,以后再見面好說話也就行了。