2017-09-05 28 views
3

私はExcel-VBA初心者です。ワークシート内のセルの値を変更した人がトリガーする短いコードを書き込もうとしています。 変更されたセルの値を0より小さい値に設定する必要があります。コードは次のようになります。今Worksheet_Changeイベントの対象範囲が正しくありません

Private Sub Worksheet_Change(ByVal Target As Range) 
'Debug.Print Target.Address 
If Target.Column = 6 Then 
    For Each Cell In Target.SpecialCells(xlCellTypeConstants, 3) 
    If Cell.Value < 0 Then 
     Cell.Value = 0 
    End If 
    Next 
End If 
End Sub 

何が起こるかは、私が6列の任意のセルの値を変更すると、ゼロ未満の数値を含むシート内のすべてのセルががゼロに変更されたことです。

Worksheet_Changeイベントハンドラ用に作成された「ターゲット」オブジェクトには、変更されたセル/セルのみが含まれていると考えられていたため、変更されたセルの値が変更されました。最初の場所。

私は出力にオブジェクトのアドレスをDebug.Printを使用して自分を助けようとしました。これはシート内のすべてのセルのアドレスを0より小さい値で表示していたので、ハンドラが何度か実行されたと仮定します。

私は実際には問題自体の回避策が見つかりましたが、私の質問は、これらのは次のとおりです:どのように私はWorksheet_Changeイベントを使用して失敗したと私はそのような問題を持っていないし、将来的に何ができるのでしょうか?

+2

application.enableevents = falseを使用するか、イベントプロシージャがそれ自身の上で実行されます。 – Jeeped

+0

'Target'は変更されたセルにのみ関連しています。あなたのエラーを複製することはできません。 Jeepedの修正案を試して、どのように乗り越えるかを見てください。 – SJR

+1

それ以降に 'Application.EnableEvents = True'に戻すことを忘れないでください。そうでなければ、あなたのイベントは次回には起動しません。 – Tom

答えて

0

EDIT 1:あなたの質問

に答えて配列数式

に対処するためのエラー処理と更新コード:バグ修正と更新されたコードのコメント

EDIT 2で提案されています

[1]は、どのように私はWorksheet_Changeイベントを使用して失敗したと[2]このような問題が起こらないように、私は将来どのように対処できますか?

  1. 技術的には以下のルールはあなたがTargetオブジェクトのご理解で正しいです一般

に役立ちますが、あなたは、

  • この種の問題のために何もしなかったん。 SpecialCellsは、動作する単一のセルが好きではないため、コードが失敗しました。それを1つ与えて、全体をシートに展開してください!他に何か与えてもうまく動作します。

    あなたDebug.Printディスプレイのすべてのセルの理由は、あなたのコードがセルを変更するたびに、が別の変更イベントがトリガされていることです。幸いなことに、2番目のものはゼロを見つけるので、トリガーしません。もう1つです。

    • は常にApplication.EnableEventsとワークブックの任意の部分を変更するイベントハンドラで任意のコードを囲む:以下の一般的なルールは、多くの問題だけではない。この特定の1つを回避するのに役立つはずです。

    コードを修正して機能するようにするには、SpecialCellsメソッド呼び出しを削除するだけです。 Cell.Value2hereを参照)の代わりにCell.Valueを使用しているため、VBA暗黙の型は、テキスト形式の数値を実際の数値に変換します。したがって、コードは数値とテキストの両方の値で動作します。

    コード:

    Private Sub Worksheet_Change(ByVal Target As Range) 
        'Debug.Print Target.Address; 
        Application.EnableEvents = False 
        For Each Cell In Target '.SpecialCells(xlCellTypeConstants, 3) 
         If Cell.Column = 6 And Cell.Value < 0 Then 
         On Error GoTo Error: 
         Cell.Value = 0 
         On Error GoTo 0 
         End If 
        Next 
    GoTo ExitSub: 
    Error: 
        If Err.Number = 1004 Then ' 1004 -> "You cannot change part of an array." 
        'Application.Undo ' Uncomment to disallow array entering a negative value formula into/across column 6 
        MsgBox "A cell could not be zeroed as" & vbCr & "it is part of an array formula.", vbExclamation, "Microsoft Office Excel" 
        On Error GoTo 0 
        Else 
        On Error GoTo 0 
        Resume 
        End If 
    ExitSub: 
        Application.EnableEvents = True 
    End Sub 
    

    注:

    - 更新1:コードが正しくマルチセルの変更を扱っています。

    - アップデート2:コードでは、配列の式を入力するためのエラー1004がトラップされます。配列式を入力して列6に負の値を持たせるか、または入力を完全に停止するかのいずれかを行うことができます。

  • +0

    私はtarget.columnの使用を避けました。なぜなら、ctrl + enterを使用して水平範囲のデータを入力できるからです。 –

    +0

    @PatrickHonorezわかりません。また、* vertical *の範囲でデータを入力することもできます。しかし、式は異なる必要があります。 – robinCTS

    +0

    'Target'は範囲であり、複数の列をカバーします。したがって、 'If Target.Column = 6'はエラーが発生しやすくなります。 –

    0

    この作品

    Private Sub Worksheet_Change(ByVal Target As Range) 
        Dim c As Range 
        For Each c In Target 
         If c.Column = 6 Then If IsNumeric(c) Then If c < 0 Then c = 0 
        Next c 
    End Sub 
    

    を(を更新しました)そして、学び、OPTION EXPLICITを使用してください!

    +0

    これは '.SpecialCells(xlCellTypeConstants、3) 'で動作するようにはできません。 – Tom

    +0

    また、3は何ですか。 [ドキュメント](https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-specialcells-method-excel)には記載されていません – Tom

    +1

    @Tom:ドキュメント3によると同等です'xlNumbers + xlTextValues'です。それは働いて、私は試しました –

    関連する問題