當前位置:成語大全網 - 新華字典 - 如何更新Excel的數據庫查詢函數庫

如何更新Excel的數據庫查詢函數庫

更新壹下之前寫的Excel的數據庫類,將其改成函數的形式,調用更簡單(省卻了生成類實例的步驟)。現在這個代碼在工作中用了壹年多,已經比較健壯。若有問題,請留言指出或與我聯系。

這些代碼有如下優勢:

無需任何配置。在VBA中新建模塊,並把代碼復制轉帖過去即可使用。

有以下函數:執行數據庫語句、查詢數據庫、結果復制到單元格(Excel中最常用)、將Excel表格上傳到數據庫。基本覆蓋Excel中對數據庫的常用操作。

會在立即窗口顯示數據庫錯誤信息,方便查錯。

在數據庫連接字符串字典中配好數據庫連接信息後,數據庫訪問時可直接使用配好的鏈接字符串。

具體的函數用法已經寫在下面代碼註釋裏。簡單描述壹下:

dqQueryToArray(sql, connection_string) 查詢數據庫,返回壹個二維數組

dbQueryOne(sql, connection_string) 查詢數據庫,返回單個變量。

dbQueryToCell(sql, range, connection_string, withHeader) 查詢數據庫後,將結果顯示在range開始的區域中;withHeader控制是否顯示列名。

dbExec(sql, necction_string) 執行數據庫語句;無返回值

dbInsertRange(table, range, connection_string, is_empty) 將本Excel文件的range區域裏的數據插入到數據庫的表table。其中is_empty控制在上傳數據前是否清空table的原數據。

其它就看壹下代碼吧:

' EXCEL的ADO數據庫操作函數庫

' 這些代碼應該放在Excel的VBA模塊中,類模塊的名字為database,並以以下形式引用:

'

' res = dbQueryToArry(sql, connection_string)

' ' 返回sql的查詢結果,結果為壹個二維數組

' res = dbQueryOne(sql, connection_string)

' ' 返回sql的查詢結果,但只返回第壹個數據(相當於數據庫查詢結果的左上角那個數據)

' dbQueryToCell sql, save_to_range, connection_string, withHeader

' ' 將sql的查詢結果直接寫入到以save_to_range開頭的單元格區域中

' ' withHeader控制是否復制表頭,默認為true(復制表頭)

'

' 其中參數sql為數據庫查詢語句,connection_string為數據庫連接字符串。

'

' 比如要連接SQL數據庫,並已經設置ODBC,連接字符串為:

' "Provider=MSDASQL;DSN=odbc_name;UID=username;PWD=password;database=database_name;"

' 如果未設置ODBC,連接字符串為:

' "driver={SQL Server};server=service_name_or_ip;uid=username;pwd=password;database=database_name;"

' 其中最後面的database變量可省略。對於SQL Server,推薦使用後壹種方法。

'

' 如果數據來源為Excel文件,connection_string參數可省略

'

' 其它功能:內置數據庫的連接字符串、查詢存儲過程

'

' Author: zhang@zhiqiang.org, 2014-03-01 v4

' url: n As Object, rst As Object, lastConn As String

Private Sub dbInitialize()

If Not sqlDict Is Nothing Then Exit Sub

Set sqlDict = CreateObject("scripting.Dictionary")

lastConn = ""

' 在這裏可以緩存壹些常用的數據庫信息,這樣在查詢數據庫時可以直接調用

' 比如dbQueryToArry(sql, "this")

With sqlDict

.Add "SQL服務器", _

"Provider=MSDASQL;DSN=odbc_name;UID=username;PWD=password;database=database_name;"

.Add "SQL服務器(無需配置ODBC)", _

"driver={SQL Server};server=ip;uid=username;pwd=password;database=database_name;"

.Add "this", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & _

";Extended Properties=Excel " & Application.Version & ";"

End With

End Sub

' 查詢數據庫,返回RecordSet對象

' sql: 數據庫查詢語句

' sqlConnectString: 數據庫連接信息,或者直接指定數據庫,比如"Wind"、"JYDB"等,

' 利用內設的數據庫連接信息

Public Function dbQuery(sql As String, _

Optional ByVal sqlConnectString As String = "this") As Object ' ADODB.Recordset

dbConnectSQL sqlConnectString

On Error GoTo errorhander

rst.Open sql, cnn

Set dbQuery = rst

errorhander:

dbDisplayError sql

End Function

' 查詢數據庫,返回壹個數組

' sql: 數據庫查詢語句

' sqlConnectString: 數據庫連接信息,或者直接指定數據庫,比如"Wind"、"JYDB"等,

' 利用內設的數據庫連接信息

Public Function dbQueryToArray(sql As String, _

Optional ByVal sqlConnectString As String = "this")

dbConnectSQL sqlConnectString

On Error GoTo errorhander

rst.Open sql, cnn

dbQueryToArray = rst.GetRows(10000000)

errorhander:

DisplayError sql

End Function

' 查詢數據庫,返回單個數值

' sql: 數據庫查詢語句

' sqlConnectString: 數據庫連接信息,或者直接指定數據庫,比如"Wind"、"JYDB"等,

' 利用內設的數據庫連接信息

Public Function dbQueryOne(sql As String, _

Optional ByVal sqlConnectString As String = "this")

dbConnectSQL sqlConnectString

On Error GoTo errorhander

rst.Open sql, cnn

dbQueryOne = rst.Fields.Item(0).value

errorhander:

dbDisplayError sql

End Function

' 查詢數據庫,返回單個數值

' sql: 數據庫查詢語句

' sqlConnectString: 數據庫連接信息,或者直接指定數據庫,比如"Wind"、"JYDB"等,

