Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
「色をCONSTで宣言する方法」についての関連議論
投稿日時: 23/06/01 09:12:45
投稿者: simple

関連スレッド:
色をCONSTで宣言する方法
https://www.moug.net/faq/viewtopic.php?t=82274
 
■ わざわざスレッドを建てたのは、前スレッドで、

VBA-stepup さんの引用:
>RGB値やHex等で、宣言してると、打ち合わせの最中に急に
>「この色もう少し薄くできる?」
>的な問答の時、ドタバタするので、ソース上で簡単にRGBの値が設定できるような方法がないかと思い質問しました。
もしよければ、私はこんな感じでやってますなど、忌憚のないご意見をお聞かせください。
との提案がありました。
私も、そこに何らか工夫の余地があるように思いました。
途中で打ち切られましたが、もう少し続けてみたらどうかと思い、
別のスレッドを建ててみました。
ご意見のあるかたは、続けてどうぞ書き込み下さい。
 
■ (ご参考)前回の議論についての私の印象
gombohoriさんの提案に対して
  RED = 255 + 256! * 0 + 65536! * 0
  GREEN = 0 + 256! * 255 + 65536! * 0
となることから、
> すげーって思ったのですが、インデントがずれると微妙に読みづらいと感じてしまいました。
とのことで却下。
 
そうであれば、hatenaさんの
    RED = 255 * R + 0 * G + 0 * B
    GREEN = 0 * R + 255 * G + 0 * B
も揃ってないので却下なんですか?
私は良い落としどころかと思いましたが。
 
桁が揃っていることにそれほどこだわるのであれば、
    RED = &HFF&              'RGB(255,  0,  0)
    GREEN = &HFF00&          'RGB(  0,255,  0)
などとするしかないのでは?
それか、それほど上司または顧客の意見で変更するのであれば、定数じゃないんだから、
変数として宣言すれば、いくらでもRGB関数が使えます。(でも桁はきちんと揃わない気がしますね)
 
コメントを付ける案はご遠慮下さいということでしたが、
あなたの要望を満たすにはそれしかないように思います。
正直言って、質問者さんの美意識はちょっと理解しかねました。

回答
投稿日時: 23/06/01 17:15:30
投稿者: VBA-stepup

引用:
■ わざわざスレッドを建てたのは、前スレッドで、
VBA-stepup さんの引用:
>RGB値やHex等で、宣言してると、打ち合わせの最中に急に
>「この色もう少し薄くできる?」
>的な問答の時、ドタバタするので、ソース上で簡単にRGBの値が設定できるような方法がないかと思い質問しました。
もしよければ、私はこんな感じでやってますなど、忌憚のないご意見をお聞かせください。
との提案がありました。
私も、そこに何らか工夫の余地があるように思いました。
途中で打ち切られましたが、もう少し続けてみたらどうかと思い、
別のスレッドを建ててみました。
ご意見のあるかたは、続けてどうぞ書き込み下さい。

 
スレッド立てていただいてありがとうございます。
上記にあるように、ユーザーによる変更依頼があるならばConstで宣言してもコードの変更があるので
変数で定義した方がコードの変更なくユーザーに変更してもらえばいいかなと思い。提案させていただきました。私がよく使う方法として、別シートにカラーパレットをセルに設定して置き好きなように色を変更してもらうやり方です。(何でもかんでも変更できる仕様にはしません。)
色のほかに、他ファイルPathとか保存先Pathとかを設定シートとして作成しコードの変更を極力しないですむようにしています。色変更はこのようにしています。
 
 
Option Explicit
Public ws As Worksheet
Public ユーザー1 As Long
Public ユーザー2 As Long
Public ユーザー3 As Long

Sub test()
    Set ws = ThisWorkbook.Sheets("mycolor")
    
    ユーザー1 = ws.Range("A1").Interior.Color
    ユーザー2 = ws.Range("C1").Interior.Color
    ユーザー3 = ws.Range("E1").Interior.Color
    
    Selection.Cells.Interior.Color = colorSet(ユーザー2)
End Sub
Function colorSet(ByVal MyColor As Long)
    
    Dim R As Long
    Dim G As Long
    Dim B As Long
    
    R = MyColor Mod 256
    G = Int(MyColor / 256) Mod 256
    B = Int(MyColor / 256 / 256)
    
