[[20260619114259]] 『条件により列も非表示したい』(ヒロ坊) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『条件により列も非表示したい』(ヒロ坊)

お尋ねします。
以下は、実際に設定しているもので、条件により行を非表示にするものです。
これに、列も非表示にしたいのです。
J116:L116のセルが0の場合は、その列(J列〜L列)を非表示にしたいというものです。
どうぞよろしくお願いします。

Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)

    Const pw As String = "11100"
    Dim rr As Range, r As Range
    If Intersect(Target, Range("D2")) Is Nothing Then Exit Sub
    ActiveSheet.Unprotect Password:=pw
   Set rr = Rows("21:82")
   rr.Hidden = False
   For Each r In rr.Rows
       If r.Range("N1").Value = 0 Then
           r.Hidden = True
       End If
   Next
    ActiveSheet.Protect Password:=pw
End Sub

< 使用 Excel:Excel2021、使用 OS:Windows11 >


以下では?

 Option Explicit

 Private Sub Worksheet_Change(ByVal Target As Range)

    Const pw As String = "11100"
    Dim rr As Range, r As Range

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

    Application.EnableEvents = False
    ActiveSheet.Unprotect Password:=pw

    Set rr = Rows("21:82")
    rr.Hidden = False

    For Each r In rr.Rows
        If r.Range("N1").Value = 0 Then
            r.Hidden = True
        End If
    Next r

    If Application.WorksheetFunction.CountIf(Range("J116:L116"), "<>0") = 0 Then
        Columns("J:L").Hidden = True
    Else
        Columns("J:L").Hidden = False
    End If

    ActiveSheet.Protect Password:=pw
    Application.EnableEvents = True

 End Sub

(稚拙) 2026/06/19(金) 11:56:02


稚拙さん、ありがとうございます。
早速、設定して実行してみたのですが、
行は非表示されますが、列は非表示になりません。
今一度、よろしくお願いします。
(ヒロ坊) 2026/06/19(金) 13:08:23

    With Rows("21:82")
        .Hidden = False
        For Each r In .Rows
            If r.Columns("N").Value = 0 Then r.Hidden = True
        Next
    End With

    ↑と同じ感じの処理にするとしたら↓こんな感じでしょうか?

    With Columns("J:L")
        .Hidden = False
        For Each r In .Columns
            If r.Rows("116").Value = 0 Then r.Hidden = True
        Next
    End With

(白茶) 2026/06/19(金) 14:09:39


白茶さん、ありがとうございます。
これは、どこの部分と差替えればよいでしょうか?
Withから始まる構文が見つけられず、、、
もしよろしければ、全体的な構文を教えていただけると助かります。
(ヒロ坊) 2026/06/19(金) 15:51:19

横からですが、差し替えでなく追加する必要がありますよ。

■1
提示のコードの主要部分だけを抜き出して整理すると↓のようになります。

    Sub 整理()
        Dim r As Range

        '▼行方向のチェック
        Stop 'ブレークポイントの代わり
        For Each r In Range("N21:N82")
            If r.Value = 0 Then
                r.EntireRow.Hidden = True
            End If
        Next
    End Sub

■2
そのうえで、列方向のチェックを加えたいということですから↓のようにすべきといわれているだけです。

    Sub 整理改()
        Dim r As Range

        '▼行方向のチェック
        Stop 'ブレークポイントの代わり
        For Each r In Range("N21:N82")
            If r.Value = 0 Then
                r.EntireRow.Hidden = True
            End If
        Next

        '▼列方向のチェック ←【こいつを追加】
        Stop 'ブレークポイントの代わり
        For Each r In Range("J116:L116")
            If r.Value = 0 Then
                r.EntireColumn.Hidden = True
            End If
        Next
    End Sub

■3
Withステートメントについては↓などで学習されたらよいとおもいます。

 【参考】
http://officetanaka.net/excel/vba/beginner/16.htm

(もこな2) 2026/06/19(金) 16:55:59


反応がないですが追加で。

■4
そもそもChangeイベントで対応すべき案件なのか?というところも疑問ですが以下のようにすればいいんじゃないでしょうか?

    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim r As Range

        If Not Intersect(Target, Range("D2")) Is Nothing Then

            '▼シートを開いた時に1度だけやればよいので、ThisWorkbookモジュールのOpenイベントにすることを検討
            With Me 'ThisWorkbookモジュールに書くならMeではダメ(ちゃんとシートを指定すること)
                .Unprotect Password:="11100"
                .Protect Password:="11100", UserInterfaceOnly:=True
            End With

            '▼行方向のチェック
            With Range("N21:N82")
                .EntireRow.Hidden = False
                For Each r In .Cells
                    If r.Value = 0 Then
                        r.EntireRow.Hidden = True
                    End If
                Next
            End With

            '▼列方向のチェック【追加分】
            With Range("J116:L116")
                .EntireColumn.Hidden = False
                For Each r In .Cells
                    If r.Value = 0 Then
                        r.EntireColumn.Hidden = True
                    End If
                Next
            End With
        End If
    End Sub

(もこな2) 2026/06/20(土) 00:37:55


もこな2さん、ご返事が遅くなり、すみません。
白茶さんからいただいたコメントも理解できておらず、すみません。
列方向のチェックを追加するということだったのですね。
また、Withステートメントについても勉強します。
もこな2さんからいただいたものを設定し、行、列ともにきちんと条件により非表示できました!
ありがとうございました。
(ヒロ坊) 2026/06/20(土) 07:56:34

