iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 6
1
自我挑戰組

Access VBA的眉眉角角系列 第 6

Access VBA 的眉眉角角Day6: SQL語法於VBA中的應用2

  • 分享至 

  • xImage
  •  

上一篇我們提到了一些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按鈕來執行,以便查看程式執行方式是否符合需求
http://ithelp.ithome.com.tw/upload/images/20161207/20007221czPIQ8bOhB.png

當執行到「DoCmd.RunSQL strSQL」這行時,會跳出警號視窗
http://ithelp.ithome.com.tw/upload/images/20161207/20007221dW6je9I5VZ.png

當按下確定後,才會產生資料到新的資料表,而繼續執行下去,執行到「RunSQL strSQL」後,就會發現不會出現警告視窗,因為由「RunSQL」子程式,將警告功能關閉,等執行完「DoCmd.RunSQL」後再開啟,這個降低我們撰寫程式的時間,十分有用。

這個SQL語句為新增一個名為「海鮮類的產品」的資料表,因此可於資料表物件中看到此名稱。
http://ithelp.ithome.com.tw/upload/images/20161207/20007221qicS4eg3i8.png

點開後就是產生的資料
http://ithelp.ithome.com.tw/upload/images/20161207/200072211cwM8LphrI.png

另外,透過撰寫的「OpenTempQuery」子程式,則可生成一個查詢

http://ithelp.ithome.com.tw/upload/images/20161207/20007221fxgHKGgcVj.png

此查詢的內容其實跟上一個生成資料表內容一樣,只是我僅有查詢,沒有生成一個資料表物件,透過子程式來處理的好處,可省略手動建立查詢物件,且如果已有查詢物件,僅會更新SQL語句,物件的欄位寬度等「版面配置」資訊會保留,待下次開啟時,之前儲存的檢視方式還會存在。

http://ithelp.ithome.com.tw/upload/images/20161207/20007221GnNr3X4PIT.png

以上介紹,希望對各位撰寫Access VBA有幫助。


上一篇
Access VBA 的眉眉角角Day5: SQL語法於VBA中的應用1
下一篇
Access VBA 的眉眉角角Day7: SQL語法於VBA中的應用3
系列文
Access VBA的眉眉角角30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
jackalchen
iT邦新手 5 級 ‧ 2021-06-11 17:18:51

Andy您好
拜讀您所撰寫「Access VBA 的眉眉角角」文章,對於增進自我Access技巧大增,感謝您提供這個實用的文章
其中翻閱該文章中並無ifObjectExists的子程式的撰寫邏輯,所以在「Access VBA 的眉眉角角Day6: SQL語法於VBA中的應用2」的執行「OpenTempQuery測試()」會有出錯的情況。
不知您能否提供ifObjectExists的子程式?
謝謝您

Andy Chiu iT邦研究生 2 級 ‧ 2021-06-11 20:10:22 檢舉

感謝您的閱讀與回饋! 我找了一下,以下是這子程式的內容:

Public Function ifObjectExists(strObjName As String) As Boolean
    '檢查物件是否存在,包含資料表、查詢
    ifObjectExists = False
    If DCount("[Name]", "MSysObjects", "[Name] = '" & strObjName & "'") = 1 Then
        ifObjectExists = True
    End If

End Function

我要留言

立即登入留言