' 利用內設的數據庫連接信息

Public Function dbQueryToCell(sql$, Optional rng As Excel.Range, _

Optional ByVal sqlConnectString$ = "this", _

Optional withHeader As Boolean = True)

On Error GoTo error_handler

dbConnectSQL sqlConnectString

rst.Open sql, cnn

Set rng = rng.Cells(1, 1)

If withHeader = True Then

Dim i As Long

For i = 0 To rst.Fields.Count - 1

rng.Offset(0, i).value = rst.Fields(i).Name

Next

rng.Offset(1, 0).CopyFromRecordset rst

Else

rng.CopyFromRecordset rst

End If

error_handler:

dbDisplayError sql

End Function

' 執行任意數據庫語句,無返回結果。如需返回結果,請使用Query、QueryOne、QueryToCell等函數

' sql: 數據庫查詢語句

' sqlConnectString: 數據庫連接信息,或者直接指定數據庫,比如"Wind"、"JYDB"等,利用內設的數據庫連接信息

Sub dbExec(ByVal sql As String, _

Optional ByVal sqlConnectString As String = "this")

dbConnectSQL sqlConnectString

On Error GoTo errorhander

cnn.Execute sql

errorhander:

dbDisplayError sql

End Sub

' 這個函數用來上傳壹個Excel區域到數據庫,數據表必須事先建好,並且包括Excel區域的第壹行

' Database.InsertRange(table, rng, sqlConnectString, isEmpty)

' table:Excel數據將上傳到這個表內

' rng: 將被上傳的Excel區域

' sqlConnectString: 數據庫連接字符串

' isEmpty: 是否清空原有表格數據

Public Function dbInsertRange(table$, rng As Excel.Range, Optional ByVal sqlConnectString$ = "this", _

Optional isEmpty As Boolean = False)

dbConnectSQL sqlConnectString

On Error Resume Next

If isEmpty Then dbExec "delete from " & table, sqlConnectString$

Dim r As Long, sqlHead$, i As Long

' 首選根據isEmpty選項,刪除原表內所有數據

For i = 1 To rng.Columns.Count

sqlHead = sqlHead & ",[" & rng.Cells(1, i) & "]"

Next i

' 其次,依次拆入每行

' 目前每壹行都需運行壹個SQL語句,效率較低,如果數據量較大,可能會引起Excel死機

sqlHead = "insert into " & table & " (" & mid(sqlHead, 2, 10000000) & ") values "

For r = 2 To rng.rows.Count

Dim sql$

sql = ""

For i = 1 To rng.Columns.Count

Dim v

v = rng.Cells(r, i).value()

If IsError(v) Then v = ""

If IsDate(v) Then

sql = sql & ",'" & Format(v, "yyyy-mm-dd") & "'"

ElseIf v <> "" And IsNumeric(v) Then

sql = sql & "," & v

Else

sql = sql & ",'" & v & "'"

End If

Next i

dbExec sqlHead & " (" & mid(sql, 2, 1000000) & ")", sqlConnectString$

Next r

End Function

' 查詢存儲過程,返回的是ADODB.RecordSet對象

Public Function dbQueryStoredProc(procName$, para, _

Optional ByVal sqlConnectString As String = "this", _

Optional returnPara As Boolean = True) As Object 'ADODB.Recordset

On Error GoTo errorhander

dbConnectSQL sqlConnectString

With com

.ActiveConnection = cnn

.CommandType = adCmdStoredProc

.CommandText = procName

' 獲取存儲過程的參數定義

.Parameters.Refresh

' 如果存在輸出參數,則刪除它,默認第壹個為輸出參數

On Error Resume Next

If returnPara Then .Parameters.Delete 0

' 設置輸入參數的值

If IsArray(para) Then

Dim i

For i = 0 To UBound(para)

.Parameters.Item(i).value = para(i)

Next i

End If

' 改變輸入參數大小

Dim tmpp

For Each tmpp In .Parameters

tmpp.Size = 255

Next tmpp

' 獲取參數返回值

Set dbQueryStoredProc = .Execute()

End With

errorhander:

DisplayError sql

End Function

Private Sub dbClose()

' 當類被註銷時,斷開數據庫連接

On Error Resume Next

If cnn.State <> 0 Then cnn.Close

End Sub

' 連接數據庫

' 此處首先檢查cnn是否已經連接到想要連接的數據庫,如果已經連接,將不產生任何操作

' 本Database對象在對象存續過程中,不會主動斷開;

' 只有在對象註銷之時,才斷開數據庫,如需斷開數據庫連接,請set db = nothing

Private Function dbConnectSQL(ByVal sqlConnectString$) As String

On Error Resume Next

Call dbInitialize

If sqlDict.Exists(LCase(sqlConnectString)) Then

sqlConnectString = sqlDict.Item(LCase(sqlConnectString))

End If

If rst Is Nothing Then Set rst = CreateObject("ADODB.Recordset")

If cnn Is Nothing Then Set cnn = CreateObject("ADODB.Connection")

If cnn.State <> 1 Or lastCnn <> sqlConnectString Then

cnn.Close

Set cnn = Nothing

Set cnn = CreateObject("ADODB.Connection")

cnn.Open sqlConnectString

lastConn = sqlConnectString

End If

dbConnectSQL = sqlConnectString

End Function

' 顯示查詢數據庫過程中出現的錯誤信息,信息被顯示在立即窗口。

Private Sub dbDisplayError(sql$)

Dim e

If cnn.Errors.Count > 0 Then

Debug.Print cnn.Errors.Count & " errors found when exec """ & sql & """"

For Each e In cnn.Errors

Debug.Print "Error info: " & e.description & " Source: " & e.Source

Next e

End If

End Sub