[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『範囲内に赤色せるがあれば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
よろしくお願いいたします。
(坂田) 2023/10/17(火) 16:40:57
それはともかく。。。
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
よければコードを勉強させてもらえると幸いです。
よろしくお願いいたします。
(坂田) 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.