VBA ADOの実行時エラーと値の取得

このQ&Aのポイント
  • VBAのADOを使用してAccessのテーブルから値を取得する際、特定の値を取得しようとするとエラーが発生します。
  • さらに別の値に変更すると、別のエラーが発生します。
  • 原因や解決策が分からず、問題を解決する方法を探しています。
回答を見る
  • ベストアンサー

VBA ADO 値が違う

アクセスのTPWテーブルのサイト名フィールドには aaa(bbb)と言う値があり、そのPasswordフィールドの値を取得したいのですが ------------------------------------------------------- Function PW取得() cn.Open "Provider = Microsoft.ACE.OLEDB.12.0;Data Source=" & "D: \PW.accdb" rs.Open "SELECT * FROM TPW", cn, adOpenStatic, adLockPessimistic rs.Find "サイト名 = 'aaa(bbb)'", 0, adSearchForward PW取得 = rs("Password") rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Function ------------------------------------------------------- を実行すると、 Passwordフィールドに依然入っていた値が取得されてしまいます。 更に、 aaa(bbb)と言う値を aaaに変更し、 rs.Find "サイト名 = 'aaa'", 0, adSearchForward とすると、 PW取得 = rs("Password") の部分で、 実行時エラー3021 「BOFとEOFのいずれかTRUEになっていか、 または現のレコード要求された操作には、現在のレコードが必要です。」 が発生します。 原因が全く分かりません。 Findと言うメソッド?は使わないほうがいいのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • piroin654
  • ベストアンサー率75% (692/917)
回答No.3

No2で変数の宣言が抜けていました。 Dim partSQL As String を追加してください。それと、 Debug.Print rs!名前 & "-------" & rs!最終登録日 を、 Debug.Print rs!名前 & "-------" & " rs!Password & "-----" & rs!最終登録日 としてください。Passwordの取得が抜けていました。 なお、Accessだけなのか、あるいはExcelなどでのVBAなのか 明記されていないので、一応質問のADOでNo2を書くと、 Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim strSQL As String Dim partSQL As String partSQL = "aaa(bbb)" strSQL = "SELECT TPW.サイト名, TPW.Password, Max(TPW.日付) AS 最終登録日 FROM TPW GROUP BY TPW.サイト名 HAVING (TPW.サイト名 Like '*" & partSQL & "*');" Set cn = New ADODB.Connection cn.Open "Provider = Microsoft.ACE.OLEDB.12.0;Data Source=" & "D: \PW.accdb" Set rs = New ADODB.Recordset rs.Open strSQL, cn, adOpenStatic, adLockPessimistic Debug.Print rs!名前 & "-------" & " rs!Password & "-----" & rs!最終登録日 rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing

その他の回答 (2)

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.2

No1です。 >Passwordフィールドに依然入っていた値が取得されてしまいます。 ということですから、実際には同じサイト名が複数ある、ということですかね。 であれば、どのレコードが一番新しいPasswordなのかは、たとえば日付/時刻 であったり、登録順にたとえばオートナンバーが振ってあったりしないと 一番新しいPasswordは特定できません。あるいは、Passwordの表記方法に 何らかの順列を示すものがある場合です。 そこで、登録した日付があるとして、たとえば、以下のようなクエリを作成するとか、 SELECT TPW.サイト名, TPW.Password, Max(TPW.日付) AS 最終登録日 FROM TPW GROUP BY TPW.サイト名 HAVING (TPW.サイト名 Like '*aaa(bbb)*'); あるいは、このクエリのSQL文をプロシージャに組み込み、 Dim db As DAO.Database Dim rs As DAO.Recordset Dim strSQL As String partSQL = "aaa(bbb)" strSQL = "SELECT TPW.サイト名, TPW.Password, Max(TPW.日付) AS 最終登録日 FROM TPW GROUP BY TPW.サイト名 HAVING (TPW.サイト名 Like '*" & partSQL & "*');" Set db = CurrentDb Set rs = db.OpenRecordset(strSQL) Debug.Print rs!名前 & "-------" & rs!最終登録日 rs.Close: Set rs = Nothing db.Close: Set db = Nothing のように、してみるとかです。なお、上記はDAOです。字数の関係で DAOにしています。このまま使用する場合は、コード表の参照設定で DAOにチェックが入っているか確認してみてください。

  • piroin654
  • ベストアンサー率75% (692/917)
回答No.1

