レコードの位置を指定する方法について

このQ&Aのポイント
  • Access2007でDAOを使用してレコードの位置を指定する方法について質問があります。
  • 現在のコードでは、rs.AbsolutePositionに値を渡してレコードにデータを挿入していますが、表示される結果が異なっています。
  • 正しく値が渡されていない可能性があるので、コードを確認しましたが、問題は見つかりませんでした。どなたか解決策を教えていただけないでしょうか。
回答を見る
  • ベストアンサー

レコードの位置を指定するがうまくいきません

よろしくお願い致します。 Access2007で、DAOを使用して以下の事を行っていますが、うまく動作しません。  一、rs.AddNewを12回繰り返してテーブルにレコードのみ作成しておく。     12回の意味は、縦に12項目分、横に時間フィールドを用意し、例えばA項目の10:00に     予定データが入っているイメージです。  二、他のテーブルから必要なデータを抽出し、rs.AbsolutePositionにデータ毎に     決まった位置を渡し、rs.Editで抽出データをセットしていきます。  三、全てのデータをセットし終えたら、フォームを表示し、そこに組み込んでいる     サブフォームにデータが所定の位置にキレイ並んでいる状態です。 エラーなく処理はされるのですが、フォームが表示されると実際の抽出データを違う位置に 予定が入っています。時間を表すフィールドは合っているので、AbsolutePositionに正しく 値が渡されていないのかなと思うのですが、順にコードをなめていくと入っているように 思います。コードは以下の通りです。 Do rsYotei.EOF Set rs = db.OpenRecordset("12レコードあるテーブル") rs.MoveLast rs.AbsolutePosition="入れたいレコードの位置" rs.Edit rs.Fields("入れたい時間").Value="予定データ" rs.Update rs.Close:Set rs=Nothing rsYotei.MoveNext Loop 以上です。 どなたかお知恵を拝借できれば幸いです。 よろしくお願い致します。

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

  • ベストアンサー
  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.2

 データベースを取り扱う時に、良くある誤解の一つのせいです。  データベースのテーブルをファイルと同じように考えると、このようなミスをやります。  ファイルの場合は、いったん書き込みをしたら、変更しない限りは、レコードの順番が変わったりすることはありません。何度開き直しても、常に同じ順番で同じデータを返すことが保証されています。ですから、レコード番号の意味があります。  データベースのテーブルの場合は、テーブルに入れたデータは、単なる集合です。ここで集合という用語を使うのは、このレコード群には、「順番」がないんです。ですから、データの書き換えをしなくても、前に見た時と、今回見た時には、データの順番が違うことがあります。順番を保証しないので、たとえ、画面で見た時に、同じ順番で返してくれているように「見えても」、前提としては、今回のレコードセットと前回のレコードセットでは順番が変わると考えてプログラムは組まなければなりません。  今回の場合は、手順の1・2・3で、当然、レコードセットは開き直しているはずです。この3回のレコードセットでのレコードの順番は、全部違います。(偶然、同じような順番になることもありますが、あくまで偶然です。偶然の比率は実は結構高いんですけどね。)  ここで、MSDNから、AbsolutePositionの説明の一部を引用します。 >AbsolutePosition プロパティを使うと、Recordset オブジェクト内の位置に基づいて特定のレコードに移動したり、カレント レコードの位置を決定することができます。  この説明通り、Recordsetの位置を決定するものなんです。たとえ、同じテーブルから同じ方法で生成したRecordsetでも、それは、違うレコードセットであり、AbsolutePositionの値を共用することはできません。  これは、次の説明にあります。 >注意 AbsolutePosition プロパティで、レコード番号の代用はできません。レコードの位置は、上位のレコードを削除すると変更されます。また、Recordset オブジェクトを再びクエリしたり開いたときに、レコードが AbsolutePosition の値と同じになるとは限りません。所定の位置を保持し、そして戻るにはブックマークを使います。ブックマークは、すべての型の Recordset オブジェクト間で位置を決定できる唯一の方法です。  はっきり書いてありますね。レコード番号の代用は出来ません。  ちなみに、acsessの場合は、ここにも書いてあるようにブックマークをこのかわりに使うことが出来ます。が、これも実は、結構使いでが制約されます。  データベースを取り扱う時に、レコードの順番が意味を持つ場合は、クエリで明確に順序を指定します。(そのための句がorder by句です。)  そして、レコードを特定する時には、常に、主キーを使用します。レコードセットから、特定の行を特定する場合は、主キーの値を基本として、findメソッドでカーソルを移動することになります。  ソート順をちゃんと指定した場合でも、テーブルの更新によりレコードの順位が変わりますから、ソート順を指定してAbsolutePositionの値をレコード番号として使うという手法はやめた方が良いです。