もう一点お尋ねします。
先日ご教示いただいたものに以下を組み合わせたいと考えています。

Private Sub Worksheet_Change(ByVal Target As Range)

     If Target.Count > 1 Then Exit Sub
     If Target.Address <> "$C$9" Then Exit Sub
     If Target.Value <> "" And IsNumeric(Target.Value) Then
         Application.EnableEvents = False
         Call Posting_Output
         Application.EnableEvents = True
     End If
End Sub

以下のような組み合わせでよいでしょうか?
ただ、実行したところ、うまく作動しません。今一度、ご教示いただきたく、よろしくお願いします。

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim r As Range

    If Not Intersect(Target, Range("D2")) Is Nothing Then

        With Me
            .Unprotect Password:="11100"
            .Protect Password:="11100", UserInterfaceOnly:=True
        End With

     If Target.Count > 1 Then Exit Sub
     If Target.Address <> "$C$9" Then Exit Sub
     If Target.Value <> "" And IsNumeric(Target.Value) Then
         Application.EnableEvents = False
         Call Posting_Output
         Application.EnableEvents = True
            End If
            Next
        End With

        With Range("J116:L116")
            .EntireColumn.Hidden = False
            For Each r In .Cells
                If r.Value = 0 Then
                    r.EntireColumn.Hidden = True
                End If
            Next
        End With
    End If
End Sub
(ヒロ坊) 2026/06/22(月) 08:19:57

ブレークポイントを設定してステップ実行してみてください。
原因はすぐわかるとおもいます。

それでもわからなければ↓が真になるときはどういうときか考えてみましょう。

 If Not Intersect(Target, Range("D2")) Is Nothing

(もこな2) 2026/06/22(月) 08:30:55


スマホで手打ちしたのでミスがあるかもですが、こういう感じになってますよね?

 Private Sub Worksheet_Change(ByVal Target As Range)
    Dim r As Range

    If Not Intersect(Target, Range("D2")) Is Nothing Then
        If Target.Count > 1 Then
            msgbox "書き換えのあったセルが2つ以上のため処理しません"
        eles
            If Target.Address <> "$C$9" Then
                If Target.Value <> "" And IsNumeric(Target.Value) Then
                    msgbox "処理対象です"
                end if
            eles
                msgbox "書き換えのあったセル番地が【$C$9】ではないため処理しません"
            end if
        end if
    eles
        msgbox "書き換えのあったセルに【D2セル】が含まれていないため処理しません"
    end if
 end sub

(もこな2) 2026/06/22(月) 09:18:07


もこな2さん、ありがとうございます。
スマホで手打ちいただいた分を実装してみてもよいのでしょうか?
(ヒロ坊) 2026/06/22(月) 12:28:54

 「組み合わせる」というか、二つの処理を必要に応じてそれぞれ実行したい、ということですね?
 ( Call Posting_Outputの内容が説明されていないので、関係があるかどうか判断不能です。
    関連しているなら、きちんと内容説明してください。)

 そうであれば、
 今回のChangeイベントプロシージャを
 Private Sub Worksheet_Change(ByVal Target As Range)
     Dim r As Range
     If Not Intersect(Target, Range("D2")) Is Nothing Then
         '' その場合の処理 をここに書きます。ここは出来ているわけです。
     End If
     '(*)
 End Sub
 のように、Exit Subを使わずに、「条件を満たすときに、これこれの処理を行う」という方式にすれば、
 今のもののあと(つまり(*)の位置)に、
 今回追加したいコード片を追加するだけでよいのでは?

 なお、(ヒロ坊) 2026/06/22(月) 08:19:57のコードは
 If と End If が対応していなかったり、Nextが突然でてきたりしています。もう少し神経使ったほうがよいでしょう。

(xyz) 2026/06/22(月) 13:37:16


少し話が進んでいますが、投稿しておきます。

■5
失礼「Else」のスペルと分岐結果の整理をミスってました。
正しく整理するとこうですね。

 Private Sub Worksheet_Change(ByVal Target As Range)
    Dim r As Range

    If Not Intersect(Target, Range("D2")) Is Nothing Then
        If Target.Count > 1 Then
            MsgBox "書き換えのあったセルが2つ以上のため処理しません"
        Else
            If Target.Address <> "$C$9" Then
                MsgBox "書き換えのあったセル番地が【$C$9】ではないため処理しません"
            Else
                If Target.Value <> "" And IsNumeric(Target.Value) Then
                    MsgBox "処理対象です"
                End If
            End If
        End If
    Else
        MsgBox "書き換えのあったセルに【D2セル】が含まれていないため処理しません"
    End If
 End Sub

提示のコードも落ち着いて見ればわかると思いますが、【D2セル】と【C9セル】を含むセル範囲をいっぺんに書き換えれば「If Not Intersect(Target, Range("D2")) Is Nothing Then」は真になりますが、同時に「If Target.Count > 1 Then」も真になるので、指示通り「Exit Sub」してるわけです。
(C9セルのみを書き換えた場合は、D2セルが含まれていませんから最初の条件を満たしません。)

