sk
2025/04/14 (月) 14:10:34
88328@16b16
実行時エラー'3061'
パラメータが少なすぎます。4を指定して下さい。
変数 strSQL に格納されている SQL がパラメータクエリになっているからです。
Forms![F_改修履歴に追加設定]![tx受付日付代入用]
Forms![F_改修履歴に追加設定]![tx改修内容代入用]
Forms![F_改修履歴に追加設定]![tx完了日付代入用]
Forms![F_改修履歴に追加設定]![tx_memo代入用]
以上の 4 箇所がそれぞれ暗黙的なパラメータとして認識されています。
そして DAO.Database オブジェクトの Execute メソッドでは、
パラメータへの値渡しを行うことが出来ません。
この場合は、次のいずれかの方法を用いるのが妥当です。
- フォーム[F_改修履歴に追加設定]がフォームビューで開かれている状態で、DoCmd オブジェクトの RunSQL メソッドを呼び出す( QBF 技法)。
'Access のシステムメッセージの表示を無効にする
DoCmd.SetWarnings False
'Access の[SQL の実行]アクションを呼び出す
DoCmd.RunSQL strSQL
'Access のシステムメッセージの表示を有効にする
DoCmd.SetWarnings True
- DAO.Database オブジェクトの CreateQueryDef メソッドにより一時的な QueryDef オブジェクトを作成し、Parameters プロパティ(コレクション)を介して値渡しを行った上、その QueryDef オブジェクトの Execute メソッドを呼び出す。
'フォーム[F_改修履歴に追加設定]のフォームモジュールから実行する場合
Dim dbTarget As DAO.Database
Dim qdfTemp As DAO.QueryDef
Dim lngInsertedCount As Long
'カレントデータベースの参照
Set dbTarget = CurrentDb
'一時的なクエリを作成する
Set qdfTemp = dbTarget.CreateQueryDef("", strSQL)
With qdfTemp
'各パラメータに値を渡す
.Parameters("Forms![F_改修履歴に追加設定]![tx受付日付代入用]").Value = Me![tx受付日付代入用].Value
.Parameters("Forms![F_改修履歴に追加設定]![tx改修内容代入用]").Value = Me![tx改修内容代入用].Value
.Parameters("Forms![F_改修履歴に追加設定]![tx完了日付代入用]").Value = Me![tx完了日付代入用].Value
.Parameters("Forms![F_改修履歴に追加設定]![tx_memo代入用]").Value = Me![tx_memo代入用].Value
'クエリを実行する
.Execute dbFailOnError
'クエリによって影響を受けたレコードの件数を取得する
lngInsertedCount = qdfTemp.RecordsAffected
End With
Set qdfTemp = Nothing
Set dbTarget = Nothing
If lngInsertedCount > 0 Then
MsgBox "[T_登録中継用_改修履歴]に " & lngInsertedCount & " 件のレコードが追加されました。", _
vbInformation, _
"実行完了"
Else
MsgBox "追加対象となるレコードがありません。", _
vbInformation, _
"対象レコードなし"
End If
後者の方法は、主に以下のようなケースにおいて用いるのが適しています。
特定のインターフェース(この場合はフォーム)に依存せず、パラメータに任意の値を直接渡したい場合
実行されたクエリ/SQLによって影響を受けたレコードの件数を取得したい場合
DAO.Workspace オブジェクトと連携してトランザクション処理を行いたい場合
通報 ...
なお、任意のコントロールの値を「 SQL 内におけるリテラル」として文字列連結させる手法もよく見られますが、以下のようなケースに備えてエスケープ処理を行うことが望ましいでしょう。
コントロールの値(文字列)にシングルクォーテーション( ' )やダブルクォーテーション(")、改行(などの制御文字)が含まれている場合。
コントロールの値が Null である場合。
DAO.QueryDef オブジェクトを使用してパラメータの値渡しを直接行なうのであれば、エスケープ処理は不要です。