COMのAPI経由でMS Office関連の操作を行う場合、色の設定に注意する必要があります。
Officeの場合、色は32bit整数で表現されるのですが、中の赤と青を示すビットの順番が、一般的なものと逆になっています。
Officeの色の16進数表記
__BBGGRR
一般的な色の16進数表記
__RRGGBB
この記事では、Officeの色をRGBに分解してSystem.Drawing.Color
等に変換してみます。
確認
まず、本当に中のビットの順番が異なるのか確認してみます。
今回はOfficeから色を取得する代わりに、VBAのRGB関数互換のVBのRGB関数で色の整数を作成し、[Drawing.Color]::FromArgb
に渡してみます。
Add-Type -AssemblyName Microsoft.VisualBasic, System.Drawing
# Officeで使われている色
[int]$offceColor = [Microsoft.VisualBasic.Information]::RGB(240, 160, 80)
# intをそのまま受け取るオーバーロードはあるが……
# static System.Drawing.Color FromArgb(int argb)
[Drawing.Color]::FromArgb( $offceColor )
<#
R : 80 # RとBが逆
G : 160
B : 240 # RとBが逆
A : 0
IsKnownColor : False
IsEmpty : False
IsNamedColor : False
IsSystemColor : False
Name : 50a0f0
# >
結果からもわかるように、そのままだと赤と青が逆になってしまいます。
分解して.NETの色に変換する
本題のRGBに分解→変換をしてみます。
intをbyte単位に分解したい場合、地道に数値演算する手もありますが、System,BitConverterのGetBytesメソッドを使用すると簡単にbyte配列に変換できます。
PowerShellの記法も利用すると以下のように記述できます。
Add-Type -AssemblyName Microsoft.VisualBasic, System.Drawing, PresentationCore
# Officeで使われている色
[int]$offceColor = [Microsoft.VisualBasic.Information]::RGB(240, 160, 80)
# byte配列に変換[R,G,B,A] => 0,1,2番目を変数に代入(3番目以降は破棄)
[byte]$drwR, [byte]$drwG, [byte]$drwB, $null = [BitConverter]::GetBytes($offceColor)
# static System.Drawing.Color FromArgb(int red, int green, int blue)
[Drawing.Color]::FromArgb($drwR, $drwG, $drwB)
<#
R : 240
G : 160
B : 80
A : 255
IsKnownColor : False
IsEmpty : False
IsNamedColor : False
IsSystemColor : False
Name : fff0a050
# >
# static System.Windows.Media.Color FromRgb(byte r, byte g, byte b)
[Windows.Media.Color]::FromRgb($drwR, $drwG, $drwB)
<#
ColorContext :
A : 255
R : 240
G : 160
B : 80
ScA : 1
ScR : 0.8713671
ScG : 0.3515326
ScB : 0.08021983
# >