■6
したがって、セルの書き換えをマクロの発動条件にする必要があるのかというところは引き続きの疑問ですが、例えば↓のようにすべきでしょう。

    Private Sub Worksheet_Change(ByVal Target As Range)

        Dim r As Range

        If Not Intersect(Target, Range("D2")) Is Nothing Then
            'D2セル(を含むセル範囲)が書き換えられたときにやりたい処理
        End If

        If Not Intersect(Target, Range("C9")) Is Nothing Then
            If Range("C9").Value <> "" And IsNumeric(Range("C9").Value) Then
                Application.EnableEvents = False
                Call Posting_Output
                Application.EnableEvents = True
            End If
        End If
    End Sub

 ※ChangeはTargetが複数になりえますので「Target.Value <> ""」などもよろしくないとおもいましたので修正しています。
   「If Target.Count > 1 Then Exit Sub」をそのままにするならば、変えなくても大丈夫です。

(もこな2) 2026/06/22(月) 15:04:33


もこな2さん、ありがとうございます。
ご提示のものを以下のとおりにしてみましたが、いかがでしょうか?

    Private Sub Worksheet_Change(ByVal Target As Range)

        Dim r As Range

        If Not Intersect(Target, Range("D2")) Is Nothing Then
            'D2セル(を含むセル範囲)が書き換えられたときにやりたい処理
        End If

        If Not Intersect(Target, Range("C9")) Is Nothing Then
            If Range("C9").Value <> "" And IsNumeric(Range("C9").Value) Then
                Application.EnableEvents = False
                Call Posting_Output
                Application.EnableEvents = True
            End If
            Next
        End With

        With Range("J116:L116")
            .EntireColumn.Hidden = False
            For Each r In .Cells
                If r.Value = 0 Then
                    r.EntireColumn.Hidden = True
                End If
            Next
        End With
    End If
End Sub
(ヒロ坊) 2026/06/23(火) 07:35:43

私のお尋ねに誤りがありました。
(もこな2) 2026/06/20(土) 00:37:55 にてご提示いただいたものに、
行方向のチェックを除いた、列方向のチェックのみに、以下を追加したいというものでした。申し訳ありません。

■(もこな2) 2026/06/20(土) 00:37:55 にてご提示いただいたもの

    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim r As Range

        If Not Intersect(Target, Range("D2")) Is Nothing Then

            '▼シートを開いた時に1度だけやればよいので、ThisWorkbookモジュールのOpenイベントにすることを検討
            With Me 'ThisWorkbookモジュールに書くならMeではダメ(ちゃんとシートを指定すること)
                .Unprotect Password:="11100"
                .Protect Password:="11100", UserInterfaceOnly:=True
            End With

            '▼行方向のチェック      ←ここから不要
            With Range("N21:N82")
                .EntireRow.Hidden = False
                For Each r In .Cells
                    If r.Value = 0 Then
                        r.EntireRow.Hidden = True
                    End If
                Next
            End With           ←ここまで不要

            '▼列方向のチェック【追加分】
            With Range("J116:L116")
                .EntireColumn.Hidden = False
                For Each r In .Cells
                    If r.Value = 0 Then
                        r.EntireColumn.Hidden = True
                    End If
                Next
            End With
        End If
    End Sub

■以下の動作を追加
Private Sub Worksheet_Change(ByVal Target As Range)

     If Target.Count > 1 Then Exit Sub
     If Target.Address <> "$C$9" Then Exit Sub
     If Target.Value <> "" And IsNumeric(Target.Value) Then
         Application.EnableEvents = False
         Call Posting_Output
         Application.EnableEvents = True
     End If
End Sub
(ヒロ坊) 2026/06/23(火) 07:59:08

 懸念点をいくつか。杞憂であればよいですが。
 (1)
 >  「組み合わせる」というか、二つの処理を必要に応じてそれぞれ実行したい、ということですね?
 >  ( Call Posting_Outputの内容が説明されていないので、関係があるかどうか判断不能です。
 >     関連しているなら、きちんと内容説明してください。)
 と書きました。

 (ヒロ坊)さん提示の、 2026/06/22(月) 08:19:57のコードを改めて見ると、
 もともとあった「行に関する非表示の処理」がなくなっていますよね。
 単に、変更処理の途中で一部だけ載せましたということならいいですが、
 その行に関する処理の代替が Call Posting_Outputということなんですか?(名前からは想定しにくいですが)
 それなら、そのように説明したうえで、Posting_Outputのコード内容を提示するのが筋でしょう。

 (2)また、行、列を非表示にする処理が、Posting_Outputの処理に影響があり、
 Posting_Outputの処理を先に処理しないといけないなら、そのことを考慮する必要があります。

 いずれにしても、正確な情報提供をしてください。でないと正確な回答は得られません。
 私はここまでとします。頑張ってください。 
 # 早朝に書いてあったもので、本日の質問者さんのコメントは読んでいない
 #  段階のものです。 

(xyz) 2026/06/23(火) 08:02:03


分かりづらく、説明不足ですみません。
今一度、整理します。
1は、これまですでに使用できている機能です。
そこに、もこな2さんよりご提示いただいたものから行方向のチェックを省いた2を合わせて、必要に応じて処理したいというものです。
xyzさんがおっしっていただいているCall Posting_Outputは、きちんと動作できているものですので、申し訳ありませんが、詳しくは省略させてください。
1と2それぞれに動作確認したところ、きちんと動作しております。
度々で分かりづらく、申し訳ありません。
どうぞお力添えの程、よろしくお願いします。

1■↓動作確認済
Private Sub Worksheet_Change(ByVal Target As Range)

    If Target.Count > 1 Then Exit Sub
    If Target.Address <> "$C$9" Then Exit Sub
    If Target.Value <> "" And IsNumeric(Target.Value) Then
        Application.EnableEvents = False
        Call Posting_Output
        Application.EnableEvents = True
    End If
