Access (VBA)

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

 
(Windows 10 Pro : Access 2016)
DAOからADOに書き換えでの不具合について
投稿日時: 20/07/23 00:07:53
投稿者: ai

いつもお世話になっております。
DAOからADOに書き換え、上手く動いていないものが発見されました。
ご教示頂けましたら幸いです。VBAは以下の通りです。
 
 
     
Dim db As ADODB.Connection
Dim cmd As ADODB.Command
Dim prm As ADODB.Parameter
                     
                     
Dim rs1 As ADODB.Recordset
Dim rs2 As ADODB.Recordset
 
 
Dim pr1 As Date '抽出日
     
            
Set db = CurrentProject.Connection
                          
Set cmd = New ADODB.Command
                          
                         
Set cmd.ActiveConnection = db
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "Q_クエリ名1"
Set prm = cmd.CreateParameter("[Forms]![F_フォーム名]![日付]", _
                                                       adDate, adParamInput, , pr1)
cmd.Parameters.Append prm
Set prm = Nothing
 
            
Set rs1 = cmd.Execute
 
 
Set rs2 = New ADODB.Recordset
rs2.Open "テーブル名1", db, adOpenKeyset, adLockOptimistic
                                                           
Do Until rs1.EOF
 
   rs2.AddNew
   rs2!伝票番号 = rs1!伝票番号
 
   rs2.Update
 
   rs1.MoveNext
 
Loop
 
rs1.Close
rs2.Close
 
Set rs1 = Nothing
Set rs2 = Nothing
Set db = Nothing
 
 
起きている現象なのですが、クエリの抽出条件が一部しか機能しておらず、
関係のないファイルまで出力されてしまいます。
 
尚、「Q_クエリ名1」には「項目1」に[Forms]![F_フォーム名]![日付]というパラーメータの他に
クエリの抽出条件に
 
「項目2」に「Not Like "0111*" And Not Like "0112*" And Not Like "0113*"
       And Not Like "9*"」
「項目3」に「Is Not Null And <>"998"」
「項目4」に「Is Null」
「項目5」に「Off」
「項目6」に「"通常"」
「項目7」に「"2"」
 
 
という抽出条件を付けています。
DAOでは「Q_クエリ名1」を使って1レコードずつ読み込んで、処理で来ていたのですが、
ADOでは「Q_クエリ名1」の抽出条件が上手く機能しなくなってしまいました・・・。
 
「項目2」にちゃんと0111から始まるものは抽出しないよう定義しているのに
抽出された結果に0111から始まる条件の伝票番号が出てきてしまっているようです・・・。
 
原因が分からず困っているのですが、
例えば、ADOでは「Not Like "0111*"」などを使ったクエリは
正しく出ないなどはありますでしょうか?
(rs1.RecordCountの結果は、必ず-1が入ってしまいDAOと同じように
 使えないというのは発見しました。もしかしたらその類でしょうか・・・。)
 
DAOからADOの書き換えで、
もしかして、クエリまで修正を入れないと正しく動かないものがあるのでしょうか?
原因が分かりましたらご教示の程よろしくお願い致しますm(_ _)m

回答
投稿日時: 20/07/23 11:10:55
投稿者: hatena
投稿者のウェブサイトに移動

ai さんの引用:
原因が分からず困っているのですが、
例えば、ADOでは「Not Like "0111*"」などを使ったクエリは
正しく出ないなどはありますでしょうか?

ADOでのワイルドカードは * ではなく % です。
 
Access VBA:ADOでLike演算子を使用する場合のワイルドカード文字は”*”ではなく”%”を使用する
https://selifelog.com/blog-entry-338.html
 

投稿日時: 20/07/25 09:58:16
投稿者: ai

hatenaさん
 
ありがとうございました!
%を使うとACCESSのクエリを実行した上(ADO上ではなく普通に実行した場合)では
今後は逆に動かなくなるようですので、ADO用のクエリを新たに作成して対応しました。
 
追加で質問で大変申し訳ないのですが、もしご存じでしたら
DAOからADOに書き換えて、
DAOでは動いていたものが動かなくなるものは
今回のケースと、RecordCountの結果以外に何かご存じなものはありますでしょうか?
 
すでにご存じなもので結構ですので、
わかる範囲でご教示いただけましたら幸いです^^;

回答
投稿日時: 20/07/26 09:57:10
投稿者: hatena
投稿者のウェブサイトに移動

私自身はDAOのものをADOに書き換えるということをしたことがないのでそれ以外ではしりません。
他の方の回答をお待ちください。

回答
投稿日時: 20/07/27 10:48:37
投稿者: sk

引用:
Set rs1 = cmd.Execute

引用:
rs1.RecordCountの結果は、必ず-1が入ってしまいDAOと同じように
使えないというのは発見しました。

引用:
Set db = CurrentProject.Connection

