Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Access 2016)
.Parameters 実行時エラー3265
投稿日時: 19/04/22 07:40:56
投稿者: ゴマゴマ

お世話になります。
 
やりたいこと
検索用フォーム(F_受注明細選択)で品種と寸法を条件に検索
→実行ボタンを押すとSQL文で絞り込んだテーブル(T_メインテーブル)のレコードが別フォームに表示され
→その際に絞り込んだレコードに対しユーザーIDを付ける
 
絞り込みまではうまくいくのですがユーザーIDを付ける際に.Parametersの条件のところで実行時エラー3265(要求された名前、または序数に対応する項目がコレクションで見つかりません。)が発生してしまいます。
 
いま作っているAccessは複数人で使うことを想定しているのでテーブルのレコードに不整合が起こらないよう先に使われているレコードは他の人に使われないようユーザーIDを付けようと考えています。
 
参考書によると他のフォームを参照して検索条件を付す場合「rs.open strSQL,cn」は使えないと載っていたので、.Parametersを使って再度検索しようと思いました。
 
実行時エラーの回避策をご教示ください。
 

Private Sub Form_Load()
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim cmd As ADODB.Command

    Set cn = CurrentProject.Connection
    Set rs = New ADODB.Recordset
    Set cmd = New ADODB.Command
             
    Dim strSQL As String
    
    strSQL = " SELECT * FROM T_メインテーブル" _
        & " WHERE T_メインテーブル.品種1=Forms!F_受注明細選択!選択した品種1txt AND T_メインテーブ      ル.品種2=Forms!F_受注明細選択!選択した品種2txt AND" _
        & " (T_メインテーブル.寸法 Between Forms!F_受注明細選択!寸法最初txt And Forms!F_受注明細選      択!寸法最後txt); "

    Me.RecordSource = strSQL
    
  With cmd
    .ActiveConnection = cn
    .CommandType = adCmdTable
    .CommandText = "T_メインテーブル"
    .Parameters.Refresh
    .Parameters("[品種]") = Forms!F_受注明細選択!選択した品種txt ←ここで実行時エラー3265発生 
    .Parameters("[品種2]") = Forms!F_受注明細選択!選択した品種2txt
    .Parameters("[寸法]") = Forms!F_受注明細選択!寸法最初txt
    .Parameters("[寸法]") = Forms!F_受注明細選択!寸法最後txt
    
    End With
    
    Set rs = cmd.Execute
    Do While Not rs.EOF
     rs!選択中ユーザーID = Me.ユーザーIDtxt
     rs.MoveNext
    Loop
 
   rs.Close:  cn.Close

End Sub

 
以上

回答
投稿日時: 19/04/22 10:15:54
投稿者: sk

引用:
絞り込みまではうまくいくのですがユーザーIDを付ける際に
.Parametersの条件のところで実行時エラー3265(要求された名前、
または序数に対応する項目がコレクションで見つかりません。)が
発生してしまいます。

引用:
With cmd
.ActiveConnection = cn
.CommandType = adCmdTable
.CommandText = "T_メインテーブル"
.Parameters.Refresh
.Parameters("[品種]") = Forms!F_受注明細選択!選択した品種txt ←ここで実行時エラー3265発生 
.Parameters("[品種2]") = Forms!F_受注明細選択!選択した品種2txt
.Parameters("[寸法]") = Forms!F_受注明細選択!寸法最初txt
.Parameters("[寸法]") = Forms!F_受注明細選択!寸法最後txt
 
End With

・パラメータクエリではなくテーブルを指定している。
 
・ありもしないパラメータを参照しようとしている。
 
引用:
やりたいこと
検索用フォーム(F_受注明細選択)で品種と寸法を条件に検索
→実行ボタンを押すとSQL文で絞り込んだテーブル(T_メインテーブル)のレコードが別フォームに表示され
その際に絞り込んだレコードに対しユーザーIDを付ける

