Interior.Color Property inverts colors? - excel

I have written a piece of code that allows me to retrieve the shading color of a specific cell inside a sheet of an excel workbook. I have successfully retrieved the RGB integer value by starting a COM server using MATLAB's actxserver, and then accessing the Color Property of the Interior Object of that particular Cell Object. Then I obtain the equivalent RGB triplet of that integer, so I can use it later for plotting in MATLAB.
In order to test that my code works properly I designed the following test: I created an Excel workbook called colorTest.xlsx with 8 different colors:
Then I run my MATLAB code, which extracts the color information on each cell of the B column. I should get a plot with the colors on the same vertical order and a table with the int value and the RGB triplet of each color.
However something unexpected happens! Look at the results:
Notice that the integer value that is obtained from the Color Property does not always match the color of the original cell, for black, white, green and magenta the integer values are correct, but this is not true for all the other colors. You can see, for example, that for red color on the Excel, the output int and RGB triplet correspond to blue color.
I have added the following table with the correct results I should get, for reference:
Color Int R G B
-------- -------- -----
Black 0 0 0 0
White 16777215 1 1 1
Red 16711680 1 0 0
Green 65280 0 1 0
Blue 255 0 0 1
Cyan 65535 0 1 1
Magenta 16711935 1 0 1
Yellow 16776960 1 1 0
I obtained the correct integer values for each color using this RGB Int Calculator.
If we compare the two tables, we can deduce that the Red and Blue channels are inverted.
The code:
The function that I execute to run the test is called getCellColor. Have a look at the code:
function getCellColor()
clear all;
clc;
% Excel
filename = 'colorTest.xlsx';
% Start Excel as ActiveX server process on local host
Excel = actxserver('Excel.Application');
% Handle requested Excel workbook filename
path = validpath(filename);
% Cleanup tasks upon function completion
cleanUp = onCleanup(#()xlsCleanup(Excel, path));
% Open Excel workbook.
readOnly = true;
[~, workbookHandle] = openExcelWorkbook (Excel, path, readOnly);
% Initialise worksheets object
workSheets = workbookHandle.Worksheets;
% Get the sheet object (sheet #1)
sheet = get(workSheets,'item',1);
% Print table headers
fprintf('Color \t Int \t R G B\n');
fprintf('--------\t --------\t -----\n');
% Create figure
figure;
hold on;
% Loop through every color on the Excel file
for row = 1:8
% Get the cell object with name of color
cell = get(sheet, 'Cells', row, 1);
cName = cell.value;
% Get the cell object with colored background
cell = get(sheet, 'Cells', row, 2);
% Get the interior object
interior = cell.Interior;
% Get the color integer property
cInt = get(interior, 'Color'); % <-- Pay special attention here(*)
% Get the RGB triplet from its integer value
cRGB = int2rgb(cInt);
% Plot the color
patch([0 0 1 1], [8-row 9-row 9-row 8-row], cRGB);
% Print row with color data
fprintf('%-8s\t %8d\t %d %d %d\n', cName, cInt, cRGB);
end
% Turn off axes
set(findobj(gcf, 'type','axes'), 'Visible','off')
end
(*) This instruction is responsible of recovering the color integer.
Note: The functions described next, do not cause the problem since they do not take part in the obtaining of the color integer (they are only used for secondary tasks). I have included this information only for completeness.
During this process I use three private functions from the MATLAB's iofun folder, which are: validpath, xlsCleanup and openExcelWorkbook. I simply copied them into a folder called private inside the project folder.
Finally, to obtain the RGB triplet from the color integer, I use a function which I adapted from this other function that I found on the net.
Here is the code for my int2rgb function:
function[RGB] = int2rgb(colorInt)
% Returns RGB triplet of an RGB integer.
if colorInt > 16777215 || colorInt < 0
error ('Invalid int value. Valid range: 0 <= value <= 16777215')
end
R = floor(colorInt / (256*256));
G = floor((colorInt - R*256*256)/256);
B = colorInt - R*256*256 - G*256;
RGB = [R, G, B]/255;
end
I am trying to make some sense out of this, but I really have no idea of what is happening. I have done some research, without much luck, but this post and this other post caught my attention. Maybe it has something to do with my problem.
So does the Interior.Color Property really inverts colors?
If this is the case, should I consider this as normal behavior or is this a bug?
Link to download:
I have packed the entire project on a .zip file and uploaded it, so you can run this test on your machine straight away. Download the file and unpack.
getCellColor.zip

There is no "right" or "wrong" here, Matlab and Excel just encode color differently. You need to account for that in your code.
The closest I can find to an official source is this MSDN article, about half way down see the example of encoding of "blue"
MSDN article
The following examples set the interior of a selection of cells to the color blue.
Selection.Interior.Color = 16711680
Selection.Interior.Color = &HFF0000
Selection.Interior.Color = &O77600000
Selection.Interior.Color = RGB(0, 0, 255)

My first thought is check the channels order RGB vs. BGR.
You could probably simplify that int2rgb function by using typecast instead. Here's an example using the values you posted:
clrs = [0; 16777215; 16711680; 65280; 255; 65535; 16711935; 16776960]
for i=1:numel(clrs)
bgra = typecast(int32(clrs(i)), 'uint8')
end
The output:
clrs =
0
16777215
16711680
65280
255
65535
16711935
16776960
bgra =
0 0 0 0
bgra =
255 255 255 0
bgra =
0 0 255 0
bgra =
0 255 0 0
bgra =
255 0 0 0
bgra =
255 255 0 0
bgra =
255 0 255 0
bgra =
0 255 255 0

Your int2rgb method inverts R and B. Replace them and you'll get the right conversion. The Interior.Color property uses the convention where R is the least significant, while the FileExchange function you used uses the opposite convention.
To convert from int to RGB:
B = floor(colorInt / (256*256));
G = floor((colorInt - B*256*256)/256);
R = colorInt - B*256*256 - G*256;
colorRGB = [R G B];
To convert from RGB to int:
colorInt = colorRGB * [1 256 256*256]';

From the MSDN article on RGB Color Model:
The RGB color model is used for specifying colors. This model
specifies the intensity of red, green, and blue on a scale of 0 to
255, with 0 (zero) indicating the minimum intensity. The settings of
the three colors are converted to a single integer value by using this
formula:
RGB value = Red + (Green*256) + (Blue*256*256)
As it was suggested in chris neilsen answer, there is no "right" or "wrong" in terms of color encoding. Microsoft has chosen this particular way to encode colors for reasons only they know, and I should stick to it.
So the RGB values that I get are totally correct.
In the following table, I have included the RGB values provided in the MSDN article next to the ones that I get in MATLAB, and they are a perfect match.
Color Int RGB values from MSDN
-------- -------- --------
Black 0 0
White 16777215 16777215
Red 255 255
Green 65280 65280
Blue 16711680 16711680
Cyan 16776960 16776960
Magenta 16711935 16711935
Yellow 65535 65535

Related

IF functions in excel - use multiple ones with the same outcome (explained)?

Here's my dilemma:
I have columns of colours (red, blue, etc). For each there's either 0 or 1 (1 if the item has blue in it, 0 if not). BUT there can be 2 (or 10) colours in an item. Is there a way to formulate this in Excel?
I tried using IF, but this is limiting me to 2 conditions: if the red is false, then it'd go to blue, but I cannot seem to find a simultaneous way of showing both blue and red for an item.
For example:
My skirt is both green and yellow. I have 0 for red, 0 for blue, 1 for green, 1 for yellow. I'd like this condensed in 1 column only, that would say: green, yellow (with a comma in between).
Help?
Guessing what is where, ie that red is in B1, the following seems to work for the example provided:
=LEFT(IF(B2=1,B$1&", ","")&IF(C2=1,C$1&", ","")&IF(D2=1,D$1&", ","")&IF(E2=1,E$1&", ",""),LEN(IF(B2=1,B$1&", ","")&IF(C2=1,C$1&", ","")&IF(D2=1,D$1&", ","")&IF(E2=1,E$1&", ",""))-2)
(Returns error where all colour flags are 0). Most of that is stripping off the last two characters so might be better to use a helper column and two formulae (but much shorter overall).
This part:
=IF(B2=1,B$1&", ","")&IF(C2=1,C$1&", ","")&IF(D2=1,D$1&", ","")&IF(E2=1,E$1&", ","")
may be extended with further IF statements to cover more than four colours.
Were the latter version in R2 then the last two characters (comma space) may be stripped with:
=LEFT(R2,LEN(R2)-2)
A VBA version (copy/paste to a regular code module in your workbook)
Function Colors(names, flags)
Dim rv, i
rv = ""
For i = 1 To names.Cells.Count
If flags(i) = 1 Then rv = rv & _
IIf(Len(rv) > 0, ", ", "") & names(i)
Next i
Colors = rv
End Function
Usage:
=Colors($B$1:$J$1,B2:J2)
Assuming your color names are in B1:J1 and first row of 1/0 is in B2:J2

Return RGB values from Range.Interior.Color (or any other Color Property)

I was trying to incrementally change the background color of a cell to black, and I found that the Range.Interior.Color method returns a Long which is seemingly arbitrary. Looking at the documentation on MSDN, there is nearly nothing about what this number represents. Is there a way to return the RGB value from this long. I effectively need the opposite of the RGB(red, green, blue) function.
That "arbitrary" number is a mathematical combination of the RGB values (B256^2 + G256 + R) and a conversion of the hex color value to a decimal number (base 16 to base 10), depending on which way you want to look at it. Just different bases. Below is the method I use in the XLAM addin file I wrote for Excel. This method has come in handy many times. I have included the documentation in my addin file.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Function Color
' Purpose Determine the Background Color Of a Cell
' #Param rng Range to Determine Background Color of
' #Param formatType Default Value = 0
' 0 Integer
' 1 Hex
' 2 RGB
' 3 Excel Color Index
' Usage Color(A1) --> 9507341
' Color(A1, 0) --> 9507341
' Color(A1, 1) --> 91120D
' Color(A1, 2) --> 13, 18, 145
' Color(A1, 3) --> 6
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function Color(rng As Range, Optional formatType As Integer = 0) As Variant
Dim colorVal As Variant
colorVal = rng.Cells(1, 1).Interior.Color
Select Case formatType
Case 1
Color = WorksheetFunction.Dec2Hex(colorVal, 6)
Case 2
Color = (colorVal Mod 256) & ", " & ((colorVal \ 256) Mod 256) & ", " & (colorVal \ 65536)
Case 3
Color = rng.Cells(1, 1).Interior.ColorIndex
Case Else
Color = colorVal
End Select
End Function
good to see that Mr Wyatt uses the fast method of color to RGB
R = C Mod 256
G = C \ 256 Mod 256
B = C \ 65536 Mod 256
which is many times faster than those using hex str with left mid right
that some recommend
Short Answer:
There is no built in functionality for this. You must write your own function.
Long Answer:
The long that is returned from the Interior.Color property is a decimal conversion of the typical hexidecimal numbers that we are used to seeing for colors in html e.g. "66FF66". Additionally the constant xlNone (-4142) can be passed to set cell to have no color in the background, however such cells are marked white RGB(255, 255, 255) from the Get property. Knowing this, we can write a function that returns one or all of the appropriate RGB values.
Luckily, a kind Mr. Allan Wyatt has done just that here!
Determining the RGB Value of a Color
The other answer did not work for me. I found that:
R = C And 255
G = C \ 256 And 255
B = C \ 256 ^ 2 And 255
and it worked properly.
This is another way to skin the cat
'
' Type definition in declarations
'
Type RGBcolor
r As Long
g As Long
b As Long
End Type
'
' Inverse RGB function
'
Function GetRGB(ByVal x As Long) As RGBcolor
With GetRGB
.r = x Mod 256
x = x \ 256
.g = x Mod 256
x = x \ 256
.b = x Mod 256
End With
End Function
'
' Sub to test the GetRGB function
'
Sub test(x As Long)
Dim c As RGBcolor
c = GetRGB(x) ' returns RGB values: c.r, c.g, c.b
Debug.Print "Original", "Red", "Green", "Blue", "Recombined value"
Debug.Print x, c.r, c.g, c.b, RGB(c.r, c.g, c.b)
End Sub
'
'
***** IMMEDIATE WINDOW *****
test 1000
Original Red Green Blue Recombined value
1000 232 3 0 1000
Should note, for the hex values, if you're exporting out to HTML you're going to get quirks too.
Ideally you'd create the hex string from the individual colours, rather than returning a hex from the ColorVal number.
The reason being you can get some invalid hex numbers if the cell is a 'pure' colour like green/blue
RED - RGB(255,0,0) returns 'FF' - it should return 'FF0000'
BLUE - RGB(0,0,255) returns 'FF00000' - it should return '0000FF'
enter image description here
If you used these to create HTML/CSS colour output, you'd get RED for any blue cells.
I modified the script to assemble each two character hex 'chunk' based on the RGB values, with a UDF that just pads with a leading 0 where output of one character is returned ( hopefully if you're reading this, you can make something similar )
Color = ZeroPad(Hex((colorVal Mod 256)), 2) & ZeroPad(Hex(((colorVal \ 256) Mod 256)), 2) & ZeroPad(Hex((colorVal \ 65536)), 2)
--Edit : forgot to include the code for the UDF...
Function ZeroPad(text As String, Cnt As Integer) As String
'Text is the string to pad
'Cnt is the length to pad to, for example ZeroPad(12,3) would return a string '012' , Zeropad(12,8) would return '00000012' etc..
Dim StrLen As Integer, StrtString As String, Padded As String, LP As Integer
StrLen = Len(Trim(text))
If StrLen < Cnt Then
For LP = 1 To Cnt - StrLen
Padded = Padded & "0"
Next LP
End If
ZeroPad = Padded & Trim(text)
ENDOF:
End Function
BTW - If you want the hex codes as displayed in the form editor ( which inexplicably has it's own standard , apart from the normal HTML Hex Colours )
Case 4 ' ::: VBA FORM HEX :::
Color = "&H00" & ZeroPad(Hex((colorVal \ 65536)), 2) & ZeroPad(Hex(((colorVal \ 256) Mod 256)), 2) & ZeroPad(Hex((colorVal Mod 256)), 2) & "&"
Mark Balhoff´s VBA script works fine. All credits go to him.
In case you´d like to get the color codes/indexes of conditionally formatted cells as well, the code may be amended like this:
'----------------------------------------------------------------
' Function Color
' Purpose Determine the Background Color Of a Cell
' #Param rng Range to Determine Background Color of
' #Param formatType Default Value = 0
' 0 Integer color of cell, not considering conditional formatting color
' 1 Hex color of cell, not considering conditional formatting color
' 2 RGB color of cell, not considering conditional formatting color
' 3 Excel Color Index color of cell, not considering conditional formatting color
' 4 Integer "real" visible color of cell (as the case may be the conditional formatting color)
' 5 Hex "real" visible color of cell (as the case may be the conditional formatting color)
' 6 RGB "real" visible color of cell (as the case may be the conditional formatting color)
' 7 Excel Color Index "real" visible color of cell (as the case may be the conditional formatting color)
' Usage Color(A1) --> 9507341
' Color(A1, 0) --> 9507341
' Color(A1, 1) --> 91120D
' Color(A1, 2) --> 13, 18, 145
' Color(A1, 3) --> 6
'-----------------------------------------------------------------
Function Color(rng As Range, Optional formatType As Integer = 0) As Variant
Dim colorVal As Variant
Select Case formatType
Case 0 To 3
colorVal = Cells(rng.Row, rng.Column).Interior.Color
Case 4 To 7
colorVal = Cells(rng.Row, rng.Column).DisplayFormat.Interior.Color
End Select
Select Case formatType
Case 0
Color = colorVal
Case 1
Color = Hex(colorVal)
Case 2
Color = (colorVal Mod 256) & ", " & ((colorVal \ 256) Mod 256) & ", " & (colorVal \ 65536)
Case 3
Color = Cells(rng.Row, rng.Column).Interior.ColorIndex
Case 4
Color = colorVal
Case 5
Color = Hex(colorVal)
Case 6
Color = (colorVal Mod 256) & ", " & ((colorVal \ 256) Mod 256) & ", " & (colorVal \ 65536)
Case 7
Color = Cells(rng.Row, rng.Column).DisplayFormat.Interior.ColorIndex
End Select
End Function
Short Answer
Drop these 3 self-explanatory one-liner's into a module, then use them in VBA or worksheet formulas:
Function rr(rgbCode): rr = rgbCode Mod 256: End Function
Function g(rgbCode): g = (rgbCode \ 256) Mod 256: End Function
Function b(rgbCode): b = rgbCode \ 65536: End Function
(I couldn't use a single R for red's function name since it's reserved for use in the Goto F5 & Name CTRL+F3 dialogs.)

Office Open XML satMod results in more than 100% saturation

I'm trying to calculate the satMod (saturation modulation) for something like the following:
<a:srgbClr val="58CAFF">
<a:satMod="300000"/>
</a:srgbClr>
Section 20.1.2.3.27 of the EMCA-376 spec says of the <satMod> element: "This element specifies the input color with its saturation modulated by the given percentage. A 50% saturation modulate reduces the saturation by half. A 200% saturation modulate doubles the saturation."
The problem I'm having is that many colors are already saturated enough that increasing the saturation by 300% (the 300000 in there corresponds to 300%) puts it way out of the 0-100% range. I have been simply capping the saturation at 100% but my results are pretty different from what Excel does.
It seems there is some special magic happening here in cases where the saturation should overflow. Anyone know what Office/Excel does in this case?
I found essentially the same question here: http://social.msdn.microsoft.com/Forums/en-US/oxmlsdk/thread/040e0a1f-dbfe-4ce5-826b-38b4b6f6d3f7
The answer indicated that the srgb color should be converted to linear rgb first and then to hsl before the saturation is modified. For me that hasn't solved the problem.
That was me that asked that original question. I have since figured it out. With ever single color transformations (satMod, redMod, lumMod, etc.), you have to clamp the value to within sRGB 0,0,0 or 255,255,255 (or 1.0,1.0,1.0). Meaning if your satMod modifies your color by 300% and the result is a color value above 255, clamp it to 255 (or 1.0). With that resulting color, you can then apply other color transforms if they are in your color srgbClr or other color spaces.
This is what I do in an example like yours.
Convert color to HSL space (these kinds of RGB->HSL routines are common on Bing/Google in a look up).
Send in that color and the satMod to a routine like this:
Public Sub modulateHSL(ByVal c As HSL, ByVal val As System.Double)
Select Case c
Case HSL.Hue
Hue = Hue * val
If Hue = 0.0 Then
If val >= 1.0 Then
Hue = val - Fix(val)
End If
Else
Hue = Hue - Fix(Hue)
End If
Case HSL.Saturation
Saturation = Saturation * val
Case HSL.Luminance
Luminance = Luminance * val
End Select
HSL_To_sRGB(Hue, Saturation, Luminance)
Clamp_sARGB()
End Sub
At the end of this routine, you'll notice two calls 1) HSL_To_sRGB(Hue, Saturation, Luminance) and 2) Clamp_sARGB(). The first one converts back to sRGB space and the second one clamps the RGB values, like this:
Public Sub Clamp_sARGB()
If Red <= 0.0 Then Red = 0.0 Else If Red >= 1.0 Then Red = 1.0
If Green <= 0.0 Then Green = 0.0 Else If Green >= 1.0 Then Green = 1.0
If Blue <= 0.0 Then Blue = 0.0 Else If Blue >= 1.0 Then Blue = 1.0
If Alpha <= 0.0 Then Alpha = 0.0 Else If Alpha >= 1.0 Then Alpha = 1.0
sRGB_To_HSL(Red, Green, Blue)
End Sub
Note there is no need to use Linear RGB in the case where you're only modifying the saturation. I maintain both RBG and HSL spaces in class level fields (RGB in 0-1 space), so that's why you see sRGB_To_HSL(Red, Green, Blue) at the end of that routine.
Now this is for DrawingML as it appears in PowerPoint. Excel may be different (there is a long drawn out thread here that deals with charts that may also have your answer). Keep in mind that modifying saturation can also modify luminance depending on how you coded your routine. If that's the case, you'll want to use the original luminance when converting back from HSL to RGB.
If none of this is working for you, can you put an example XLSX on a
DropBox point somewhere with what is going on, what you're expecting, etc.?

Programatically step through 24 bit color spectrum, get x amount of average colors

Yes, I AM trying to re-invent the wheel. :-) . I am doing my own image compression, (testing some ideas for transmitting parts of images over tcp). Anyway... I am trying to step through 24 bit rgb color, get a complete linear range, and (step through) that range at x intervals.
I am trying to get the average 99 colors over the complete spectrum. (24bit / 99) = 167488.6363636364 , so at 16K interval I want to pic a color for my 99 color palette.
I am having trouble understanding how RGB really works... It seems the is NO linear range..., or is there...?
I am currently doing the following:
var_interval = (255 * 255 * 255) / 99
For r = 0 To 255
For g = 0 To 255
For b = 0 To 255
If var_counter = var_interval Then
objWriter.Write(r & "," & g & "," & b)
End If
var_counter += 1
Next
Next
Next
I am getting my colors, but this step does not generate "scaling" colors if you will.
Any ideas?
There certainly is a way to iterate through the color spectrum, but whether you go this approach is your own choice :). You can make use of the HSL color space (Hue, saturation, and lightness) instead of RGB (red, green, blue). The hue represents which color (ranging from 0 to 360), the saturation is how much of that color your want (0 to 100), and the lightness is how bright you want it.
So, to answer your question, you can take 360/99 as your sampling rate from the hue, choose a consistent value and intensity that you'd want and then convert that to RGB space to display it. For the conversion see:
http://web2.clarkson.edu/class/image_process/RGB_to_HSI.pdf
and for information on HSL color space see:
http://en.wikipedia.org/wiki/HSL_and_HSV

Excel 2007 conditional formatting - how to get cell color?

Let's assume i have the following range from (a1:c3)
A B C
1 -1 1 1
2 -1 0 0
3 0 0 1
Now i have selected the following range, and formatted it using Conditional Formatting (using default red yellow green color scale).... now range colors became
A B C
1 Green Red Red
2 Green Yellow Yellow
3 Yellow Yellow Red
Now I want to ask the color of any cell in the range, for example MsgBox Range("A1").Interior.Color
but it does not say that it is Green, why? Plz can you help me?
Range("A1").Interior.Color always returns 16777215
Range("A1").Interior.ColorIndex always returns -4142
(no matter whether the color of A1 is red, blue, green, ...)
Range("A1", "C3").FormatConditions.Count
this one returns always 0, why?
.Interior.Color returns the "real" color, not the conditionally-formatted color result.
#sss: It's not available via the API.
The best you can do is to test the same conditions you used in the conditional formatting.
To avoid this resulting in duplicate code, I suggest moving your conditional criteria to a UDF. Examples:
Function IsGroup1(ByVal testvalue As Variant) As Boolean
IsGroup1 = (testvalue < 0)
End Function
Function IsGroup2(ByVal testvalue As Variant) As Boolean
IsGroup1 = (testvalue = 0)
End Function
Function IsGroup3(ByVal testvalue As Variant) As Boolean
IsGroup1 = (testvalue > 0)
End Function
Then use these formulas in your Conditional formatting:
=IsGroup1(A1)
=IsGroup2(A1)
=IsGroup3(A1)
Then your code, rather than looking at the color of the cells, looks to see if the condition is met:
If IsGroup1(Range("$A$1").Value) Then MsgBox "I'm red!"
You need to refer the <Cell>.FormatConditions(index that is active).Interior.ColorIndex to retrieve the conditional formatting color of a cell.
You may refer to the below link for an example:
http://www.xldynamic.com/source/xld.CFConditions.html#specific
As a follow up to #richardtallent (sorry, I couldn't do comments), the following link will get you a function that returns you the color index by evaluating the conditional formatting for you.
http://www.bettersolutions.com/excel/EPX299/LI041931911.htm
To get the color of a cell in a Range, you need to reference the individual cell inside the array in the form of Range("A1","C3").Cells(1,1) (for cell A1). The Excel help is pretty good if you look up the name of the property you're having issues with.
Also, Excel 2007 uses Integers for its color types, so your best bet is to assign the color index to an integer, and using that throughout your program. For your example, try:
Green = Range("A1","C3").Cells(1,1).Interior.Color
Yellow = Range("A1","C3").Cells(1,3).Interior.Color
Red = Range("A1","C3").Cells(2,1).Interior.Color
And then to switch the colors to all red:
Range("A1","C3").Interior.Color = Red
Again, check the Excel help for how to use Cells([RowIndex],[ColumnIndex]).
If the above doesn't work for you, check to see what .Interior.PatternColorIndex is equal to. I typically leave it set at xlAutomatic (solid color), and it could be set to something else if the color isn't changing.
According to XlColorIndex Enumeration ColorIndex=-4142 means No color
As to why this happens I'm clueless. The returned value seems to be the decimal representation of the RGB value. The improved version of this script to decrypt the value into hex RGB notation
Function RGB(CellRef As Variant)
RGB = ToHex(Range(CellRef).Interior.Color)
End Function
Function ToHex(ByVal N As Long) As String
strH = ""
For i = 1 To 6
d = N Mod 16
strH = Chr(48 + (d Mod 9) + 16 * (d \ 9)) & strH
N = N \ 16
Next i
strH2 = ""
strH2 = Right$(strH, 2) & Mid$(strH, 3, 2) & Left$(strH, 2)
ToHex = strH2
End Function
It doesn't appear that the "Conditional Format"-color is available programmatically. What I'd suggest that, instead, you write a small function that calculates cell color, and then just set a macro to run it on the active cell whenever you've edited the value. For example (sorry for the psuedo-code - I'm not a VBA expert anymore):
Function GetColorForThisCell(Optional WhatCell as String) as Int
If WhatCell="" Then WhatCell = ActiveCell
If Range(WhatCell).value = -1 then GetColorForThisCell = vbGreen
If Range(WhatCell).value = 0 then GetColorForThisCell = vbYellow
If Range(WhatCell).value = 1 then GetColorForThisCell = vbRed
End Function
Sub JustEditedCell
ActiveCell.color = GetColorForThisCell()
End Sub
Sub GetColorOfACell(WhatCell as string)
Msgbox(GetColorForThisCell(WhatCell) )
End Sub
Though you wouldn't be able to use the built-in Excel Conditional Formatting, this would accomplish the same thing, and you'd be able to read the color from code. does this make sense?
since i may have more than three different colors in a time... i didn't find any good way of handling this with conditional formatting's default colors... i did it this way. then whenever i ask the color of the cell, i retrieve the correct color!
for (int t = 0; t < d_distinct.Length; t++ )
{
Excel.FormatCondition cond =
(Excel.FormatCondition)range.FormatConditions.Add(
Excel.XlFormatConditionType.xlCellValue,
Excel.XlFormatConditionOperator.xlEqual,
"="+d_distinct[t],
mis, mis, mis, mis, mis);
cond.Interior.PatternColorIndex =
Excel.Constants.xlAutomatic;
cond.Interior.TintAndShade = 0;
cond.Interior.Color = ColorTranslator.ToWin32(c[t]);
cond.StopIfTrue = false;
}
d_distinct holds all the distinct values in a range... c is a Color[] which holds distinct colors for every distinct value! this code can easily be translated to vb!

Resources