'    Selection.Cells.Value = "RGB(" & R & ", " & G & ", " & B & ")"
'    MsgBox "RGB(" & R & ", " & G & ", " & B & ")"
    colorSet = RGB(R, G, B)
End Function

回答
投稿日時: 23/06/01 22:42:32
投稿者: MMYS

simpleさん、スレ立てられたので、コメント致します。
 

わっしょい さんの引用:

'使用する色
'=============== VBAでできないのはわかっていて記載 ===============
Public Const エラー時の背景色1 AS Double = RGB(255, 0, 0)
Public Const エラー時の前景色1 AS Double = RGB(255, 255, 0)
てな感じで本当はやりたいんです。できないけど。

下記のように記述すれば目的は達成できると思いますが。
 
Public Const エラー時の背景色1  As Long = XlRgbColor.rgbRed
Public Const エラー時の前景色1  As Long = XlRgbColor.rgbBlue

組み込み定数でオートコンプリート働くし、エラーチェックも働く。必要な色は大抵、用意されているので、自前で色定義する必要性が理解できないのですが。打ち合わせ中に色変更あっても、大抵は用意されている色で間に合うと思います。
 
わっしょい さんの引用:

RGB値やHex等で、宣言してると、打ち合わせの最中に急に
「この色もう少し薄くできる?」
的な問答の時、ドタバタするので、ソース上で簡単にRGBの値が設定できるような方法がないかと思い質問しました。

ご指摘のように、色を薄くしたいなら、色は24bit整数で並び順が「青」「緑」「赤」の順なので(各8ビット)下記のように16進で指定しましょう。
 
Public Const エラー時の背景色1  As Long = &hFF   '赤
Public Const エラー時の前景色1  As Long = &HFF0000 '青

16進を2桁ずつ下位から読めば下位ビットか「赤」、真ん中は「青」、上位ビットが「青」ですから、各色の色成分はコードから分かります。
 

投稿日時: 23/06/02 06:31:41
投稿者: simple

重複部分がありますが、書いて置いたメモを載せます。
 
私も、R,G,Bの値だけで色を想像するなんて芸当はできませんね。
それらの数値をいかに素早く求めるかについては、
例えば以下の標準機能を使った方法ではどうかなあと思っていました。
 
・「フォント」 -「塗りつぶし色」のアイコンをクリックしてから、
  「その他の色」の「ユーザー設定」タブを押すと、
  ActiveCellの塗りつぶし色の、R,G,Bの数値、Hex値?が表示されます。
   
・現在の色の付近をクリックしたり、右のバーを操作したりすれば、
  右下隅のボックスに、現在の色とその変更候補の色が対比して表示されます。
  ここで上司だか同僚だか顧客だかの確認をとればいいでしょう。
 
・HSLというもうひとつのカラーモデル(色合い、鮮やか、明るさ)があるので、
  これも選択上の役にたつかもしれません。
 
・これで、色を決めて、あとは、表示されているHex値?を使って
  Const myColor as long = &.....& とすればよいのではないですか?
  (#を&Hに変え、なおかつ1バイト目と3バイト目を逆転させる必要があります。
    ここだけBGR方式を採用している理由が不明ですけど、
    R,G,Bの要素を、そのままの順序で表示したということなんでしょうか。)

投稿日時: 23/06/02 06:43:19
投稿者: simple

(つづき)
以下、余談めいたものです。
ご紹介いただいた、
Colorプロパティの設定値一覧(カラー定数、XlRgbColor列挙)
https://excel-ubara.com/excelvba4/EXCEL285.html
ですが、実は余り使ったことがありませんでした。(汗)
 
XlRgbColor Enumerationですが、142個の定数が定義されているようですね。
予め色を固定しておくなら、これで十分かとも思いました。
 
ただ、話からすると、どうやら、もっと微妙な色の修正をしたいという話のようです。
# 濃い薄いというのは、色とはまた違うスケールなのかもしれないとも思いました。
# HSLカラーモデルで色を選択したほうがよいかもしれません。
 
