イベント | Excel作業をVBAで効率化 https://vbabeginner.net いつものExcel作業はVBAを使えば数秒で終わるかもしれませんよ Sat, 09 Nov 2024 14:17:27 +0000 ja hourly 1 https://wordpress.org/?v=6.6.2 https://vbabeginner.net/wp-content/uploads/2019/02/favicon-150x150.png イベント | Excel作業をVBAで効率化 https://vbabeginner.net 32 32 VBAでシートが追加時に処理を行う(Workbook_NewSheet) https://vbabeginner.net/workbook_newsheet/ Sat, 17 Dec 2022 05:59:52 +0000 https://vbabeginner.net/?p=6545 Workbook_NewSheetイベント

シートが追加されたときにマクロを動かしたい場合があります。シートが追加されたことを検知するには、ThisWorkbookシートにWorkbook_NewSheetという名前のプロシージャ(関数)を用意しておく必要があります。

Workbook_NewSheetプロシージャの追加手順は以下の通りです。

  1. VBA画面で対象ブックのThisWorkbookシートを開きます。
  2. Workbookオブジェクトを選択します。このときWorkbook_Openプロシージャが作成されますが、これは使いませんので後で削除します。
  3. Workbook_NewSheetイベントを選択します。
  4. Workbook_NewSheetプロシージャが追加されます。先に作成されていたWorkbook_Openプロシージャは不要のため削除します。

これでWorkbook_NewSheetプロシージャが作成された状態になり、シートが追加されたときに検知できるようになります。

構文

Private Sub Workbook_NewSheet(ByVal Sh As Object)

Workbook_NewSheetプロシージャは、ブックの制御を行うThisWorkbookシートに書きます。シートが追加されたタイミングで呼び出されます。

ByVal 引数の値が変更不可であることを示します。
Sh 追加されたシートを表します。データ型はObject型です。「Sh」は”Sheet”の略と思われますが、「addSheet」など任意の引数名に書き換えても構いません。
Object 引数Shのデータ型はObject型です。別のデータ型への変更は出来ません。変更した場合、Workbook_NewSheetプロシージャが呼び出されたタイミングでエラー「コンパイルエラー:プロシージャの宣言が、イベントまたはプロシージャの定義と一致していません。」になります。

シートの追加時に発生するイベントなのに、データ型がWorksheet型ではなくObject型なのは、Excelにはシートの種類が複数あるためです。一般的にはワークシートしか使いませんが、グラフシート、Excel4.0マクロシート、ダイアログシートなどもシートとしては存在します。それを考慮してObject型として汎用的に扱えるようになっています。

追加されたシートを特定する

追加されたシートを特定するには、Workbook_NewSheetプロシージャの引数を利用します。

引数はObject型のデータですが、ワークシートを追加した場合はWorksheet型が実体になります。そのため、追加されたシートがワークシートであることが分かっている場合は、Worksheet型に変換して使う方が、以降の処理でWorksheetオブジェクトのメソッドやプロパティを利用しやすくなります。

念のため、WorksheetオブジェクトかどうかをTypeName関数で判定しておくと、Worksheetオブジェクトに変換できない場合のエラー回避になります。

以下のコードでは、引数がWorksheetオブジェクトの場合に引数のObject型からWorksheet型の変数に代入し、追加シートのシート名を出力しています。

Private Sub Workbook_NewSheet(ByVal Sh As Object)
    Dim ws  As Worksheet
    
    '// 引数がWorksheet型である場合
    If TypeName(Sh) = "Worksheet" Then
        '// Object型からWorksheet型に代入
        Set ws = Sh
        
        '// 追加シートの名前を出力
        Debug.Print ws.Name
    End If
End Sub

]]>
VBAでセルを右クリック時に処理を行う(Worksheet_BeforeRightClick) https://vbabeginner.net/worksheet_beforerightclick/ Mon, 06 May 2019 06:45:35 +0000 https://vbabeginner.net/?p=4308 Worksheet_BeforeRightClickイベント

セルや行見出しや列見出しを右クリックしたときにマクロを動かしたい場合があります。セルの右クリックを検知するには、セルがある対象のシートにWorksheet_BeforeRightClickという名前のプロシージャを作っておく必要があります

そのため、複数のシートがある場合でそれぞれのシートで右クリックを検知させたい場合は、各シートでWorksheet_BeforeRightClickプロシージャの作成が必要になります。

Worksheet_BeforeRightClickプロシージャのようにイベント関連のプロシージャは基本的にVBA画面の操作で作成します。手順は以下になります。

  1. VBA画面で対象シートのコードを開きます。
  2. 左上のプルダウンから「Worksheet」オブジェクトを選択します。このときWorksheet_SelectionChangeプロシージャが作成されますが、これは使いませんので後で削除します。
  3. Worksheet_BeforeRightClickイベントを選択します。
  4. これでWorksheet_BeforeRightClickが作成されます。先に作成されていたWorksheet_SelectionChangeプロシージャは不要なため削除します。

