Access 如何在程式內使用 SQL語法與VBA

自學了半年一直不懂,執行SQL有很多方法。許多的書也沒有明白的講解。
維基百科內的Access說明;初學者一定要去看啊。

在Access的VBA中執行SQL語句,有三種方法。
  • DoCmd.RunSQL:基於Access的物件方法,使用Microsoft Jet SQL,可以在SQL語句中可以使用VBA函式。需要在呼叫前設定DoCmd.SetWarnings False關閉提示或確認對話方塊。執行時在Access狀態列顯示進度條,可通過Esc鍵中止執行。不能取得SQL語句影響的記錄行數。不能將多個SQL語句的執行放在同一事務中。
  • CurrentDB.Execute:基於DAO物件,使用Microsoft Jet SQL,可以在SQL語句中可以使用VBA函式。能取得SQL語句影響的記錄行數。可以將多個SQL語句的執行放在同一事務中。
  • CurrentProject.Connection.Execute:基於ADO物件模型,連線到不同資料庫(Excel)。對Access使用ISO SQL標準語法並可以使用VBA函式。沒有提示或確認對話方塊的顯示。執行時沒有在Access狀態列顯示進度條,不可以通過Esc鍵中止執行。能取得SQL語句影響的記錄行數。可以將多個SQL語句的執行放在同一事務中。
例如:
Dim strSQL As String
strSQL = "SELECT * INTO [excel 8.0;database=d:\gz.xls].sheet1 FROM tableA WHERE tableA.city = 'gz' " 
 :REM 執行該函數進行SQL查詢 
CurrentProject.Connection.Execute strSQL

以上例子是ADO物件方法連結到Excel , 更多說明請連結 : 使用 ADO 查詢 Excel 試算表


自學了半年一直不懂,如何正確使用語法,在網路上依樣照抄也可以用,如下:

Set m=CurrentDB.OpenRecordset(“Select * From 客 戶”) 

為什麼SQL語法放在這裡面就可以用,很神奇的。更加深我的研究精神,雖然我還是不懂。
現在我懂了;因為這一篇文章片斷,我懂了CurrentDB是DAO的方法,如下:





DAO

DAO物件(Data Access Object)

資料來源 : http://jsl0924.myweb.hinet.net/access/aca4.htm

我們在Access 的表單劃面中,可以使用DAO或ADO物件,來存取其他的資料庫(excel)中的資料。
DAO說明前先了解Jet 是什麼:
  • Access採用 Microsoft Jet 資料庫引擎.
  • Microsoft Jet 資料庫引擎可以存取如 Access、FoxPro、dBase等關聯式資料庫
  • 所有的DAO查詢服務必須在本機上執行,遠端的資料需先傳送到本機才可處理。
  • Microsoft Jet是微軟針對檔案型資料庫所發展的資料庫引擎(Database Engine),它的適用資料來源種類相當多,像是Microsoft AccessMicrosoft ExceldBase等等檔案型資料來源都可以利用Microsoft Jet資料庫引擎就可以使用SQL指令目前的Jet引擎最新版本為4.0,並且未來在x64平台上將不再支援。
    使用Jet 連到Access.Text.Excel


DAO物件模型 For Microsoft Jet Workspaces:Access說明→內容→DAO 3.60

宣告(定義)物件變數

Dim ObjVar As MyClass:宣告一個物件變數,類別為 MyClass,此時物件尚未存在。
Set ObjVar = [ New ] MyClass :以 New ( 可省略 ) 產生一個物件,並用 Set 把他指派給 ObjVar 變數。 

開啟資料庫(OpenDatabase)

Set 參數一 = 數二.OpenDatabase (數三, 數四, 數五, 數六)
  • 參數一:database 資料庫物件變數。
  • 參數二:workspace 工作區名稱。預設是Workspaces ( 0 ),可省略。
  • 參數三:dbname 資料庫名稱,包含完整路徑。
  • 參數四:options True表示 " 獨佔 " ;False表示 " 共享 "。
  • 參數五:read-only True表示 " 唯讀 ";False表示 " 非唯讀 "。
  • 參數六:connect 連結資訊、密碼。
