Microsoft Access 掲示板

ADOでレコードが飛ばされてしまう。

16 コメント
views
4 フォロー

よろしくお願いいたします。
テーブル tbl残業管理
フィールド 残業管理ID、日付、担当者ID、残業区分、(その他)

残業管理ID日付担当者ID残業区分
842024/04/20441
1302024/04/21101
952024/04/21102
852024/04/21111

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をちゃんと読み込むような対処はありますでしょうか?

あん
作成: 2024/05/01 (水) 16:38:16
最終更新: 2024/05/01 (水) 16:56:28
通報 ...
1

残業管理ID 130までは残業区分が3に変わりますが、
次は95がとばされてしまい、85のレコードの処理になってしまいます。

If rs!残業区分 = 1 Then

[残業管理ID]の値が 95 であるレコードの[残業区分]の値は 2 であり、上記の条件を満たしていないため。

2
hiroton 2024/05/01 (水) 16:52:10 6bf03@f966d

コードが途中までしか記述されていないので実際にどのような動作をしているのか読み切れませんが、本当に飛ばされているのか確認のテストコードを実行してみるといいと思います

たとえば、Do Until rs.EOFの次にそれ用のコードを記述します

    Do Until rs.EOF
        Debug.Print rs!残業管理ID    'デバッグ用コードを追加してみる

詳しい確認方法などは参考サイトがたくさんあるので適当に覗いてみてください
https://www.google.com/search?q=VBA デバッグ

3
あん 2024/05/01 (水) 16:57:28 b41ab@001b1

申し訳ございません。
コードの一部を追加しました。
残業区分 = 2の時の処理を記述しました。

4

コードの一部を追加しました。
残業区分 = 2の時の処理を記述しました

「元から ElseIf ブロックのコードがモジュールに記述されていた(が、最初の投稿時に端折っただけ)」とおっしゃりたいのか、「実際にはモジュールに記述されていなかったのでコードを修正した」という意味でおっしゃっているのか、どちらなのでしょうか。

仮に前者であるとして、

残業管理ID 130までは残業区分が3に変わりますが、
次は95がとばされてしまい、85のレコードの処理になってしまいます。

rs.Sort = "日付 ASC, 担当者ID ASC, 残業区分 ASC"

現時点では以下のいずれの意味でおっしゃっているのかが不明瞭です。

  1. レコードの並べ替え順が Sort プロパティで指定した通りにならず、[残業管理ID]が 130 であるレコードの次のレコードが 85 のレコードとなり、更にその次のレコード以降に 95 のレコードが現れる。

  2. レコードの並べ替え順は Sort プロパティで指定した通りになっているが、ElseIf ブロック内で呼び出された DCount 関数の戻り値が 0 となる(ので[残業区分]の書き換えとレコードの更新が実行されない)。

  3. レコードの並べ替え順は Sort プロパティで指定した通りになっているが、[残業管理ID]が 95 であるレコードを参照した際、最後の rs.MoveNext メソッドが呼び出されるより前のいずれかのタイミングで次のレコード( 85 )に移動している。

  4. それどころか、レコードセットの中に[残業管理ID]の値が 95 であるレコードが含まれていない。

  5. 上記以外の意味。

例えば 1,2 のいずれかに該当するならテーブル[tbl残業管理]の各レコードの[日付]に格納されている実際の値(例えば日付だけでなく時刻が含まれていないか等)を確認すべきですし、3 に該当するなら「(途中略)」とされた部分全てのコードが疑惑の対象となります。

5

sk様
追加のコードについては、投稿時に端折っただけです。

ご提示の1~5の選択肢については3だと思われます。

下記のコードに書き換えて実行してみました。
それでも同じく残業管理ID 95の残業区分が4にならずに2のままでした。
他の残業区分IDは残業区分が3になっています。

    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
            
                rs!残業区分 = 3
                rs.Update
                
            End If

    
        ElseIf rs!残業区分 = 2 Then
        
            If DCount("休日", "tbl休日", "休日 = #" & rs!日付 & "#") > 0 Then
            
                rs!残業区分 = 4
                rs.Update
            
            End If

        End If
        
        rs.MoveNext
          
    Loop


    rs.Sort = ""

    rs.Close: Set rs = Nothing
    cn.Close: Set cn = Nothing
7

書き換えたコードは途中略なしです。

10

ならば考えられる原因は 1 つだけです。

rs.Sort = "日付 ASC, 担当者ID ASC, 残業区分 ASC"

rs!残業区分 = 3

