上一篇我們提到了一些VBA的語法,這篇我們將運用這些語法,組合成另一個子程式,以便於後續程式開發。
自寫程式:
OpenTempQuery:餵給它SQL語法後,吐出表格內容,可便於使用者複製表格資料至Excel中繼續加工
Function OpenTempQuery(strQueryName As String, _
strSQL As String, _
Optional strDataMode As String = acReadOnly)
'建立與開啟暫時使用的查詢語句
'strQueryName 查詢名稱
'strSQL 查詢語句
'strDataMode 資料模式,可以選擇 acReadOnly,acAdd,acEdit
Dim strTemp As String
'加入前置名稱,以便於判斷
strTemp = "Q_TEMP_" & strQueryName
'如果Query存在,則變更SQL內容
'不存在,則建立一個新的,並填入SQL
If ifObjectExists(strTemp) Then
CurrentDb.QueryDefs(strTemp).SQL = strSQL
Else
CurrentDb.CreateQueryDef strTemp, strSQL
End If
'開啟此Query
DoCmd.OpenQuery strTemp, acViewNormal, strDataMode
End Function
RunSQL:餵給它SQL後,會安靜的執行,有需要時可將語法印到Debug視窗中,以便於調整程式
Function RunSQL(strSQL As String, _
Optional bnShowDebug As Boolean = False, _
Optional bnDebugPrintError As Boolean = False, _
Optional bnChgQuotationMark As Boolean = True)
' strSQL SQL語句
' bnShowDebug 是否秀出SQL語句於執行執行運算視窗中
' bnDebugPrintError 是否秀出錯誤訊息於執行運算視窗中
' bnChgQuotationMark 是否將單引號變更為雙引號
If bnShowDebug = True Then Debug.Print strSQL
If bnDebugPrintError = True Then On Error GoTo RunSQLOnError:
If bnChgQuotationMark = True Then
strSQL = Replace(strSQL, "'", """")
If bnShowDebug = True Then Debug.Print "ChgQM: " & vbCrLf & strSQL
End If
DoCmd.SetWarnings False
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
Exit Function
RunSQLOnError:
Debug.Print "SQL: " & strSQL
Debug.Print err.Number & ": " & err.Description
Resume Next
End Function
將這兩個子程式放置在上一篇建立的Public模組內,以便讓其他程式取用。
接下來,請各位再插入一個模組,改名稱為「範例」,並且把以下兩個範例程式複製到該模組內使用
Sub RunSQL測試()
Dim strSQL As String
strSQL = "" & _
"SELECT 產品資料.產品編號, 產品資料.產品, 產品類別.類別名稱 INTO 海鮮類的產品 " & vbCrLf & _
"FROM 產品類別 INNER JOIN 產品資料 ON 產品類別.類別編號 = 產品資料.類別編號 " & vbCrLf & _
"WHERE (((產品類別.類別名稱)='海鮮')) " & vbCrLf & _
"ORDER BY 產品資料.產品; "
'一般執行SQL,有寫入資料會跳出警告視窗
DoCmd.RunSQL strSQL
'使用子程式執行,跳過警告視窗
RunSQL strSQL
End Sub
Sub OpenTempQuery測試()
Dim strSQL As String
'使用查詢
strSQL = "" & _
"SELECT 產品資料.產品編號, 產品資料.產品, 產品類別.類別名稱 " & vbCrLf & _
"FROM 產品類別 INNER JOIN 產品資料 ON 產品類別.類別編號 = 產品資料.類別編號 " & vbCrLf & _
"WHERE (((產品類別.類別名稱)='海鮮')) " & vbCrLf & _
"ORDER BY 產品資料.產品; "
'開啟查詢
OpenTempQuery "海鮮產品", strSQL
End Sub
然後我們試著執行這兩個範例,各位可以用F5按鈕直接執行,或者F8按鈕逐行執行,如果於設計初期,我會建議用F8按鈕來執行,以便查看程式執行方式是否符合需求
當執行到「DoCmd.RunSQL strSQL」這行時,會跳出警號視窗
當按下確定後,才會產生資料到新的資料表,而繼續執行下去,執行到「RunSQL strSQL」後,就會發現不會出現警告視窗,因為由「RunSQL」子程式,將警告功能關閉,等執行完「DoCmd.RunSQL」後再開啟,這個降低我們撰寫程式的時間,十分有用。
這個SQL語句為新增一個名為「海鮮類的產品」的資料表,因此可於資料表物件中看到此名稱。
點開後就是產生的資料
另外,透過撰寫的「OpenTempQuery」子程式,則可生成一個查詢
此查詢的內容其實跟上一個生成資料表內容一樣,只是我僅有查詢,沒有生成一個資料表物件,透過子程式來處理的好處,可省略手動建立查詢物件,且如果已有查詢物件,僅會更新SQL語句,物件的欄位寬度等「版面配置」資訊會保留,待下次開啟時,之前儲存的檢視方式還會存在。
以上介紹,希望對各位撰寫Access VBA有幫助。
Andy您好
拜讀您所撰寫「Access VBA 的眉眉角角」文章,對於增進自我Access技巧大增,感謝您提供這個實用的文章
其中翻閱該文章中並無ifObjectExists的子程式的撰寫邏輯,所以在「Access VBA 的眉眉角角Day6: SQL語法於VBA中的應用2」的執行「OpenTempQuery測試()」會有出錯的情況。
不知您能否提供ifObjectExists的子程式?
謝謝您
感謝您的閱讀與回饋! 我找了一下,以下是這子程式的內容:
Public Function ifObjectExists(strObjName As String) As Boolean
'檢查物件是否存在,包含資料表、查詢
ifObjectExists = False
If DCount("[Name]", "MSysObjects", "[Name] = '" & strObjName & "'") = 1 Then
ifObjectExists = True
End If
End Function