Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


1767 / 13645 ツリー ←次へ | 前へ→

【72043】セル更新時のマクロ けい 12/5/21(月) 19:27 質問[未読]
【72044】Re:セル更新時のマクロ ponpon 12/5/21(月) 23:42 発言[未読]
【72051】Re:セル更新時のマクロ けい 12/5/22(火) 14:46 質問[未読]
【72047】Re:セル更新時のマクロ UO3 12/5/22(火) 11:14 発言[未読]
【72050】Re:セル更新時のマクロ けい 12/5/22(火) 14:04 質問[未読]
【72054】Re:セル更新時のマクロ UO3 12/5/22(火) 21:46 発言[未読]
【72060】Re:セル更新時のマクロ けい 12/5/23(水) 11:07 質問[未読]
【72055】Re:セル更新時のマクロ UO3 12/5/22(火) 21:51 発言[未読]
【72061】Re:セル更新時のマクロ けい 12/5/23(水) 11:34 質問[未読]
【72063】Re:セル更新時のマクロ UO3 12/5/23(水) 12:44 発言[未読]
【72066】Re:セル更新時のマクロ けい 12/5/23(水) 13:53 お礼[未読]
【72052】Re:セル更新時のマクロ ponpon 12/5/22(火) 15:01 発言[未読]

【72043】セル更新時のマクロ
質問  けい E-MAIL  - 12/5/21(月) 19:27 -

引用なし
パスワード
   どうかよろしくお願いします。

セルが更新されたら自動的に他のセルが更新されるようにマクロを作成しています。
セルL30が更新(入力)されたら、メッセージボックスで"有り"or"無し"をYesNoで答えそのどちらかの結果を自動的にセルI36へ入力させます。

セルL30が削除され空白になった時はI36も空白に自動的にしたいのですが、以下のマクロでは空白になりませんでした。
どこがおかしいのでしょうか。
更新時というのは削除や空白は含まれないのでしょうか。

Private Sub WorkSheet_change(ByVal Target As Range)
If (Target.Address = "$L$30") Then

  
 If (Range("L30")) <> "" Then

   P = MsgBox("有りですか?", vbYesNo)
  
   If P = vbYes Then
  
   Range("I36") = "有り"
  
   Else
  
   Range("I36") = "無し"
 
   End If
 
 ElseIf (Range("L30")) = "" Then

  Range("I36") = ""
  
 End If

End If

End Sub

【72044】Re:セル更新時のマクロ
発言  ponpon  - 12/5/21(月) 23:42 -

引用なし
パスワード
   エクセルのバージョンは何でしょう?

2003で確かめましたが、ちゃんと動きますよ。

いろいろ書き方はあると思いますが、私なら以下のようにします。


Private Sub Worksheet_Change(ByVal Target As Range)

 If Target.Count > 1 Then Exit Sub
 If Application.Intersect(Target, Range("l30")) Is Nothing Then Exit Sub
 
 Application.EnableEvents = False
 
 If Target.Value = "" Then
   Range("I36") = ""
   
 Else
   P = MsgBox("有りですか?", vbYesNo)
   If P = vbYes Then
     Range("I36") = "有り"
   Else
     Range("I36") = "無し"
   End If
 
 End If
 Application.EnableEvents = True

End Sub

【72047】Re:セル更新時のマクロ
発言  UO3  - 12/5/22(火) 11:14 -

引用なし
パスワード
   ▼けい さん:

こんにちは

はずしているかもしれませんが・・・・

たとえば L30 を「セル削除」した場合、確かにTarget.Address は
$L$30 になります。
ただし、その値は Target.Value であれ Range("L30").Value であれ
「新しいL30」の値になります。(削除前のL30の値は返りません)

ただし、「空白」、つまり、L30を「クリア」すれば、値は空白で返ってきます。
なので、ElseIf での処理がなされると思うのですが?

ブレークポイントの設定と、ステップ実行はご存知でしょうか?
最初の If 文にブレークポイントを設定し、L30をクリアして、このコードでとまった後
F8を押しながら1ステップずつ実行させますと、コードが、どのような順序で実行されるのかが
わかります。是非、お試しください。

それと、今回のケースでは、最初にTargetのアドレスをL30 と聞いていますので
実害はないのですが、L36へのセットで、Changeイベントが発生し、その瞬間に
このプロシジャに再入してきます。(イベントの連鎖)