[残業管理ID]の値が 130 であるレコードの[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間に、そのレコードが 2 番目から 3 番目のレコードに、[残業管理ID]の値が 95 である([残業区分]の値が 2 である)レコードが 3 番目から 2 番目のレコードになった(レコードセット内での絶対位置が入れ替わった)からです。

【 3 を代入する直前の状態】
画像1

【 3 を代入した直後の状態】
画像2

順番が入れ替わってもその時点でのカレントレコードは[残業管理ID]の値が 130 であるレコードのままなので、その後 MoveNext メソッドを呼び出せばその次( 4 番目)のレコードは[残業管理ID]の値が 85 であるレコードとなります。

回避手段としては、Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すことが挙げられます。

rs.Open "SELECT * FROM [tbl残業管理] ORDER BY [日付] ASC, [担当者ID] ASC, [残業区分] ASC", cn, adOpenKeyset, adLockOptimistic
12

もっとも、「[日付]の値が休日に該当する場合は[残業区分]の値を書き換える」という処理だけに着目するのであれば、そもそもレコードを並べ替えること自体が不要であるとも言えますが。

6
あん 2024/05/02 (木) 10:12:49 b41ab@001b1

Hiroton様

Debug.Print rs!残業管理ID を実行しましたが、95が表示されていませんでした。

8

84、130、85しか表示されていませんでした。

9

コードには問題がなさそうなので、データの問題の可能性が大です。

このような場合は、こちらにはデータがないのでそちらでデバッグ作業をするしかなです。
デバッグの方法についてはすでにリンクが紹介されていますので、そちらを参照してもらうとして、
とりあえず下記のデバッグコードを埋め込んで、イミディエイトの出力結果を確認してみてください。

'前略

        ElseIf rs!残業区分 = 2 Then
            Debug.Print rs!残業管理ID, rs!日付     'デバッグコード
            If DCount("休日", "tbl休日", "休日 = #" & rs!日付 & "#") > 0 Then

'後略
11

hatena様
イミディエイトでは何も出力されませんでした。

デバッグコードの位置を以下にすると、

Do Until rs.EOF

    Debug.Print rs!残業管理ID, rs!日付

        If rs!残業区分 = 1 Then

以下のように出ます。
 84           2024/04/20
 130          2024/04/21
 85           2024/04/21

13
あん 2024/05/02 (木) 11:39:49 b41ab@001b1

sk様
ご提示の
「Sort プロパティを使用せず Open メソッドの呼び出し時に「 ORDER BY 句付きの SELECT 文」を渡すこと」
で出来ました!

debug.printでも95が表示されますし、処理も残業区分が4になってます。

ちなみにレコードの並び替えが必要な理由は、途中略の部分にありますので(おそらく並び替えが必要な処理)

やはり、残業管理ID=130で残業区分=3にして、rs.updateで並び替えが行われているということですかね。

15

やはり、残業管理ID=130で残業区分=3にして、rs.updateで並び替えが行われているということですかね。

いえ、「[残業区分]の値に 3 を代入( 1 から 3 に変更)した瞬間」です。
Update メソッドが呼び出されるより先に並べ替えが行われています。

Debug.Print "【値の代入前】"
Debug.Print "[残業管理ID]の値: " & rs![残業管理ID].Value
Debug.Print "[残業区分]の値: " & rs![残業区分].Value
Debug.Print "レコードセット内の絶対位置: " & rs.AbsolutePosition
rs!残業区分.Value = 3
Debug.Print "【値の代入後】"
Debug.Print "[残業管理ID]の値: " & rs![残業管理ID].Value
Debug.Print "[残業区分]の値: " & rs![残業区分].Value
Debug.Print "レコードセット内の絶対位置: " & rs.AbsolutePosition
rs.Update

(イミディエイトウィンドウへの出力結果)

【値の代入前】
[残業管理ID]の値: 130
[残業区分]の値: 1
レコードセット内の絶対位置: 2
【値の代入後】
[残業管理ID]の値: 130
[残業区分]の値: 3
レコードセット内の絶対位置: 3

以上のように、AbsolutePosition プロパティの値の変化からも今回の現象の原因を説明することができます。

16

ご解説ありがとうございます。
値を代入した瞬間にレコード位置が変わっていたのですか。

Sortプロパティも良く気を付けて使わなければならないですね。
Sort設定した瞬間だけ並び替えが行われるのものかと。

14
あん 2024/05/02 (木) 11:45:51 b41ab@001b1

sk様、Hiroton様、Hatena様
皆様、この度は真摯なご回答誠にありがとうございました。
問題解決することができました!