• ベストアンサー

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になります。 このような仕組みなのでしょうか。 ご教授お願いいたします。

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

  • ベストアンサー
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.2

結局、「AccessでadOpenDynamicは使うべきではない」ということなんだと思います。 もともとAccessの場合、Jet/Aceが動的カーソルをサポートしていないので、カーソルタイプは LockType=adReadOnlyのときはadOpenKeysetに、それ以外のときはadOpenStaticに変更される とよくいわれますが、その割にRowCountはとれないことを考えると、結局adOpenKeysetや adOpenStaticとして処理が行われているわけでもなく、意味不明のカーソルになっている と考える方が自然です。 確かにMovePreviousがおかしな動きをしますが、それは仕様だからというよりは、 「動的カーソルをサポートしていない場合の動きを保証していないから」と考えるべきでしょう。

tokonoko
質問者

補足

回答ありがとうございます。 以下の2つでそれぞれテストしてみました。 1.adOpenDynamic, adLockReadOnly 一度目のdebug.printは5 二度目のdebug.printは4 CursorTypeはadOpenStaticになっていました。 2.adOpenStatic, adLockReadOnly 一度目のdebug.printは5 二度目のdebug.printは5 >意味不明のカーソルになっていると考える方が自然です。 ほんと意味不明と感じますが 納得できました。 ありがとうございました。

その他の回答 (1)

noname#140971
noname#140971
回答No.1

  rs.MoveNext   Debug.Print rs.Fields("フィールド1").Value   rs.MovePrevious   Debug.Print rs.Fields("フィールド1").Value で、どうなるかですね。 「次へ行きなさい」で次に行く準備をしたとします。 で、次に行って何をするかの指令を待機中だとします。 その待機中に「いいや、一つ手前の命令を実行せよ!」との新たな指示が到着。 こういう推測が当を得ているかどうかはテストるのみでしょう。

tokonoko
質問者

補足

回答ありがとうございます。   Do Until rs.EOF    rs.MoveNext   Loop   rs.MovePrevious   Debug.Print rs.Fields("フィールド1").Value   ↑   5になりました。   rs.MoveNext   Debug.Print rs.Fields("フィールド1").Value   ↑   エラーになりました。   実行時エラー'3021':   BOFとEOFのいずれかがTrueになっているか、または現在の   レコードが削除されています。要求された操作には、現在の   レコードが必要です。   rs.MoveNextではeofになっているようです。   