一般的には、処理の前に、
Application.EnableEvents = False と記述してイベント発生を抑止し
処理後に
Application.EnableEvents = True として復旧させますね。

アップされたコードと基本、同じですが、少し手直ししたものを参考まで以下に。

Private Sub WorkSheet_change(ByVal Target As Range)
  Dim P As VbMsgBoxResult
  
  If Target.Address <> "$L$30" Then Exit Sub
  
  Application.EnableEvents = False
    
  If Range("L30") <> "" Then
  
    P = MsgBox("有りですか?", vbYesNo)
    
    If P = vbYes Then
    
      Range("I36").Value = "有り"
  
    Else
  
      Range("I36").Value = "無し"
    
    End If
    
  Else
    
    Range("I36").ClearContents
    
  End If
  
  Application.EnableEvents = True
  
End Sub

【72050】Re:セル更新時のマクロ
質問  けい E-MAIL  - 12/5/22(火) 14:04 -

引用なし
パスワード
   ▼UO3 さん:

こんにちは!ご回答いただきありがとうございました。
手直しいただいたコードを貼り付け、ブレークポイントを設定して実行してみた結果、L30をDeleteした時はExit Subに飛んで終わっていました。

空白として更新されたと認識されないようです。
どうしたら空白と認識されるのでしょうか、、、


>▼けい さん:
>
>こんにちは
>
>はずしているかもしれませんが・・・・
>
>たとえば L30 を「セル削除」した場合、確かにTarget.Address は
>$L$30 になります。
>ただし、その値は Target.Value であれ Range("L30").Value であれ
>「新しいL30」の値になります。(削除前のL30の値は返りません)
>
>ただし、「空白」、つまり、L30を「クリア」すれば、値は空白で返ってきます。
>なので、ElseIf での処理がなされると思うのですが?
>
>ブレークポイントの設定と、ステップ実行はご存知でしょうか?
>最初の If 文にブレークポイントを設定し、L30をクリアして、このコードでとまった後
>F8を押しながら1ステップずつ実行させますと、コードが、どのような順序で実行されるのかが
>わかります。是非、お試しください。
>
>それと、今回のケースでは、最初にTargetのアドレスをL30 と聞いていますので
>実害はないのですが、L36へのセットで、Changeイベントが発生し、その瞬間に
>このプロシジャに再入してきます。(イベントの連鎖)
>
>一般的には、処理の前に、
>Application.EnableEvents = False と記述してイベント発生を抑止し
>処理後に
>Application.EnableEvents = True として復旧させますね。
>
>アップされたコードと基本、同じですが、少し手直ししたものを参考まで以下に。
>
>Private Sub WorkSheet_change(ByVal Target As Range)
>  Dim P As VbMsgBoxResult
>  
>  If Target.Address <> "$L$30" Then Exit Sub
>  
>  Application.EnableEvents = False
>    
>  If Range("L30") <> "" Then
>  
>    P = MsgBox("有りですか?", vbYesNo)
>    
>    If P = vbYes Then
>    
>      Range("I36").Value = "有り"
>  
>    Else
>  
>      Range("I36").Value = "無し"
>    
>    End If
>    
>  Else
>    
>    Range("I36").ClearContents
>    
>  End If
>  
>  Application.EnableEvents = True
>  
>End Sub

【72051】Re:セル更新時のマクロ
質問  けい E-MAIL  - 12/5/22(火) 14:46 -

引用なし
パスワード
   ▼ponpon さん:
ご回答をありがとうございます。
バージョンは2007です。

こちらで試したのですが、やはり空白にした場合
ExitSubで終了し、I36も空白にしたいという処理には進まないようです。

I36を消してからExitSubとはならないものでしょうか。


>エクセルのバージョンは何でしょう?
>
>2003で確かめましたが、ちゃんと動きますよ。
>
>いろいろ書き方はあると思いますが、私なら以下のようにします。
>
>
>Private Sub Worksheet_Change(ByVal Target As Range)
>
> If Target.Count > 1 Then Exit Sub
> If Application.Intersect(Target, Range("l30")) Is Nothing Then Exit Sub
> 
> Application.EnableEvents = False
> 
> If Target.Value = "" Then
>   Range("I36") = ""
>   
> Else
>   P = MsgBox("有りですか?", vbYesNo)
>   If P = vbYes Then
>     Range("I36") = "有り"
>   Else
>     Range("I36") = "無し"
>   End If
> 
> End If
> Application.EnableEvents = True
>
>End Sub

