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
我流の私で良ければ・・・(正しいのかは、専門家に聞いていただくとして)
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) でも
上記は単なるコピーの例なので、コピー元が複数レコード存在する等々・・・
修正点はいっぱいあると思います。
お礼
ご回答頂きまして、ありがとうございました。 非常に助かりました。 >1)rsClone での判別が正しいと思います。 安心しました。 rsCloneで氏名検索したのに、何故rsで判別?と悩んでしまいました。 クローンと複製元はカレントが同期するの?いやそうでもなさそうだし・・・と。 > ただし、> 次行からの処理 ではないと思います。 rsClone で山田太郎さんがいたら(EOFでなかったら)、rsにAddNewして値を代入・・・ とIFの中の処理のことを「次行からの処理」と表現してしまったのですが、 使い方が良くなかったでしょうか。 あ、下の方で書いて頂いたコードを拝見しましたが、複製元からクローンにコピーをされていますね。 元は「クローンで検索して、複製元にコピーする」の例だったのですが、 (初心者へのCloneメソッドの説明のための例なのでおかしいのかもしれませんが) そうではないと思われて「次行からの処理ではない」という意味でしたでしょうか。 >2)そのような話は聞いた事がありません。 実は某PCスクールのテキストに記載のあったプロシージャで (転記NGとのことですのでSELECT文など一部変えています) 1.を疑問に思い講師に質問したところ、2.と言われたのです。 あまりに腑に落ちないテキストと講師の説明を信用出来ず、 実際にADOを使われている方のご意見をお聞きしたかったのです。 ありがとうございます。 >a)私なら、こう記述します その方がわかりやすいですね! 参考にさせて頂きます。 >b)変数名に気をつけます >ドット?ピリオド?( . )の、あり/なしで同じ綴りになるものは使いません。 非常に役立ちます!ありがとうございます。 >以下の ★ 部分の記述は間違いですよね >> rs.Clone.Close ' ★ これは私の打ち間違いです。すみません。 これも変数名に気を付けると、間違いを防げそうに思います。 >参考になるかどうかわかりませんが、私が記述したとしたら以下の様な感じに どういう構造にしたらわかりやすいかなど、参考になります。 オートナンバの部分も、スクールに行った時に打ち込んで試してみます。 ありがとうございました。
補足
わざわざ補足するほどでもないかもしれませんが、修正し忘れたので・・・ >SELECT文など一部変えています 元々SELECT文使われていないです。条件等変更しました。