引用:
strSQL = " SELECT * FROM T_メインテーブル" _
        & " WHERE T_メインテーブル.品種1=Forms!F_受注明細選択!選択した品種1txt AND T_メインテーブル.品種2=Forms!F_受注明細選択!選択した品種2txt AND" _
        & " (T_メインテーブル.寸法 Between Forms!F_受注明細選択!寸法最初txt And Forms!F_受注明細選択!寸法最後txt); "

この処理自体は、無理に ADO を使う必要はないようにも
思えますが。
(例えば更新クエリでも実現可能ですし)
 
引用:
いま作っているAccessは複数人で使うことを想定しているので
テーブルのレコードに不整合が起こらないよう
先に使われているレコードは他の人に使われないよう
ユーザーIDを付けようと考えています。

引用:
Private Sub Form_Load()

引用:
Do While Not rs.EOF
 rs!選択中ユーザーID = Me.ユーザーIDtxt
 rs.MoveNext
Loop

この仕組みで本当に競合を避けられるかどうかについては
現時点では不明。

回答
投稿日時: 19/04/22 10:52:34
投稿者: Suzu

パラメーターは、パラメータークエリに対して設定します。
 
つまり今回のレコードセットのレコードソースが
パラメータークエリでなく、テーブルなのでエラーとなります。
 
 

引用:
参考書によると他のフォームを参照して検索条件を付す場合「rs.open strSQL,cn」は使えないと載っていたので、.Parametersを使って再度検索しようと思いました。

 
どういう状況の事をもって「使えない」なのか判りませんが
 
Me.RecordSource = strSQL の部分。
レコードセットの SQLは、希望の条件での抽出は出来ているのですよね?
だったら、そのレコードセットを使えば良いのでは?
 
Set rs = Me.RecordSet
 
 
希望の動作についてですが。。
なぜ、IDを表示させなければならないのでしょうか。
誰が使用しているか表示の為だけの処理ですよね。
表示しないとダメなのですか?
 
 
結局、使用しているのは、連結フォームです。
Accessに任せるのが楽と思います。

投稿日時: 19/04/22 12:50:17
投稿者: ゴマゴマ

 sk様  Suzu様
 
早速にご回答ありがとうございます。
Accessを体系的に勉強したことが無いのでわからないまま難しいことをやろうとしている、と自分でも感じることがあります。できないことがあって回避策を考えてもそもそもが間違っていて(わかってなくて)、時間を無駄にするという悲惨なことに。。
 
「・パラメータクエリではなくテーブルを指定している。 ・ありもしないパラメータを参照しようとしている。 」「レコードセットのレコードソースがパラメータークエリでなく、テーブルなのでエラー」というのはとても勉強になりました。
 
簡単にできればと思いMe.RecordSource = strSQLの次にSet rs = Me.RecordSetを入れて実行したところ「実行時エラー13 型が一致いません」となりました。With〜End Withmまで一旦コメント化しました。Me.RecordSource = strSQLまではうまくいっていて検索条件通りのレコードがフォームに表示されます。
 
追加の質問となり恐縮ですが再度回避策を教示いただけばと思います。
 
以上
 
 

回答
投稿日時: 19/04/22 17:30:37
投稿者: sk

引用:
Dim rs As ADODB.Recordset

引用:
簡単にできればと思いMe.RecordSource = strSQLの次に
Set rs = Me.RecordSetを入れて実行したところ
実行時エラー13 型が一致いません」となりました。

この場合、フォームの Recordset プロパティによって返されているのは
ADO ではなく DAO の Recordset オブジェクトですので。
 
(フォームモジュール)
---------------------------------------------------
Private Sub Form_Load()
 
    Dim rs As DAO.Recordset
    Dim strSQL As String
     
    strSQL = " SELECT * FROM T_メインテーブル" _
           & " WHERE T_メインテーブル.品種1=Forms!F_受注明細選択!選択した品種1txt AND T_メインテーブル.品種2=Forms!F_受注明細選択!選択した品種2txt AND" _
           & " (T_メインテーブル.寸法 Between Forms!F_受注明細選択!寸法最初txt And Forms!F_受注明細選択!寸法最後txt); "
 
    Me.RecordSource = strSQL
 
    Set rs = Me.Recordset
    With rs
        Do Until .EOF
            .Edit
            ![選択中ユーザーID] = Me![ユーザーIDtxt]
            .Update
            .MoveNext
        Loop
    End With
    Set rs = Nothing
     
    Me.Requery
     