あとは、Worksheet_BeforeRightClickプロシージャの中で、セルの値が変わった際に行いたい処理を書いていくことになります。必要であれば引数のセルの値が変わった対象であるRangeオブジェクトを使います。

イベント発生タイミング

Worksheet_BeforeRightClickプロシージャが呼ばれるのはセルや列見出しや行見出しを右クリックした直後になります。右クリックを押すとコンテキストメニューが表示されますが、コンテキストメニューはWorksheet_BeforeRightClickプロシージャの処理が終わったあとに表示されます。

セルや列見出しや行見出しの他にはシートタブも右クリックできますが、シートタブの右クリックではWorksheet_BeforeRightClickイベント発生しません。

構文

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)

Target 右クリックした際のセルや列範囲や行範囲のRangeオブジェクトが設定されます。

結合セルや複数セルを右クリックした場合はそのセル範囲のRangeオブジェクトが設定されます。

Cancel プロシージャを終了後にコンテキストメニューを表示する(False)かしない(True)かを設定します。

右クリックイベントが発生した際にはFalseが設定された状態で渡されます。

初期値のFalseのままだとプロシージャの処理終了後にコンテキストメニューが表示されますが、Trueに変更した場合はコンテキストメニューは表示されません。

右クリックしたセルを特定する

右クリックを行ったセルを特定するには、Worksheet_BeforeRightClickプロシージャの第一引数のRangeオブジェクトを利用します。プロシージャが自動生成されたときに「Target」という名前が付いています。

Rangeオブジェクトのため、セル操作で利用するメソッドやプロパティを利用できます。

例えば右クリックしたセルの座標を取得するには以下のようにAddressプロパティを利用します。

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    Debug.Print Target.Address(False, False)
End Sub

このように第一引数のRangeオブジェクトを使ってセル操作を行うことが可能です。

複数のシートで右クリックを検知させたい場合

最初に少し書きましたが、ブックに複数のシートがあり、それぞれのシートのセル右クリックを検知させたい場合は、各シートでWorksheet_BeforeRightClickプロシージャを作成しておく必要があります。

複数のシートのそれぞれで作成したWorksheet_BeforeRightClickプロシージャからは、同じ処理をさせたい場合が多いと思われます。

その場合は標準モジュールを作成して同じ処理をさせたい関数を用意しておき、各シートのWorksheet_BeforeRightClickプロシージャからはその関数を呼び出すようにしておくとよいです。

なお、標準モジュールの追加は、下の画像の左上にある「VBAProject (Book1.xlsm)」を右クリックして、挿入→標準モジュール、を選択すると追加されます。

標準モジュールに書く関数の例です。ここでは、呼び出し元から渡されたRangeオブジェクト(引数r)を元に、シート名とセル座標を出力する処理としています。

Sub GetCellAddress(r As Range)
    Dim sht As Worksheet    '// シート
    
    '// 引数セルのシート(Worksheetオブジェクト)を取得
    Set sht = Worksheets(r.Parent.Name)
    
    '// シート名とセル座標を出力
    Debug.Print sht.Name & "/" & r.Address(False, False)
End Sub

 

各シートのWorksheet_BeforeRightClickプロシージャから標準モジュールの関数を呼び出すようにします。右クリックされたときのセルは引数Targetのためそれをそのまま呼び出す関数に渡しています。

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    Call GetCellAddress(Target)
End Sub

あとは、Worksheet_BeforeRightClickプロシージャがある各シートで右クリックすると、イミディエイトウィンドウに以下のように出力されます。

Sheet1/A1
Sheet4/D63
Sheet3/L5

]]>
VBAでセルの値が変更時に処理を行う(Worksheet_Change) https://vbabeginner.net/worksheet_change/ https://vbabeginner.net/worksheet_change/#comments Sat, 04 May 2019 16:26:12 +0000 https://vbabeginner.net/?p=4301 Worksheet_Changeイベント

セルの値が変わったときにマクロを動かしたい場合があります。セルの値が変わったことを検知するには、セルがある対象のシートにWorksheet_Changeという名前のプロシージャを作っておく必要があります。

Worksheet_Changeプロシージャのようにイベント関連のプロシージャは基本的にVBA画面の操作で作成します。手順は以下になります。

  1. VBA画面で対象シートのコードを開きます。
  2. Worksheetオブジェクトを選択します。このときWorksheet_SelectionChangeプロシージャが作成されますが、これは使いませんので後で削除します。
  3. Worksheet_Changeイベントを選択します。
  4. これでWorksheet_Changeが作成されます。先に作成されていたWorksheet_SelectionChangeプロシージャは不要なため削除します。

あとは、Worksheet_Changeプロシージャの中で、セルの値が変わった際に行いたい処理を書いていくことになります。必要であれば引数のセルの値が変わった対象であるRangeオブジェクトを使います。

構文

Private Sub Worksheet_Change(ByVal Target As Range)

Target 直前に値が変わったセルのRangeオブジェクトが設定されます。

対象セルが結合セルや複数セルの場合はそのセル範囲のRangeオブジェクトが設定されます。

値が変わったセルを特定する

