家計簿データベースの作成 VBA編
Visual Basic Editorを開く
家計簿入力フォームのデザインビュー画面を開きます。
VBE(Visual Basic Editor)を開く方法は色々とありますが、今回は登録ボタンを押したときの処理を書きますので、 フォームの登録ボタンをクリックしてプロパティシートのイベントタブから、クリック時の右側の[…]をクリックして開きます。
ビルダーの選択画面が開きますので、コードビルダーを選びます。

宣言セクションにOption Explicitと自動的に挿入されていない時は、変数の宣言を強制するようにします。
VBA(Visual Basic Application)では変数を宣言しなくてもエラーにならないので 、マクロがうまく動かなかった場合、どこが間違っているのか見つけるのに大変苦労します。
変数名を書き間違えた時はすぐにわかります。
面倒でも変数の宣言をするようにして下さい。
VBE画面の[ツール]の[オプション]をクリックして、[オプション]ダイアログボックスの[編集]タブにある「変数の宣言を強制する」にチェックを入れ、OKボタンを押します。
Option Compare Databaseの下にOption Explicitと入力して下さい。
以降、自動的に入力されます。


VBAのプログラムコードは、Private Sub 登録ボタン_Click()とEnd Sub、の間に入力します。
データベースにアクセスする
データベースへの接続方法
データベースにアクセスするにはDAO(Data Access Object)を使う方法と、ADO(ActiveX Data Objects)を使う方法の2つがあります。
DAOはAccessに特化したデータアクセス方法です。
Access以外のデータベースエンジン、OracleやSQL ServerにアクセスするときはADOを使いますが、今回はDAOを使います。
DAOに接続するための定型文
Dim db As DAO.Database ・・・・・・・・・①
Dim rs As DAO.Recordset ・・・・・・・・・②
Set db = CurrentDb ・・・・・・・・・・・③
Set rs = db.OpenRecordset(“テーブル名”)・・④
rs.Close ・・・・・・・・・⑤
Set rs = Nothing ・・・・・⑥
db.Close ・・・・・・・・⑤
Set db = Nothing ・・・・⑥
① Database型オブジェクト変数rsを定義します。
② Recordset型オブジェクト変数dbを定義します。
③ Setステートメントでオブジェクト変数dbにオブジェクトを関連付けます。
CurrentDb()関数はカレントデータベース(開いているデータベース)を返す関数
です。
④ OpenRecordsetメソッドでレコードセットを開きます。
⑤ ⑥ Closeでデータベースを閉じ、Nothingで変数を開放しています。
※ 変数名は何でもかまいません。
※ Dao.は省略できますが、DAOを使用することを明示的にするために使っています。
※以下のように省略して書くこともできます。
Dim myRecordset As DAO.Recordset
Set myRecordset = CurrentDb.OpenRecordset(“tbl_家計簿”)
myRecordset.Close: Set myRecordset = Nothing
入力データを反映させる処理
データベースに接続して新しいレコードを挿入する
AddNewメソッドで、家計簿入力フォームに入力したデータをtbl_家計簿の対応するフィールドに代入し、新規レコードを作成します。
Dim myRecordset As DAO.Recordset
Set myRecordset = CurrentDb.OpenRecordset(“tbl_家計簿”)
myRecordset.AddNew ‘
IDフィールドの処理
主キーに設定していますので、必ず入力しなければなりません。
If~Thenを使った条件分岐で、家計簿入力フォームのN_IDテキストボックスが未入力の時、入力を促すメッセージを表示します。
Meは家計簿入力フォームを表します。省略することもできますが、明示的に使っています。
If Not Me.N_ID = “” Then ‘N_IDテキストボックスが””でない時
myRecordset(“ID”) = Me.N_ID ‘tbl_家計簿の「ID」にデータを代入
Else
MsgBox “IDを入力して下さい。” ‘メッセージを表示し入力を促します
Me.N_ID.SetFocus ‘カーソルをN_IDテキストボックスへ移動
Exit Sub ‘処理が次の行に移動しないようSubプロシージャから抜け出します
End If ‘条件分岐を終了して次の行へ移動します
最初は
If Me.N_ID = “” Then
MsgBox “IDを入力して下さい。”
Me.N_ID.SetFocus
Exit Sub
Else
myRecordset(“ID”) = Me.N_ID
End If
としていたのですが、フォームを立ち上げたときは、N_IDが空白のままN_日付に移動してしまいます。
何回か確認してみたところ、どうも初めてフォームを立ち上げたときになるようです。
そのままフォームを閉じずに続けて入力したときは、2回目以降はちゃんと入力を促されるようになります。
インターネットで検索したところ、Accessのテキストボックスには初期値としてVariant型のEmpty値が設定されているのですが、非連結のテキストボックスの場合はNull値が設定されているようです。
Null値は、バリアント型の変数に格納される特殊な値(リテラル値)で、有効なデータが格納されていないことを表しています。
非常に理解することが難しいのですが、つまりIf Me.N_収入 = “” ThenではFalseになり、2回目以降ではテキストボックスを長さ0の文字列””でクリアしていますので、Trueになります。
これを回避する方法としては、Nz関数を使う方法と発想を転換する方法があります。
Nz関数を使う方法
If Nz(Me.ID,””) = “” Then
MsgBox “IDを入力して下さい。”
Me.N_ID.SetFocus
Exit Sub
Else
myRecordset(“ID”) = Me.N_ID
End If
発想を転換する方法
If Not Me.N_ID = “” Then
myRecordset(“ID”) = Me.N_ID
Else
MsgBox “IDを入力して下さい。”
Me.N_ID.SetFocus
Exit Sub
End If
※N_IDが””でなければ実行するようにします。
N_IDは長整数型に設定していますので、初期値としてNullが入っているか、
2回目以降は数値か””が入っていることになります。
つまり数値以外はElse以降に飛びます。
日付フィールドの処理
If Not IsDate(Me.N_日付) Then ‘入力された値が日付に変換できなっかた場合
MsgBox “日付を入力してください。”
Me.N_日付.SetFocus
Exit Sub
Else
myRecordset(“日付”) = Me.N_日付
End If
※IsDate関数・・・指定した値が日付に変換できる場合、Trueを返します。
費目名フィールドの処理
If Not Me.N_費目名 = “” Then
myRecordset(“費目ID”) = Me.N_費目名
Else
MsgBox “費目名を入力してください。”
Me.N_費目名.SetFocus
Exit Sub
End If
収入フィールドの処理
If Not Me.N_収入 = “” Then
myRecordset(“収入金額”) = Me.N_収入
Else
myRecordset(“収入金額”) = 0
End If
支出フィールドの処理
If Not Me.N_支出=”” Then
myRecordset(“支出金額”) = Me.N_支出
Else
myRecordset(“支出金額”) = 0
End If
獲得Pフィールドの処理
If Not Me.N_獲得P = “” Then
myRecordset(“獲得ポイント”) = Me.N_獲得P
Else
Me.N_獲得P = 0
End If
使用Pフィールドの処理
If Not Me.N_使用P = “” Then
myRecordset(“使用ポイント”) = Me.N_使用P
Else
Me.N_使用P = 0
End If
明細名フィールドの処理
If Not Me.N_明細名 = “” Then
myRecordset(“明細ID”) = Me.N_明細名
Else
MsgBox “明細名を入力してください。”
Me.N_明細名.SetFocus
Exit Sub
End If
カード使用日フィールドの処理
If IsDate( Me.N_カード使用日) Then
myRecordset(“カード使用日”) = Me.N_カード使用日
End IF
使用カードの処理
If Not Me.N_使用カード = “” Then
myRecordset(“使用カードID”) = Me.N_使用カード
End If
備考フィールドの処理
myRecordset(“備考”) = Me.N_備考
レコードを登録してデータベースの接続を終了する
myRecordset.Update
Me.Recalc
myRecordset.Close
Set myRecordset = Nothing
フォームのテキストボックスをクリアして新規入力へ戻る
Me.N_ID = “”
Me.N_日付 = “”
Me.N_費目名 = “”
Me.N_収入 = “”
Me.N_支出 = “”
Me.N_獲得P = “”
Me.N_使用P = “”
Me.N_明細名 = “”
Me.N_カード使用日 = “”
Me.N_使用カード = “”
Me.N_備考 = “”
Me.N_ID.SetFocus
End Sub
Dim myRecordset As DAO.Recordset
Set myRecordset = CurrentDb.OpenRecordset(“tbl_家計簿”)
myRecordset.AddNew
If Not Me.N_ID = “” Then
myRecordset(“ID”) = Me.N_ID
Else
MsgBox “IDを入力して下さい。”
Me.N_ID.SetFocus
Exit Sub
End If
If Not IsDate(Me.N_日付) Then
MsgBox “日付を入力してください。”
Me.N_日付.SetFocus
Exit Sub
Else
myRecordset(“日付”) = Me.N_日付
End If
If Not Me.N_費目名 = “” Then
myRecordset(“費目ID”) = Me.N_費目名
Else
MsgBox “費目名を入力してください。”
Me.N_費目名.SetFocus
Exit Sub
End If
If Not Me.N_収入 = “” Then
myRecordset(“収入金額”) = Me.N_収入
Else
myRecordset(“収入金額”) = 0
End If
If Not Me.N_支出=”” Then
myRecordset(“支出金額”) = Me.N_支出
Else
myRecordset(“支出金額”) = 0
End If
If Not Me.N_獲得P = “” Then
myRecordset(“獲得ポイント”) = Me.N_獲得P
Else
Me.N_獲得P = 0
End If
If Not Me.N_使用P = “” Then
myRecordset(“使用ポイント”) = Me.N_使用P
Else
Me.N_使用P = 0
End If
If Not Me.N_明細名 = “” Then
myRecordset(“明細ID”) = Me.N_明細名
Else
MsgBox “明細名を入力してください。”
Me.N_明細名.SetFocus
Exit Sub
End If
If IsDate( Me.N_カード使用日) Then
myRecordset(“カード使用日”) = Me.N_カード使用日
End IF
If Not Me.N_使用カード = “” Then
myRecordset(“使用カードID”) = Me.N_使用カード
End If
myRecordset(“備考”) = Me.N_備考
myRecordset.Update
Me.Recalc
myRecordset.Close
Set myRecordset = Nothing
Me.N_ID = “”
Me.N_日付 = “”
Me.N_費目名 = “”
Me.N_収入 = “”
Me.N_支出 = “”
Me.N_獲得P = “”
Me.N_使用P = “”
Me.N_明細名 = “”
Me.N_カード使用日 = “”
Me.N_使用カード = “”
Me.N_備考 = “”
Me.N_ID.SetFocus
End Sub