参考までに、任意に定めた色と、それに最も近い"XlRgbColor定数"を採用する
というロジックを試してみましたが、予想以上に二つの色は違う印象です。
("最も近い"というのは、R,G,Bの3次元の点と見て、互いの距離が最小のものを言います)
 
つまり、142個程度では稠密にはなりえない、ということでしょうか。
(もちろん142色で代表できるわけではないでしょ?と言われればそれまでですが)

投稿日時: 23/06/02 06:46:49
投稿者: simple

ちなみに、

&H00FF00&  'RGB(  0,255,  0)
といった文字列をユーザー定義関数で取り出すには、こんな感じでしょうか。
Function getColorInfo(rng As Range) As String
    Dim col&
    Dim s$
    Dim r&, g&, b&
    Dim rS$, gS$, bS$

    col = rng.Interior.Color
    
    '16進数
    s = Application.Dec2Hex(col)
    s = Right("000000" & s, 6)
    s = "&H" & s & "&"
    
    'RGB表現
    r = col Mod 256
    g = Int(col / 256) Mod 256
    b = Int(col / 256 / 256)
    rS = Right("  " & CStr(r), 3)
    gS = Right("  " & CStr(g), 3)
    bS = Right("  " & CStr(b), 3)
    getColorInfo = s & "  " & "'RGB(" & rS & "," & gS & "," & bS & ")"
End Function

回答
投稿日時: 23/06/02 07:15:28
投稿者: VBA-stepup

MMYSさん、simpleさん有難うございます。
自分のレベルをはるかに超えていますが・・・・・
 
少しでも理解できるように勉強します。

回答
投稿日時: 23/06/02 14:08:38
投稿者: たらのり

こんにちは
 
ちょっと趣旨からは逸れるのかな……?
 

'                                 BB     GG     RR    ww
Const RED       As Long = "&h" & "00" & "00" & "FF"
Const GREEN     As Long = "&h" & "00" & "FF" & "00"
Const BLUE      As Long = "&h" & "FF" & "00" & "00"
Const YELLOW    As Long = "&h" & "00" & "FF" & "FF"

Sub Numclenicer()
    With Sheet1
        .Cells(1, 1).Interior.Color = RED
        .Cells(2, 1).Interior.Color = GREEN
        .Cells(3, 1).Interior.Color = BLUE
        .Cells(4, 1).Interior.Color = YELLOW
    End With
End Sub

回答
投稿日時: 23/06/02 22:15:33
投稿者: たらのり

こんばんは
 
日中の投稿は,桁位置を揃えることのみに注目していました。
 
gombohori さんの案では,R G B ごとにカッコで括ると,
視認性がやや向上するのではと思いました:
 

    RED = 255 + 256! * 0 + 65536! * 0
    GREEN = 0 + 256! * 255 + 65536! * 0

    ↓
 
    RED = (255) + (256! * 0) + (65536! * 0)
    GREEN = (0) + (256! * 255) + (65536! * 0)

 
ここでも気になったのは,色の要素の値なのか,桁の重みの
値なのかが識別しにくいことで(とくに 255 と 256),
 
hatena さんのアイデアのように,桁の重みに名前をつけて
しまえばよいと思いました:
 
    RED = 255 * R + 0 * G + 0 * B
    GREEN = 0 * R + 255 * G + 0 * B

 
ちなみに僕の方法は,最後に長整数を表す "&" を付加すると
NGとなってしまう,たいへんお粗末な方法でした:
 
○  Const RED   As Long = "&h" & "00" & "00" & "FF"

×  Const RED   As Long = "&h" & "00" & "00" & "FF" & "&"

たしか「型が一致しない」のようなエラーでした。
 
あと,Enum では使えない曲芸ですね(桁位置が揃いません)。
 

投稿日時: 23/06/02 22:42:52
投稿者: simple

# 雨のなかでしたが、久しぶりに旧交を叙しておりました。遅くなりました。
 
たらのりさんの案、ナイスというかクールというか、そういう気がしました。
型変更に任せてしまうというのは気づきませんでした。
 
なお、
hatenaさんの案は、
   RED = R * 255 + G * 0 + B * 0
   GREEN = R * 0 + G * 255 + B * 0
のほうが直感により訴えるかもしれません。

回答
投稿日時: 23/06/03 00:25:04
投稿者: たらのり