End Sub

2■↓動作確認済
Private Sub Worksheet_Change(ByVal Target As Range)

    Dim r As Range

    If Not Intersect(Target, Range("B9")) Is Nothing Then

        With Me
            .Unprotect Password:="11100"
            .Protect Password:="11100", UserInterfaceOnly:=True
        End With

        With Range("E17:AH17")
            .EntireColumn.Hidden = False
            For Each r In .Cells
                If r.Value = 0 Then
                    r.EntireColumn.Hidden = True
                End If
            Next
        End With
    End If
End Sub
(ヒロ坊) 2026/06/23(火) 08:14:57

■7
うーん。困っている部分は何処なんでしょうか?
提示されたものを適当に切り貼りするだけじゃ解決しないと思います。

気になるところを何点か。
★1
同じシートモジュールに【Worksheet_Change】は1つしか記述できません。
なので、私もxyzさんも↓のように分けて書く必要がありますよと言ってるわけです。

    Private Sub Worksheet_Change(ByVal Target As Range)

        'D2セル(を含むセル範囲)が書き換えられたときにやりたい処理

        'C9セルのみが書き換えられたときにやりたい処理

    End Sub

★2
ガン無視されましたが、以下はブックを開くときに1度だけ行えばよい処理です。

 With Me
     .Unprotect Password:="11100"
     .Protect Password:="11100", UserInterfaceOnly:=True
 End With

何を言われているかわからない場合は↓のように、元に戻したほうが理解しやすいとおもいます。

 保護解除
     〜処理〜
 保護し直し

★3
>必要に応じて処理したいというものです。
こちらも無視されていますが、尚更、Changeイベントで処理する話なのか疑問があります。

■8(余談です)
今更ですが、

   For Each r In Rows("21:82").Rows
       If r.Range("N1").Value = 0 Then
           r.Hidden = True
       End If
   Next


   For Each r In Range("N21:N82")
       If r.Value = 0 Then
           r.EntireRow.Hidden = True
       End If
   Next

【r】に取り出されるもの違うのですが気づいてますよね?

 前者は行全体、後者はセル単体です。

(もこな2) 2026/06/23(火) 09:06:36


再開記念。

■9
2026/06/23(火) 08:14:57のセル番地に合せるとこういうことになるんじゃないでしょうか?

    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim r As Range
        Stop 'ブレークポイントの代わり

        '▼C9セルのみ書き換えがあった時の処理
        If Not Target.Count > 1 Then
            If Not Target.Address <> "$C$9" Then
                If Target.Value <> "" And IsNumeric(Target.Value) Then
                    Application.EnableEvents = False
                    'Call Posting_Output
                    Application.EnableEvents = True
                End If
            End If
        End If

        '▼B9セルを含むセル(範囲)の書き換えがあった時の処理
        If Not Intersect(Target, Range("B9")) Is Nothing Then
            ActiveSheet.Unprotect Password:="11100"
            With Range("E17:AH17")
                .EntireColumn.Hidden = False
                For Each r In .Cells
                    If r.Value = 0 Then
                        r.EntireColumn.Hidden = True
                    End If
                Next
            End With
            ActiveSheet.Protect Password:="11100"
        End If
    End Sub

いずれにせよ、切り貼りしたものをこれでよいか?って聞くんじゃなくて、○○になるとおもって✕✕のようにしたんだけど(ステップ)実行すると、△△のようになってしまうので困っているなど、具体的にお困りの状況を説明できないでしょうか?

(もこな2) 2026/06/25(木) 20:28:34


もこな2さん、ありがとうございます。
ようやくサイトが再開して安心しました。
また、再開記念をお送りいただき、重ねてありがとうございます。
ご指摘もいただき、早速いただいたものを確認・実行したうえでのお尋ねをさせていただきます。
まず、以下のように修正して実行しました。
B9セルの方は実行できました。
C9の方は動きません。
もちろん、Stopは消しておりますが、Notも消す必要があると思い、消して実行しましたが、動きません。
よろしくお願いします。
(ヒロ坊) 2026/06/26(金) 07:53:00

>まず、以下のように修正して実行しました。
自己判断で修正するから不具合が出るんです。
回答されたものを使用して実行しそれでも希望する結果が違うなら
その都度質問すればいいでしょう。
(閲覧者) 2026/06/26(金) 08:20:14

編集が被りましたがそのまま。
■10
>もちろん、Stopは消しておりますが
なぜ消したのですか?
ステップ実行するのに必要になると思いますが...

■11
>Notも消す必要があると思い
なぜそう思ったのですか?

以下は、それぞれどういう命令だと理解してますか?

 If Target.Count > 1 Then Exit Sub
 →〜〜のとき〜〜する

 If Target.Address <> "$C$9" Then Exit Sub
 →〜〜のとき〜〜する

 If Not Intersect(Target, Range("D2")) Is Nothing Then
       ★処理★
 End If
 →〜〜のときに処理が実行される

(もこな2) 2026/06/26(金) 08:39:52


■12
追加で。
 Private Sub Worksheet_Change(ByVal Target As Range)
     If Not Intersect(Target, Range("D2")) Is Nothing Then
         If Target.Count > 1 Then Exit Sub
         If Target.Address <> "$C$9" Then Exit Sub
         If Target.Value <> "" And IsNumeric(Target.Value) Then
             ★処理★
         End If
     End If
 End Sub