関連するQ&A

  • なぜrs.Move i ではダメなのでしょうか?

    access2003です。 テーブル1には、 フィールド1 あ い う え お が入っています。 Sub test() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim i As Long Set cn = CurrentProject.Connection rs.Open "テーブル1", cn, adOpenKeyset, adLockOptimistic For i = 0 To rs.RecordCount rs.Move i Debug.Print rs.Fields(0).Value Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub をすると、 あ い え とイミディエイトウインドウに表示されるのですが Debug.Print rs.Fields(0).Value の部分で 「実行時エラー'3021' BOFとEOFのいずれかTRUEになっていか、または現在のレコードが削除されています。 要求された操作には、現在のレコードが必要です。」 となります。 その時のiの値は、3です。 rs.MoveFirst For i = 1 To rs.RecordCount Debug.Print rs.Fields(0).Value rs.MoveNext Next にすると、 あ い う え お が取得されます。 なぜrs.Move i ではダメなのでしょうか? 理由を教えてください。

  • アクセス ADO レコードの件数がおかしい

    アクセスADOでクエリの行数を取得したいのですが クエリが200行でも100行でも必ず12が返ります。 クエリ1は、一度12行の時にadoで数を取得し、その時は、正しく12が返ったのですが、 行数が変わっても12が返ります。 コードは、 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 Debug.Print rs.RecordCount rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub です。 Debug.Print DCount("*", "クエリ1") だと、正しいレコード数が取得されるのですが、ADOだとおかしいです。 クエリ1のSQL文は、 SELECT Q_作業用.* FROM Q_作業用; のように、別のクエリを持ってきています。 何が原因なのでしょうか? よろしくお願いします。

  • ACCESSADOについて

    ACCESSでADO接続でEOFとBOFがともにTUREでうまく動作しません どなたか回避する方法を教えてください。 Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Set cn = CurrentProject.Connection Set rs = New ADODB.Recordset rs.Open "Q_発生原価合計", cn, adOpenForwardOnly, adLockReadOnly rs.MoveFirst Do Until rs.EOF Debug.Print rs!決算年月, rs!金額の合計, rs!科目CD rs.MoveNext Loop '終了 rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing クエリーにはデータは存在します。

  • adoのループについて カレントレコードについて

    adoのFor i = 1 To rs.RecordCountについて質問があります。 Sub test() Dim i As Long Dim MyFileName As String Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset MyFileName = CurrentProject.FullName cn.Open "Provider = Microsoft.ACE.OLEDB.12.0;" & "Data Source= " & MyFileName rs.Open "Tテーブル", cn, adOpenKeyset, adLockOptimistic For i = 1 To rs.RecordCount Debug.Print rs.Fields(0).Value rs.MoveNext Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub これを実行した時に、テーブルには、1,2,3・・・という値が入っていて、 イミディエイドウインドウにも1,2,3・・・と順番に取得されるのですが、 For i = 1 To rs.RecordCountを実行した時は、強制的にrs.MoveFirstされるのでしょうか? For i = 1 To rs.RecordCount rs.MoveFirst Debug.Print rs.Fields(0).Value rs.MoveNext Next これと同じ意味なのでしょうか? RecordCount プロパティ (ADO) のヘルプを見ましたが、この件に関する記述は探せませんでした。 ご回答よろしくお願いします。

  • アクセスVBA。ADO

    CSVから列を分割してテーブルにしたいかったので 下記のコードを記述しましたが、 Dim cn As ADODB.Connection Dim rs As New ADODB.Recordset Dim datacount As Long Set cn = New ADODB.Connection With cn .ConnectionString = "Provider=Microsoft.jet.OLEDB.4.0;Data Source=" & CurrentProject.Path & "\;" .Properties("Extended Properties").Value = "text;HDR=YES;" .Open End With Set rs = cn.Execute("SELECT * FROM 構成マスタ.csv") datacount = rs.Fields.Count For i = 0 To datacount strsql = "SELECT " & rs.Fields(i).Name & " INTO " & rs.Fields(i).Name & " FROM 構成マスタ.csv;" cn.Execute strsql Next i rs.Close cn.Close Set rs = Nothing Set cn = Nothing SQLを実行するところで、「日付エラー」となってしまいます。 データには特に日付等はないのでエラーになる原因がわかりません。 どなたかご教示いただけますでしょうか。

  • 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 としました。今のところ動いているようですが、 何か勘違い、気をつけないといけない事等ありますでしょうか・・・?

  • 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しなくてもメモリの開放は行われているのでしょうか? アドバイスよろしくお願いいたします。

  • 数値の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 英語を含むレコードを抽出したい

    テーブルに保存されてるフィールド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 サンプルを作ってみたのですが ご教示頂けないでしょうか? よろしくお願い致します。

  • ExcelでADOを使って他のブックを参照したい

    いつも楽しく勉強させていただいております。 VBA関連のサイトを参照して同じブックにあるシートをADOを使って参照することに成功しました。 Dim CN As New ADODB.Connection Dim RS As New ADODB.Recordset Dim SQL As String Set CN = New ADODB.Connection CN.Provider = "Microsoft.Jet.OLEDB.4.0" CN.Properties("Extended Properties") = "Excel 8.0" CN.Open ThisWorkbook.FullName SQL = "SELECT * FROM [userlist$]" RS.Open SQL, CN, adOpenStatic, adLockReadOnly Do Until RS.EOF Debug.Print RS![P-1] RS.MoveNext Loop RS.Close CN.Close これを現在開いている別のブック、たとえばBook1にあるシートを参照するにはどこをどう書き換えたらいいでしょうか。