和風スパゲティのレシピ

日本語でコーディングするExcelVBA

Colorプロパティの値からRGBの値を求める

Colorプロパティの値や、マクロ記録で記録されたコードに書いてある色は、
「16764390」のように謎の数字で、見ただけでは何色かわかりません。

この値はRGB値と呼び、RGB関数(R, G, B)が返す値です。

このRGB値から、RGBそれぞれの値「230,205,255」を取得する関数を紹介します。

いわゆるRGB関数の逆関数ですね。

ソースコード

' パターン①  230,205,255 のようなテキストで結果を表示
Function RGB値を各色の値に変換する(RGB値 As Long) As String
    Dim R, G, B
    R = RGB値 Mod 256
    G = Int(RGB値 / 256) Mod 256
    B = Int(RGB値 / 256 / 256)
    
    RGB値を各色の値に変換する = R & "," & G & "," & B
End Function

' パターン② 参照渡しの引数に結果を返す
Sub RGB値を各色の値に変換して引数に返す(RGB値 As Long _
    , ByRef R As Long, ByRef G As Long, ByRef B As Long)
    R = RGB値 Mod 256
    G = Int(RGB値 / 256) Mod 256
    B = Int(RGB値 / 256 / 256)
End Sub

使い方

欲しい答えが3つある関数なので、答えの返し方を考える必要があります。

  1. 3つの答えを、カンマで区切った1つのテキストにする
  2. 3つの答えを、参照渡しの3つの変数に代入して返す

目で見てわかりやすいのが上、プログラムに組み込むなら下が便利です。
お好きな方を使ってください。

使用用途を考えると、値を目で見て確認するような場面が多そうなので、
上のテキスト返しが便利かな?と思います。


イミディエイトウィンドウ(使ったことない方はVBAの画面でCtrl + G)に、

?RGB値を各色の値に変換する(16764390)

と入れると、230,205,255が返ってきます。(?はDebug.Printの省略呼出)

イミディエイトウィンドウに「?○○」という方法は、何かの値や関数の結果を調べるのに便利なので、合わせて覚えてしまいましょう。


パターン②は一応書きましたが、これをプログラムに組み込む場面は、なかなか思いつかないですね。

「セルの色を別のセルにコピーする」場合は、RGB値の中身を調べる必要はなく、

Range("A1").Interior.Color = Range("A2").Interior.Color

↑これでColorプロパティの値を直接コピーできるため、そもそも変数がいらないのです。

※ 使う場面を頑張って考えたみたところ、「セルからセルまでをグラデーションで配色する」をなんとか思いつきました。

より便利なマクロ「選択セルのRGBを表示する」

さて、この記事を読んでいる方は、「セルのColorプロパティのR,G,Bが知りたい」方が多いのではないでしょうか?

 ① セルのColorプロパティ値を調べる
 ② R,G,Bを調べる

この②をやるためにこの記事を読んでいる方は、
そもそも①も一緒にやってしまう、
選択したセルのR,G,Bを表示する」マクロを作ったほうが便利です。

さらに、最終的な目的が、
 ③「=RGB(調べた値)」のようにマクロに使う
である場合は、そのままコピーして使えるテキストをマクロに書いてもらいましょう。


要するに、「A1セルを選択して実行」すると、
↓のテキストが表示されるマクロを作っちゃおうということです。

Cells(1, 1).Interior.Color = RGB(255,192,0)
Cells(1, 1).Font.Color = RGB(0,0,0)
Cells(1, 1).DisplayFormat.Interior.Color = RGB(244,176,132)

RGB値を調べてくれて、ついでに結果をコードっぽく返してくれます。
これで「Cells(1, 1)」を書き換えるだけで、別のマクロに使えますね。
すごい便利!

こういう、マクロにマクロを書かせることを、「メタプログラミング」と呼びます。

コードの中身と解説はこちらへどうぞ

RGBを求める計算式の解説

使う上では知る必要はありませんが、なぜ

    R = RGB値 Mod 256
    G = Int(RGB値 / 256) Mod 256
    B = Int(RGB値 / 256 / 256)

で計算できるのか気になった人のために、内容を解説します。


唐突ですが「3枚のコイントスの結果を数値で表せ」って言われたらどうしますか?

簡単ですね。
表を1、裏を0として、101,001,110 のようにすればいいですね。


でも、「たった8通りなのに111まで使ったらもったいないから、連番にしろ」って言われたらどうしましょう?

そしたら、101みたいな並びがちょうど2進数になっているので、2進数 → 10進数に変換してあげれば連番になります。

[百の位] × 2^2 + [十の位] × 2^1 + [一の位] × 2^0

これでOK。
000 → 0 から 111 → 7 までの、ちょうど8つの連番になりました。


じゃあコインをサイコロに変えて、「サイコロ3つの結果を数値化」はどうでしょう?

316,223,451 のようにすればいいですね。

でも、たった216通りなのに、666までまで使ったらもったいないから、
連番にするために6進数にしましょう。

[百の位] × 6^2 + [十の位] × 6^1 + 一の位 × 6^0

これでOK。
0から215までの連番になります。

※ 正確にはサイコロの1-6を0-5に直す必要がありますが、細かいことは気にしないでね


じゃあ「256面サイコロ3つの結果を数値化して連番に」はどうでしょう?


と言うことで、もうわかりましたね。

RGB関数の仕組みは単純で、
RGB = B * 256 * 256 + G * 256 + R
を計算しているだけです。

これで16777215までの連番になります。
256256256までメモリを使わなくて済みました。

8桁も9桁も誤差って時代だし、もう下をRGB値にした方が分かりやすくない?


百の位が230、十の位が205、一の位が255 の3桁の数字ってイメージです。桁があふれちゃってて、不思議な感じがしますが。


さて、ようやく本題。これを逆から求めます
それにはこの方程式を解けばいい訳ですね。なつかしい。


まずはBですが、RとGを移項して、256で2回割って、
B = RGB/256/256 - G/256 - R/256/256
を解きます。

ここで1つテクニックを使います。
例えば「27から2を取り出す」とき、
「(27-7)/10 」と律儀に1の位を消さなくても、
「27/10 を切り捨て」でも求まります。-7はいらなくなるのです。

RGBは256進数でしたから、256で同じことができますね。
「式全体を切り捨て」ると、RとGの項を消すことができます。

よって
B = RGB/256/256 の切り捨て
が残ります。無事、マクロの式になりました。


同じく、
R = RGB - B * 256 * 256 - G * 256
ですが、

「27から7を取り出す」とき、
「(27-20)」と律儀に十の位を消さなくても、
「27を10で割った余り」でも求まります。-20は無くせますね。

と言うことで256で同じことをやれば、
「式全体を割った余り」で、BとGの項を消すことができ、

R = RGB を 256 で割った余り
こちらもマクロの式になりました。

RとBが求まったので、Gは連立方程式を解くように、
G = (RGB - B * 256 * 256 - R)/256 を解いてもいけますが、
せっかくなので、↑の方法をどっちも使って、
G = RGB/256 の切り捨て(Rが消える) を256で割った余り(Bが消える)
とかきましょう。こちらもマクロの式になりました。


以上です。

ネットの解説は、数論的な理屈までちゃんとしてるものがなくて悲しかったので、頑張って書いてみました。

ここまで読んでくださったもの好きなあなたへ、ありがとうを贈ります。