[[20240730225245]] 『2箇所同時に実行したい』(ネットカフェ) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『2箇所同時に実行したい』(ネットカフェ)

チェンジイベントマクロなんですが
B列を変更するとAI列にもB列の文字列がコピーされるのですが
2箇所にするとどうしてもうまく動作してくれないので
変更をお願いします

Selection.Copy
ActiveCell.Offset(0, 32).Range("B1").Select'-------AI列
'ここにもう一つ条件を追加したい
'ActiveCell.Offset(0, 40).Range("B1").Select------AQ列

    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False'ここでデバックがかかってしまい止まってしまう。

< 使用 Excel:Excel2007、使用 OS:Windows10 >


 チェンジイベントマクロの全体を省略せずに書いてもらえませんか?
 Targetを制約するような条件はつけているのでしょうか?

 チェンジイベントマクロのなかでセルを変更すると、それがまたChangeイベントを引き起こします。
 そのことを考慮する必要があります。

(xyz) 2024/07/30(火) 23:11:44


すいません。こちらです
 Private Sub Worksheet_Change(ByVal Target As Range)

 If Target.Row < 12151 Then Exit Sub
 If Target.Column = 2 Then
Selection.Copy
ActiveCell.Offset(0, 32).Range("B1").Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False

   With Selection.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .Color = 255
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With

 End If
 Application.CutCopyMode = False

End Sub
(ネットカフェ) 2024/07/30(火) 23:22:01


 エラーの原因はわかりませんでした。

 それ以前に、基本的にところで勘違いがあるように見受けました。
 (1)TargetとSelect,ActiveCellの違いを理解されていますか?
    TargetはChangeがあったセル範囲、Selectは現在の選択範囲です。
    例えば、入力後、カーソルを下に移動させる設定にしてあると、TargetとSelectは位置がずれます。
    SelectはTargetのひとつ下のセルです。コピー元が意図に合っているものか確認して下さい。
 (2)
 |    ActiveCell.Offset(0, 32).Range("B1").Select'-------AI列
 |   'ここにもう一つ条件を追加したい
 |   'ActiveCell.Offset(0, 40).Range("B1").Select------AQ列
     ActiveCellは動きますから、二番目の処理ではAQ列にはなりません。確認してください。   
     (ActiveCell.Offset(0, 32).Range("B1")の意図もよくわかりませんでした)

 想像を交えていますので、そちらでよく確認して下さい。

 Private Sub Worksheet_Change(ByVal Target As Range)
     Dim rng  As Range
     If Target.Row < 12151 Then Exit Sub
     If Target.Column = 2 Then
         Target.Copy
         Set rng = Union(Target.Offset(0, 33), Target.Offset(0, 41))
         Application.EnableEvents = False            'イベントの捕捉を一時停止
         rng.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, _
                 SkipBlanks:=False, Transpose:=False
         Application.EnableEvents = True             'イベントの捕捉を再開
         With rng.Interior
             .Pattern = xlSolid
             .PatternColorIndex = xlAutomatic
             .Color = 255
             .TintAndShade = 0
             .PatternTintAndShade = 0
         End With
         Application.CutCopyMode = False
     End If
 End Sub
(xyz) 2024/07/31(水) 06:36:45

動作これでバッチリOKです

Offset(0, 41))のTarget「41」で同一行の右へ移行したAQ列に意図したことが無事移動しました。
難しかったです。
この度はどうもありがとうございました。

(ネットカフェ) 2024/07/31(水) 06:53:20


結果オーライは分かりました。
指摘させていただいた点については如何ですか?

(xyz) 2024/07/31(水) 07:30:15


話は終わってる?ようですが何点か。

■1
ChangeイベントのTargetは、(飛び飛びのセルを含む)複数のセル(範囲)になることがあり得ます。
このとき「Target.Row」「Target.Column」は、それぞれ一番左上のセルのことになりますので、複数セルが同時に変更されることがあるのであれば、判定に使うのはお勧めできません。
(削除や消去、貼付などでいっぺんに書き換わることは往々にしてあります)

■2
既にあるように「Target」「Selection」「ActiveCell」それぞれの違いをちゃんと理解することお勧めします。
xyzさんの説明と重複する部分もありますが、私なりに説明すると

 Target・・・・・書き換えのあったセル。飛び飛びの複数セル(範囲)であることがあり得る。

 Selection ・・・現在選択しているもの。セル範囲以外のものでもSelectionになり得る。(たとえばシェイプなど)
                 セルを意味する場合でも飛び飛びの複数セル(範囲)であることがあり得る。

 ActiveCell・・・そのままアクティブなセル。単一セルであり複数(またはセル範囲)になることはない