Find の引数のSkipRowsの値を0だけで更新しなくても 何も問題は起こらなかったのですか? サイト名 = 'aaa(bbb)' で、aaaとは、()の中の bbb は何を意味しているのですか? Findは普通はレコードの先頭から検索します。aaa(bbb) というサイト名がテーブルに複数あるのならば、最初のレコードが 取り出されたのでしょう。必要ならば、連続検索をするならば、 Loop処理をして検索します。 >aaa(bbb)と言う値を >aaaに変更し、 >rs.Find "サイト名 = 'aaa'", 0, adSearchForward >とすると、 >実行時エラー3021 >「BOFとEOFのいずれかTRUEになっていか、・・・ これは、そのようなデータがないということです。 Findはデータの並びによってはあまり精度がよくないときも あるのであまり使いません。 Findの使い方は、以下にありますが、 http://www.geocities.jp/cbc_vbnet/ADO/find.html Loop処理、SkipRpwsなどもあります。 一度、普通に、レコードにフィルタをかけて、 rs.Filter = "サイト名 like 'aaa(bbb)*'" rs.MoveFirst Do Until rs.EOF   Debug.Print rs!サイト名 & "------" & rs!Password rs.MoveNext Loop としてみては?

関連するQ&A

  • ADOで現在のレコードの次のレコードの値も取得

    ADOで現在のレコードの次のレコードの値も取得するには? アクセスに対してADOでデータを取得しているのですが 例えばテーブルに フィールド1 あああ いいい ううう と入ってる時に、1レコード目のあああの値を取得しているときに、同時に次のレコードのいいいの値も取得することは可能ですか? Sub Sample() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection rs.Open "SELECT * FROM テーブル1", cn, adOpenStatic, adLockPessimistic For i = 1 To rs.RecordCount MsgBox rs("フィールド1") '現在のレコード MsgBox rs("フィールド1") + 1 '次のレコード rs.MoveNext Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub これだとダメなようです。 あああ いいい が表示されるようにしたいのですが、どうすればいいか教えてください。

  • 数値のMAXの値を取得したい ADO VBA

    アクセスです。 ADOで該当のフィールドの数値のMAXの値を取得するにはどうすればいいですか? テーブルの番号フィールドには、 1 2 3 4 5 と入っているのですが、 この場合、一番大きい値は5なので MAX関数のようなもので5を返したいのですが ADOにそのようなプロパティはありますか? オブジェクトブラウザーでRecordsetを見てみましたが 見つけられませんでした。 Sub Sample() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection rs.CursorLocation = adUseClient rs.Open "SELECT * FROM T_test", cn, adOpenStatic, adLockPessimistic rs.Sort = "番号 DESC" Debug.Print rs("番号").Value rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub これで同じような動きは出来ますが、 もっとシンプルにできませんか?

  • ADOでアポストロフィー入りの値をフィルタしたい

    例えばレコードの値が「あああ'ああ」だった場合、 ----------------------------------------------------- Sub test() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim MyFileName As String MyFileName = CurrentProject.FullName cn.Open "Provider = Microsoft.ACE.OLEDB.12.0;" & "Data Source= " & MyFileName rs.Open "テーブル1", cn, adOpenKeyset, adLockOptimistic rs.Filter = "フィールド1 = " & "'あああ'ああ'" MsgBox rs.RecordCount rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub ----------------------------------------------------- とすると 実行時エラー3001「引数が間違った型、許容範囲外、または競合しています。」 になってしまいます。 ADOでアポストロフィー入りの値をフィルタする方法を教えてください。

  • DAOでのコードをADOへ書き直し

    Access2003、WinXPです。 レコードセットの取得関係をDAOで書いていたのですが ADOに途中から変更しました。 変数宣言を Public db As DAO.Database ⇒Public cn As ADODB.Connection Public rs As DAO.Recordset ⇒Public rs As ADODB.Recordset Public Fld As DAO.field  ⇒Public Fld As ADODB.field レコードセット取得を Set db = CurrentDb      Set rs = db.OpenRecordset(strSQL) ↓ Set cn = CurrentProject.Connection Set rs = New ADODB.Recordset rs.Open strSQL, cn レコードセット クローズを Set rs = Nothing Set db = Nothing ↓ rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing としました。今のところ動いているようですが、 何か勘違い、気をつけないといけない事等ありますでしょうか・・・?

  • 【ADO】「Filter」を使うか「WHERE」を使うか

    こんばんは。 アクセス2003です。 「Filter」を使うか「WHERE」を使うかべきかわからないので教えてください。 Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Sub test1() cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & アクセスファイル名 rs.Open "SELECT * FROM Tテーブル WHERE 'フィールド1'='りんご", cn, adOpenKeyset, adLockOptimistic rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub Sub test2() cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & アクセスファイル名 rs.Open "SELECT * FROM Tテーブル", cn, adOpenKeyset, adLockOptimistic rs.Filter = "フィールド1 = " & "'" & "りんご" & "'" rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub 以上のふたつのステートメントは Tテーブルのフィールド1にりんごの文字が入力されているレコート゛を抽出します。 いくつかこのような動作をするプログラムを書くのですが どちらのほうがコート゛として適していますか? WHEREを使うtest1の方がコート゛が短くなるからいいのでしょうか? というのもいつかこのファイルを引き継ぐので他人が見てもわかりやすくしたいです。 よろしくお願い致します。

  • ADO 英語を含むレコードを抽出したい

    テーブルに保存されてるフィールド1の英語が含まれているレコード(ABC株式会社 など)を抽出したいのですが 方法がわかりません。 *[a-z]* を使うんだなと思いますが、フィルタのかけかたがわかりません。 Sub test() Dim CN As New ADODB.Connection Dim RS As New ADODB.Recordset CN.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ファイル名 RS.Open "テーブル1", CN, adOpenStatic, adLockOptimistic RS.Filter = "フィールド1 = " '←ここをどうすればいいでしょうか? RS.Close: Set RS = Nothing CN.Close: Set CN = Nothing End Sub サンプルを作ってみたのですが ご教示頂けないでしょうか? よろしくお願い致します。

  • ACCESS ADOのMovePreviousについて

    毎度お世話になっております。 ACCESS2003を使用しています。 ACCESS ADOにて、レコードセットがeofになった後、 MovePreviousをし、MoveNextをし、 さらにもう一度MovePreviousをすると、 最終レコードの一つ前に戻ってしまいます。 テーブル1 フィールド1 フィールド2    1     あ    2     い    3     う    4     え    5     お コード Sub test()   Dim cn As New ADODB.Connection   Dim rs As New ADODB.Recordset   Set cn = CurrentProject.Connection   rs.Open "select * from テーブル1 order by フィールド1", cn, adOpenDynamic, adLockReadOnly   Do Until rs.EOF    rs.MoveNext   Loop   rs.MovePrevious   Debug.Print rs.Fields("フィールド1").Value   rs.MoveNext   rs.MovePrevious   Debug.Print rs.Fields("フィールド1").Value   rs.Close: Set rs = Nothing   cn.Close: Set cn = Nothing End Sub 一度目のdebug.printは5に、 二度目のdebug.printは4になります。 このような仕組みなのでしょうか。 ご教授お願いいたします。

  • Access ADOについて質問です。

    Access ADOについて質問です。 以下コードでレコードセットを返す関数を使用しています。 動作的には問題ないのですが、標準モジュール内のレコードセットをClose及びNothingしていないのが気になります。 Private Sub Form_Open(Cancel As Integer) Dim rs2 As ADODB.Recordset Set rs2 = New ADODB.Recordset Set rs2 = CreateRecordSet("SELECT * FROM T_Standard;") Set Me.Recordset = rs2 rs2.Close: Set rs2 = Nothing end sub '標準モジュール Public Function CreateRecordSet(strSQL As String) As ADODB.Recordset Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Set cn = New ADODB.Connection cn.ConnectionString = "provider=Microsoft.Jet.OLEDB.4.0;" _ & "Data Source=O:\標準DB\StandardBackEnd.mdb" cn.Open Set rs = New ADODB.Recordset rs.Open strSQL, cn, adOpenStatic, adLockReadOnly Set CreateRecordSet = rs ' rs.Close: Set rs = Nothing   ←この部分 ' cn.Close: Set cn = Nothing   ←この部分 End Function 標準モジュール内ではCloseやNothingしなくてもメモリの開放は行われているのでしょうか? アドバイスよろしくお願いいたします。

  • アクセスADO 複数のレコードがあるのに-1が返る

    アクセスのADOを作っています。 テーブルにレコードは複数あるのですが、Filterをすると必ず-1が返ります。 どうしてでしょうか? エラーになってるのでしょうか? ---------------------------------------------------- Set cn = CurrentProject.Connection myStr = "test" rs.Open "Tテーブル", cn, adOpenForwardOnly, adLockReadOnly rs.Filter = ("フィールド1=" & "'" & myStr & "'") MsgBox rs.RecordCount ’マイナス-1になる rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing ---------------------------------------------------- rs.Open の下に、MsgBox rs.RecordCountを置いても、-1になることから、Filter のせいではないと思うのですが 原因がわかりません。 ご教授よろしくお願いします。

  • ADOでループすると1レコードずつ飛ばしてしまう

    アクセスなのですが Sub test() Set cn = CurrentProject.Connection rs.Open "テーブル", cn, adOpenKeyset, adLockOptimistic rs.Filter = "(店名 = '" & str店名 & "') And (URL = '未')" For j = 1 To rs.RecordCount rs("URL") = "http" rs.Update rs.MoveNext Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub このようにして、既存のレコードにフィルタをかけて該当のレコードの値を更新しているのですが rs.MoveNext をいれると、 1レコード目、3レコード目、5レコード目・・・と言う順番になってしまい、 最終的にrs.RecordCountの数を越したレコードを指定してしまい 実行時エラー 3021 「BOFとEOFのいずれかTRUEになっていか、または現のレコードが要求された操作には、現在のレコードが必要です。」 となってしまいます。 だからって rs.MoveNextをいれないと、rs.RecordCountに達するまで、 いつまでも同じレコードをループしてしまいます。 1レコードずつ順番にデータを掴む方法を教えてください。

専門家に質問してみよう