MENU

AccessVBAの基礎

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
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAの学習中です。

目次