![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?08b1c8b)
Access VBA 学習中の初心者です。ADOについて教えて下さい。
RecordsetオブジェクトのCloneメソッドを使用してレコードのコピーを行う以下のプロシージャで、
If Not rs.EOF Then
の存在意義がわかりません。
1.
rsClone に対象のレコードがあった場合は次行からの処理をする、ということであれば
If Not rsClone.EOF Then
にすれば良いかと思うのですが、それでは違いますでしょうか?
2.
とある人に聞いたところ、
「rsのカレントがEOFだとAddNewでエラーになるから、そのエラー回避のためそうなっている」
と言われたのですが、
テキストやヘルプで AddNewメソッド についてそのような注意事項を見つけられませんでした。
自分なりに試してみてもその条件下でエラーになりませんでした。(試し方に自信ないですが。)
AddNewメソッドを使う際にEOFであるかどうか気にした方が良いものなのでしょうか?
質問が分かりづらく、ご回答頂くにあたり追加の情報が必要でしたらご指摘下さい。
「プロシージャをこうした方がわかりやすい、適切」などのご意見も歓迎です。
どうぞよろしくお願いいたします。
--------------------------
Dim cn As ADODB.Connection
Dim rs As New ADODB.Recordset
Dim rsClone As ADODB.Recordset
Dim myField As Variant, cnt As Integer
Set cn = CurrentProject.Connection
rs.Open "名簿", cn, adOpenStatic, adLockOptimistic
Set rsClone = rs.Clone(adLockReadOnly)
rs.Clone.Bookmark = rs.Bookmark
rsClone.Find "名簿 like '山田 太郎'"
If Not rs.EOF Then ←★★★質問★★★
rs.AddNew
cnt = 0
For Each myField In rsClone.Fields
rs.Fields(cnt) = myField
cnt = cnt + 1
Next
End If
rs.Update
rs.Clone.Close
Set rsClone = Nothing
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
No.1ベストアンサー
- 回答日時:
我流の私で良ければ・・・(正しいのかは、専門家に聞いていただくとして)
1)rsClone での判別が正しいと思います。
ただし、> 次行からの処理 ではないと思います。
2)そのような話は聞いた事がありません。
VBA記述で気になった点
a)私なら、こう記述します
> cnt = 0
> For Each myField In rsClone.Fields
> rs.Fields(cnt) = myField
> cnt = cnt + 1
> Next
↓
For cnt = 0 To rs.Fields.Count - 1
rs.Fields(cnt) = rsClone.Fields(cnt)
Next
b)変数名に気をつけます
rsClone → rsC
つまり、ドット?ピリオド?( . )の、あり/なしで同じ綴りになるものは使いません。
以下の ★ 部分の記述は間違いですよね
> rs.Clone.Close ' ★
> Set rsClone = Nothing
参考になるかどうかわかりませんが、私が記述したとしたら以下の様な感じに
(未検証ですので、雰囲気で・・・ということに)
Dim rs As New ADODB.Recordset
Dim rsC As ADODB.Recordset
Dim i As Long
rs.Source = "SELECT * FROM 名簿 WHERE 名簿 = '山田 太郎';"
rs.Open , CurrentProject.Connection, adOpenStatic, adLockOptimistic
If (Not rs.EOF) Then
Set rsC = rs.Clone
rsC.AddNew
For i = 0 To rs.Fields.Count - 1
rsC(i) = rs(i)
Next
rsC.Update
rsC.Close
Set rsC = Nothing
End If
rs.Close
rs を得る時にコピー元を抽出しておきます。
なかったら処理しない様に・・・・
なお、コピーする中で、オートナンバ「an」を除外するとしたら
For i = 0 To rs.Fields.Count - 1
Select Case rs.Fields(i).Name
Case "an"
Case Else
rsC(i) = rs(i)
End Select
Next
の様にすると思います。
※ rsC(i) = rs(i) は rsC.Fields(i) = rs.Fields(i) でも
上記は単なるコピーの例なので、コピー元が複数レコード存在する等々・・・
修正点はいっぱいあると思います。
この回答への補足
わざわざ補足するほどでもないかもしれませんが、修正し忘れたので・・・
>SELECT文など一部変えています
元々SELECT文使われていないです。条件等変更しました。
ご回答頂きまして、ありがとうございました。
非常に助かりました。
>1)rsClone での判別が正しいと思います。
安心しました。
rsCloneで氏名検索したのに、何故rsで判別?と悩んでしまいました。
クローンと複製元はカレントが同期するの?いやそうでもなさそうだし・・・と。
> ただし、> 次行からの処理 ではないと思います。
rsClone で山田太郎さんがいたら(EOFでなかったら)、rsにAddNewして値を代入・・・
とIFの中の処理のことを「次行からの処理」と表現してしまったのですが、
使い方が良くなかったでしょうか。
あ、下の方で書いて頂いたコードを拝見しましたが、複製元からクローンにコピーをされていますね。
元は「クローンで検索して、複製元にコピーする」の例だったのですが、
(初心者へのCloneメソッドの説明のための例なのでおかしいのかもしれませんが)
そうではないと思われて「次行からの処理ではない」という意味でしたでしょうか。
>2)そのような話は聞いた事がありません。
実は某PCスクールのテキストに記載のあったプロシージャで
(転記NGとのことですのでSELECT文など一部変えています)
1.を疑問に思い講師に質問したところ、2.と言われたのです。
あまりに腑に落ちないテキストと講師の説明を信用出来ず、
実際にADOを使われている方のご意見をお聞きしたかったのです。
ありがとうございます。
>a)私なら、こう記述します
その方がわかりやすいですね!
参考にさせて頂きます。
>b)変数名に気をつけます
>ドット?ピリオド?( . )の、あり/なしで同じ綴りになるものは使いません。
非常に役立ちます!ありがとうございます。
>以下の ★ 部分の記述は間違いですよね
>> rs.Clone.Close ' ★
これは私の打ち間違いです。すみません。
これも変数名に気を付けると、間違いを防げそうに思います。
>参考になるかどうかわかりませんが、私が記述したとしたら以下の様な感じに
どういう構造にしたらわかりやすいかなど、参考になります。
オートナンバの部分も、スクールに行った時に打ち込んで試してみます。
ありがとうございました。
No.5
- 回答日時:
#4です
> ここを見たのですが、見る場所、理解が間違っていますでしょうか・・・
> http://msdn.microsoft.com/ja-jp/library/cc376486 …
見てみました。
コード例からしてみると EOF = True 判別で良いみたいですね。
Access2007のヘルプでは、
> Recordset から、指定した条件を満たす行を検索します。必要に応じて、検索の方向、開始行、および開始行からのオフセットを指定できます。条件が一致すると、カレント行の位置は、検出されたレコードに設定されます。条件を満たす行がない場合は、Recordset の最後 (または最初) に設定されます。
という記述のほかに、メモとして
> レコードセットに対して Find メソッドを呼び出す場合で、レコードセット内の現在の位置が最後のレコードまたはファイルの最後 (EOF) の場合、何も検索されません。あらかじめ MoveFirst メソッドを呼び出して、現在の位置またはカーソルをレコードセットの先頭に設定する必要があります。
引数 SearchDirectionEnum の説明では、
> 一致するレコードが見つからない場合、レコード ポインタは EOF に移動します。
という記述もあるんですけどね。
言葉の遊びなのかもしれませんが、
・「Recordset の最後」
・「ファイルの最後 (EOF)」
使い分けている?表現を変えている?っていう事は、何かあるんじゃないですかね・・・
と疑ったわけです。
msdn での説明でも
> 条件に合うレコードを検索できない場合、前方 (EOF = True) に検索していたときは、現在のレコードが Recordset オブジェクトの一番後ろに置かれます。
っていう表現で、EOF = True 判別されているので、ヘルプ内の表現
「Recordset の最後」=「ファイルの最後 (EOF)」
と、解釈した方が良さそうですね。(#4のコード例は、いらないという事で・・・)
迷わせてしまって申し訳ありません。
ありがとうございました。
色々悩ませてしまいましたが、結果的に最初の回答で問題ありませんでしたので
#1をベストアンサーにさせて頂きます。
テキストの誤字から始まりましたが、色々検索したりテストしたり、ご意見もお聞きし、
大変勉強になりました。
No.4
- 回答日時:
#3です
たびたびの連投ですみません。
Find 後の EOF についてなんですが、私の環境では対象がなければ EOF = True となってました。
そういう動きを想定していたので、フムフム・・・ということでヘルプ等は参照してませんでした。
その中で、あの回答を目にし、改めてヘルプを読んでみると・・・
私の場合、動作が食い違っていた時にはヘルプ側を信じて見る事をします。
で、その動きを再現する様にいろいろとやってみます。
(今もですが)#3ではその時間がないので・・・で記述していました
私の場合、Find を使ったものは、あまり作ってないので、
今後、ヘルプ通りの動きになったとしても、さほど影響は無いのですが・・・
どうしても再現できなかった場合、どちらでも動く記述にしておきますか・・・
例えば、
Dim sS As String
Dim bNext As Boolean
・・・・・・
・・・・・・
sS = "山田 太郎"
rsC.Find "名簿 = '" & sS & "'"
bNext = True
If (rsC.EOF) Then
bNext = False
Else
If (rsC("名簿") <> sS) Then bNext = False
End If
If (bNext) Then
' 見つかった時の処理・・・
※ Find はあまり使った事がないです。
Find よりも Filter を使った絞り込みの方を良く使ってました。
Filter 後は、RecordCount でレコード数を知る事が出来るし・・・
(EOF を見た単純ループでクルクル処理できる・・・・等など)
Filter は Find より遅くなると思いますが、想定したデータ量で満足できる応答であれば・・・
※ 今もチョコチョコと再現を試みていますが難儀しています(Vista + 2007)
現状では、
・対象がなかったら EOF = True になるし、
・他の部分 AbsolutePosition は負値になるみたい
惑わせてすみません。
回答としては、ヘルプ(仕様?)を提示すべきだったんでしょうか・・・
※ #2で記述したものはそのまま生きると思います。
失礼しました。(識者の回答を待ってください)
この回答への補足
あ、すみません。
DAOならNoMatchプロパティ・・・は当然のこととして、
ADOの時EOFで判断出来ない、というヘルプが存在しているということでしょうか?
ここを見たのですが、見る場所、理解が間違っていますでしょうか・・・
http://msdn.microsoft.com/ja-jp/library/cc376486 …
No.3
- 回答日時:
#2です
連投すみません
1)について、私の勘違いもあって・・・件名は違いますが以下の#1さんの回答を参照ください。
Access 重複しないメールをテーブルに取り込む
http://oshiete.goo.ne.jp/qa/8056866.html
なので、Find は使わない方向が良いのかも・・・・
引き続きありがとうございます。
テキストには、Findの検索方向が「adSearchForward」(規定値)の場合、
レコードが見つからなかったらEOFと書いてあるのですが。
動きも確認したような・・・次回スクールで再度確認します。
No.2
- 回答日時:
#1です
試されるという事なので、補足等記述できるように回答しておきます。
> 実は某PCスクールのテキストに・・・・
であれば、まずはソコソコ動くものを・・・
で、徐々に環境/条件を変化させて・・・以前の記述ではエラーになるね・・・とか?
というストーリーも考えられます。
> 1.を疑問に思い講師に質問したところ、2.と言われたのです。
推測するに、たぶんですが
・ Find では必ず一致するものがある
これが前提であり、If Not rs.EOF Then としたのは、テーブルが空だったら・・・・
という事になるんでしょうか。
チェックがチグハグの様な気がしますが、
元々の上位記述で、対象のレコードがなければ実行しない・・・・
とかしていれば、それなりに動くとは思いますけど・・・
(とは言っても、私は私のスタイルで記述しますけど)
> rsのカレントがEOFだとAddNewでエラーになるから・・・
を素直に受け止めると、空のテーブルにレコードは追加できない・・・に、なると思います。
(やはり、何かストーリーがあるような気がします)
私が参考として提示したものは、rs を求める時にコピー元を求めており、
テーブルが空 / 対象がない 時には EOF が True になるので、まとめた判別が出来てます。
(コピー元があって、クローンを作るようにしています)
で、コピー元があったら、それは rs のカレント=先頭になっているので、
Clone して クローン側の Bookmark 操作云々を省く事が出来ると思います。
なので、Clone 側に AddNew する事を、私はよくやります。
また、Clone して作った rsC の初期の位置は先頭(???)
この辺は、ヘルプに記述があったような・・・で、確認してください。
(余談で、Filter は解除されたものになる?・・・とかも確認ください)
※ rs.Clone.Bookmark = rs.Bookmark も、変数名・・・・での記述ミスでしょうか
※ 次行 については、勘違いをしていました。
Find で求めた次の行(レコード)と・・・・失礼しました。
引き続きありがとうございます。悩ませてしまってすみません
本日、わざわざ別の校舎の講師に話を聞きに行きました。
結果は
1.rs→rsClone にすべき
2.AddNewがEOFでエラーになるという話はない
※その講師も「エラーになる」と言った講師からそのように習ったそうで
最初は「エラーになる」と言っていたのですが、
どこのテキストにもヘルプにも載っていない、実際EOFでもエラーにならないことを見せ、
確認してもらいました。
まず前提に、そのスクールのオリジナルテキストには誤字が多い、というのがあります。
通常は、テキストで説明された通り、基本に忠実なプロシージャが載っています。
テキストの解説には「対象のレコードがあった場合・・・」と書いてあって、
rsClobeでレコードを探してるのに If Not rs.EOF Then となっていることに
違和感を感じました。
>・Find では必ず一致するものがある
>これが前提であり、If Not rs.EOF Then としたのは、テーブルが空だったら・・・・
>という事になるんでしょうか。
>チェックがチグハグの様な気がしますが、
チグハグですよね。
「rsがEOFだとエラーになるから」と言われた後、
「対象レコードがあった場合、という条件になっていないですよね」と言ったら、
「必ず一致する前提で進んでいますね」と言われました。
If Not rs.EOF Then は
「通常Openしたら先頭レコードがカレントですがEOFのこともあるので」
と言われました。
「そうしたら、EOFの時にコピーできるように対応してないのは何故ですか」と聞いたら
「テキストの例ですので、実務とは違います」と言われました。
そんなチグハグをおかしいと思わない講師にこれ以上聞いても
納得行く回答はされないだろうとあきらめ、
こちらに相談させて頂き、違和感を感じるのは私だけではないはずと確信し、
他の校舎の講師をわざわざ訪ねてみました。
愚痴になってすみません。
>rs.Clone.Bookmark = rs.Bookmark も、変数名・・・・での記述ミスでしょうか
そうです!すみません。
これも直した上で、教えていただいたオートナンバーの処理も確認しました!
ちなみにですが、
「イメージしやすいようにBookmarkの処理を入れていますが、なくても結果は同じです。」
と書いてありました。
(それなくてもイメージ出来るのに、そんなことより誤字をなくして欲しい・・・)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) access count数を変数に格納 2 2022/03/30 19:21
- Access(アクセス) DoCmd.SearchForRecord が動かない時の解決方法 3 2022/07/22 15:31
- Visual Basic(VBA) データベースから絞り込んでデータを読み込み 1 2023/02/21 19:51
- Access(アクセス) 実行時エラー3131 FROM 句の構文エラーです について 7 2022/06/13 15:45
- Access(アクセス) docmd.gotorecordを起動するには 5 2022/06/17 15:20
- Access(アクセス) チェックボックスにチェックが入った後の挙動 1 2022/08/21 12:39
- Visual Basic(VBA) Excel vbaについての質問 3 2023/04/18 16:14
- Visual Basic(VBA) エクセルVBAのコードで質問です。 下のコードはJ16の文字列をB3を起点とする範囲から探して、見つ 5 2023/04/07 11:07
- Visual Basic(VBA) VBA This Workbookモジュールを別ファイルにコピーする方法 1 2022/09/14 01:51
- Visual Basic(VBA) 【VBAエラー】Nextに対するForがありません 対策について 5 2022/11/21 21:26
このQ&Aを見た人はこんなQ&Aも見ています
-
あなたの「必」の書き順を教えてください
ふだん、どういう書き順で「必」を書いていますか? みなさんの色んな書き順を知りたいです。 画像のA~Eを使って教えてください。
-
歳とったな〜〜と思ったことは?
歳とったな〜〜〜、老いたな〜〜と思った具体的な瞬間はありますか?
-
もし10億円当たったら何に使いますか?
みなさんの10億円プランが知りたいです!
-
この人頭いいなと思ったエピソード
一緒にいたときに「この人頭いいな」と思ったエピソードを教えてください
-
集中するためにやっていること
家で仕事をしているのですが、布団をはじめ誘惑だらけでなかなか集中できません。
-
ADOレコードセットのコピー
その他(データベース)
-
ACCESSのBookmarkプロパティの使い方
その他(データベース)
-
カレントレコードが無い事を判定させる方法
Visual Basic(VBA)
-
-
4
フォームを開くときに、コンボボックスの値を選択(アクセスVBA)
Visual Basic(VBA)
-
5
日付型のフィールドに空白を入れる方法を教えてください
その他(データベース)
-
6
ADOを使ったDBアクセス後のメモリ解放
その他(データベース)
-
7
Access サブフォームでの選択行の取得
その他(データベース)
-
8
実行時エラー 3020の対策
Access(アクセス)
-
9
Accessのテーブルデータを一気にVBAで追加したい・・
その他(データベース)
-
10
[Access]帳票フォームにて連続する非連結コントロールに個々の値を入れるには
Access(アクセス)
-
11
新規レコード行を非表示にしたい
Access(アクセス)
-
12
AccessのSQL文で1件のみヒットしたら終了させる構文。
その他(データベース)
-
13
ADOでRecordsetオブジェクトをレコードソースに設定したい
その他(データベース)
-
14
Accessサブレポートの内容が重複して表示される
Excel(エクセル)
-
15
レコードを保存するコード アクセスvba
その他(Microsoft Office)
-
16
サブフォームに対してGoToRecordするには?
その他(Microsoft Office)
-
17
スクロールバーをVBAで操作したい
Access(アクセス)
-
18
実行時エラー -2147217900 ADODBでレコードセットオープン時エラー
Access(アクセス)
-
19
実行時エラー3251対応処理方法
Access(アクセス)
-
20
Accessでレコードを別テーブルへコピーするには
Access(アクセス)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・「これはヤバかったな」という遅刻エピソード
- ・初めて自分の家と他人の家が違う、と意識した時
- ・いちばん失敗した人決定戦
- ・思い出すきっかけは 音楽?におい?景色?
- ・あなたなりのストレス発散方法を教えてください!
- ・もし10億円当たったら何に使いますか?
- ・何回やってもうまくいかないことは?
- ・今年はじめたいことは?
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
アクセスでレポートの1印刷内...
-
Line Inputで文字化け(助けて...
-
VB.netでmdbのレコードを取得
-
DataGridViewの内容をDBに反映...
-
Access でレコードセレクタが押...
-
固有レコード識別子の選択とは
-
差し込み印刷のレコード数について
-
レコードが存在しなかった場合
-
DataGridViewの、選択されてい...
-
クラスモジュールを使ったレコ...
-
GROUP BYを行った後に結合した...
-
実績累計の求め方と意味を教え...
-
MERGE文を単体テーブルに対して...
-
Accessで日付が変わると番号が...
-
GROUP BYを使ったSELECT文の総...
-
キーが同じを複数行を1行にま...
-
OracleのSQL*PLUSで、デー...
-
【SQL】existsでの商演算
-
Recordset.FindFirstについて
-
【Access】選択クエリのグルー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
レコードが存在しなかった場合
-
ファイル書込みで一行もしくは...
-
カレントレコードが無い事を判...
-
アクセスでレポートの1印刷内...
-
DataGridViewの、選択されてい...
-
ADO VBA 実行時エラー3021
-
差し込み印刷のレコード数について
-
JSPのNULLレコード表示について...
-
レコードセット(ADO.Recordset)...
-
[VBA] ADOの Clone と AddNew
-
ACCESSで大量の更新を行うと「...
-
サブフォームに新規レコードを...
-
ワードの差込印刷で教えて下さ...
-
Access を×ボタンで閉じ...
-
サブレンジ分割されたNDB(富士...
-
固有レコード識別子の選択とは
-
DataGridViewの内容をDBに反映...
-
データセットのレコード更新が...
-
DataGridViewにてセル以外をク...
-
Accessデータシートビューの行...
おすすめ情報