上記のコードで、それぞれ以下の場合、どうなるとおもってますか?
(全体を9行と考えて答えてください)
(答えは■5にありますが、ひとまずカンニングなしで考えてみてください)

 ★1 D2のみ入力があった場合
     →〇行目のExit Subが実行される

 ★2 C9のみ入力があった場合
     →〇行目が偽と判定されるから〇行目に進む

 ★3 D2とC9に同時に入力があった場合
     →〇行目のExit Subが実行される

(もこな2) 2026/06/26(金) 09:16:09


ありがとうございます。
以下で合ってるでしょうか?
ただ、D2とC9はセットではない気がするのですが・・・
B9とC9はセットだと思うのですが。間違っていたら、すみません。

★1 D2のみ入力があった場合

     →21行目のExit Subが実行される

★2 C9のみ入力があった場合

     →17行目が偽と判定されるから21行目に進む

★3 D2とC9に同時に入力があった場合

     →17行目のExit Subが実行される
(ヒロ坊) 2026/06/26(金) 10:04:42

■13
先に「■12」のお答えを頂いたので、今時点ということでコメントします。
 01  Private Sub Worksheet_Change(ByVal Target As Range)
 02      If Not Intersect(Target, Range("D2")) Is Nothing Then
 03          If Target.Count > 1 Then Exit Sub
 04          If Target.Address <> "$C$9" Then Exit Sub
 05          If Target.Value <> "" And IsNumeric(Target.Value) Then
 06              ★処理★
 07          End If
 08      End If
 09  End Sub

上記の9行を前提に話をしているつもりなので、21行目とか17行目とか存在しない行を言われても理解できてるのかわかりません。
見切り発車ですが、解説をアップします。

 ★1 D2のみ入力があった場合
     →「Target.Address」が"$C$9"ではありませんから4行目のExit Subが実行されて終了します。

 ★2 C9のみ入力があった場合
     →D2セルが含まれませんから、2行目が偽と判定され8行目に進み、次の行のEnd Subで終了します。

 ★3 D2とC9に同時に入力があった場合
     →「Target.Address」が2(1より大きい)になりますから3行目のExit Subが実行されて終了します。

このように、「2026/06/22(月) 08:19:57」で質問のあったコードは構文としては間違ってませんが、★処理★にたどり着くものが無いのです。
「2026/06/22(月) 08:30:55」でも述べましたが、これはご自身でブレークポイントを設定し、ステップ実行して確認すれば容易に気づけます。

繰り返しになりますが、提示されたコードを切り貼りするだけではなく、ちゃんとコードの意味を理解していないと修正できないと思います。

(もこな2) 2026/06/26(金) 12:34:59


もこな2さん、たびたびありがとうございます。
もこな2さんのヒントに応えきれず、ごめんなさい。ですが、

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim r As Range

    If Not Intersect(Target, Range("D2")) Is Nothing Then

        With Me
            .Unprotect Password:="11100"
            .Protect Password:="11100", UserInterfaceOnly:=True
        End With

     If Target.Count > 1 Then Exit Sub
     If Target.Address <> "$C$9" Then Exit Sub
     If Target.Value <> "" And IsNumeric(Target.Value) Then
                    ←この行に処理にたどり着くものが必要ということでしょうか?
         Application.EnableEvents = False
         Call Posting_Output
         Application.EnableEvents = True
            End If
            Next
        End With

        With Range("J116:L116")
            .EntireColumn.Hidden = False
            For Each r In .Cells
                If r.Value = 0 Then
                    r.EntireColumn.Hidden = True
                End If
            Next
        End With
    End If
End Sub
(ヒロ坊) 2026/06/26(金) 16:26:38

>必要に応じて処理したいというものです。
1■↓動作確認済
2■↓動作確認済

C9 が書き変えられたら1■を、B9 が書き変えらたら2■を処理する
と言うことですよね。


コパイロットに聞いてみました。
Worksheet_Change 内での統合版を作成してみました。

Private Sub Worksheet_Change(ByVal Target As Range)

    If Target.CountLarge > 1 Then Exit Sub

    Select Case Target.Address

        '-------------------------
        ' 1■ C9 が変更されたとき
        '-------------------------
        Case "$C$9"
            If Target.Value <> "" And IsNumeric(Target.Value) Then
                Application.EnableEvents = False
                Posting_Output
                Application.EnableEvents = True
            End If

        '-------------------------
        ' 2■ B9 が変更されたとき
        '-------------------------
        Case "$B$9"

            With Me
                .Unprotect Password:="11100"
                .Protect Password:="11100", UserInterfaceOnly:=True
            End With

            Dim r As Range
            With Range("E17:AH17")
                .EntireColumn.Hidden = False
                For Each r In .Cells
                    If r.Value = 0 Then r.EntireColumn.Hidden = True
                Next
            End With

        Case Else
            Exit Sub

    End Select

End Sub

これで合っているかどうかわからんけど。
(マクロ苦手) 2026/06/26(金) 18:15:09


■14
>←この行に処理にたどり着くものが必要ということでしょうか?
まずは、■10、■11の確認に答えてください。

そのうえでわからない(悩んでいる)部分はどこですか?
「2026/06/22(月) 08:19:57」と「2026/06/26(金) 16:26:38」で提示のコードは同じものかとおもいますが、そこから判定・分岐の部分だけ抜き出したものが↓です。

 01  Private Sub Worksheet_Change(ByVal Target As Range)
 02      If Not Intersect(Target, Range("D2")) Is Nothing Then
 03          If Target.Count > 1 Then Exit Sub
 04          If Target.Address <> "$C$9" Then Exit Sub
 05          If Target.Value <> "" And IsNumeric(Target.Value) Then
 06              ★処理★
 07          End If
 08      End If
 09  End Sub

