あじちゃんのブログ。備忘録。

〜SEもOLなんですかね?

【VBA】ColorIndexは色によってユニークな値ではなかった話

こんな関数を作って同じ背景色の合計を出そうとしました。

'## 背景色が合致したセルをカウントする ##
Function CountColor(計算範囲, 条件色セル)
    Application.Volatile
    CountColor = 0
    For y = 1 To 計算範囲.Columns.Count
        For x = 1 To 計算範囲.Rows.Count
            If 計算範囲.Rows(x).Columns(y).Interior.ColorIndex = 条件色セル.Interior.ColorIndex Then
                CountColor = CountColor + 1
            End If
        Next
    Next
End Function

これ、同系色?は同じ色としてカウントするみたい。(正確なルールがよく分からない)
取得できるColorIndexには皆さん気をつけてくださいませ・・・

ちなみに確認するために作った関数。

'## 背景色のColorIndexを取得する
Function GetColorIndex(対象セル) 
    Application.Volatile
    GetColorIndex = 対象セル.Interior.ColorIndex
End Function

この画像を見ていただくと分かるのですが、E6~H6のColorIndexをE7~H7に出しました。 f:id:azix:20180327161754p:plain

見事に同じ・・・
これのせいで計算が間違っているように見えたみたい。
一定の透明度?濃度?からさがるとColorIndexが共通しちゃうのかな?原因は不明です。
(いつか調査するかも)

【調べました】
ColorIndex() は古いExcelの時のメソッドらしく新しめのExcelの色合いには対応していないそう。
代わりに使うのが Color() で、これはRGB値をlong型で返してくれる。
このlong値は「B・G・R」の順に「bbbbbbbbggggggggrrrrrrrr(1文字1bit)」で返ってくるので、R,G,Bの形にするには計算の必要がある。

なので、

Sub Sample()

  Dim n As Long
  Dim r As Byte
  Dim g As Byte
  Dim b As Byte

  # 対象セルの色をLong値で取得
  n = 対象セル.Interior.Color

  # それぞれRGBごとに計算
  r = n \ 256 ^ 0 Mod 256    # 0~16,777,215の範囲の値(R,G,B) % 256
  g = n \ 256 ^ 1 Mod 256    # 256~16,777,215の範囲の値(G,B) % 256
  b = n \ 256 ^ 2 Mod 256    # 65,536~16,777,215の範囲の値(B) % 256

  # #rrggbb の形で出力
  MsgBox "#" & r & g & b

End Sub


「0~16,777,215の範囲の値」とか言っているのは、10進数/16進数 で見た時に各値が持つ範囲が以下のようになるので算出している。
 R:0~255/000000~0000FF
 G:256~65,535/0000FF~00FFFF
 B:65,536~16,777,215/00FFFF~FFFFFF

簡単に言うと、532円を100の位、10の位、1の位に分けているようなもの。



※「\」とは、割り算の商・整数部だけを計算する演算子で、JavaScriptで言うところの「parseInt()」↓と同じ

var ans = parseInt(9 / 2);     // ans = 4

※「Mod」とは、割り算での余りの数を計算するための演算子で、JavaScriptで言うところの「%」↓と同じ

var ans = 9 % 2    // ans = 1