End Sub
---------------------------------------------------

回答
投稿日時: 19/04/22 17:42:12
投稿者: Suzu

確認できる環境でないので、、
 
レコードセットオブジェクトに、フォームのレコードソースを設定するのではなく
フォームのレコードセットプロパティーに、レコードセットオブジェクトを設定しましょうか。。
 
Private Sub Form_Load()
  Dim cn As ADODB.Connection
  Dim rs As ADODB.Recordset
  Dim strSQL As String
 
  Set cn = CurrentProject.Connection
  Set rs = New ADODB.Recordset
 
  strSQL = "SELECT * FROM T_メインテーブル " & _
    "WHERE " & _
    "T_メインテーブル.品種1=Forms!F_受注明細選択!選択した品種1txt " & _
    "AND " & _
    "T_メインテーブル.品種2=Forms!F_受注明細選択!選択した品種2txt " & _
    "AND " & _
    "(T_メインテーブル.寸法 Between " & _
        "Forms!F_受注明細選択!寸法最初txt " & _
        "And " & _
        "Forms!F_受注明細選択!寸法最後txt);"
 
  rs.Open strSQL, cn, adOpenKeyset, adLockOptimistic
 
  Do While Not rs.EOF
    rs!選択中ユーザーID = Me.ユーザーIDtxt
    rs.MoveNext
  Loop
  Set rs = Nothing
  Set cn = Nothing
End Sub
 
だといかがでしょう。

投稿日時: 19/04/22 18:44:37
投稿者: ゴマゴマ

Suzu 様
 
早速に助かります。
「rs.Open strSQL, cn, adOpenKeyset, adLockOptimistic」でやってみたところ「1つ以上の必要なパラメータの値が設定されていません」となり、このコードが黄色になりました(「Me.RecordSource = strSQL」はコメント化しました)。以前にもこのコードでやってみてダメだったので調べたところ「他のフォームを参照して検索条件を付す場合「rs.open strSQL,cn」は使えない」と載っていたので、.Parametersを使って再度検索しようと思った次第です。
 
sk様のDAOにつきましてはこれからやらせていただきます。
 
以上

回答
投稿日時: 19/04/23 09:35:30
投稿者: Suzu

ゴマゴマ さんの引用:

「rs.Open strSQL, cn, adOpenKeyset, adLockOptimistic」でやってみたところ「1つ以上の必要なパラメータの値が設定されていません」となり

 
SQLに問題がある事で表示されるメッセージです。
先のSQL生成の部分を下記に替えてください。
SQL側でフォームの値を参照するのではなく、VBA側で参照させて SQLを生成します。
さらに、直後 Debug.Print にて、SQL内容をイミディエイトウィンドに表示させる事で
SQLを容易に確認できる様にします。
 
   strSQL = "SELECT * FROM T_メインテーブル " & _
    " WHERE " & _
    " T_メインテーブル.品種1=" & Forms!F_受注明細選択!選択した品種1txt & _
    " AND " & _
    " T_メインテーブル.品種2=" & Forms!F_受注明細選択!選択した品種2txt & _
    " AND " & _
    " (T_メインテーブル.寸法 Between " & _
        Forms!F_受注明細選択!寸法最初txt & _
        " And " & _
        Forms!F_受注明細選択!寸法最後txt & _
    " );"
 
  Debug.Print strSQL
 
 
引用:
「他のフォームを参照して検索条件を付す場合「rs.open strSQL,cn」は使えない」と載っていたので、
.Parametersを使って再度検索しようと思った次第です。

 
そんな事は無いと思うのですが。。
カーソルがサーバーサイド かつ、SQLにフォーム参照を埋め込みと言う事でしょうかね。
具体的にそのサイトを提示できますか?

