よろしくお願いいたします。
テーブル tbl残業管理
フィールド 残業管理ID、日付、担当者ID、残業区分、(その他)
残業管理ID | 日付 | 担当者ID | 残業区分 |
---|---|---|---|
84 | 2024/04/20 | 44 | 1 |
130 | 2024/04/21 | 10 | 1 |
95 | 2024/04/21 | 10 | 2 |
85 | 2024/04/21 | 11 | 1 |
ADOにて、
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Set cn = CurrentProject.Connection
rs.CursorLocation = adUseClient
rs.Open "tbl残業管理", cn, adOpenKeyset, adLockOptimistic
rs.Sort = "日付 ASC, 担当者ID ASC, 残業区分 ASC"
rs.MoveFirst
Do Until rs.EOF
If rs!残業区分 = 1 Then
If DCount("休日", "tbl休日", "休日 = #" & rs!日付 & "#") > 0 Then '休日テーブルに休日があれば(4/20、4/21が休日)
rs!残業区分 = 3
rs.Update
End If
ElseIf rs!残業区分 = 2 Then
If DCount("休日", "tbl休日", "休日 = #" & rs!日付 & "#") > 0 Then
rs!残業区分 = 4
rs.Update
(途中略)
rs.MoveNext
Loop
を実行すると、
残業管理ID 130までは残業区分が3に変わりますが、
次は95がとばされてしまい、85のレコードの処理になってしまいます。
自分ではrs.updateの時に並び替えが再度行われていて、飛ばされてしまうのかと思ってます。
95をちゃんと読み込むような対処はありますでしょうか?
[残業管理ID]の値が 95 であるレコードの[残業区分]の値は 2 であり、上記の条件を満たしていないため。
コードが途中までしか記述されていないので実際にどのような動作をしているのか読み切れませんが、本当に飛ばされているのか確認のテストコードを実行してみるといいと思います
たとえば、
Do Until rs.EOF
の次にそれ用のコードを記述します詳しい確認方法などは参考サイトがたくさんあるので適当に覗いてみてください
https://www.google.com/search?q=VBA デバッグ
申し訳ございません。
コードの一部を追加しました。
残業区分 = 2の時の処理を記述しました。
「元から ElseIf ブロックのコードがモジュールに記述されていた(が、最初の投稿時に端折っただけ)」とおっしゃりたいのか、「実際にはモジュールに記述されていなかったのでコードを修正した」という意味でおっしゃっているのか、どちらなのでしょうか。
仮に前者であるとして、
現時点では以下のいずれの意味でおっしゃっているのかが不明瞭です。
レコードの並べ替え順が Sort プロパティで指定した通りにならず、[残業管理ID]が 130 であるレコードの次のレコードが 85 のレコードとなり、更にその次のレコード以降に 95 のレコードが現れる。
レコードの並べ替え順は Sort プロパティで指定した通りになっているが、ElseIf ブロック内で呼び出された DCount 関数の戻り値が 0 となる(ので[残業区分]の書き換えとレコードの更新が実行されない)。
レコードの並べ替え順は Sort プロパティで指定した通りになっているが、[残業管理ID]が 95 であるレコードを参照した際、最後の rs.MoveNext メソッドが呼び出されるより前のいずれかのタイミングで次のレコード( 85 )に移動している。
それどころか、レコードセットの中に[残業管理ID]の値が 95 であるレコードが含まれていない。
上記以外の意味。
例えば 1,2 のいずれかに該当するならテーブル[tbl残業管理]の各レコードの[日付]に格納されている実際の値(例えば日付だけでなく時刻が含まれていないか等)を確認すべきですし、3 に該当するなら「(途中略)」とされた部分全てのコードが疑惑の対象となります。
sk様
追加のコードについては、投稿時に端折っただけです。
ご提示の1~5の選択肢については3だと思われます。
下記のコードに書き換えて実行してみました。
それでも同じく残業管理ID 95の残業区分が4にならずに2のままでした。
他の残業区分IDは残業区分が3になっています。
書き換えたコードは途中略なしです。
ならば考えられる原因は 1 つだけです。
[残業管理ID]の値が 130 であるレコードの[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間に、そのレコードが 2 番目から 3 番目のレコードに、[残業管理ID]の値が 95 である([残業区分]の値が 2 である)レコードが 3 番目から 2 番目のレコードになった(レコードセット内での絶対位置が入れ替わった)からです。
【 3 を代入する直前の状態】
【 3 を代入した直後の状態】
順番が入れ替わってもその時点でのカレントレコードは[残業管理ID]の値が 130 であるレコードのままなので、その後 MoveNext メソッドを呼び出せばその次( 4 番目)のレコードは[残業管理ID]の値が 85 であるレコードとなります。
回避手段としては、Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すことが挙げられます。
もっとも、「[日付]の値が休日に該当する場合は[残業区分]の値を書き換える」という処理だけに着目するのであれば、そもそもレコードを並べ替えること自体が不要であるとも言えますが。
Hiroton様
Debug.Print rs!残業管理ID を実行しましたが、95が表示されていませんでした。
84、130、85しか表示されていませんでした。
コードには問題がなさそうなので、データの問題の可能性が大です。
このような場合は、こちらにはデータがないのでそちらでデバッグ作業をするしかなです。
デバッグの方法についてはすでにリンクが紹介されていますので、そちらを参照してもらうとして、
とりあえず下記のデバッグコードを埋め込んで、イミディエイトの出力結果を確認してみてください。
hatena様
イミディエイトでは何も出力されませんでした。
デバッグコードの位置を以下にすると、
以下のように出ます。
84 2024/04/20
130 2024/04/21
85 2024/04/21
sk様
ご提示の
「Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すこと」
で出来ました!
debug.printでも95が表示されますし、処理も残業区分が4になってます。
ちなみにレコードの並び替えが必要な理由は、途中略の部分にありますので(おそらく並び替えが必要な処理)
やはり、残業管理ID=130で残業区分=3にして、rs.updateで並び替えが行われているということですかね。
いえ、「[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間」です。
Update メソッドが呼び出されるより先に並べ替えが行われています。
(イミディエイトウィンドウへの出力結果)
以上のように、AbsolutePosition プロパティの値の変化からも今回の現象の原因を説明することができます。
ご解説ありがとうございます。
値を代入した瞬間にレコード位置が変わっていたのですか。
Sortプロパティも良く気を付けて使わなければならないですね。
Sort設定した瞬間だけ並び替えが行われるのものかと。
sk様、Hiroton様、Hatena様
皆様、この度は真摯なご回答誠にありがとうございました。
問題解決することができました!