例如:
Dim db As Database
Set db = OpenDatabase ( " mydb.mdb ", False, False ) 
         
指派資料庫物件為目前資料庫的三個方法
  • Set db = DBEngine.Workspaces( 0 ). DataBases( 0 )  
  • Set db = DBEngine( 0 )( 0 )
  • Set db = CurrentDB( ) ( 使用 CurrentDb 函數 )
  • db.Close     '使用 Close 方法,關閉資料庫


建立記錄集(OpenRecordset)

For Database objects:
Set recordset = object.OpenRecordset (source, type, options, lockedits)
For QueryDef, Recordset, and TableDef objects:
Set recordset = object.OpenRecordset (type, options, lockedits)
  • recordset :記錄集物件變數。
  • object :想要建立記錄集的物件,如 Database, QueryDef, Recordset, and TableDef objects。
  • source :可以是資料表、查詢或者SQL陳述式。
  • type :記錄集型態。如 dbOpenTable ... 等,若在 MS Jet Workspace 建立記錄集,可以不指定型態,預設為 dbOpenTable ( 開啟資料表型態記錄集 )。 
  • options :如 dbAppendOnly, dbDenyWrite, dbDenyRead, dbReadOnly ... 等。 
  • lockedits :鎖定編輯。如 dbReadOnly, dbPessimistic, dbOptimistic ... 等
例如:
Dim rs As Recordset , sql As String
Set rs = db.OpenRecordset ( " 員工 " , dbOpenTable )
sql = " SELECT [姓名] FROM 員工 "
Set rs = db.OpenRecordset ( sql , dbOpenDynaset )
Set rs = db.OpenRecordset ( sql , dbOpenSnapshot )
記錄集的型態
語法型態說明
dbOpenTableTable-typeMS Jet Workspaces only 
dbOpenDynasetDynaset-typelinked table or query 預設值 
dbOpenSnapshotSnapshot-type
dbOpenForwardOnlyForward-only-typeODBCDirect Workspaces 預設值 
dbOpenDynamicDynamic-typeODBCDirect Workspaces only 
比較表:
RecordsetMembershipRecords Updatableresult of a query 
Table-typeCan changeCan add, change, delete N/A
Dynaset-typeFixedCan add, change, delete Yes
Snapshot-typeFixedFixedYes
Forward-only-typeFixedFixedYes
Dynamic-typeCan changeCan add, change, delete Yes
存取記錄集的資料
針對目前指標所在的當筆記錄。例如:存取記錄集中目前記錄的 " 姓名 " 欄位資料,以第三種方法最快。
  1. [LName] = rs.Fields("姓名").Value
  2. [LName] = rs("姓名")
  3. [LName] = rs![姓名]

移動記錄集指標

用以改變記錄集物件,目前所在記錄指標的位置。有 " 方法 " 和 " 屬性 " 兩種設定方式。
方法:
  • MoveFirst:第一筆
  • MoveLast:最後一筆
  • MoveNext:下一筆
  • MovePrevious:上一筆
  • Move rows [,start] :移動若干筆,從第幾筆開始
屬性:
  • BOF:Begin Of Flie 
  • EOF:End Of File 
  • RecordCount:記錄筆數
  • PercentPosition:位置百分比
注意:
  1. 若目前記錄指標 ( Current Row ) 已經在第一筆,BOF 屬性為 True,再使用 MovePrevious ,則BOF 屬性仍為 True,但會出現執行時期錯誤 ( run-time error )。
  2. 若目前記錄指標 ( Current Row ) 已經在最後一筆,EOF 屬性為 True,再使用 MoveNext ,則 EOF 屬性仍為 True,但會出現執行時期錯誤 ( run-time error )。

資料處理

更新記錄
  1. Edit method →Modify data →Update method 
  2. Run-time erroe if Update without Edit or AddNew
例如:
rs.Edit
rs("Last Name")=[LName]
rs.Update
新增記錄
  1. AddNew method →Add data →Update method
  2. Changes lost if no Update is executed
