[[20231017153822]] 『範囲内に赤色せるがあればNG,以外はOKを表示したax(坂田) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『範囲内に赤色せるがあればNG,以外はOKを表示したい』(坂田)

最終列と行はその都度変わる範囲内に
赤色のセルがあればA2に"NG"、
それ以外であればA3に"OK"を表示したいです。

ご教示頂けませんでしょうか。

< 使用 Excel:Microsoft365、使用 OS:Windows10 >


赤い色のついたセルのある範囲と赤い色のついたセルを用意してください。

範囲を仮にB1:D10とします。赤い色のついたセルをF1とします。

以下のマクロをコピーします。


 Option Explicit

 Function CountColor(r As Range, c As Range) As Long

    Dim cell As Range
    Dim count As Long

    For Each cell In r
        If cell.Interior.Color = c.Interior.Color Then
            count = count + 1
        End If
    Next

    CountColor = count

 End Function


A2に=if(CountColor(B1:D10,F1)>0,"NG","")
A3に=if(A2="","OK","")

こんなのでどうでしょうか?
(ゆたか) 2023/10/17(火) 16:27:48


ありがとうございます。
範囲内に赤以外のセルもあるのですが、赤いセルのみNG表記をしたいと思います。
また、A2、A3と分けずにA2のみにOKもしくはNGと表示したい場合はどうしたらよいでしょうか?

よろしくお願いいたします。
(坂田) 2023/10/17(火) 16:40:57


