【Access】毎日続ける!家計簿をAccessで作ってみた。⑤

家計簿の画像まりや

家計簿データベースの作成 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

家計簿データベースの作成 フォーム作成編へ