上記のコードで"うまく作動しません"と仰っていることについて、実際には何が起こってるかは「■13」で解説済です。

 (確認方法はステップ実行するのが一番わかりやすいとおもいます。(だから■10でなんで消したのか聞いています。))

また、何を勘違いしているのか想像はついていますし、解決方法もいくつか思いついていますが、■11の答えを見てから説明しようと思っています。

 大ヒント(というか答え)
 「Exit Sub」してそこで終わっちゃってるのが問題でしょう。
 そして、解消方法は【(xyz) 2026/06/22(月) 13:37:16】で既に指摘されています。

(もこな2) 2026/06/26(金) 18:29:09


■15(余談2です)
マクロ苦手さんが提示されたコードでもよいとは思いますが、列の表示/非表示のトリガーになっているD2セル(B9セルに変更?)について、そのセルのみ書き換わったときじゃないと、「Target.CountLarge > 1」を満たして即終了になります。

セルの書き換えは単純な入力だけではなく、セル範囲をまとめて貼付けしたときや消去したときも含まれますから、意外と複数セルの書き換えが起こることは多いです。(もちろん、複数セルを選択している状況で入力し、Ctrl + Enterで確定したときも複数セルの書き換えになります)
したがってIntersectメソッドでの判定はそのまま採用されたほうがいいんじゃないかと思いました。

(もこな2) 2026/06/26(金) 19:03:09


もこな2さん
解説有難うございました。1つ勉強になりました。
(マクロ苦手) 2026/06/26(金) 20:16:57

■16(余談2の余談)
本筋と多少それちゃいますが、「■6」で述べたように2つ以上のセルが同時に書き換わった場合【Target.Value】の判定ができなくなっちゃうので「Target.Count > 1」の時は処理せず抜けるという発想になっていると思います。

逆を言えば、Target.Addressが「"$C$9"」のときは、絶対に1つのセルしか書き換わってないわけです。
なので↓のようにすれば、Select Caseでの分岐でもよいとおもいます。

    Private Sub Worksheet_Change(ByVal Target As Range)

        Select Case True
            Case Target.Address = "$C$9"
                '◆1 C9セルのみが変更されたとき
                MsgBox "C9セルのみが書き換えられました"

            Case Not Intersect(Range("B9"), Target) Is Nothing
                '◆2 B9セルを含むセル範囲が変更されたとき
                MsgBox "B9セルを含むセル範囲が書き換えられました"

            Case Else
                'Exit Sub  ←この後の処理分岐や処理はなく、End Subするだけなので無くてもよい

        End Select
    End Sub

ただ、Select Caseの処理は排他(1回の実行で両方が処理されることはない)となりますが、既に述べたようにChangeイベントは、複数のセルが書き換わることが往々にしてありうるので、「■6」で提示したように、どちらの条件も満たすときは両方の処理をするという設計にしたほうがいいんじゃないかと思っています。

    Private Sub Worksheet_Change(ByVal Target As Range)
        If Not Intersect(Target, Range("D2")) Is Nothing Then
            '◆3 D2セルを含むセル範囲が変更されたとき
            MsgBox "D2セルを含むセル範囲が書き換えられました"
        End If

        If Not Intersect(Target, Range("C9")) Is Nothing Then
            '◆4 C9セルを含むセル範囲が変更されたとき
            MsgBox "C9セルを含むセル範囲が書き換えられました" & vbLf & "C9セルの値は「" & Range("C9").Value & "」です"
        End If
    End Sub

(もこな2) 2026/06/26(金) 22:43:29


皆さん、ありがとうございます。
■10、11
実行した際に作動しなかったため、そう考えました。
そのうえで、(もこな2) 2026/06/26(金) 18:29:09を見返して、理解できたように思います。
私の理解度は、皆さんのレベルをはるかに下回っており、質問そのものの意味もよく理解できていないのかもしれません。申し訳ありません。

(ヒロ坊) 2026/06/27(土) 07:00:46


(ヒロ坊) 2026/06/23(火) 08:14:57 の
「必要に応じて処理したいというものです。」は解決したのですか。
コードはどうなったんですか。

(匿名) 2026/06/27(土) 09:47:30


■17
>実行した際に作動しなかったため、そう考えました。
それはないはずですが・・・・・
トリガーにしてるセルがずれたとかそういうことはないですか?
(実際に、途中からセル変わってますし)

あと、確認がなかったので理解してると解釈してますが、【ステップ実行】や【ブレークポイント】という言葉の意味がわからないのであれば↓などを読んでみてください。

  【ステップ実行】
https://www.239-programing.com/excel-vba/basic/basic023.html
http://plus1excel.web.fc2.com/learning/l301/t405.html

 【ブレークポイント】
https://www.239-programing.com/excel-vba/basic/basic022.html
https://www.tipsfound.com/vba/01010

■18
>2026/06/26(金) 18:29:09を見返して、理解できたように思います。
そもそも、こちらが確認したかったことは以下の通りです。

 ■10での確認 ステップ実行するためにブレークポイントを設定する必要があるはずですがなんで消したのか?

 ■11での確認 ↓は、それぞれどういう命令と理解しているか。 
      If Target.Count > 1 Then Exit Sub

      If Target.Address <> "$C$9" Then Exit Sub

      If Not Intersect(Target, Range("D2")) Is Nothing Then
            ★処理★
      End If