回答
投稿日時: 19/04/23 11:54:29
投稿者: sk

ゴマゴマ さんの引用:
「rs.Open strSQL, cn, adOpenKeyset, adLockOptimistic」でやってみたところ
「1つ以上の必要なパラメータの値が設定されていません」となり、
このコードが黄色になりました

ゴマゴマ さんの引用:
他のフォームを参照して検索条件を付す場合「rs.open strSQL,cn」は使えない

Recordset オブジェクトではパラメータの受け渡しが出来ませんので。
( ADO なら Command オブジェクトを介する必要がある)
 
ゴマゴマ さんの引用:
strSQL = " SELECT * FROM T_メインテーブル" _
        & " WHERE T_メインテーブル.品種1=Forms!F_受注明細選択!選択した品種1txt AND T_メインテーブル.品種2=Forms!F_受注明細選択!選択した品種2txt AND" _
        & " (T_メインテーブル.寸法 Between Forms!F_受注明細選択!寸法最初txt And Forms!F_受注明細選択!寸法最後txt); "

そもそもの話として、上記のような書き方をすれば
赤字部分は全てパラメータとして解釈されます。
(各コントロールの値を「 SQL 文内のリテラル」となるように
文字列連結しているわけではない)
 
ゴマゴマ さんの引用:
Me.RecordSource = strSQL

この場合は、フォームのレコードソースとして設定された
SQL を Access が解析して、上記赤字のパラメータに該当する
フォーム/コントロールの値を Access が受け渡してくれている
に過ぎません。
( Query By Form と呼ばれる技法/機能)
 
ゴマゴマ さんの引用:
With cmd
.ActiveConnection = cn
.CommandType = adCmdTable
.CommandText = "T_メインテーブル"
.Parameters.Refresh
.Parameters("[品種]") = Forms!F_受注明細選択!選択した品種txt ←ここで実行時エラー3265発生 
.Parameters("[品種2]") = Forms!F_受注明細選択!選択した品種2txt
.Parameters("[寸法]") = Forms!F_受注明細選択!寸法最初txt
.Parameters("[寸法]") = Forms!F_受注明細選択!寸法最後txt
 
End With
 
Set rs = cmd.Execute

(全体的な書き方が誤っている件については置くとして)
仮にパラメータの受け渡しが出来たとしても、
Command オブジェクトの Execute メソッドによって返されるのが
編集可能なレコードセットであるかどうかはまた別の話です。
 
Suzu さんの引用:
strSQL = "SELECT * FROM T_メインテーブル " & _
 " WHERE " & _
 " T_メインテーブル.品種1=" & Forms!F_受注明細選択!選択した品種1txt & _
 " AND " & _
 " T_メインテーブル.品種2=" & Forms!F_受注明細選択!選択した品種2txt & _
 " AND " & _
 " (T_メインテーブル.寸法 Between " & _
     Forms!F_受注明細選択!寸法最初txt & _
     " And " & _
     Forms!F_受注明細選択!寸法最後txt & _
 " );"

各コントロールの値を「 SQL 文内のリテラル」となるように
文字列連結するのであれば、比較対象となるフィールドのデータ型に応じて
数値リテラル/文字列リテラル/日時リテラルとして適切に解釈される書き方を
する必要があるでしょう。
(コントロールの値が Null である場合にも考慮する必要がある)

投稿日時: 19/04/24 07:03:31
投稿者: ゴマゴマ

sk様  Suzu様
 
できました!
Suzu様の「VBA側で参照させて SQLを生成」のコードとsk様の「フィールドのデータ型に応じて」を参考にあーでもないこーでもないと試行錯誤しましたら、結果思い通りの動作にすることができました(実際にはパラメータの部分は日付と文字がありましたが調べまくりました)。ほぼあきらめかけていたので、できたときには感動しました。お二人に感謝です。
引き続き宜しくお願い致します。
 
以上