という感じになります。
このときに注意すべきなのは、飛び飛びのセル(範囲)の場合、コピーできる(場合もある)が、飛び飛びのセル(範囲)へ貼付はできないというところです。
以下のコードをステップ実行していただければ、言わんとしていることは伝わると思います。

    Sub 実験01()
        Stop

        On Error GoTo エラー表示

        Range("B1:C2,C4").Copy '←失敗する例1

        With Range("B1:B2,B4")
            .Copy
            .Offset(, 1).PasteSpecial Paste:=xlPasteValues ' ←失敗する例2

            .Areas(1).Cells(1, 1).Offset(, 1).PasteSpecial Paste:=xlPasteValues ' ←エラーにならないが結果は・・・
            MsgBox .Offset(, 1).Address(0, 0) & "ではなく、" & vbLf & Selection.Address(0, 0) & "に貼付しました"
        End With

    Exit Sub

    エラー表示:
        MsgBox "エラーが発生しました" & vbLf & vbLf & "エラー番号:" & Err.Number & vbLf & Err.Description
        Err.Clear
        Resume Next
    End Sub

■3
したがって、仰る「2箇所同時」というのが、飛び飛びの2か所(以上)を同時に変更した場合のことを言っているのであれば、[[20240727134719]]で学習されたように、ループ処理で1セル(範囲)ごとに処理する必要があります。
(今回は違うようですが)

■4
余談になりますが↓の記述も適切とは思えません。

 ActiveCell.Offset(0, 32).Range("B1").Select
                         ~~~~~~~~~~~~
エクセル君の忖度により何とかなっちゃっていますが↓のように解釈されています。
 ActiveCell.Offset(0, 32).Cells(1, 2).Select

別に間違いではないですが、それなら素直に↓のように書くべきでしょう。

 ActiveCell.Offset(0, 33).Select

また、ExcelVBAでは基本的にシートやセルなど(オブジェクトと言います)は、きちんと明示すればいちいちアクティブにしたり選択したりする必要はありませんし、可読性向上の観点からもActive○○やSelection.○○に依存するような書き方はお勧めしません。(好みの問題ではありますが)

■5
上記を踏まえると、以下のようなコードでも解決できたとおもいます。
興味があればステップ実行等により、研究してみてください。

    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim bufRNG As Range, MyRNG As Range

        Set bufRNG = Intersect(Target, Me.Range("B1:B12150"))
        If Not bufRNG Is Nothing Then
            For Each MyRNG In bufRNG.Areas
                MyRNG.Copy
                Intersect(MyRNG.EntireRow, Me.Range("AI:AI,AQ:AQ")).PasteSpecial Paste:=xlPasteValues
            Next MyRNG
            Application.CutCopyMode = False

            Intersect(bufRNG.EntireRow, Me.Range("AI:AI,AQ:AQ")).Interior.Color = 255
        End If
    End Sub

 ※上記のコードは研究材料としての提供であり、完成品プレゼントの意図はありません。
  ちゃんと理解して頂きたいので丸パクリして完成!というのはご遠慮ください。
  (ご自身のコードを修正していって、結果が同じになってしまっただけならOKです)

■6
ちなみに、上記の処理だとAI,AQ列の塗りつぶしはいったん塗りつぶししたらそのままになります。
もしも、B列の値がクリアされたら(""になったら)塗りつぶしを解除したいということなら↓のように1セル(行)ごとに判定する必要があります。

    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim bufRNG As Range, MyRNG As Range

        Set bufRNG = Intersect(Target, Me.Range("B1:B12150"))
        If Not bufRNG Is Nothing Then
            Application.ScreenUpdating = False

            For Each MyRNG In bufRNG '←1セルずつに変更
                With Intersect(MyRNG.EntireRow, Me.Range("AI1,AQ1").EntireColumn)
                    '↓値が「""」かどうかで処理分岐
                    If MyRNG.Value <> "" Then
                        MyRNG.Copy
                        .PasteSpecial Paste:=xlPasteValues
                        .Interior.Color = 255
                    Else
                        .Clear
                    End If
                End With
            Next MyRNG
            Application.CutCopyMode = False
            Application.ScreenUpdating = True
        End If
    End Sub

(もこな2 ) 2024/08/01(木) 19:13:01


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.