Set db = CurrentProject.AccessConnection
 
引用:
DAOからADOに書き換えて、
DAOでは動いていたものが動かなくなるもの
今回のケースと、RecordCountの結果以外に何かご存じなものはありますでしょうか?

DAO.QueryDef オブジェクトの OpenRecordset メソッドによって
パラメータクエリの実行結果を DAO.Recordset オブジェクトとして取得し、
その参照を任意のフォームの Recordset プロパティに渡し、
編集可能な連結フォームとして使用しているケースなど。
(恐らくそういうことはやってないと思われますが)

投稿日時: 20/07/29 22:36:52
投稿者: ai

sk様
 
ありがとうございます!
 
 
 
ちなみに
Set db = CurrentProject.Connection
 
と記載されている箇所をご提示頂いた↓
Set db = CurrentProject.AccessConnection
 
に書き換えて実行した所、rs1.RecordCountの結果が「-1」と表示されず
DAOと同じように正しい値が出力されました!
 
 
 
 
もしかして、Set db = CurrentProject.AccessConnectionに書き換えれば
全てDAOと同じように動くのかと思い
ワイルドカードの「%」を「*」に戻したらこちらは上手く動かないようです・・・。
 
Set db = CurrentProject.Connection

Set db = CurrentProject.AccessConnection
はどのような違いがあると認識すればよろしいでしょうか?
 
 
 
 
 
これは将来的にSQLサーバーに移行(フロントエンド側のリンクテーブルの参照先を
SQL Server データベース上のテーブル/ビューに変更)する場合、
安全を考えて
Set db = CurrentProject.AccessConnection
に念の為、書き換えた方が良いのでしょうか?
 
質問ばかりが続いて申し訳ありませんが、
お時間がある時に、ご教示頂ければ幸いです!

回答
投稿日時: 20/07/30 11:28:02
投稿者: sk

引用:
もしかして、Set db = CurrentProject.AccessConnectionに書き換えれば
全てDAOと同じように動くのかと思い
ワイルドカードの「%」を「*」に戻したらこちらは上手く動かないようです

それは RecordCount プロパティとは別の問題(仕様)なので。
 
引用:
Set db = CurrentProject.Connection

Set db = CurrentProject.AccessConnection
はどのような違いがあると認識すればよろしいでしょうか?

AccessConnection プロパティ自体は主に、
フォームの Recordset プロパティを介して
そのフォームと任意の ADODB.Recordset オブジェクトを
連結させるコードを実行する場合に使用されます。
 
ただ RecordCount プロパティの振る舞いに関連している両者の違いは、
ADODB.Command オブジェクトの Execute メソッドによって返された
ADODB.Recordset オブジェクトが、ブックマークをサポートしているか否かです。
 
ブックマークをサポートしていない ADODB.Recordset オブジェクトの場合、
たとえカーソルの種類が静的カーソルであっても、
その RecordCount プロパティは -1 を返します。
 
ADODB.Command オブジェクトによってクエリの実行結果を
ADODB.Recordset オブジェクトとして取得する方法としては、
Execute メソッドとは別に以下のようなものが挙げられます。
 
引用:
Set rs1 = cmd.Execute

Set rs1 = New ADODB.Recordset
With rs1
    .CursorLocation = adUseClient
    .CursorType = adOpenStatic
    .LockType = adLockReadOnly
    Set .Source = cmd
    .Open
    Debug.Print "rs1 のレコード件数は" & .RecordCount
End With
 
----------------------------------------------------------
 
(より簡略化した場合)
----------------------------------------------------------
 
Set rs1 = New ADODB.Recordset
rs1.Open cmd, , adOpenStatic, adLockReadOnly
 
----------------------------------------------------------
 
上記の場合は、CurrentProject.Connection プロパティから
参照した ADODB.Connection オブジェクトを使用していても、
RecordCount プロパティによって正確なレコード件数を取得できるはずです。
 
引用:
将来的にSQLサーバーに移行(フロントエンド側のリンクテーブルの参照先を
SQL Server データベース上のテーブル/ビューに変更)する場合、
安全を考えて
Set db = CurrentProject.AccessConnection
に念の為、書き換えた方が良いのでしょうか?

フォームと Recordset オブジェクトを連結させるようなコードを
書かない限りは、CurrentProject.Connection のままで構わないと思います。
 
特定の条件に該当するレコードの件数を取得する方法は他にもあるでしょうし、
また「レコードの有無」を知りたいだけなら、Open された直後の
EOF プロパティの値によって判定することが可能ですので。

投稿日時: 20/07/31 22:30:01
投稿者: ai

skさん
 
 
大変丁寧なご説明、ありがとうございます!
もやっとしていた物が理解できました!
 
hatenaさんもこの度はありがとうございました^^
助かりました!
 
まだまだ未熟なため、またご質問してしまうかもしれませんが
よろしくお願い致します!