例如:
rsCustomers.AddNew
rsCustomers("Customer ID")="FINNF"
rsCustomers("Company Name")="Finnegan's Foods"
rsCustomers.Update
刪除記錄
Delete Method
  1. Removes current record
  2. No warning or prompt occurs
  3. Your code should move off deleted record
例如:
rs.Delete
If rs.EOF Then
  rs.MoveLast
End If

搜尋記錄

Find:
  • For a Dynaset-type or Snapshot-type Recordset Only 
  • 一筆一筆地比對
  • 使用屬性 " Bookmark " 儲存目前指標位置
  • FindFirst, FindLast, FindNext, FindPrevious 
語法:rs.FindFirst criteria ( criteria = any valid Where clause without Where. ) 
例如:
Public Sub DAO_Find()
  ...
  strFind="[職稱]='業務經理'"
  rs.FindFirst strFind
  Do Until rs.NoMatch
    Debug.Print rs("姓名")
    rs.FindNext strFind
  Loop
  ...
End Sub
注意:為了避免混淆,在雙引號中若需再加上雙引號,請使用單引號,加以區別。
Seek:
  • For a Table-Type Recordset Only 
  • 只能搜尋定義過 " 索引 " 的欄位 
  • 採 " 二分法 " 比對 
語法:rs.Seek comparisonkey1, key2... ( comparison:比較運算子 ) 
例如:
Public Sub DAO_Seek()
  Dim ...
  ...
  rs.INDEX="PrimaryKey"
  rs.Seek "=",7
  If Not rs.NoMatch Then
    Debug.Print rs("姓名")
  End If
  ...
End Sub

使用查詢物件

使用選取查詢
  1. Set QueryDef Object to Query ( 定義查詢定義物件 ) 
    • Dim qdf As QueryDef
    • Set qdf=db.QueryDefs("Products On Order")
  2. Set any Parameters ( 設定參數 ) 
    • qdf.Parameters("Beginning Date")=#01/01/94#
  3. Create Recordset ( 建立記錄集 ) 
    • Set rs=qdf.OpenRecordSet(dbOpenDynaset)
使用動作查詢
Execute Method - Executes an action query
  • No recordset created
  • Use DB_FailOnError to return a run-time error if query fails 
使用SQL
  1. SQL Select Statement
    • strSQL = " Selcet * From Employees "
    • Set rs = db.OpenRecordset ( strSQL, dbOpenDynaset )
  2. SQL Update Statement - Useful for batch updates 
    • strSQL = " Update Products Set [ Discount ] = 1 Where [ Discount ] = 0 " 
    • db.Execute strSQL, dbFailOnError
  3. SQL Insert Statememt - May be faster than AddNew
    • strSQL = " Insert Into Employees... "
    • db.Execute strSQL, dbFailOnError

Transactions ( 交易 )

一筆更新,將在兩個資料表產生對應的變動,而且必須同時完成。
  1. Transaction Methods of Workspace Object 
    • BeginTrans - begins a transaction
    • CommitTrans - commits all changes
    • Rollback - cancels all changes since BeginTrans 
  2. Transactions Can Improve Performance 

Lock ( 鎖定 )

以 Access 資料庫的查詢為例:
  1. 建立查詢→修改查詢中的某一筆記錄,並保持編輯狀態,
  2. 再開啟 MS Access →開啟同一個資料庫檔案。( 若以開啟舊檔方式開啟同一個資料庫,將無法產生二個資料庫視窗。)
  3. 開啟同一個查詢物件→修改同一筆記錄,
  4. 先後儲存查詢→測試記錄鎖定狀態,是否允許更新或修改。
查詢設計檢視→屬性→記錄鎖定:
  • 無鎖定:預設值。允許多使用者同時編輯,但儲存時進行鎖定。
  • 所有記錄:只允許一個使用者編輯同一個查詢。
  • 編輯的記錄:允許多使用者同時開啟同一個查詢,但不允許同時編輯同一筆記錄。
記錄鎖定屬性設定:
  • rs.LockEdits = True ( Pessimistic, 悲觀的 ) - Default
