【问题标题】:Interior.Color Property inverts colors?Interior.Color 属性反转颜色?
【发布时间】:2016-05-16 11:03:39
【问题描述】:

我编写了一段代码,允许我检索 Excel 工作簿工作表中特定单元格的阴影颜色。通过使用 MATLAB 的actxserver 启动 COM 服务器,然后访问该特定单元对象的内部对象的Color Property,我已成功检索 RGB 整数值。然后我获得了该整数的等效 RGB 三元组,以便稍后在 MATLAB 中使用它进行绘图。

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

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

然而,意想不到的事情发生了!查看结果:

请注意,从 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 文件夹中的三个 private 函数,它们是:validpathxlsCleanupopenExcelWorkbook。我只是将它们复制到项目文件夹内名为 private 的文件夹中。

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

这是我的int2rgb 函数的代码:

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

我试图对此有所了解,但我真的不知道发生了什么。我做了一些研究,运气不佳,但this postthis other post 引起了我的注意。可能和我的问题有关。

那么 Interior.Color 属性真的会反转颜色吗?

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


下载链接:

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

getCellColor.zip

【问题讨论】:

  • 您现在可以在 Excel 调色板中进行更改吗?我发现这可能很有用。不幸的是,我自己没有 Matlab 来解决这个问题:link --- 您可以通过修改 Workbook 对象的 Colors 数组来更改默认调色板中的值。例如,要将 ColorIndex 值 3 引用的颜色更改为蓝色,请使用 ==> Workbooks("SomeBook.xls").Colors(3) = RGB(0,0,255)
  • 我从未见过 Interior.Color 的这个问题。我的猜测是你的 RGB-int 转换是倒退的。这就是我在设置 Interior.Color 时将 RGB 转换为 int 的方式:longColor = rgbColor * [1 256 256*256]';。适用于您喜欢的任何颜色。
  • 我现在检查了你的int2rgb 方法。它确实颠​​倒了 R 和 B。
  • @Naveh 确实,我知道我可以更改我的int2rgb 函数并修复颜色反转,但这不是我要问的(请阅读注释)。问题的根源远在此之前,可能与Excel的颜色编码有关。

标签: excel matlab


【解决方案1】:

您的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]';

【讨论】:

    【解决方案2】:

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

    您可以改用typecast 来简化int2rgb 函数。这是使用您发布的值的示例:

    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
    

    【讨论】:

      【解决方案3】:

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

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

      MSDN article

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

      【讨论】:

      • 这令人惊讶。我认为每个人的颜色编码都是一样的,就像一种标准。
      【解决方案4】:

      来自MSDN article RGB 颜色模型:

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

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

      正如chris neilsen answer 中所建议的,在颜色编码方面没有“正确”或“错误”。微软选择了这种特殊的颜色编码方式,原因只有他们知道,我应该坚持下去。

      所以我得到的 RGB 值是完全正确的。

      在下表中,我将 MSDN 文章中提供的 RGB 值包含在我在 MATLAB 中获得的值旁边,它们是完美匹配的。

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-08
        • 2016-03-28
        • 2021-09-23
        • 2013-07-24
        • 2011-06-05
        相关资源
        最近更新 更多