質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

5087閲覧

Worksheet_Changeで変更した行をすべて取得した

pegy

総合スコア245

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2019/07/18 04:33

下記のようなコードの場合、A3を変更した場合には
"3"を取得することができました。一方でセルの範囲でA2:A5にまとめて
"Hello"をペーストした場合、"2"しか取得できません。
これをすべて取得して順番にFor each等で行ごとに処理することはかのなのでしょうか?

vba

1Private Sub Worksheet_Change(ByVal Target As Range) 2 If Intersect(Target, Range("A1").EntireColumn) Is Nothing Then 3 Exit Sub 4 5 Else 6 Debug.print Target.Row 7 End If 8End Sub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ご推察通り、For each で可能です。

vba

1Private Sub Worksheet_Change(ByVal Target As Range) 2 If Intersect(Target, Range("A1").EntireColumn) Is Nothing Then 3 Exit Sub 4 Else 5 Dim r As Range 6 For Each r In Target 7 Debug.Print r.Row 8 Next 9 End If 10End Sub

投稿2019/07/18 05:57

hatena19

総合スコア34347

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pegy

2019/07/18 06:14

有難うございます! 因みになのですが A2に何か変化を与えると期待した動作をしてくれるのですが 「行を挿入」をする固まってしまいます。Debug.Printの出力結果は最初の行が無限に 出力されてしまいます。 コードからそのような動作が理解できないのですが、なぜそのような挙動をするのもしわかれば ご教示いただけますでしょうか?
hatena19

2019/07/18 09:56 編集

なりますね。 プロシージャの先頭に、 Application.EnableEvents = False を挿入してイベント発生を抑制すればいいかと思いましたが、 それでもだめですね。
imihito

2019/07/18 10:30

「無限に」じゃ無くて16384回な気がしますね
hatena19

2019/07/18 13:53

行挿入なので、Targetは1行全体の範囲になるということですね。 納得です。
guest

0

すでに解決済みのようですが、、、

下記のようなコードの場合、A3を変更した場合には
"3"を取得することができました。一方でセルの範囲でA2:A5にまとめて
"Hello"をペーストした場合、"2"しか取得できません。
これをすべて取得して順番にFor each等で行ごとに処理することはかのなのでしょうか?

ホントに解決なんですか?

ExcelVBA

1Private Sub Worksheet_Change(ByVal Target As Range) 2 If Intersect(Target, Range("A1").EntireColumn) Is Nothing Then 3 Exit Sub 4 5 Else 6 Debug.Print Target.EntireRow.Address(false,false) 7 End If 8End Sub

こういう答えを期待してたのでは?

あるいは、こうかな?

ExcelVBA

1Private Sub Worksheet_Change(ByVal Target As Range) 2 Dim c As Range 3 4 Set Target = Intersect(Target, Me.Columns("A")) 5 6 If Not Target Is Nothing Then 7 For Each c In Target 8 Debug.Print c.Address 9 Next 10 End If 11End Sub

行番号を全部取得する必要があるかどうか判断する材料がないので、
行番号が全部取得できたとして何に使いたいかを、
説明してほしいなと思います。
というか、ほんとにやりたいことを説明してくれないと、
なにか勘違いされてるような気がします。

投稿2019/07/19 12:58

mattuwan

総合スコア2167

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

hatena19さんの回答への補足です。

ExcelのRangeが示すセルの状態は時と場合により異なり、その状態によって各種挙動が変わることがあります。

Worksheet_Changeの引数のTargetの場合は、「セル範囲(単一セル・単一領域範囲・複数領域範囲)」を示し、
For Eachを行うと、Target内のセル1個1個がZ字の順番で取り出されます。

イメージ説明

どういうことかというと、行を挿入した場合は新規に挿入された行のセル全てが、Targetに入ります。
そのため、Targetを対象にFor Eachを行うと、その行の1列目のセルから最後の列のセルまでが1個ずつ列挙されます。

イメージ説明

対策案はいくつかありますが、汎用的な方法としてはRowsプロパティを使う方法があります。

任意のRangeに対してRowsプロパティを参照すると、参照している範囲自体は変わりませんが、そのRangeを「行毎に区切った範囲」を示すRangeの集合が返されます。
そのため、Target.Rowsに対してFor Eachを行うと、確実に1行ずつのRangeを得られます。
ただし、このRangeは「行毎に区切った範囲」を示しているためやや挙動が特殊になります。
そのため、Cellsプロパティで再度「セル範囲」に戻したほうが扱いやすいです。

他の案として、今回の質問の場合ではA列さえ取得できればいいようにも見えます。
そのため、Intersectで取得した範囲(変更されたセルの内、A列と重なる範囲)を対象にFor Eachしても良いかもしれません。

vba

1Private Sub Worksheet_Change(ByVal Target As Range) 2'https://teratail.com/questions/ 3 4 'Intersect(Target, Range("A1").EntireColumn) 5 'を無駄に堅牢に書いているだけ 6 Dim columnACells As Excel.Range 7 Set columnACells = Target.Application.Intersect( _ 8 Target, _ 9 Target.Worksheet.Range("A1").EntireColumn, _ 10 Target.Worksheet.UsedRange _ 11 ) 12 If columnACells Is Nothing Then 13 Exit Sub 14 End If 15 16 Dim r As Excel.Range 17 For Each r In columnACells 18 Debug.Print r.Row, r.Address 19 Next r 20 21 '参考:汎用的な方法 22 If False Then 23 For Each r In Target.Rows 24 Debug.Print r.Address, 'Targetの各行 25 Debug.Print r.Item(1).Address, '上の行と同じ結果(rが行を示す範囲なため) 26 Debug.Print r.Cells.Item(1).Address '変更された各行の先頭のセルのアドレス 27 Next r 28 End If 29End Sub

投稿2019/07/18 11:06

編集2019/07/18 22:12
imihito

総合スコア2166

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hatena19

2019/07/18 14:17

A列を選択して、列挿入したり、Deleteキーを押したりすると、1048576回繰り返すことになるので、Intersect(Target, Range("A1:A1000")) というように範囲を制限したほうがいいかもしれませんね。
imihito

2019/07/18 22:17

そこの考慮が漏れていました、ありがとうございます。 今回の用途的には Worksheet.UsedRange と Intersect すれば、おおよそ問題無さそうですかね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問