理解できたということなので詳しい説明は省きますが、前者2つは条件を満たしたときにそこで処理を終了するという命令になっている一方で、3番目は条件を満たしたときに「★処理★」を実行するという命令です。

 出かける用事があるので、残りは後程にします。

(もこな2) 2026/06/27(土) 10:04:15


もこな2さん、ありがとうございます。
ステップ実行、ブレークポイントについても勉強します。
(ヒロ坊) 2026/06/28(日) 06:48:06

失礼。ちょっと間が空いちゃいました。続きです。

■19
おそらくですがトピ主はIF関数の記述方法を勘違いしているものと思われます。
IF関数の基本的な形は以下の通りです。

 If 条件式 Then
     真のときの処理内容  ←Then節といいます
 Else
     偽のときの処理内容  ←Else節といいます
 End If

そして、Then節のみの場合は以下のようにElse節を省略することができます。

 If 条件式 Then
     真のときの処理内容  ←Then節のみ記述する
 End If

さらに、Then節が1行のみの場合は以下のような記述も可能です。

 If 条件式 Then 真のときの処理内容  ←「End If」は記述してはいけません

 -----------------------------------
ここまでが理解できていなければ、もう一度読み直すなり、実験するなり、質問するなりしてください。
以下は理解できたものとして話しています。
 -----------------------------------

上記を踏まえると、

 If Target.Address <> "$C$9" Then Exit Sub

↑は↓と同じ意味ということが理解できるかとおもいます。

 If Target.Address <> "$C$9" Then
     Exit Sub
 End If

ですが、今回の場合は「Target.Address」が【"$C$9"じゃないとき】【じゃないとき】に"処理したい"わけですよね。
すると以下のように、Else節に処理を書けばよいと思いつくかもしれません。

 If Target.Address <> "$C$9" Then
     Exit Sub
 Else
     ★処理★ ←条件が真【じゃないとき】にやりたいこと
 End If

ですが、余談2の余談でも触れてますが、Exit SubしなくてもそのままEnd Subに向かって進むだけならば、どのみち処理終了しますので無くてもよいわけです。これを踏まえると↓のようにThen節に何も書かなくてもよいことになります。

 If Target.Address <> "$C$9" Then
 Else
     ★処理★ ←【条件が真】【じゃないとき】にやりたいこと
 End If

ここでちょっと考えてみましょう。「【条件が真】【じゃないとき】」って別の書き方ができないでしょうか?
書くとややこしくなりますが「条件が真じゃないとき」という条件にすることもOKです。
すなわち↓でもOKということになります。

 If Not 条件 Then
    ★処理★
 End If

と、ここまで書けばわかったと思いますが↓からNotを取ってしまったらマズイですよね?

 If Not 【Target.Addressが"$C$9"じゃないとき】 Then
     ★処理★
 End If

なので、「■11」でどういう命令と理解してるのか確認したのです。

■20
ちなみに、以下は同じ意味になりますから、Notを記述したくないといったことであれば、採用されるとよいでしょう。

 If Not Target.Address <> "$C$9" Then

 If Target.Address = "$C$9" Then

また、Target.Addressが「"$C$9"」のときは、かならず「Target.Count」も「1」ですから、理屈が理解できているならば省略してもよいとおもいます。
(逆に実害があるわけじゃないので、数か月後の自分が理屈をわすれてしまいそうならばそのままにしたほうがよいでしょう)

 ------------------------------------------------------------
 長くなったのでいったん区切ります。
 ------------------------------------------------------------
「■19」について、Else IFやマルチステートメントは意図して説明していません。
説明できる回答者さんいらっしゃいましたらフォローをお願いします。

(もこな2) 2026/06/28(日) 15:36:52


■21
ここまで理解されたかとおもいますが、「2026/06/22(月) 08:19:57」に動かないとおっしゃっていた以下のコードは何が問題だったかわかりますよね?(すでに指摘があった構文のミスは除きます)
 Private Sub Worksheet_Change(ByVal Target As Range)
    Dim r As Range

    If Not Intersect(Target, Range("D2")) Is Nothing Then
        If Target.Count > 1 Then Exit Sub
        If Target.Address <> "$C$9" Then Exit Sub
        If Target.Value <> "" And IsNumeric(Target.Value) Then
            Call Posting_Output

            Range("J116:L116").EntireColumn.Hidden = False                
            For Each r In Range("J116:L116").Cells
                If r.Value = 0 Then
                    r.EntireColumn.Hidden = True
                End If
            Next
        End If
    End If
 End Sub

そうです。「■5」でも述べていますが、「TargetがD2セルを含む」という条件と「Target.Addressが"$C$9"のもの」という条件のどちらも満たすものがないので処理に進まなかったわけです。
だから「■6」などで↓のようにすべきだという話をしていたわけです。

    Private Sub Worksheet_Change(ByVal Target As Range)

        Dim r As Range

        If Not Intersect(Target, Range("D2")) Is Nothing Then
            'D2セル(を含むセル範囲)が書き換えられたときにやりたい処理
        End If

        If Not Intersect(Target, Range("C9")) Is Nothing Then
            'C9セル(を含むセル範囲)が書き換えられたときにやりたい処理
        End If
    End Sub

■22
>ステップ実行、ブレークポイントについても勉強します。
是非そのようにしてください。いずれも、デバッグ作業の超基本となる技術です。

