Excel VBA質問箱 IV

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

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


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

【76585】コンパクト化 こずえ 15/1/22(木) 15:01 質問[未読]
【76586】Re:コンパクト化 kanabun 15/1/22(木) 17:56 発言[未読]
【76588】Re:コンパクト化 β 15/1/22(木) 20:49 発言[未読]
【76589】Re:コンパクト化 kanabun 15/1/22(木) 20:54 発言[未読]
【76590】Re:コンパクト化 kanabun 15/1/22(木) 23:11 発言[未読]
【76587】Re:コンパクト化 β 15/1/22(木) 20:19 発言[未読]
【76591】Re:コンパクト化 こずえ 15/1/23(金) 10:53 質問[未読]
【76592】Re:コンパクト化 β 15/1/23(金) 14:15 発言[未読]
【76593】Re:コンパクト化 こずえ 15/1/24(土) 1:01 質問[未読]
【76594】Re:コンパクト化 β 15/1/24(土) 10:47 発言[未読]
【76595】Re:コンパクト化 こずえ 15/1/24(土) 23:28 お礼[未読]

【76585】コンパクト化
質問  こずえ  - 15/1/22(木) 15:01 -

引用なし
パスワード
   いつもお世話になっております。
Sheet(エネ)の範囲に値が入った場合、Sheet(メニュー)のC10〜J10に「印刷」と言う文字が入ります。
モジュールは、Sheet(エネ)のSheetモジュールに書いてます。
コンパクトにできますか?
宜しくお願いします