lienciel
質問者

お礼

ご回答ありがとうございます。 基本的な勉強不足でした。 大変適切な回答でよく理解できました。 本当にありがとうございました。

その他の回答 (1)

回答No.1

下記のリンク先を熟読してください。 [ACC2003] MDB のレコードの並び順について http://support.microsoft.com/kb/834927/ja データベースは一般的にそうなのですが、入力順というのを保持していません。 並び替えを指定していない場合、次に開くときに入力順に開くとは限りません。 大量のデータを効率的に扱うためにそのような仕様になっています。 テーブルに並び順を決定するフィールドかオートナンバー型のフィールドを追加して、それを主キーにします。 主キーをもとにレコードを特定して値を入力するようにしてください。 フォームで開くときには、主キーフィールドで並び替えを設定します。

lienciel
質問者

お礼

ご回答ありがとうございます。 もっとしっかり調べれば分かることでしたね。 非常に助かりました。ありがとうございました。

関連するQ&A

  • "カレントレコードがありません"とでてきます

    Access97を使用しています。 データは テーブルAの項目B、項目Cが下記のようにあるとします。 フォーム上のText"B"に項目Bを入力します。 項目B 項目C 11 a 11 b 22 aa 22 bb 22 cc 33 aaa 33 ccc この時 Set DB = CurrentDb() strSQL = "SELECT * FROM A WHERE " strSQL = strSQL + "B='" & Me.B & "';" Set RS = DB.OpenRecordset(strSQL, dbOpenDynaset, dbReadOnly) RS.MoveFirst RS.MoveLast m = RS.RecordCount For i = 1 To m COIL_N = RS.Fields("C") Call RS.MoveNext Next i 上記のようなモジュールですが、例えば 項目Bの"11"を選んだ時、項目Cの二番目のデータbが 取得できません。 "カレントレコードがありません"とでてきます。何故でしょうか?

  • 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 これだとダメなようです。 あああ いいい が表示されるようにしたいのですが、どうすればいいか教えてください。

  • レコード更新について

    レコード更新について 環境:ACCESS2000 状況:メインフォーム(マスター登録ボタン付)    サブフォーム(マスターテーブルをドラッグして貼り付けたもの)    マスターテーブル(品番 / レンタル日 / 返却日 / 貸出状況) やりたい事:サブフォームに表示してあるデータに       返却日をサブフォーム上で入力し(件数は不定)、そして       返却日が入力されたものの貸出状況を"返却済"と変更登録したい。 現状:コマンドボタンのイベントに Private Sub マスター登録ボタン_Click() Dim db As DAO.Database Dim rs As DAO.Recordset Set db = CurrentDb Set rs = db.OpenRecordset("マスターテーブル", dbOpenDynaset) If rs!返却日 <> "" Then rs.Edit rs!貸出状況 = "返却済" rs.Update End If rs.Close Set rs = Nothing db.Close Set db = Nothing End Sub しかし、上記コードでは返却日はマスターテーブルに反映しているのですが 貸出状況が変わってなく、どのようにしたら良いかわからないため ご質問させて頂きました。 まだまだACCESS勉強中で未熟なため、検討違いなコードになっているかもしれませんが コードの修正・改善、または全く違う方法等ご教授願えればと思います。        

  • テーブルのレコードが0件時にmsg表示(アクセス)

    とてつもない初歩的な質問で すみません! フォーム1をメニュー画面として、 フォーム1にある「ボタン」を押すと テーブルにレコードが追加され、処理が走る・・・という仕様を作っています。 ですが、 このテーブルにレコードが追加されなかった=0件 の場合の回避策を どうしたら良いのかが わかりません。 ちなみに、 Private Sub ボタン_Click() On Error GoTo errmsg DoCmd.SetWarnings False Dim DB As DAO.Database Dim rs1 As DAO.Recordset Dim rs2 As DAO.Recordset Dim i As Long Set DB = CurrentDb Set rs1 = DB.OpenRecordset("テーブル1") Set rs2 = DB.OpenRecordset("テーブル2", dbOpenDynaset) rs1.MoveFirst Do Until rs1.EOF If rs1!フィールドA1 = rs1!フィールドA2 Then rs2.AddNew rs2!ID = rs1!ID rs2!フィールドA = rs1!フィールドA1 rs2!B = rs1!フィールドB rs2!C = rs1!フィールドC rs2.Update End If If rs1!フィールドA1 < rs1!フィールドA2 Then For i = rs1!フィールドA1 To rs1!フィールドA2 Step 1 rs2.AddNew rs2!ID = rs1!ID rs2!フィールドA = i rs2!フィールドB = rs1!フィールドB rs2!フィールドC = rs1!フィールドC rs2.Update Next i End If rs1.MoveNext Loop rs1.Close: Set rs1 = Nothing rs2.Close: Set rs2 = Nothing DB.Close: Set DB = Nothing Call 次処理 errmsg: MsgBox "元データが未投入です。" End Sub としたのですが、 これでは データが投入され、処理が成功=完了した場合にも エラーメッセージが出てしまいました。 ご教示いただけますと幸いです。 お手数をおかけしますが、よろしくお願い致します。

  • Access レコードを分割してフォームで表示

    Access 2007です。 下記のような日記テーブルがあり、 その「行動」フィールドの中身を「●」の記号で レコードに分割して、 フォームに表示したいと思っています。 日記テーブル ID 年月日   天気  行動 1 2014/1/10  晴  ●読書。●新聞を読む。●散歩。 2 2014/1/11  曇  ●電車に乗る。●新年会。●庭の手入れ。●カラオケ。 3 2014/1/12  曇  ●昼寝。 4 2014/1/13  雨  ●買い物。●読書。 ・・・・ 結果フォーム(データシートビュー)で表示 年月日    行動 2014/1/10  読書。 2014/1/10  新聞を読む。 2014/1/10  散歩。 2014/1/11  電車に乗る。 2014/1/11  新年会。 2014/1/11  庭の手入れ。 2014/1/11  カラオケ。 2014/1/12  昼寝。 2014/1/13  買い物。 2014/1/13  読書。 もとの日記テーブルのデータは変更しません。 下記のように、VBAのコードの中で、 レコードセットを使えば、上記のようなレコードの分割ができると思うのですが、 うまくいきません。 rs2というレコードセットをどうやって作成すればいいのかわかりません。 (Set rs2 = DB.OpenRecordset ・・・ のような行が必要ではないか、と思うのですが、 そのやり方がわかりません。) やり方を教えていただけたら幸いです。 Dim DB As DAO.Database Set DB = CurrentDb() Dim rs1 As DAO.Recordset Dim rs2 As DAO.Recordset Set rs1 = DB.OpenRecordset("日記テーブル", dbOpenForwardOnly) Dim A As Variant Do Until rs1.EOF A = Split(rs1!行動, "●") For i = 1 to UBound(A) rs2.AddNew rs2!年月日 = rs1!年月日 rs2!行動 = rs1!A(i) rs2.Update Next i rs1.MoveNext Loop DoCmd.OpenForm "結果フォーム" Set Forms!結果フォーム.Recordset = rs2

  • 条件指定の特定レコードのフィールド値の差をとりたい

    お世話になります。 テーブル1(TBL_1)の社員コードそれぞれにおけるレコードのフィールド値のデータ1と別テーブル(TBL_2)のデータ2との差をとる方法が知りたいです。差をとりたいレコードは以下の条件によります。 ・テーブル2の期間1と期間2の範囲にはいっているテーブル1のレコードのみ差をとる。 ・データ1とデータ2の差がマイナス(-)になることはありません。 ・社員コードは百程度、レコード数は数千にのぼります。 ・フィールドの期間1と期間2は同一社員コードにおいて重複することはありません。 ・テーブル2(TBL_2)は年度をまたいでの期間設定は基本しません。年度をまたぐ場合はレコードを増やします。 テーブル1名:TBL_1 社員コード 期間1   期間2   データ1 00123   2012/6/30  2014/3/31  30 00123   2014/4/1   2015/3/31  100   00456   1995/9/15  2008/3/31   15 00789   2001/6/2  2013/3/31  224  ・ 00456   2008/4/1  2016/3/31  628  ・ 00789   2013/4/1  2015/3/31  1089  ・ 00123   2015/4/1  2017/3/31   95  ・ テーブル2名:TBL_2 社員コード 期間1     期間2  データ2 00123   2012/11/6  2013/3/31   5 00123   2013/4/1   2013/11/5   13 00456   2013/6/12  2013/10/6   22 00789   1995/6/7   2000/2/11   6 具体的には、上記例においてテーブル1を下記の結果にしたいです。 テーブル1名:TBL_1 社員コード  期間1    期間2     データ1 00123   2012/6/30  2014/3/31    12 ←30-(5+13)=12 00123   2014/4/1   2015/3/31   100 ←変わらない 00456   1995/9/15  2008/3/31    15 ←変わらない 00789   2001/6/2   2013/3/31   224 ←変わらない  ・ 00456   2008/4/1   2016/3/31   606 ←628-22=606  ・ 00789   2013/4/1   2015/3/31  1089 ←変わらない  ・ 00123   2015/4/1   2017/3/31   95 ←変わらない  ・ なにとぞお力添えをお願い致します。

  • VB6,Access2000のMDBでのデータ型指定

    VB6でAccess2000のMDBを使用しています。 次のような形で一時的なレコードセットRS(0)を作成しようと思うのですが、このときの DataTypeEnum に相当するデータ形式がわかりません。 目的はMDBテーブルから作成したレコードセットRS(1)とのデータ交換です。そのMDBテーブルで数値としてあるフィールドとやりとりするRS(0)側のフィールドのデータ型(DataTypeEnum)を何に設定していいのかわかりません。 選択肢は次のページにあります。 http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpado260/htm/mdcstdatatypeenum.asp Set RS(0) = New ADODB.Recordset RS(0).Fields.Append "LinNo", adDouble ← この adDouble の位置で 何を指定するか。。。 RS(0).Fields.Append "JobID", adDouble RS(0).Fields.Append "JobName", adVarChar, 200 RS(0).Open よろしくお願いします。

  • テーブル1から抽出したものをテーブル2に入れたい

    ACCESSのVBA初心者です。 基本的な質問で申し訳ないのですが、どうかご教授をお願いします。 まず、まったく同じフィールドを持つテーブル1とテーブル2があります。 抽出したい項目は、テーブル1の中にある[性別]と[登録月]が一致するデータの全てです。 性別と登録月は別のフォームのコンボボックスで選択したもので抽出しようと思っています。 該当するデータが含まれているレコードを全てテーブル2に移したいです。 説明が下手で申し訳ないのですが、どうかご教授をお願い致します。 Dim rs As DAO.Recordset Set db = CurrentDb() Set rs = db.OpenRecordset("テーブル1", dbOpenDynaset) DoCmd.RunSQL "DELETE FROM テーブル2" rs.Filter = " テーブル1.性別 = テーブル2.性別 & テーブル1.登録月 = テーブル2.登録月" テーブル2 = テーブル1.RecordsetClone 最初にdeleteがあるのは、前回の抽出条件を消したいからです。 よろしくお願い致します。

  • MySQL+PHP 特定レコードの更新と作成

    MySQL+PHPの初心者です。 特定レコードの変更または新規作成のサンプルなどあればお教えいただけるでしょうか。 例えば特定商品の単価のレコードがあれば新しい単価に変更と そのレコードが無ければ新規にレコードを作成するようなケースになります。 VBAなどでは検索のSQL文からレコードセットを作成し レコードが無い場合は レコードセット名.addnewで必要なフィールドに 値をセットし レコードセット名.update 該当するレコードがあった場合は レコードセット名.edit で必要なフィールドに 値をセットし レコードセット名.updateなど簡単な処理なのですが MySQL+PHP の場合データの検索と新規レコードの単純な記述は ある程度はわかるのですが上記のようなケースは実際どのように 書かれているのかお教え願えると幸いです。 商品単価テーブルには商品コードと単価のフィールドになります。 よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • Access2000でのレコードの削除と移動

    ccess2000で テーブルがA と Bあり テーブルAは一時保存用で最終的にBに保存しようとしてます。 まず、データをフィールド1が空欄でAに保存して、後にそのデータをフォームで呼び出し、フィールド2を入力後テーブルBに保存その呼び出したカレントレコードのみ削除したいのですが、どうすればいいのでしょうか> フォームは連結されていません。 可能であればサンプルコードをいただくと助かります。 お願い致します。