直前に値が変わったセルを特定するには、Worksheet_Changeプロシージャの引数のRangeオブジェクトを利用します。

Rangeオブジェクトのため、セル操作で利用するメソッドやプロパティを利用できます。

例えば対象のセルの座標を取得するには以下のようにAddressプロパティを利用します。

Private Sub Worksheet_Change(ByVal Target As Range)
    '// 対象セルの座標を表示
    Debug.Print Target.Address(False, False)
End Sub

また、背景色を黄色にしたいのであれば、以下のようにInterior.Colorプロパティで設定することで背景色が設定されます。

Private Sub Worksheet_Change(ByVal Target As Range)
    '// 対象セルの座標を表示
    Debug.Print Target.Address(False, False)
    
    '// 対象セルの背景色を黄色に設定
    Target.Interior.Color = vbYellow
End Sub

このように引数のRangeオブジェクトを使ってセル操作を行うことが可能です。

VBAの処理で値が変わった場合

手でセルの値を入力したり変更した場合は上のような対応でOKですが、VBAの処理でセルの値が変わった場合はどうなるでしょうか。

結果は、手入力の場合は同様に、VBAでセルの値を変更した場合もWorksheet_Changeプロシージャが呼び出されます。

以下のように複数セルに対して同時に値を変更したとします。

Sub aaaa()
    Range("A1:B3,A5,C6").Value = "222"
End Sub

そして、Worksheet_Changeプロシージャが呼び出されます。

Private Sub Worksheet_Change(ByVal Target As Range)
    '// 対象セルの座標を表示
    Debug.Print Target.Address(False, False)
    
    '// 対象セルの背景色を黄色に設定
    Target.Interior.Color = vbYellow
End Sub

手でセルの値を変えた場合と同様に、背景色を黄色に設定する処理も各セルに対して行われます。

Worksheet_Changeプロシージャが動作しない場合

Worksheet_Changeプロシージャが動作していないように見えることがあります。

これはほとんどの場合が、セルの値が変わったシートと、Worksheet_Changeプロシージャを書いているシートが異なることが原因です。

Sheet1のコードにWorksheet_Changeプロシージャを書いている場合に、Sheet2のセルの値を変更しても、Sheet1のWorksheet_Changeプロシージャは呼び出されません。

複数のシートを持っているブックを操作する場合には勘違いしやすいので注意してください。

]]>
https://vbabeginner.net/worksheet_change/feed/ 1
VBAでセルのダブルクリックを検知する https://vbabeginner.net/detect-cell-double-clicks/ Wed, 14 Nov 2018 16:31:35 +0000 https://vbabeginner.net/?p=3684 Worksheet_BeforeDoubleClickイベント

セルをダブルクリックしたことを検知するには、セルがある対象のシートにWorksheet_BeforeDoubleClickという名前の関数を作ります。

このようなイベント関連のプロシージャは基本的に自分で書かずに以下の手順で作成してください。

  1. 対象シートのコードを開く。
  2. Worksheetオブジェクトを選択する。このときWorksheet_SelectionChangeプロシージャが作成されますが、これは使いませんので後で削除します。
  3. BeforeDoubleClickイベントを選択する。
  4. これでWorksheet_BeforeDoubleClickが作成されます。
  5. 先に作成されていたWorksheet_SelectionChangeプロシージャは不要なため削除する。

あとは、Worksheet_BeforeDoubleClickプロシージャの中で、セルがダブルクリックされた際に行いたい処理を書いていくことになります。

構文

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)

Target ダブルクリックした際のセルのRangeオブジェクトが設定されます。

結合セルをダブルクリックした場合はそのセル範囲のRangeオブジェクトが設定されます。

Cancel プロシージャを終了後に対象セルを編集状態にするかしないかを設定します。

ダブルクリックイベントが発生した際にはFalseが設定された状態で渡されます。

Falseのままだとプロシージャの処理終了後にダブルクリックしたセルにカーソルが当たり編集状態になりますが、Trueに変更した場合は編集状態になりません。

 

ダブルクリックしたセルを特定する

ダブルクリックを行ったセルを特定するには、Worksheet_BeforeDoubleClickプロシージャの第一引数のRangeオブジェクトを利用します。

Rangeオブジェクトのため、セル操作で利用するメソッドやプロパティを利用できます。

例えばダブルクリックしたセルの座標を取得するには以下のようにAddressプロパティを利用します。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    '// 対象セルの座標を表示
    Debug.Print Target.Address(False, False)
End Sub

このように第一引数のRangeオブジェクトを使ってセル操作を行うことが可能です。

結合セルをダブルクリックした場合

結合セルをダブルクリックした場合は、その結合セルを構成するセル範囲が第一引数のRangeオブジェクトとして利用することが出来ます。

上のコードをそのまま使って以下のようにA1からC2まで結合しているセルをダブルクリックすると、、、

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    '// 対象セルの座標を表示
    Debug.Print Target.Address(False, False)
End Sub

結合セル範囲のA1:C2がDebug.Printにて出力されます。

]]>