Interior.Color属性反转颜色?

时间:2016-02-06 13:32:20

标签: excel matlab

我编写了一段代码,允许我检索excel工作簿中特定单元格的着色颜色。我已成功检索RGB整数值,方法是使用MATLAB的actxserver启动COM服务器,然后访问该特定Cell对象的Interior Object的Color Property。然后我获得了该整数的等效RGB三元组,因此我可以稍后在MATLAB中使用它进行绘图。

为了测试我的代码是否正常工作,我设计了以下测试:我创建了一个名为colorTest.xlsx的Excel工作簿,其中包含8种不同的颜色:

enter image description here

然后我运行我的MATLAB代码,它提取B列的每个单元格的颜色信息。我应该得到一个带有相同垂直顺序颜色的图和一个带有int值和每种颜色的RGB三元组的表。

然而出乎意料的事情发生了!查看结果:

enter image description here

请注意,从Color属性获取的整数值并不总是与原始单元格的颜色匹配,对于黑色,白色,绿色和洋红色,整数值是正确的,但对于所有其他颜色,情况并非如此。例如,您可以看到Excel上的红色,输出int和RGB三元组对应蓝色。

我添加了下表,其中包含了我应该得到的正确结果,供参考:

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

我使用this RGB Int Calculator为每种颜色获取了正确的整数值。

如果我们比较两个表,我们可以推断出红色和蓝色通道被反转

代码:

我执行以运行测试的函数称为getCellColor。看看代码:

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

(*)该指令负责恢复颜色整数。

注意:下面介绍的功能不会导致问题,因为他们不参与获取颜色整数(它们仅用于辅助任务) )。我已将此信息仅用于完整性。

在此过程中,我使用MATLAB的 iofun 文件夹中的三个私有函数,它们是:validpathxlsCleanup和{{1} }。我只是将它们复制到项目文件夹中名为 private 的文件夹中。

最后,为了从颜色整数中获取RGB三元组,我使用了一个我在网上找到的this other function改编的函数。

以下是我的openExcelWorkbook功能的代码:

int2rgb

我试图弄清楚这一点,但我真的不知道发生了什么。我做了一些研究,没有太多运气,但this postthis other post引起了我的注意。也许这与我的问题有关。

那么Interior.Color属性是否真的颠倒了颜色?

如果是这种情况,我应该将此视为正常行为还是这是一个错误?

下载链接:

我已将整个项目打包到 .zip 文件上并上传,因此您可以立即在您的计算机上运行此测试。下载文件并解压缩。

getCellColor.zip

4 个答案:

答案 0 :(得分:5)

这里没有“正确”或“错误”,Matlab和Excel只是对颜色进行不同的编码。您需要在代码中考虑到这一点。

我能找到的最接近官方来源的是这篇MSDN文章,大约有一半的内容看到“蓝色”编码的例子

MSDN article

  

以下示例将选定单元格的内部设置为蓝色。   Selection.Interior.Color = 16711680
  Selection.Interior.Color =&amp; HFF0000
  Selection.Interior.Color =&amp; O77600000
  Selection.Interior.Color = RGB(0,0,255)

答案 1 :(得分:4)

我的第一个想法是检查频道顺序RGB与BGR。

您可以使用int2rgb来简化typecast功能。以下是使用您发布的值的示例:

clrs = [0; 16777215; 16711680; 65280; 255; 65535; 16711935; 16776960]
for i=1:numel(clrs)
    bgra = typecast(int32(clrs(i)), 'uint8')
end

输出:

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

答案 2 :(得分:3)

您的int2rgb方法会反转R和B.替换它们,您将获得正确的转换。 Interior.Color属性使用R是最不重要的约定,而您使用的FileExchange函数使用相反的约定。

要从int转换为RGB:

B = floor(colorInt / (256*256));
G = floor((colorInt - B*256*256)/256);
R = colorInt - B*256*256 - G*256;
colorRGB = [R G B];

要从RGB转换为int:

colorInt = colorRGB * [1 256 256*256]';

答案 3 :(得分:2)

从RGB颜色模型的MSDN article

  

RGB颜色模型用于指定颜色。这个模型   指定0到0的红色,绿色和蓝色的强度   255,0(零)表示最小强度。的设置   使用此颜色将三种颜色转换为单个整数值   公式:

     

RGB值=红色+(绿色* 256)+(蓝色* 256 * 256)

正如chris neilsen answer中所建议的那样,没有&#34;对&#34;或&#34;错误&#34;在颜色编码方面。微软已选择这种特殊的方式来编码颜色,原因只有他们知道,我应该坚持下去。

因此我得到的RGB值完全正确。

在下表中,我已经在MSDN文章中提供了我在MATLAB中获得的RGB值,它们是完美的匹配。

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