【72052】Re:セル更新時のマクロ
発言  ponpon  - 12/5/22(火) 15:01 -

引用なし
パスワード
   >セルL30が削除され空白になった時は

どのようなやり方で空白にしているのでしょうか?
この程度のことなら2007でも関係ないと思いますが・・

削除したあとエンターで確定してますか?

【72054】Re:セル更新時のマクロ
発言  UO3  - 12/5/22(火) 21:46 -

引用なし
パスワード
   ▼けい さん:

こんばんは

>ブレークポイントを設定して実行してみた結果、L30をDeleteした時はExit Subに飛んで終わっていました。
>
>空白として更新されたと認識されないようです。
>どうしたら空白と認識されるのでしょうか、、、

Exit SUb で終わったと言うことは
If Target.Address <> "$L$30" Then Exit Sub
この Exit Sub ですね?

ということは L30が空白かどうかの判定の前ですから、ここで抜けると言うことは
そのDelete(Deleteキーによるクリアですね)したセルがL30じゃなかったということですが?

そうではなく、その下に進んだということですか?

【72055】Re:セル更新時のマクロ
発言  UO3  - 12/5/22(火) 21:51 -

引用なし
パスワード
   ▼けい さん:

追加で。

たとえばL30を含んで、複数セルを選択して(たとえがL30とL31)クリアキーを押すと
Target.Address は "$L$30:$L$31" になりますので、 $L$30 ではないと見なされます。
このような場合を想定するなら、PonPonさんがアドバイスされたように、Intersect を使ってください。
ただし、PonPonさんのコードでは、その前に、変更のあったセルが1つではなかったらExitさせています。
これをなくせばよろしいかと。

【72060】Re:セル更新時のマクロ
質問  けい E-MAIL  - 12/5/23(水) 11:07 -

引用なし
パスワード
   ▼UO3 さん:

こんにちは。
DaleteしたのはL30です。

If Target.Address <> "$L$30" Then Exit Sub
のExitSubでストップしてF8を押してもその後何も動きませんでした。

TargetはL30なのですが、Range("I36").ClearContents
に進んでくれませんでした。


>▼けい さん:
>
>こんばんは
>
>>ブレークポイントを設定して実行してみた結果、L30をDeleteした時はExit Subに飛んで終わっていました。
>>
>>空白として更新されたと認識されないようです。
>>どうしたら空白と認識されるのでしょうか、、、
>
>Exit SUb で終わったと言うことは
>If Target.Address <> "$L$30" Then Exit Sub
>この Exit Sub ですね?
>
>ということは L30が空白かどうかの判定の前ですから、ここで抜けると言うことは
>そのDelete(Deleteキーによるクリアですね)したセルがL30じゃなかったということですが?
>
>そうではなく、その下に進んだということですか?

【72061】Re:セル更新時のマクロ
質問  けい E-MAIL  - 12/5/23(水) 11:34 -

引用なし
パスワード
   ▼UO3 さん:

色々とご説明をありがとうございます。
確かにL30もI36も結合セルだったため動いてなかったようです。
セルを結合させずにマクロを実行したら動きました。

もし結合セルのままマクロを動かすとした場合、以下の
If Target.Count > 1 Then Exit Subを外せばよいのでしょうか。
また、外してみたのですがその場合If Target.Value = "" Then
のところで型が違うとエラーになりました。
空白だった時と他の書き方はありますか?


Private Sub Worksheet_Change(ByVal Target As Range)

 If Target.Count > 1 Then Exit Sub ’<<ここを省略?
 If Application.Intersect(Target, Range("l30")) Is Nothing Then Exit Sub
 
 Application.EnableEvents = False
 
 If Target.Value = "" Then’<<ここで型が違うとエラーが出ます。
   Range("I36") = ""
   
 Else
   P = MsgBox("有りですか?", vbYesNo)
   If P = vbYes Then
     Range("I36") = "有り"
   Else
     Range("I36") = "無し"
   End If
 
 End If
 Application.EnableEvents = True

End Sub


>▼けい さん:
>
>追加で。
>
>たとえばL30を含んで、複数セルを選択して(たとえがL30とL31)クリアキーを押すと
>Target.Address は "$L$30:$L$31" になりますので、 $L$30 ではないと見なされます。
>このような場合を想定するなら、PonPonさんがアドバイスされたように、Intersect を使ってください。
>ただし、PonPonさんのコードでは、その前に、変更のあったセルが1つではなかったらExitさせています。
>これをなくせばよろしいかと。