# 酒気帯びですが
 
ブチブチ区切らず,これでもよかったのか……
 

'                            BBGGRR
Const RED       As Long = "&h0000FF"
Const GREEN     As Long = "&h00FF00"
Const BLUE      As Long = "&hFF0000"
Const YELLOW    As Long = "&h00FFFF"

スレ汚し,失礼いたしました m(_ _)m

回答
投稿日時: 23/06/03 12:48:24
投稿者: VBA-stepup

こだわってみました。
  

Public Const RED      As String = "RGB(255,  0,  0)"
Public Const GREEN    As String = "RGB(  0,255,  0)"
Public Const BLUE     As String = "RGB(  0,  0,255)"
Public Const YELLOW   As String = "RGB(255,255,  0)"
'変更の時に使用
Sub RGB値から色設定()
    Dim myRGB As String
    Dim R As Long
    Dim G As Long
    Dim B As Long
    
    myRGB = YELLOW
    R = Mid(myRGB, 5, 3)
    G = Mid(myRGB, 9, 3)
    B = Mid(myRGB, 13, 3)
    
    Selection.Cells.Value = "RGB(" & R & ", " & G & ", " & B & ")"
    Selection.Cells.Interior.Color = colorSet(R, G, B)
End Sub
Sub セルの色からRGB値()
    Dim myColor As Long
    Dim R As Long
    Dim G As Long
    Dim B As Long
    
    myColor = Selection.Cells.Interior.Color
    
    R = myColor Mod 256
    G = Int(myColor / 256) Mod 256
    B = Int(myColor / 256 / 256)
    
    Selection.Cells.Value = "RGB(" & R & ", " & G & ", " & B & ")"
    Selection.Cells.Offset(0, 1).Value = "#" & Right(0 & Hex(R), 2) & _
                                               Right(0 & Hex(G), 2) & _
                                               Right(0 & Hex(B), 2)

End Sub
Function colorSet(ByVal R As Long, ByVal G As Long, ByVal B As Long)
    colorSet = RGB(R, G, B)
End Function

 
とりあえず動いたのでアップしてみました・・・・・
これでインデントとRGBに関して了解してもらえるのかな?

回答
投稿日時: 23/06/03 20:18:11
投稿者: VBA-stepup

一部修正
 
Selection.Cells.Interior.Color = colorSet(R, G, B)
      ↓
Selection.Cells.Interior.Color = RGB(R, G, B)
 
これはいらない。
Function colorSet(ByVal R As Long, ByVal G As Long, ByVal B As Long)
    colorSet = RGB(R, G, B)
End Function
 
Selection.Cells.Offset(0, 1).Value = "#" & Right(0 & Hex(R), 2) & _
                                           Right(0 & Hex(G), 2) & _
                                           Right(0 & Hex(B), 2)
       ↓
Selection.Cells.Offset(0, 1).Value = "&h" & Right(0 & Hex(R), 2) & _
                                            Right(0 & Hex(G), 2) & _
                                            Right(0 & Hex(B), 2)
 
すみませんでした。
 
実際に使うとしたらこんな感じかな?
 

Option Explicit
Public Const RED      As String = "RGB(255,  0,  0)"
Public Const GREEN    As String = "RGB(  0,255,  0)"
Public Const BLUE     As String = "RGB(  0,  0,255)"
Public Const YELLOW   As String = "RGB(255,255, 15)"

Sub test()
'   判定式
    Call ColorSet(Selection.Cells, GREEN)
End Sub
Sub ColorSet(ByVal myRng As Range, ByVal myRGB As String)
    Dim R As Long
    Dim G As Long
    Dim B As Long
    
    R = Mid(myRGB, 5, 3)
    G = Mid(myRGB, 9, 3)
    B = Mid(myRGB, 13, 3)
    
'    myRng.Value = "RGB(" & R & ", " & G & ", " & B & ")"
    myRng.Interior.Color = RGB(R, G, B)
