- ベストアンサー
ExcelVBAのrangeのdeleteの検出方法
- ExcelVBAでのrangeのdelete機能を検出する方法について解説します。
- deleteしたセルをif文で検出する方法について詳しく説明します。
- setしたrangeをdeleteした場合の検出方法について、on error gotoを使わずに処理する方法を紹介します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
蛇足的ですが Sub test2() With Workbooks.Add(xlWBATWorksheet).Sheets.Add .Name = "monitoring" .Range("A1").Formula = "=Sheet1!C3" .Visible = xlSheetVeryHidden End With End Sub 上記で作成したBookの非表示シート 'monitoringのSheetModuleに Option Explicit Private Sub Worksheet_Calculate() Const chk = "Sheet1" '監視対象Sheet名 Dim ws As Worksheet Dim x As String With Range("A1") x = .Formula On Error Resume Next Set ws = Sheets(Mid$(x, 2, InStr(x, "!") - 2)) On Error GoTo 0 If ws Is Nothing Then MsgBox "Sheet削除" Else If ws.Name <> chk Then MsgBox "Sheet名変更" ElseIf InStr(x, "#REF!") > 0 Then MsgBox "C3削除" ElseIf x <> "=Sheet1!C3" Then MsgBox "C3移動" End If Set ws = Nothing End If End With End Sub 作業用ダミーシートに数式を入れて そのCalculateイベントを使えば、 例示であげた種類のイベントについて、ある程度監視できます。 #監視イベント次第では、参照するセルアドレスの位置を工夫したり、 #EnableEvents制御しつつ、数式を再セットしたりする必要がありますが。 セル削除だけだったら Private Sub Worksheet_Calculate() If InStr(Range("A1").Formula, "#REF!") > 0 Then MsgBox "C3削除" End If End Sub
その他の回答 (3)
- end-u
- ベストアンサー率79% (496/625)
On Error Resume Next On Error GoTo 0 で挟んで処理するのが簡単だと思いますが 使いたくない場合は Sub test() With Workbooks.Add(xlWBATWorksheet) Dim r As Range Set r = .Sheets(1).Range("C3") r.Name = "check" MsgBox r Is Nothing MsgBox InStr(.Names("check"), "#REF!") > 0 r.Delete shift:=xlUp MsgBox r Is Nothing MsgBox InStr(.Names("check"), "#REF!") > 0 End With End Sub こんな感じでチェックできます。 名前定義や数式の参照エラーを使うと良いでしょう。
お礼
ありがとうございます。 正直に言って私の知らない”技”がいっぱいで、とても参考になりました。 InStr(.Names("check"), "#REF!") こういう使い方は思いもよりませんでした。 しっかりとじっくりとまた考えてみたいと思います。
- DreamyCat
- ベストアンサー率56% (295/524)
コードというかやっていることがでたらめのように見えます。 (わからないから試行ということで載せているだけなのだとは思いますが。。。) deleteした時点で、 それより上の行のどこかに、 または、絶対に使わない下のほうの特定行のどこかに、 または別シートに、削除フラグ(数字でもなんでも)を書き込むようにして、 シートのchageイベントがおこるたびに削除したのかどうかをチェックし、 削除したとわかった場合はフラグをリセットしておく。これでできそうですが。 (確認していないのでやってみてください。)
補足
回答ありがとうございます。 コードは一つの例としてのせました。目的の部分だけが分かりやすいかなあと思ってのせました。 「deleteした時点で」、というのは、deleteの前後に、プログラム上で、フラグをセットするということでしょうか。あるいは、deleteしたことを何か別のイベントとして認識し、自動的にフラグをセットするのでしょうか。もし、後者の場合、よく分からないので、もう少し詳しく教えてていただけますか。また、changeイベントは、既に別の用途で使用しているので、そこまではしたくないと考えています。もっと単純にnothingかnullかemptyか””か、みたいな感じで、簡単にif文で判断できる方法はないのかなあと思ったのです。
- imogasi
- ベストアンサー率27% (4737/17069)
質問に書いているようなコードではダメでしょう。セルの値なら空白であるかどうか「判断してはダメですか。 DELETEキーを押されたイベントを捕まえるのはAPIなど(*)になっって、質問者のコードの書きぶりから推測して、難しいと思う。 エクセルVBA程度で、そういうタイミングをとらえなければならない理由は。総合的にどういうことがしたいのか質問文に書いて質問したら。今までの質問で、初心者がコードを開示しても、アイデアからして、的外れなことが多い。 (*)http://okwave.jp/qa/q3207578.html
補足
早速の回答ありがとうございます。 セルそのものをdeleteしている場合、空白でもありません。ですから例えば、aがdeleteしたセルだとして、if a.value="" then としてもエラーになります。 また、別のルーチンでBVAで、deleteするので、deleteキーを押されたイベントを捉えることも目的とはしていません。 コードは一つの例として書いたものです。 もともとの目的は、あるシートにいくつかの表があり、それぞれのデータが色々な関連があり、そのうちのある表のデータを書き換えたり、削除したり、コピーを作ったりします。その時、関連するデータから、それらを制限したり、あるいは、変更した結果から他のいくつかの表の内容を書き換えたりするプログラムです。ある表のデータを書き換えたり、新しく作ったり、削除したりしたことを別のルーチンから認識したいのです。 よろしくお願いします。
お礼
ありがとうございます。今回はセル削除のモニターだけを考えているので、InStr(rangeを示す何か.Formula,"#REF!")>0 を使います。助かりました。 他にも、私にとっては新鮮な驚きがたくさんあり、実に勉強になりました。具体的には以下のようなものです。 with のあとでのdim withの部分で、オブジェクト.add という形 nameやnamesの使い方 is の使い方 ありがとうございます。これからもいろんな事を学んでいきたいと思います。