【72063】Re:セル更新時のマクロ
発言  UO3  - 12/5/23(水) 12:44 -

引用なし
パスワード
   ▼けい さん:

こんにちは

結合セルでしたか。
そうしますと、Targetに入ってくる領域は結合されたセルアドレス(たとえば I30:J30 等)
なので I30 ではないわけです。かつ、この場合、Target.Count は結合されたセルの数。
ですから 1 ではありません。

・If Target.Count > 1 Then Exit Sub

 これで抜けると具合が悪いので削除しましょう。

・If Intersect(Target, Range("I30")) Is Nothing Then Exit Sub

 I30 が l30 (小文字のエル)になってますよ〜。

・If Target.Value = "" Then

 結合セルが変更された場合、あるいは、複数領域が変更された場合(複数セルを選んでクリア
 あるいは、複数セルをコピーした上でペースト)Targetは複数領域ですから、
 たとえば Range("I30:J30").value というのは配列です。したがって、そのValue を参照すると
 エラーになります。
 結合セルでも、クリアではなく、値の入力の場合、I30 となりますけど、複数セル領域が入っている
 と認識したほうがいいでしょうね。

 Target(1).Value (領域の先頭の値)といった書き方をすることもありますが、
 必ずしも I30 が先頭ではないですよね。
 ですから、ここは、素直に、If Range("I30").Value = "" Then にされたらよろしいかと。

ということを加味して整理しますと

Private Sub Worksheet_Change(ByVal Target As Range)
  Dim P As VbMsgBoxResult
  
  If Application.Intersect(Target, Range("I30")) Is Nothing Then Exit Sub
  
  Application.EnableEvents = False
  
  If Range("I30").Value = "" Then
    Range("I36").ClearContents
  Else
    P = MsgBox("有りですか?", vbYesNo)
    If P = vbYes Then
      Range("I36").Value = "有り"
    Else
      Range("I36").Value = "無し"
    End If
  End If
  Application.EnableEvents = True

End Sub

【72066】Re:セル更新時のマクロ
お礼  けい E-MAIL  - 12/5/23(水) 13:53 -

引用なし
パスワード
   ▼UO3 さん:

ようやく成功しました!感激です。
If Application.Intersect(Target, Range("I30:AG30")) Is Nothing Then Exit Sub
というようにセルの範囲を指定したらうまくいきました。

ほんとうにありがとうございました。


>▼けい さん:
>
>こんにちは
>
>結合セルでしたか。
>そうしますと、Targetに入ってくる領域は結合されたセルアドレス(たとえば I30:J30 等)
>なので I30 ではないわけです。かつ、この場合、Target.Count は結合されたセルの数。
>ですから 1 ではありません。
>
>・If Target.Count > 1 Then Exit Sub
>
> これで抜けると具合が悪いので削除しましょう。
>
>・If Intersect(Target, Range("I30")) Is Nothing Then Exit Sub
>
> I30 が l30 (小文字のエル)になってますよ〜。
>
>・If Target.Value = "" Then
>
> 結合セルが変更された場合、あるいは、複数領域が変更された場合(複数セルを選んでクリア
> あるいは、複数セルをコピーした上でペースト)Targetは複数領域ですから、
> たとえば Range("I30:J30").value というのは配列です。したがって、そのValue を参照すると
> エラーになります。
> 結合セルでも、クリアではなく、値の入力の場合、I30 となりますけど、複数セル領域が入っている
> と認識したほうがいいでしょうね。
>
> Target(1).Value (領域の先頭の値)といった書き方をすることもありますが、
> 必ずしも I30 が先頭ではないですよね。
> ですから、ここは、素直に、If Range("I30").Value = "" Then にされたらよろしいかと。
>
>ということを加味して整理しますと
>
>Private Sub Worksheet_Change(ByVal Target As Range)
>  Dim P As VbMsgBoxResult
>  
>  If Application.Intersect(Target, Range("I30")) Is Nothing Then Exit Sub
>  
>  Application.EnableEvents = False
>  
>  If Range("I30").Value = "" Then
>    Range("I36").ClearContents
>  Else
>    P = MsgBox("有りですか?", vbYesNo)
>    If P = vbYes Then
>      Range("I36").Value = "有り"
>    Else
>      Range("I36").Value = "無し"
>    End If
>  End If
>  Application.EnableEvents = True
>
>End Sub

1767 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free