End Sub
'変更の時に使用
Sub セルの色からRGB値()
    Dim myColor As Long
    Dim R As Long
    Dim G As Long
    Dim B As Long
    
    myColor = Selection.Cells.Interior.Color
    
    R = myColor Mod 256
    G = Int(myColor / 256) Mod 256
    B = Int(myColor / 256 / 256)
    
    Selection.Cells.Value = "RGB(" & R & ", " & G & ", " & B & ")"
    Selection.Cells.Offset(0, 1).Value = "&h" & Right(0 & Hex(R), 2) & _
                                               Right(0 & Hex(G), 2) & _
                                               Right(0 & Hex(B), 2)

End Sub

投稿日時: 23/06/03 20:50:02
投稿者: simple

最後のところは、こうですか。
 Selection.Cells.Offset(0, 1).Value = "&h" & Right(0 & Hex(B), 2) & _
                                             Right(0 & Hex(G), 2) & _
                                             Right(0 & Hex(R), 2)

回答
投稿日時: 23/06/03 20:54:05
投稿者: VBA-stepup

その通りです。
有難うございます。

回答
投稿日時: 23/06/04 01:35:27
投稿者: MMYS

そもそも、目的は、下記だと思います。
・エラー時にメーセージを表示。
・メッセージの色を指定。
 
メッセージの色は、ユーザーも開発者も、こだわりは無いのては。
・重大なエラー ⇒ 赤色
・軽微なエラー ⇒ 黄色
・入力ミスなど ⇒ 黒色
 
ユーザーからすれば、そんなことより、早く開発を進めて、早くリリースしてください。業務で一日でも早く使いたい。となるでしょう。開発遅れはユーザーにも開発者にも、デメリットです。
また、開発最終段階で、色変更すれば、済む話。ユーザーに、一覧からどの色にしますかと。他の色を希望したら、その時点で独自色を作ればそれで十分と思います。
 
色は24bitの整数に過ぎないのですから。
 
※趣味なら、自身の納得いくまで、いくらでも時間かけられますが、業務では、工数管理が求められます。
 
 
■以下補足
色は三原色で各色8ビット。1677万色なのはご存知の通り。
  
 256色(赤)×256色(緑)×256色(青)=1677万色
  
また、整数型は
・Byte型  8ビット
・Int型  16ビット
・Long型 32ビット
  
つまり、2進数では、
・Byte型  b7〜b0
・Int型  b15〜b0
・Long型 b31〜b0
  
となります。色は24bitなので、32bit整数型を用意して、各ビットに色を割り当て。
・b7〜b0  ⇒ 赤
・b15〜b8  ⇒ 緑
・b23〜b16 ⇒ 青
・b31〜b24 ⇒ 未使用
 
※本来2進数ですが、コード上は、16進表記します。16進なら、4ビットを1文字で表現できるから。
 
色は1677万色ですから、、色の各成分を、+1 や -1 した程度では、肉眼ではほとんど分かりません。例えば、
・&hFF0000 ⇒ 青色
・&hFE0000 ⇒ 薄い青色
 
これは −1 ですが、色の違いはほとんど分からないと思います。つまり、色変更は、16単位ぐらいで変化さて
・&hFF0000
・&hEF0000
・&hDF0000
・&hCF0000
・&hBF0000
・&hAF0000
 
と言った感じ。つまり、実務では色の変化は数パターンで十分かと。
 
 
※そもそも、「エラーメッセージの色」です。ユーザーからすれば、色は些細な問題。気軽に要望したに過ぎないと思います。色に工数を掛ける所では無と思います。
 
 

投稿日時: 23/06/04 12:56:21
投稿者: simple

ご指摘ありがとうございます。
 
定数へのこだわりとか、表示のレイアウトとか、
個人的にはやや過剰なこだわりという印象は持っていました。
 
ただし、色はエラーメッセージに関するもの、という見立てはどうなんでしょうか。
私はそのようには捉えていませんでした。
確かにそのように書かれていましたが、
 
'致命的なエラーです'の前景色、背景色
・・・
'予期せぬエラーです'の前景色、背景色
といわれてもピンと来ませんでした。
 
形式を示すための例示に過ぎないのでは、と思っていました。
 
===============
コメントいただいた皆様、ありがとうございました。
議論が途中になっていたとすれば、それが継続出来てよかったです。
 
個人的にいろいろと勉強になりました。
HSL表現は知ってはいましたが、Excelで出てくるとは予想外でした。
 
閉じます。