Lock from Edit through Update
  • rs.LockEdits = False ( Optimistic, 樂觀的 )
Lock during Update only 

設計具載入資料命令鈕的表單(DAO實作) 

修改同一個物件的多個屬性:
With 物件名稱
      .物件屬性1 = 屬性1
      .物件屬性2 = 屬性2
      ...
End With
將 Recordset 的指標,指定給表單的指標:
Me.Bookmark = rs.Bookmark 
RecordsetClone:
參照表單屬性 Recordsource 指定的 Recordset 物件。 
除了自行設計的表單之外,利用精靈建好表單,再建立按鈕→將程式碼由範例中複製過來→重新設定建立 Recordset 物件。
Private Sub Form_Load () 
  Set res = Me.RecordsetClone
End Sub

修改windows7資料夾瀏覽窗格內容--移除家用群組(Homegroup)、網路(Network)等

初始狀態


步驟1:開啟登錄檔編輯器
  操作:開始→搜尋列輸入regedit→在上方regedit按右鍵→系統管理員身分執行

打開後會跳出下圖


步驟2找到想要移除部分的機碼
   操作:ctrl+f搜尋→填入你要刪除的項目按enter
(好比我要刪除家用群組,我就複製{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}貼上)

各項目(要刪哪個填哪個)
我的最愛:
{323CA680-C24D-4099-B94D-446DD2D7249E}

媒體櫃:
{031E4825-7B94-4dc3-B131-E946B44C8DD5}

家用群組:
{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}

網路:
{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}


效果如下

步驟3點開你搜到的機碼ShellFolder上按右鍵→選使用權限

步驟4:選Administrator→允許完全控制

步驟5選擇Attributes點右鍵選擇 "修改修改數值資料,填入新資料確定完成


各項目新數值(要改哪個填哪個)
我的最愛:
a9400100

媒體櫃:
b090010d

家用群組:
b094010c

網路:
b0940064

步驟6登出或重開機就可以看到結果(我刪了家用群組跟網路)




最後附上原始機碼位置

我的最愛:
HKEY_CLASSES_ROOT\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder

媒體櫃:
HKEY_CLASSES_ROOT\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}\ShellFolder

家用群組:
HKEY_CLASSES_ROOT\CLSID\{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}\ShellFolder

網路:
HKEY_CLASSES_ROOT\CLSID\{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}\ShellFolder

Windows Media Player 關閉服務

自重安裝了Windows Media Player 11以後
執行msconfig在啟動那邊就會出現這個東西wmpnscfg.exe。
解決方法程序如下:
1.關閉服務
我的電腦-控制台-系統管理工具-服務
Windows Media Player Network Sharing Service 關閉服務

2.關閉媒體共用
開啟Windows Media Player 11工具-選項-媒體櫃-設定共用-共用我的媒體
2.關閉媒體共用
開啟Windows Media Player 11工具-選項-媒體櫃-設定共用-共用我的媒體(不勾選按確定)
 
3.開始-執行輸入regedit到
HKEY_CURRENT_USER\Software\Microsoft\MediaPlayer\Preferences\HME
底下的 DisableBrowse修改成 2 (16進位)
 
4.開始-執行輸入regedit到
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
底下將wmpnscfg.exe項目刪除

不要使用ACCESS的自動儲存功能

access在資料表的設計是只要離開該紀錄,就自動幫你儲存,所以

子資料表的部分只要一離開子表單,或游標移到另一紀錄就無法復原了

按\"新增\"或\"修改\"後,輸入了幾個欄位的資料後,
在按下\"取消\"指令鈕後,
之前有輸入欄位的資料會回復到原先的樣子,用意是在不要使用ACCESS的自動儲存功能

如果真要做到這效果,可能要在開啟表單前

動態產生一個暫存的資料表,
子表單抓的是這暫存表的資料表,如果使用者按下"取消",就從原資料表重新產生這暫存的資料表,
子表單畫面再requery即可,當然如果使用者沒按"取消"的話,你還要記得把暫存資料表再更新回原資料表