Private Sub Worksheet_Change(ByVal Target As Range)
  Worksheets("メニュー").Range("C10").Value = IIf(Range("C13").Value = "" And Range("C14").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("E10").Value = IIf(Range("C64").Value = "" And Range("C65").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("G10").Value = IIf(Range("C115").Value = "" And Range("C116").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("I10").Value = IIf(Range("C166").Value = "" And Range("C167").Value = "", "", "印 刷")
  
  Worksheets("メニュー").Range("D10").Value = IIf(Range("C219").Value = "" And Range("C220").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("F10").Value = IIf(Range("C248").Value = "" And Range("C249").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("H10").Value = IIf(Range("C277").Value = "" And Range("C278").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("J10").Value = IIf(Range("C306").Value = "" And Range("C307").Value = "", "", "印 刷")
End Sub

【76586】Re:コンパクト化
発言  kanabun  - 15/1/22(木) 17:56 -

引用なし
パスワード
   ▼こずえ さん:

>コンパクトにできますか?

コンパクトというか、現状のコードだと 「エネ」シートのどのセルが変化しても
Changeイベント・プロシージャ内の処理が走りますね?
それは無駄なことなので、C列の入力(あるいはクリア)でなければ、
チェックはしないことにしましょう。

Private Sub Worksheet_Change(ByVal Target As Range)
 Dim c As Range
 Dim r As Range
 Dim ss As String, zz As String
 Dim i As Long
  If Target.Column <> 3 Then Exit Sub 'C列の Change でなければ抜ける
  
  zz = "C64:C65,C115:C116,C166:C167,C115:C116,"
  zz = zz & "C219:C220,C248:C250,C277:C278,C306:C307"
  ss = "CEGIDFHJ"
  For Each r In Range(zz).Areas
    i = i + 1
    If Not (Intersect(Target, r) Is Nothing) Then
      Set c = Worksheets("メニュー").Range(Mid$(ss, i, 1) & "10")
      If WorksheetFunction.CountBlank(r) = 2 Then
        c.ClearContents
      Else
        c.Value = "印 刷"
      End If
      Exit For
    End If
  Next
End Sub

【76587】Re:コンパクト化
発言  β  - 15/1/22(木) 20:19 -

引用なし
パスワード
   ▼こずえ さん:

これぐらいのセル数なら、すべてを毎回洗い替える、こんなコードでも。

Private Sub Worksheet_Change(ByVal Target As Range)
  Dim r As Range
  Dim c As Range
  Dim p As Range
  Dim x As Long
  
  Set r = Range("C13:C14,C64:C65,C115:C116,C166:C167,C219:C220,C248:C249,C277:C278,C306:C307")
  If Intersect(Target, r) Is Nothing Then Exit Sub
  With Sheets("メニュー")
    Set p = .Range("C10, E10, G10, I10, D10, F10, H10, J10")
    p.Value = Empty
  End With
  For Each c In r.Areas
    x = x + 1
    If WorksheetFunction.CountBlank(c) < 2 Then p.Areas(x).Value = "印刷"
  Next
      
End Sub

【76588】Re:コンパクト化
発言  β  - 15/1/22(木) 20:49 -

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

失礼します

こういう操作はしないとは思いますが、仮に、2組のセルに値が入っていて
メニューシートに印刷が2か所記入されたとします。
で、その2組のセルをともに選択してDeleteキーでクリアしたとします。
そうすると、下のほうの組に対するメニューシートの 印刷 は残ったままになりませんか?

【76589】Re:コンパクト化
発言  kanabun  - 15/1/22(木) 20:54 -

引用なし
パスワード
   ▼β さん:
>▼kanabun さん:


>こういう操作はしないとは思いますが、仮に、2組のセルに値が入っていて
>メニューシートに印刷が2か所記入されたとします。
>で、その2組のセルをともに選択してDeleteキーでクリアしたとします。
>そうすると、下のほうの組に対するメニューシートの 印刷 は残ったままになりませんか?

2組のセルをともに選択してクリアすれば、あとのほうは「残ったまま」になります。
つまり、そういう操作がない希望的観測のコードでした m(_ _)m

【76590】Re:コンパクト化
発言  kanabun  - 15/1/22(木) 23:11 -

引用なし
パスワード
   ごめんね、セル範囲がまちがってました m(_ _)m
ついでに、β さんのアドバイスにしたがって、複数セル範囲を一括クリア(Delete)
した場合にも対応するように、◆か所の Exit For をコメント化しておきます。

Private Sub Worksheet_Change(ByVal Target As Range)
 Dim c As Range
 Dim r As Range
 Dim ss As String, zz As String
 Dim i As Long
  If Target.Column <> 3 Then Exit Sub
  
  zz = "C13:C14,C64:C65,C115:C116,C166:C167,C219:C220,"
  zz = zz & "C248:C249,C277:C278,C306:C307"
  ss = "CEGIDFHJ"
  For Each r In Range(zz).Areas
    i = i + 1
    If Not (Intersect(Target, r) Is Nothing) Then
      Set c = Worksheets("メニュー").Range(Mid$(ss, i, 1) & "10")
      If WorksheetFunction.CountBlank(r) = 2 Then
        c.ClearContents
      Else
        c.Value = "印 刷"
      End If
      'Exit For  '◆使わない
    End If
  Next
End Sub

【76591】Re:コンパクト化
質問  こずえ  - 15/1/23(金) 10:53 -

引用なし
パスワード
   kanabunさん βさん

大変お返事が遅くなりました。
色々、勉強をさせていだだきました。
有難うございました。

「【76585】コンパクト化 」で印刷と表記してある箇所を
ファームボタンで印刷をしたのですが、「印刷」の文字が
1〜2秒ほど関係ない所まで出てきまして、投稿をさせていただいたのです。

kanabunさん、βさんのモジュールは、印刷しても関係ない所まで出て
きませんでした。

何がいけなかったのでしょうか?

【76592】Re:コンパクト化
発言  β  - 15/1/23(金) 14:15 -

引用なし
パスワード
   ▼こずえ さん:

こんにちは

>「【76585】コンパクト化 」で印刷と表記してある箇所を
>ファームボタンで印刷をしたのですが、「印刷」の文字が
>1〜2秒ほど関係ない所まで出てきまして、投稿をさせていただいたのです。

私のコードもkanabunさんのコードも、また、こずえさんのコードも書き方は違っても
やっていることは同じなんですが?

・そのボタンで印刷をした、そのコードをアップしてもらえますか?

・【1〜2秒ほど】というところの意味がよくわからないのですが?

【76593】Re:コンパクト化
質問  こずえ  - 15/1/24(土) 1:01 -

引用なし
パスワード
   βさん

こんばんは
*βさんのコードとkanabunさんのコードでは、関係ない所まで出ませんでした。

>>ファームボタンで印刷をしたのですが、「印刷」の文字が
>>1〜2秒ほど関係ない所まで出てきまして、投稿をさせていただいたのです。

私のコード今までのコードです。
Sheet(エネ)に
Private Sub Worksheet_Change(ByVal Target As Range)
  Worksheets("メニュー").Range("C10").Value = IIf(Range("C13").Value = "" And Range("C14").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("E10").Value = IIf(Range("C64").Value = "" And Range("C65").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("G10").Value = IIf(Range("C115").Value = "" And Range("C116").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("I10").Value = IIf(Range("C166").Value = "" And Range("C167").Value = "", "", "印 刷")
  
  Worksheets("メニュー").Range("D10").Value = IIf(Range("C219").Value = "" And Range("C220").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("F10").Value = IIf(Range("C248").Value = "" And Range("C249").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("H10").Value = IIf(Range("C277").Value = "" And Range("C278").Value = "", "", "印 刷")
  Worksheets("メニュー").Range("J10").Value = IIf(Range("C306").Value = "" And Range("C307").Value = "", "", "印 刷")
End Sub

標準モジュール(Sheet(メニュー)にファームボタン )に
Sub 印_エネ_簡易書留_小()
If MsgBox("この台帳を印刷しますします。" & Chr$(13) & "よろしいですか?", vbYesNo) = vbYes Then
With Sheets("エネ").Range("C213:I238")
      .Offset(.Rows.Count).Resize(2).EntireRow.Insert
      .EntireRow.Copy
      .Offset(.Rows.Count + 2).Resize(2).EntireRow.Insert
      Application.CutCopyMode = False
      .Resize(.Rows.Count * 2 + 2).PrintOut Copies:=1, Collate:=True ', Preview:=True
      .Offset(.Rows.Count).Resize(.Rows.Count + 2).EntireRow.Delete
    End With
  End If
End Sub
です。

【76594】Re:コンパクト化
発言  β  - 15/1/24(土) 10:47 -

引用なし
パスワード
   ▼こずえ さん:

おはようございます。

「1〜2秒ほど関係のないところ・・・」というのが、処理に1〜2秒ほどかかり
メニューシートのC10〜G10に本来セットされる条件じゃないところに
【印刷】という文字が入ったということならわかりました。
(1〜2秒ほどの間、印刷が繰り返されたということなら、もう少し情報が必要ですが)

イベント処理の最初に kanabun さんのコードでは

If Target.Column <> 3 Then Exit Sub 'C列の Change でなければ抜ける

私のコードでは

Set r = Range("C13:C14,C64:C65,C115:C116,C166:C167,C219:C220,C248:C249,C277:C278,C306:C307")
If Intersect(Target, r) Is Nothing Then Exit Sub

こういうところがありますね。

kanabunさんのコードの意味は、コメントにもあるように変更され、ここにとんできたときの
Target(変更領域のアドレス)がC列でなければ処理しないで抜けます。

私のコードでは、その領域が、Set r = ・・・で指定したセル領域以外なら抜けます。

一方、こずえさんのコードは、シート上のどこが変更されても実行されます。

で、このSub 印_エネ_簡易書留_小() 、お気づきかどうか、変更が3回行われています。

.Offset(.Rows.Count).Resize(2).EntireRow.Insert

.Offset(.Rows.Count + 2).Resize(2).EntireRow.Insert

.Offset(.Rows.Count).Resize(.Rows.Count + 2).EntireRow.Delete

その変更時の、Target はすべて行単位、たとえば 最初のコードなら

$239:$240 というものです。

Target.Column は、この場合、1。また私のコードで規定したセル群は、この$239:$240には
はいっていませんので、処理せず抜けます。

こずえさんのコードは、3か所の変更が起こる都度、イベントプロシジャが実行され
【その時の】セル位置に対して判断が行われ【その時の】C10〜G10の場所に値が入ります。

こういった現象をイベントの連鎖といって、もし、コード実行で、こういうことがありうるなら
それを回避する手立てをいれる必要があります。
kanabunさんのコードや私のコードは、【たまたま】処理が必要だというチェックをしている場所が
変更のあった場所に【ひっかからなかっただけ】で、本来は、イベントそのものを発生させないように
することが必要なんです。

イベントは

Application.EnableEvents = False

これで発生がとまりますので、印_エネ_簡易書留_小()の最初 With句の下あたりに
に、このコードを記述しましょう。
で、このままでは、永久にイベントが発生しなくなりますので、End WIth の前に
Application.EnableEvents = True と記述してください。

kanabunさんや私のコードをお使いになる場合でも、【たまたま】セーフということですから
必ず、このApplication.EnableEvents = False/True の手当てをしておいてくださいね。

【76595】Re:コンパクト化
お礼  こずえ  - 15/1/24(土) 23:28 -

引用なし
パスワード
   βさん

原因が分かってスッキリしました。

ご丁寧な説明有難うございました。
これからも、このサイトで勉強させていただきます。

有難うございました

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