色のついたセルが増減しても、自動で再計算されない。。。
Application.VolatileをFunctionの直後に入れたら良いらしい。。。
入れてみましたが、うまく行きませんでした(~~;
(たぶん、誰かが答えてくれると思います(汗))

それはともかく。。。

A2に=if(CountColor(B1:D10,F1)>0,"NG","OK")

とすれば、一つのセルでいけます。
(ゆたか) 2023/10/17(火) 16:44:18


ありがとうございます!

今更なのですが、セルに計算式を入れるのではなくマクロで対応は難しいのでしょうか。
マクロボタンを配置したいと思っているのですが・・・

また範囲も都度変わるのでできれば、直接セルを指定せずに組めたらと思います。

わがままばかり申し訳ないです。
(坂田) 2023/10/17(火) 16:54:12


マクロボタンを設置して起動することも、もちろんできますよ。
コードは多少変更になるかも知れませんが。
また、範囲はマクロ起動後に力しても良いかと思います。

色も赤で決まっているのであれば、値をコード中に入れることもできます。

(ゆたか) 2023/10/17(火) 17:03:50


色は赤のみNG表示、その他の色と色なしはOK表示と決まっています!

よければコードを勉強させてもらえると幸いです。
よろしくお願いいたします。
(坂田) 2023/10/17(火) 17:05:38


 >色のついたセルが増減しても、自動で再計算されない。。。
 >Application.VolatileをFunctionの直後に入れたら良いらしい。。。
 >入れてみましたが、うまく行きませんでした(~~;

とりあえず、この件について。
セルのバックグラウンドカラーを変える行為は再計算の契機とはならないようです。
そのシートのいずれかのセルに入力、変更が行われた場合には、再計算が行われます。

(ゆたか) 2023/10/18(水) 08:42:51


 >最終列と行はその都度変わる範囲内に

 この範囲をどう特定するかが問題です。
 都度、ユーザーが指定するのか、プログラムで自動的に判定するのか。

 もし自動的に判定する必要があるなら、その特定ルールを説明してください。

(半平太) 2023/10/18(水) 09:33:10


ボタンから呼び出すタイプはこんな感じです。

選択範囲を入力するタイプです。マウスで範囲を選ぶこともできます。

 Sub CountColor1()

    Dim area As Range, cell As Range
    Dim count As Long

    On Error GoTo ErrExit

    Set area = Application.InputBox(Prompt:="範囲を選択してください。", Type:=8)

    For Each cell In area
        If cell.Interior.ColorIndex = 3 Then '赤を指定
            count = count + 1
        End If
    Next

    If count = 0 Then
        MsgBox "OK"
    Else
        MsgBox "NG"
    End If

 ErrExit:

 End Sub

もし、A1など特定のセルは必ず表に含まれ、表にはデータが入っていて、
空白行、空白列で区切られているなら、以下のようなコードも使えます。

 Sub CountColor2()

    Dim area As Range, cell As Range
    Dim count As Long

    On Error GoTo ErrExit

    Set area = Range("A1").CurrentRegion 'A1セルから表範囲を自動で選択
    area.Select                          '特に必要ないが選択範囲を明示

    For Each cell In area
        If cell.Interior.ColorIndex = 3 Then '赤を指定
            count = count + 1
        End If
    Next

    If count = 0 Then
        MsgBox "OK"
    Else
        MsgBox "NG"
    End If

 ErrExit:

 End Sub

何かエラーがあれば、とりあえず終了します(笑)
(ゆたか) 2023/10/18(水) 11:29:52


 回答じゃなく完全な脱線話でアレなんですが・・・

 >> 勉強させてもらえると幸い
 なんて言われると「つい」語りたくなっちゃってw ^^;

 この手の課題で自分の中では割と長期の宿題(棚上げとも云う)にしてしまっている事があります。
 (たいへん実用性に乏しい課題なので、なかなか真面目に取り組む気になれないだけですけど... ^^;)

 例えば、
    Function CreateInteriorColorList(Optional ByVal ChkArea As Range) As Object
    Rem 引数[ChkArea]に含まれる塗りつぶし色の一意リストを作って返す関数
    Rem 戻値---KeyがCOLORREF値(またはXlColorIndex定数)で値がRangeのScripting.Dictionary
                                                                   ・・・の様な汎用関数を考える場合、

 引数[ChkArea]に列全体(行全体ならまだしも)を指定される事を想定すると、
 各セルの塗りつぶし色を総当たりで調べるのは、処理速度の観点から出来れば避けて通りたい訳ですが、
 かと言って、
 調査対象をUsedRange内に限定してしまう訳にも行きません。
 値や数式とは違い、色付きセルはUsedRange外にも存在し得るからです。

 総当たりの回避策として、
 矩形単位や列単位・行単位で全てのセルが同じ色か否かが↓これで確認出来ますから、
    If IsNull(調査単位.Interior.ColorIndex) Then
 Nullだった場合は(仕方なく)セル単位で確認する様な組み方も考えられます。

 でも、
 それだけでは結局総当たりになってしまうケースの遭遇率は依然として高そうです。
 (例えばA列全体を黄色で塗って[A10]セルだけ色を消す。で、引数にA列全体を指定した場合等)

 で、調査対象をUsedRange「内」と「外」で分割して考えてみてはどうだろうか?
 少なくともUsedRangeの外側まで総当たりする必要は無い筈だよね?
 と思って、試しに素案を練っている途中で自分が何やってたのか見失ってしまい、現在に至ります。

 ChkAreaの属するシートを4つのエリアに分割し、
    1---.Range("A1", .UsedRange)
    2---1の右
    3---1の下
    4---2の下(3の右でもよい)
 ChkArea(内各Area毎)とのIntersect毎で調査する
    1---列(or行)単位に調査し、Nullだった列(or行)はセル単位に再調査
    2---Intersect内の1列目だけで同様に調査
    3---Intersect内の1行目だけで同様に調査
    4---Intersect内の先頭(TopLeft)セルだけで判断

 だいたいの流れ
    ◇当該矩形内が複数色
    ├Y:列または行単位で調査
    │◇縦方向に長い矩形
    │├Y:列単位で調査
    ││◇当該列内が複数色
    ││├Y:セル単位で再調査して辞書に登録
    ││└N:列ごと辞書に登録
    │└N:行単位で調査
    │ ◇当該行内が複数色
    │ ├Y:セル単位で再調査して辞書に登録
    │ └N:行ごと辞書に登録
    └N:矩形ごと辞書に登録
                                                       ・・・ホントか? ホントにそれでいいのか?

    Function CreateInteriorColorList(Optional ChkArea As Range) As Object
        If ChkArea Is Nothing Then
            If ActiveSheet Is Nothing Then Exit Function
            Set ChkArea = ActiveWindow.RangeSelection
        End If
        Dim Dic As Object
        Dim iArea As Range, a As Range, c As Range
        Set Dic = CreateObject("Scripting.Dictionary")
        If IsNull(ChkArea.Interior.ColorIndex) Then
            Dim uRect As Range, UnUsedR As Range, UnUsedB As Range, UnUsedBR As Range, LastCell As Range
            With ChkArea.Worksheet
                Set uRect = .Range("A1", .UsedRange)
                Set LastCell = .Cells(uRect.Rows.Count, uRect.Columns.Count)
                If LastCell.Column < .Columns.Count Then
                    Set UnUsedR = .Range(.Cells(1, LastCell.Column + 1), .Cells(LastCell.Row, .Columns.Count))
                    If LastCell.Row < .Rows.Count Then Set UnUsedBR = .Range(LastCell.Offset(1, 1), .Cells(.Rows.Count, Columns.Count))
                End If
                If LastCell.Row < .Rows.Count Then Set UnUsedB = .Range(.Cells(LastCell.Row + 1, 1), .Cells(.Rows.Count, LastCell.Column))
            End With
            For Each iArea In ChkArea.Areas
                If IsNull(iArea.Interior.ColorIndex) Then
                    Set a = Intersect(iArea, uRect)
                    If Not a Is Nothing Then
                        If IsNull(a.Interior.ColorIndex) Then
                            If a.Rows.Count > a.Columns.Count Then
                                CreateInteriorColorList_ChkColumns Dic, a
                            Else
                                CreateInteriorColorList_ChkRows Dic, a
                            End If
                        Else
                            CreateInteriorColorList_DicAdd Dic, a
                        End If
                    End If
                    Set a = Intersect(iArea, UnUsedR)
                    If Not a Is Nothing Then
                        If IsNull(a.Interior.ColorIndex) Then
                            For Each c In a.Rows
                                CreateInteriorColorList_DicAdd Dic, c
                            Next
                        Else
                            CreateInteriorColorList_DicAdd Dic, a
                        End If
                    End If
                    Set a = Intersect(iArea, UnUsedB)
                    If Not a Is Nothing Then
                        If IsNull(a.Interior.ColorIndex) Then
                            For Each c In a.Columns
                                CreateInteriorColorList_DicAdd Dic, c
                            Next
                        Else
                            CreateInteriorColorList_DicAdd Dic, a
                        End If
                    End If
                    Set a = Intersect(iArea, UnUsedBR)
                    If Not a Is Nothing Then
                        CreateInteriorColorList_DicAdd Dic, a
                    End If
                Else
                    CreateInteriorColorList_DicAdd Dic, iArea
                End If
            Next
        Else
            CreateInteriorColorList_DicAdd Dic, ChkArea
        End If
        Set CreateInteriorColorList = Dic
    End Function
    Private Sub CreateInteriorColorList_ChkRows(d As Object, a As Range)
        Dim r As Range
        For Each r In a.Rows
            If IsNull(r.Interior.ColorIndex) Then
                Call CreateInteriorColorList_ChkColumns(d, r)
            Else
                CreateInteriorColorList_DicAdd d, r
            End If
        Next
    End Sub
    Private Sub CreateInteriorColorList_ChkColumns(d As Object, a As Range)
        Dim c As Range
        For Each c In a.Columns
            If IsNull(c.Interior.ColorIndex) Then
                Call CreateInteriorColorList_ChkRows(d, c)
            Else
                CreateInteriorColorList_DicAdd d, c
            End If
        Next
    End Sub
    Private Sub CreateInteriorColorList_DicAdd(d As Object, ByVal a As Range)
        Dim k As Long
        k = a(1).Interior.ColorIndex
        If (k And &HFF000000) = 0 Then k = a(1).Interior.Color
        If d.Exists(k) Then Set d(k) = Union(d(k), a) Else Set d(k) = a
    End Sub
    '**************************************************************************
    Sub test()
        Dim d As Object, v
        Set d = CreateInteriorColorList()
        If d.Count = 0 Then Exit Sub
        For Each v In d.Keys
            Debug.Print Hex(v), d(v).Address(False, False)
        Next
    End Sub

 たまにはこういう「つまらぬ課題」に取り組んでみるのも面白いものです。
 スミマセン、お邪魔しました〜 ^^;

(白茶) 2023/10/18(水) 21:55:14


 今更ですが、範囲内に特定の色のセルがあるかないかを判定する(しかできない)マクロ

 Sub sample()
   Dim aCol As Range
   For Each aCol In Range("A:H").Columns
      Debug.Print aCol.Address; vbTab; HasColorCell(aCol, RGB(255, 0, 0))
   Next
 End Sub

 Function HasColorCell(Rng As Range, ByVal Color) As Boolean
    Dim aCell As Range
    Application.FindFormat.Interior.Color = Color
    With Rng
       Set aCell = .Find(What:="", After:=.Cells(1, 1), _
                                         LookIn:=xlFormulas, _
                                         LookAt:=xlPart, _
                                         SearchOrder:=xlByRows, _
                                         SearchDirection:=xlNext, _
                                         MatchCase:=False, _
                                         MatchByte:=False, _
                                         SearchFormat:=True)
    End With
    HasColorCell = Not (aCell Is Nothing)
 End Function
(´・ω・`) 2023/10/23(月) 15:29:06

課題か何かなのかな。似たような質問が他で上がってます。

http://www.vbalab.sakura.ne.jp/vbaqa/c-board.cgi?cmd=ntr;tree=82205;id=excel
(MK) 2023/10/23(月) 15:56:22


 おそらく同じ人だと思いますよ

 さて、先ほどの Function HasColorCell は条件付き書式 の色だと対応できないですね

 たぶんなんとなくですが、質問者さんの要望にあってない気がする
(´・ω・`) 2023/10/23(月) 16:30:37

コメント返信:

[ 一覧(最新更新順) ]


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