正直に言うと、「2026/06/23(火) 07:35:43」の時点で↓のような状態でしたので、ただ切り貼りしてるだけで、ステップ実行もしていないのだろうと推測していました。
・「'D2セル(を含むセル範囲)が書き換えられたときにやりたい処理」がそのまま残っている
・構文ミスが直っていない

おそらく元のコードは引き継いだものだったり、ネットで見かけたものなどでご自身で書いたものではないのでしょが、今の担当者はあなたです。
何度も言っているように、中身がわからないまま切り貼りすれば何とかなるってものでもないので、わからない命令や用語はちゃんとしらべて、それでも不安なら「××について〇〇と理解したけどあってますか?」などのように追加質問して理解されるとよいとおもいます。

■23
話がそれますが、仕組み(理屈)が分かった今なら、「D2セルに関する処理」と「C9セルに関する処理を」分けて書くべきって指摘をされているのに↓はおかしなことを確認しているとわかりますよね?

   ←この行に処理にたどり着くものが必要ということでしょうか?

また、「Exit Sub」する書き方にこだわりがあるということならば、↓のように順番を変えれば対応することはではあります。

    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim r As Range

        If Not Intersect(Target, Range("D2")) Is Nothing Then
            '〜〜処理〜〜
        End If

        If Target.Address <> "$C$9" Then Exit Sub
        '〜〜処理〜〜

    End Sub

よって、「2026/06/22(月) 08:19:57」の何が一番マズかったかというと、「TargetにD2セルが含まれているか」という判定をしている中に、まったく別の「C9セルに関する判定(と処理)」をいれてしまったことが問題だったわけです。(構文のミスもよくはありませんが、実行以前にコンパイルエラーでエクセル君から指摘されて気づけたはずです)

■24
閑話休題。ここまでで、大まかな部分の説明はしたかとおもいます。
細かい部分で余談的な話を追加するかもしれませんが、ひとまず私もここまでとします。

トピックは追ってますので、追加質問等あれば↓のように具体例を挙げて状況を説明いただければわかる範囲で解説します。

 〇〇のとき××になるとおもい、ステップ実行で確認したところ、△△から☆☆のところに進んでしまった。
 ××のところで、〇〇というエラーが発生してしまった

(もこな2) 2026/06/28(日) 17:19:48


■25
残念ながらリアクションがないですが、暇つぶしに「■9」のコードを微修正したのでアップしておきます。
    Private Sub Worksheet_Change(ByVal Target As Range)
        Dim r As Range
        Debug.Print Target.Address(RowAbsolute:=False, ColumnAbsolute:=False, ReferenceStyle:=xlA1, External:=False)

        '▼C9セルのみ書き換えがあった時の処理
        If Target.Address = "$C$9" Then
            If Target.Value <> "" And IsNumeric(Target.Value) Then
                Stop 'ブレークポイントの代わり
                Application.EnableEvents = False
                Call Posting_Output
                Application.EnableEvents = True
            Else
                Debug.Print "Target.Valueは「" & Target.Value & "」です"
            End If
        End If

        '▼B9セルを含むセル(範囲)の書き換えがあった時の処理
        If Not Intersect(Target, Range("B9")) Is Nothing Then
            Stop 'ブレークポイントの代わり
            ActiveSheet.Unprotect Password:="11100"
            With Range("E17:AH17")
                .EntireColumn.Hidden = False
                For Each r In .Cells
                    If r.Value = 0 Then
                        r.EntireColumn.Hidden = True
                    End If
                Next
            End With
            ActiveSheet.Protect Password:="11100"
        End If
    End Sub

もし、こちらでも思い通りの動作にならず、かつ自己解決ができない場合は、イミディエイトに何と出力されたのかを添えて質問されるとよいと思います。
(※イミディエイトが何なのかわからない場合は↓で学習してみてください。)

 【イミディエイトウィンドウ】
https://www.sejuku.net/blog/46859#index_id2
https://excel-ubara.com/excelvba1/EXCELVBA486.html

また、↓も覚えておいて損はないと思います。

 【ローカルウィンドウ】
https://excel-ubara.com/excelvba4/EXCEL266.html
http://excelvba.pc-users.net/fol8/8_2.html

■26(余談3)
「■6」「■9」で触れてますが「Target.Value」に拘る場合は、Targetが複数セルだとマズいわけです。
もっと言うと複数のセルを対象にValueプロパティで値を取り出そうとすると問題になります。
なので、最初のコードでは↓のように「r」に【行全体】を取り出してから、【行全体】のうち"N1セルに相当するセル"という指定の仕方をしていたのです。

   Set rr = Rows("21:82")
   For Each r In rr.Rows
       If r.Range("N1").Value = 0 Then
           r.Hidden = True
       End If
   Next

よって、同じようにE〜AH列から「r」に【列全体】を取り出して、【列全体】のうち116行目という指定をするなら次のようになります。

   Set rr = Columns("E:AH")
   For Each r In rr.Columns
       If r.Range("A116").Value = 0 Then
           r.Hidden = True
       End If
   Next

この点について、私が示したコードだと、「r」に取り出すものが【セル単体】になっています。
一方で、【セル単体】は独立して表示/非表示といったことはできませんから、私の提示したものではEntireRow(EntireColumn)を使って【セル単体】.【を含む行(列)全体】というようにして操作しています。
このあたりも、提示のあったものを何も考えず切り貼りするのではなく、ご自身が理解(納得)した方法にされるとよいでしょう。

(もこな2) 2026/07/04(土) 07:58:44


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.