AccessVBAの基本的な使い方をまとめてみました。
目次
----
全般
DoCmd
フォーム/コントロール
データベース操作
ADOとDAOの違い
ADO
DAO
===================================
..全般
===================================
起動時のマクロ実行
「AutoExec」という名前のマクロを作成する
Nullの判定
VBA、クエリ内の式、フォーム上のテキストボックスで使う場合
基本的には、IsNull(F1)を使う
F1 Is Nullも可
F1=Null、F1=""は使わない(エラーとはならないが、正しく判定されない)
長さ0の文字列が格納されている場合はF1=""を使う(基本的には格納されていない)
どのような場合に長さ0の文字列が入るのは不明
クエリの抽出条件に記入する場合
Is Null、Is Not Nullを使う
SQLも WHERE F1 Is NULL とする
(参考)ExcelVBAではIs Nullは使えない
Range("A1")=""とする
空欄でない判定
フォーム上のテキストボックスで使う場合
Not IsNull(F1)
F1 <> ""
Nullと長さ0の文字列(空文字列、="")
フィールドの定義
値要求が「いいえ」ならNullにできる
空文字列の許可が「はい」なら""(長さ0の文字列)を格納できる
値要求が「いいえ」、空文字列の許可が「はい」の場合、Null値と長さ0の文字列が混在する状況が発生しうる
フィールドの型による違い
文字列型 Nullあり、長さ0の文字列あり
数値型、日付型 Nullあり
Yes/No型 Nullあり
主キーはNullにできない
計算でのNull値の扱い(F1=Nullの場合)
Avg(F1)→正しく計算される
MsgBox(F1 + 1)→エラー発生
i = F1 + 1→エラー無、iはNullとなる
Nullのセット
日付型の変数には、Nullはセットできない
他の型はできる(v=Null)
長さの単位
Accessのプロパティで設定する場合 cm
VBAから設定する場合 twips(1cm = 567twips)
コンピューター名の取得
Option Compare Database
Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Function GetMyComputerName() As String
Dim strCmptrNameBuff As String * 21
GetComputerName strCmptrNameBuff, Len(strCmptrNameBuff)
GetMyComputerName = Left$(strCmptrNameBuff, InStr(strCmptrNameBuff, vbNullChar) - 1)
End Function
ネットワークユーザー名の取得
Option Compare Database
Private Declare Function WNetGetUser Lib "mpr" Alias "WNetGetUserA" (ByVal lpName As String, ByVal lpUserName As String, lpnLength As Long) As Long
Function NetUserName() As String
Dim strUserName As String * 255
If WNetGetUser("", strUserName, 255) = 0 Then
NetUserName = Left$(strUserName, InStr(strUserName, Chr$(&H0)) - 1)
Else
NetUserName = ""
End If
End Function
プリンタ名
Application.Printer.DeviceName
Application.Printer=Application.Printers("a")
通常使うプリンタに設定されているシステム既定のプリンタ名
ファイル名
CurrentProject.Path データベースファイルのあるフォルダ、最後の\は含まない
CurrentProject.Name データベースファイルの名前(短い名前)
CurrnetDb.Name データベースファイルのフルパス(名前を含む)
Dir(CurrentDb.Name) フルパスから短い名前を取り出す
関数
Nz(a,"")
Nullの場合に変換
第二引数を省略すると、文脈に応じて0、または""(空文字)
定義域集計関数
いずれも抽出条件は省略可
DSum("F1","T1","F2=1")
DCount("F1","T1","F2=1")
Nullはカウントされない
同じ値が入力されていても別々にカウント
DCount("*","T1") レコードの総数
DLookup("F1","T1","F2=1") 先頭のレコードが返る
DAvg(F1","T1","F2=1")
DMax("F1","T1","F2=1")
DMin("F1","T1","F2=1")
DFirst("F1","T1","F2=1") データが格納された順番で先頭
DLast("F1","T1","F2=1") データが格納された順番で最後
===================================
..DoCmd
===================================
DoCmdオブジェクト
データベースオブジェクトを操作するためのもの
データベースオブジェクト=テーブル、クエリ、フォーム、レポート
DoCmd.OpenTable "tbl1", acViewNormal, acEdit
第二引数
acViewNormal 既定
acViewDesign
acViewPreview
第三引数
acAdd
acEdit 既定
acReadOnly
DoCmd.OpenQuery "qry1"
引数はOpenTableと同じ
DoCmd.OpenForm "frm1"
DoCmd.OpenForm "frm1",acPreview
DoCmd.OpenForm "frm1", , ,"F1 = 1"
第二引数(ビュー)
acNormal 既定
acDesign
acPreview
acFormsDS
acLayout
第三引数(フィルタ名)
第四引数(フィルタ条件(SQL))
第五引数(データモード)
acFormPropertySettings 既定
acFormAdd
acFormEdit
acFormReadOnly
第六引数(ウィンドウモード)
acDialog
第七引数(OpenArgs)
開かれたフォームのプロパティOpenArgsから参照できる
複数形になっているが配列は渡せない(Stringのみ)
省略するとNull
DoCmd.OpenReport "rpt1", acPreview
DoCmd.OpenReport "rpt1", acViewNormal, , "F1=1"
引数はOpenFormとほぼ同じ(第二引数にViewを追加、データモードはない)
DoCmd.Save acForm, "Frm1"
DoCmd.Close
DoCmd.Close acForm, "Frm1" acSaveNo
acSaveNo 保存しない
acSavePrompt 保存確認のダイアログを表示(規定値)
acSaveYes 保存する
DoCmd.Close acReport, "rpt1"
DoCmd.RunSQL strSQL
DoCmd.RunMacro "mcr1"
DoCmd.Requery
DoCmd.SelectObject acForm, "T1"
データベースオブジェクトを選択肢してアクティブにする
acTable
acQuery
acFrom
acReport
描画停止
コードの実行が終了してもリセットされない
Application.Echo False ' 描画停止
Application.Echo True ' 描画再開
DoCmd.Echo False
DoCmd.Echo True
DoCmd.SetWarnings False システムメッセージ非表示(警告・確認メッセージ)
コードの実行が終了してもリセットされない
DoCmd.Hourglass True カーソル砂時計
SysCmd acSysCmdSetStatus, "abc" ステータスバーに表示
SysCmd acSysCmdClearStatus ステータスバーの初期化
レコードの抽出
DoCmd.GoToControl "btn1" コントロールにフォーカス移動(Me!btn1.SetFocus)
フォーカスのあるコントロール Me.ActiveControl
Screen.PreviousControl.SetFocus ' 直前にフォーカスのあったコントロール
DoCmd.GoToRecord acForm, "frm1", acNext レコード移動
DoCmd.ApplyFilter "", "F1=1" アクティブなテーブル、クエリ、フォームにフィルタ設定
DoCmd.ShowAllRecords フィルター解除
レコードの検索
DoCmd.OpenForm "Frm1"
DoCmd.GoToControl "F1"
DoCmd.FindRecord "10" 最初のレコードを検索
検索した値が存在するかどうかを調べたい場合はRecordsetを使う
DoCmd.FindNext 次のレコードを検索
DoCmd.Quit Access 終了
DoCmd.Quit acQuitPrompt 保存してない場合は確認のダイアログを表示する(既定)
acQuitSaveAll 全てのオブジェクトを保存
acQuitSaveNone 保存せず終了
Application.Quit acQuitPrompt 上記と同じ
DoCmd.CopyObject , "Frm2", acForm, "Frm1"
コピー(Frm1→Frm2)、コピー先を省略するとカレントデータベース
DoCmd.DeleteObject acForm, "Frm1"
DoCmd.Rename "Frm2", acForm, "Frm1" オブジェクトの名前の変更(Frm1→Frm2)
DoCmd.TransferText acExportDelim,,"T1","C:\a.txt",True
テキストファイルにエクスポート
acExportDelim カンマ区切りでエクスポート
acImportDelim(既定) カンマ区切りでインポート
True 1行目をフィールド名とする
False(既定) 1行目をフィールド名としない
DoCmd.TransferSpreadsheet
DoCmd.Maximize アクティブウィンドウを最大化(タブを使わない設定の場合)
DoCmd.Minimize アクティブウィンドウを最小化(同上)
DoCmd.Restore アクティブウィンドウを元のサイズに戻す(同上)
DoCmd.MoveSize 100,100,10000,5000 アクティブウインドウの移動とサイズ変更
水平位置,垂直位置,ウィンドウ幅,ウィンドウ高さ
単位はtwip(567twip=1論理cm、1論理cmは印刷したときに1cm)
DoCmd.PrintOut acPrintAll 開いているオブジェクトのアクティブなウィンドウを印刷
DoCmd.Beep 警告音を鳴らす
DoCmd.RunCommand acCmdZoom100
DoCmd.RunCommand acCmdCloseDatabase 今実行しているAccessファイルのみ閉じる(Access本体は終了せずに残る)
DoCmd.CloseDatabase 同上
PDF保存
DoCmd.PrintOut acPrintAll, 1, 1, acHigh, 1, True
From 開始ページ
To 終了ページ
Copies 印刷部数
Preview 印刷プレビュー
ActivePrinter プリンター名
プリンタ名 on ポート名
ActivePrinter:="PrimoPDF on Ne04:"
Application.ActivePrinter = "Printer A on LPT1:" と事前に変えてもよい(後で戻す必要あり)
アクティブプリンタの名前を調べる方法 Debug.Print Application.ActivePrinter
PrintToFile ファイルへの出力
Collate True=部単位で印刷
PrToFileName True=出力先のファイル名を指定
IgnorePrintAreas True=印刷範囲を無視してオブジェクト全体を印刷
複数シートを一括印刷
ページ設定(印刷品質を含む)を同じにすると、通常の印刷で一括で印刷できる(VBA不要)
別名保存でpdf作成
Dim i As Integer
Dim strFolder As String
strFolder = "C:\"
For i = 1 To 5
Cells(4, 6) = i
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=strFolder & Format(i, "000") & ".pdf", OpenAfterPublish:=False
Next
同名のファイルが既に存在している場合は、上書きされる
quality
xlQualityStandard 標準(規定値)
xlQualityMinimum 最小限
openafterpublish
True 保存後にpdfを開く
複数シートをpdf保存
Worksheets.Select ' 全シート
Worksheets(Array("Sheet1", "Sheet2")).Select
ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:=strFolder & Format(i, "000") & ".pdf", OpenAfterPublish:=False
PrimoPdfで連続印刷
'標準モジュールに記入
Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long
Sub Sub1()
Dim hWnd As Long
ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True, ActivePrinter:="PrimoPDF"
Do
hWnd = FindWindow(vbNullString, "PrimoPDF by Nitro PDF Software") ' ウィンドウタイトルからハンドルを取得
Loop While hWnd = 0 ' ウィンドウが開くまで待つ
SetForegroundWindow hWnd ' ウィンドウをアクティブ化
With CreateObject("Wscript.Shell") '保存先の所まで移動して名前をつける
'.SendKeys "{ENTER}"
Application.Wait (Now + TimeValue("0:00:05")) ' 2秒待つ
'.SendKeys "abc" ' ファイル名
'.SendKeys "{ENTER}"
End With
End Sub
(備考)
フォームやレポートのページ設定がプリンタを保持している。デザインで開いて設定する。
===================================
..フォーム/コントロール
===================================
フォーム
--------
主なコレクション
Forms 開いているすべてのフォーム(Application.Forms)
Reports 開いているすべてのレポート
Printers 使用可能なすべてのプリンタ
Me.Controls フォーム、レポート上のすべてのコントロール
CurrentProject.AllForms
CurrentProject.AllReports
Screenオブジェクト
Screen.ActiveForm アクティブなフォーム
Screen.ActiveReport アクティブなレポート
Screen.ActiveControl アクティブなコントロール
フォームの参照(レポートの参照も同じ)
Forms.frm1
Forms!frm1
Forms![frm1]
Forms("frm1")
コントロールの参照
Forms.frm1.con1
Forms.frm1!con1
Forms.frm1![con1]
Forms.frm1("con1")
Forms.frm1.Controls("con1")
Forms.frm1.Controls("txt" & i) 'コントロール名を変数で扱う
サブフォームの参照
Forms.frm1.subFrm1.Form
Me.Parent '親フォームの参照
サブフォームのコントロールの参照
Forms.frm1.subFrm1.Form.con1
フォーム上のすべてのコントロール
Forms("frm1").Controls
frm1.RecordSource = "Q1" クエリ、テーブル、SQLを指定
frm1.Section(0).BackColor = RGB(240, 240, 240)
frm1.CurrentRecord 現在のレコードのレコード番号を取得(設定は不可)
frm1.Undo レコードの変更を取り消し(レコード更新前)
frm1.RecordSelectors = True フォームにレコードセレクターを表示
抽出
frm1.Filter = "F1 = 1"
frm1.Filter = "F1 Like 'a*'"
frm1.FilterOn = True
並べ替え(設定、取得)
frm1.OrderBy = "F1 ASC,F2 DESC"
frm1.OrderByOn = True
検索
frm1.Recordset.RecordCount レコードの件数を取得
frm1.Recordset.FindFirst "F1 = 1" レコードを検索してカレントレコードにする
FindFirst
FindLast
FindNext
FindPrevious
If frm1.Recordset.NoMath Then 検索して見つからなかった場合
frm1.Recordset.MoveFirst レコードの移動
MoveFirst
MoveLast
MoveNext
MovePrevious
イベント
--------
コントロールのプロパティのイベントに、関数を直接記入する方法
ユーザー定義関数の場合
Private Function F1() '戻り値は無くても良い
Debug.print "a"
End Function
プロパティシートのイベント欄
=F1()
=F1("a") '引数がある場合
=F1([Name]) 'オブジェクト名(ボタンでも、なぜかフォーム名となる)
既存の関数の場合
プロパティシートのイベント欄「=[Requery]」
ウィンドウイベント
Open->Load->Resize->Activate->Current
Unload->Deactivate->Close
Open 開く時、Cancel可
Load 読み込み時
Resize サイズ変更時
Activate アクティブ時
Current レコード移動時(画面が表示される)
Unload 読み込み解除時、Cancel可
Deactivate 非アクティブ時
Close 閉じる時
データイベント
BeforeInsert->BeforeUpdate->AfterUpdate->AfterInsert
BeforeInsert 新規レコードが追加される前、Cancel可
BeforeUpdate データ更新される前、Cancel可
AfterUpdate
AfterInsert
Delete->BeforeDelConfirm->AfterDelConfirm
Delete レコードが削除される前、Cancel可
BeforeDelConfirm 削除確認のダイアログボックスが表示される前
AfterDelConfirm レコードが削除された後
削除がキャンセルされた後にも発生(引数Status = acDeleteOK、acDeleteCancel)
複数のレコードが一括して削除された場合、Deleteは複数回、BeforeDelConfirmは1回発生
キーボードイベント
KeyDown->KeyPress->Change->KeyUp
KeyDown
KeyPress ANSI文字コードに対応するキーを入力したとき
キー操作を無効にするには引数KeyAscii=0
If KeyAscii=8(BackSpace) Then
9(Tab)、13(Enter)、27(Esc)、Asc("a")
Change コントロールの内容が変化したとき
KeyUp
マウスクリックイベント
Click 左ボタンをクリックしたとき
印刷イベント
Format
レポートを印刷、プレビューする際に、セクションごとに発生
Me.PrintSection = Fasleとすると、そのセクションは印刷されない
詳細セクションではレコードごとに発生する
詳細セクションで、Me.改ページ.Visible = Trueとすると改ページされる
Print
フォーマットされた後、印刷、プレビューする前に発生
NoData
印刷するレコードがない場合に発生
引数Cancel=Trueとすると、印刷されない
GotFocusイベント コントロールがフォーカスを得たときに発生
Exitイベント コントロールがフォーカスを失う前に発生
Timerイベント 一定のの時間間隔で発生
Me.TimerInterval=1000(1秒)で時間間隔を指定
フォームのその他
----------------
var1 = SysCmd(acSysCmdGetObjectState, acForm, "frm1") 'フォームが開いているかどうか
フォームのスクロール位置を調整
通常のスクロールバー(フォーム)によるスクロール位置
単位はtwip、約567twip = 1cm
i=CurrentSectionLeft
GoToPage 1, -1*i, 0 ' 横スクロール(マイナスで取得されるので、-1をかける)
Forms.frm1.GoToPage 1, 5000, 0 ' 横スクロール
i=CurrentSectionTop
GoToPage 1, 0, -1*i ' 縦スクロール(マイナスで取得されるので、-1をかける)
Forms.frm1.GoToPage 1, 0, 2000 ' 縦スクロール
帳票フォームでRequeryの後に、スクロール位置を戻す
Dim i As Integer
i = Me.CurrentRecord ' 取得1(選択されているレコード)
Me.Requery
DoCmd.GoToRecord acDataForm, "frm1", acGoTo, i ' 移動
recordNumber = Forms![親画面名].[適当なレコードデータ].Parent.SelTop
(選択レコードが画面の途中にある場合に調整する方法)
Dim iCur,iTop As Integer
f1.SetFocus '任意のフィールドにフォーカスを移す
iCur = CurrentRecord
iTop = CurrentRecord - (Int(CurrentSectionTop / Section("詳細").Height) - Int(Me.Section("フォームヘッダー").Height / Me.Section("詳細").Height))
On Error Resume Next '必要
Me.Requery
If (i = 0) Then
i = 1
Else
If (i<30) And (Recordset.RecordCount > 30) then DoCmd.GoToRecord acDataForm, "frm1", acGoTo, 30 ' 最初に画面に表示されている30行程度を調整、選択セルが画面外(i<0)
DoCmd.GoToRecord acDataForm, "frm2", acLast
DoCmd.GoToRecord acDataForm, "frm1", acGoTo, iTop
DoCmd.GoToRecord acDataForm, "frm1", acGoTo, iCur
End If
ドラッグアンドドロップを受け付ける
Microsoft ProgressBar Controlを配置しプロパティOLEDropMode=1とする
他のAccessのFormを開く
Sub openAnotherAccessForm
Dim obj1 As Object
Set obj1 = CreateObject("Access.Application")
obj1.OpenCurrentDatabase CurrentProject.path & "\db1.mdb"
obj1.DoCmd.OpenForm "frm1"
obj1.Visible = True
obj1.UserControl = True 'その後、ユーザーに操作させる
Set obj1 = Nothing
End Sub
右クリックでコンテクストメニュー表示(フォーム上)
以下をModuleに記述
Private Sub makeMenu(m1 As Object)
Set m1 = Application.CommandBars.Add(Name:="myMenu",Position:=5, Temporary:=True)
With m1
With .Controls.Add
'.Caption = "メニュー1"
'.OnAction = "=MsgBox(""aa"")"
End With
With .Controls.Add
'.BeginGroup = True ' 直前に区分線
'.Caption = "メニュー2"
'.OnAction = "b1"
End With
End With
End Sub
Public Sub b1() ' module1に記述、引数不可
MsgBox Application.CommandBars.ActionControl.Caption ' メニュから実行される
End Sub
以下をフォームに記述
Private Sub txt1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim m1 As Object
If Button = acRightButton Then
Me.ShortcutMenu = False
Call makeMenu(m1)
gMenu1.ShowPopup
Application.CommandBars("myMenu").Delete
Set m1 = Nothing
End If
End Sub
Private Sub txt1_Exit(Cancel As Integer)
Me.ShortcutMenu = True
End Sub
OldValue による更新チェック
Function CheckOldValue() As String
Dim s As String
Dim con As Control
For Each con In Controls
If (con.Visible And (con.ControlType = acCheckBox Or _
con.ControlType = acComboBox Or _
con.ControlType = acListBox Or _
con.ControlType = acOptionGroup Or _
con.ControlType = 109 Or _
con.ControlType = acToggleButton)) Then
If (con.Value <> con.OldValue) Then s = s & con.Name & "(" & con.ControlSource & ")古:" & con.OldValue & " 新:" & con.Value & vbCrLf
End If
Next
CheckOldValue = s
End Function
ControlType
106 acCheckBox
107 acOptionGroup
109 acTextBox
111 acComboBox
コントロール
------------
ボタン
btn1.Caption コントロールの標題
btn1.Name 名前
テキストボックス
txt1.Value
txt1.Text コントロールにフォーカスがある場合のみ、Valueと同じ
txt1.Looked = True データが編集できるか
テキストボックスのスクロール(マウスホイール)
コードで制御する必要があり、簡単ではない
コンボボックス
cbo1.value = "a"
RowSource(リストボックスでの使い方と同じ)
comboBox1.RowSourceType = "Value List"
comboBox1.RowSource = "値1,値2"
comboBox1.AddItem "項目1",0
comboBox1.RemoveItem 0
comboBox1.RowSourceType = "Table/Query"
comboBox1.RowSource = "T1"
comboBox1.RowSourceType = "Field List"
comboBox1.RowSource = "T1"
タブコントロール
tab1.Value = 2
i = tab1.Value
tab1.Value = pge1.PageIndex
レポート
--------
rpt1.FillColor = RGB(255, 0, 0)
rpt1.FillStyle = 0 ' 塗りつぶし
rpt1.Line (0,0)-(100, 100) ' 始点x,y-終点x,y
rpt1.Line (0,0)-(100, 100), RGB(255, 0, 0),B ' 四角形
rpt1.Line (0,0)-(100, 100), RGB(255, 0, 0),BF ' 塗りつぶし四角形
rpt1.Circle (100,100),5,RGB(255, 0, 0)) ' 中心、半径、外周の色
rpt1.Circle (100,100),5,RGB(255, 0, 0),1,1,1 ' 始点、終点,縦横比
始点、終点:扇形の場合の始点、終点(ラジアン、-2π~2π)
縦横日:規定1.0
扇形は、両端の半径が描画されている円弧で塗りつぶし可能
始点を、0ではなく、-.00000001 等を指定する
レポートに直線や四角形を描く
イベント Print、Formatなどに記述する
ラベルやテキストボックスの位置はFormatでのみ指定可なのでFormatを使う方が便利
rpt1.DrawWidth = 11 ' 線の太さを変更
rpt1.DrawStyle = 6
0実線 (既定値)
1破線
2点線
3一点鎖線
4二点鎖線
5透明
6塗りつぶし
===================================
..データベース操作
===================================
...ADOとDAOの違い
-----------------------------------
DAO(Data Access Object)
古くからあり安定している。Accessに特化した仕組み
Access単体を扱うならDAOが適している
既定で参照設定されている
Mirosoft Office xx.x Access database engine Object Library
テーブルやクエリを作成する機能がある
CurrentDBを使う
ADOの多くの機能(RS、トランザクションなど)は、DAOで実現できる。
ADO(ActiveX Data Object)
Access2000からの新しい手法。VBA、VB、VBScriptなどから汎用的に使うことができる
Accessに限らずMicrosoft SQL Serverなどのデータベースに接続できる
Connectionを使う
DAOとADOで同じ名前のオブジェクトを宣言した場合、参照設定で上位にあるオブジェクトとして認識される。明示的に宣言したほうがよい。
Dim Rs As Recordset
Dim Rs As ADODB.Recordset
Dim Rs As DAO.Recordset
SQLの実行方法、RSの取得方法
DAO
CurrentDb.Execute strSQL 'アクションクエリのみ
Set RS = CurrentDb.OpenRecordset(strSQL)
Set RS = frm1.RecordsetClone
ADO
RS.Open strSQL,CN,adOpenStatic
Set RS = CN.Execute(strSQL) '常に前方スクロール、読み取り専用
DoCmd
DoCmd.RunSQL strSQL 'アクションクエリのみ
...ADO
-----------------------------------
ADOの主なオブジェクト
Connection
Command
Recordset
Field
Parameter
Property
Error
Connectionオブジェクト
----------------------
プロパティ
ConnectionString
State 接続状態
adStateOpen(接続している)、adStateClosed(接続していない)
メソッド
Open
Close
Execute
BeginTrans
CommitTrans
RollbackTrans
参照設定あり(Microsoft ActiveX Data Objects x.x Library)
カレントデータベースに接続
Dim CN As ADODB.Connection
Set CN = CurrentProject.Connection
CN.Openは不要
カレント以外のデータベースに接続
Dim CN As ADODB.Connection
Set CN = NEW ADODB.Connection
CN.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\a.accdb"
CN.Open
CN.Close
(別の記述方法)
Dim CN As New ADODB.Connection
CN.Open "Provider~"
CSVファイルへの接続
CN.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\;Extended Properties='Text:HDR=YES'" 'HDR=YESは1行目がフィールド名
CN.Open
Set RS = CN.Execute("SELECT * FROM a.csv")
(別の記述方法)
CN.Provider="Microsoft.Jet.OLEDB.4.0"
CN.Properties("Extended Properties")='Text:HDR=YES'
CN.ConnectionString="C:\"
CN.Open
Set RS = CN.Execute("SELECT * FROM a.csv")
Excelブックへの接続
CN.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\a.xlsx;Extended Properties='Excel 12.0:HDR=NO'" 'HDR=Noは1行目がデータ
CN.Open
Set RS = CN.Execute("SELECT * FROM [Sheet1$] WHERE [Sheet1$].F1 = 1") 'HDR=NOの場合、1列目から順番にF1、F2・・・と指定する
トランザクション
CN.BeginTrans トランザクションを開始
CN.CommitTrans トランザクションにおける変更を保存
CN.RollbackTrans トランザクションにおける変更を取り消し
Recordsetオブジェクト
---------------------
プロパティ
BOF
EOF
RecordCount
CursorType
CursorLocation
adUseServer(既定)、adUseClient
LockType
Bookmark
メソッド
Open
Close
Move 3 '3だけ移動
MoveFirst
MoveLast
MoveNext
EOF=TrueでMoveNextすると実行時エラー
MovePrevious
Find
Clone
AddNew
Update
Delete
Dim RS As ADOBD.Recordset
Set RS = New ADODB.Recordset
RS.Open "T1",CN,adOpenStatic
RS.Close
CN.Close
(別の記述方法)
Dim RS As New ADODB.Recordset
Set RS = CN.Execute("T1") '常に前方スクロール、読み取り専用、Newは不要
RS.Open
RS.Open "tbl1", CurrentProject.Connection, adOpenKeyset, adLockOptimistic
RS.Open "qry1"
RS.Open strSQL
Set RS = CN.Execute(strSQL) '常に前方スクロール、読み取り専用
CN.Execute strSQL 'アクションクエリの場合
第三引数(CursorType)
adOpenForwardOnly 既定、前方スクロールカーソル、その他は静的カーソルと同じ
前方以外に移動すると実行時エラー
adOpenKeyset キーセットカーソル、他のユーザーによる追加、削除は確認できない
adOpenDynamic 動的カーソル、他のユーザーによる追加、更新、削除を確認できる
adOpenStatic 静的カーソル、他のユーザーによる追加、更新、削除は確認できない
第四引数(LockType)
adLockReadOnly 既定
adLockPessimistic レコード単位の排他的ロック
adLockOptimistic レコード単位の共有的ロック
adLockBatchOptimistic 共有的バッチ更新
adLockUnspecified ロックタイプを指定しない
(別の記述方法)
RS.ActiveConnection = CN
RS.Source = "tbl1"
RS.Open
(基本形)参照設定なし
Sub sub1
Dim CN As Object
Dim RS As Object
Set cn = CurrentProject.Connection
Set RS = CreateObject("ADODB.Recordset")
RS.Open "T1", CN, adOpenKeyset, adLockOptimistic
RS.MoveFirst
Do Until RS.EOF
Debug.Print RS![F1]
RS.MoveNext
Loop
RS.Close
CN.Close
Set RS = Nothing
Set CN = Nothing
End Sub
Do Until RS.EOF
RS.MoveNext
Loop
フィールドの参照
RS![F1]
RS!F1
RS.Fields("F1")
RS("F1")
rs(s) 'フィールド名を変数で指定
RS.Fields(n)
RS(n)
レコードの更新
RS.Update "F1",1
RS("F1") = 1
RS.Update
Updateしてもカレントレコードは移動しない
※(SQL)UPDATE T1 SET F1=1;
レコードの追加
RS.AddNew "F1",1
Rs.AddNew Array("F1","F2"),Array(1,"a")
RS.AddNew
RS("F1") = 1
RS.Update
追加したレコードがカレントレコードになる
レコードの削除
RS.Delete カレントレコードが削除される、移動するまではカレントのまま
Do Until RS.EOF 全レコードの削除
RS.Delete
RS.MoveNext
Loop
(参考:SQL)DELETE * FROM T1;
レコードの検索
RS.Open "T1",CN,adOpenStatic '前方スクロールカーソル以外
RS.Find "F1=1"
カレントレコードが移動
複数条件の指定不可(DAOでは可)
見つからなかったらRS.EOF=True
Nullの検索はF1=Null
(参考)
DoCmd.FindRecord "10"
RS.FindFirst "F1 = 1"(DAO)
frm1.Recordset.FindFirst "F1 = 1"
レコードの並べ替え
RS.CursorLocation = adUseClient
RS.Open "T1",CN
RS.Sort = "F1 ASC, F2 DESC"
RS.Sort = "" '並べ替えの解除
※SELECT F1 FROM T1 ORDER BY F1;
frm1.OrderBy = "F1"、frm1.OrderByOn = True
レコードの抽出
RS.Filter = "F1=1 Or F2=2"
RS.Filter = "" 'フィルターの解除、カレントレコードは先頭に移動
※DoCmd.ApplyFilter , "F1=1"
frm1.Filter ="F1=1"、frm1.FilterOn = True
レコードセットをコンボボックス(リストボックス)に表示
RS.CursorLocation = adUseClient
RS.Open "T1",CN
Set list1.Recordset = RS
Set list1.Recordset = Nothing リストボックスの内容をクリア
list1.Requery
Errorオブジェクト
Dim error1 As ADODB.Error
error1.Number
error1.Source エラーを起こしたオブジェクト
error1.Description
...DAO
-----------------------------------
Data Access Object
カレントデータベースへの接続
Dim DB As DAO.Database
Set DB = CurrentDb
カレント以外のデータベースへの接続
Dim DB As DAO.Database
Set DB = OpenDatabase(path1)
SQLの実行
CurrentDb.Execute strSQL 'アクションクエリのみ(選択クエリは不可)
OpenRecordset
Set RS = CurrentDb.OpenRecordset(strSQL)
Set RS = CurrentDb.OpenRecordset("Q1")
(基本形)
Sub sub1
Dim DB As DAO.Database
Dim RS As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT F1 FROM table1;"
strSQL = "Q1"
Set DB = CurrentDb
Set RS = DB.OpenRecordset(strSQL)
RS.MoveFirst
Do Until RS.EOF
RS.Edit ' 編集モードにする
RS!F1 = 1
RS.Update
RS.MoveNext
Loop
Set RS = Nothing
Set DB = Nothing
End Sub
レコードの更新
RS.Edit ' DAOのみ
RS!F1 = "a"
RS.Update
レコードの検索
rs.FindFirst "F1 = '*a*'"
rs.FindNext
rs.FindPrevious
rs.FindLast
rs.NoMatch ' 見つかればFalse
(使用例)rs.FindFirst
Set db = CurrentDb
Set rs = db.OpenRecordset("tbl1", dbOpenDynaset) '前方スクロールカーソル以外
rs.FindFirst "F1 = '*a*'" ' 見つからなかった場合、RecordCount=全部
Do Until rs.NoMatch
Debug.Print rs!F2
rs.FindNext "F1 = '*a*'"
Loop
rs.Close
QueryDefs
strSQL = CurrentDb.QueryDefs("qry1").SQL ' クエリからSQLを取得
CurrentDb.QueryDefs("qry1").SQL = strSQL ' クエリにstrSQLをセット
qry1内に重複するフィールドがあるとエラーとなる
qry1内でソートしているとエラーとなる(ソートはフォームで行う)
テーブルの新規作成
Dim DB As DAO.Database
Dim TD As DAO.TableDef
Set DB = CurrentDb
Set TD = DB.CreateTableDef("T1")
TD.Fields.Append TD.CreateField("F1", dbText, 3) 'フィールドサイズ3
dbLong、dbDouble、dbDate、dbBoolean
DB.TableDefs.Append TD '同名のテーブルがあると実行時エラー
クエリの新規作成
Dim DB As DAO.Database
Dim QD As DAO.QueryDef
Set DB = CurrentDb
Set QD = DB.CreateQueryDef("Q1",strSQL) 'クエリを作成
Q1を省略すると一時的なクエリとして作成される
QD.Execute 'アクションクエリを実行
Set RS = QD.OpenRecordset() 'クエリをRSに格納
添付ファイルを保存
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("Select T1.* from t1 Where F1 = 'a';")
rs("F2").Value.Fields("FileData").SaveToFile "C:\" ' 添付ファイルが1個の場合
テーブルのフィールド名一覧を取得
For Each v In CurrentDb.TableDefs!T1.Fields
Debug.Print = v.Name ' フィールド名
Next