VBA 返回文本的 RGB 颜色

4

我能够返回使用自定义颜色选取的Word文档中文字的RGB颜色,但是无法返回使用标准颜色选取的颜色。我最初使用了以下代码:

Function GetRGBTest(Colour As Long) As String

GetRGBTest = "rgb(" & (Colour Mod 256) & "," & ((Colour \ 256) Mod 256) & "," & ((Colour \ 256 \ 256) Mod 256) & ")"

End Function

Sub TestColour()

MsgBox GetRGBTest(Selection.Font.Color)

End Sub

在使用标准颜色时,selection.font.color 返回一个负值,且 RGB 值不正确。

我尝试编辑它,使其如下所示(其中 Dict 是颜色索引和相应 RGB 值的列表):

Function GetRGBTest(Colour As Long, colInd As Integer) As String

If Colour > 0 Then
    GetRGBTest = "rgb(" & (Colour Mod 256) & "," & ((Colour \ 256) Mod 256) & "," & ((Colour \ 256 \ 256) Mod 256) & ")"
Else
    colInd = LTrim(Str(colInd))
    GetRGBTest = Dict.Item(colInd)
End If
End Function

Sub TestColour()

MsgBox GetRGBTest(Selection.Font.Color, Selection.Font.ColorIndex)

End Sub

虽然我认为ColorIndex返回的值与标准颜色无关。

有人知道如何将这些值转换为RGB值吗?


如果RGB值超出其范围,您将无法接收它。 - user2140173
这篇文章表明似乎不可能,这太奇怪了。 - enderland
有点令人失望。我想当出现这种情况时,我需要添加一个警告信息。 - user2554448
好的,RGB 颜色由红、绿、蓝三种光组成。如果你使用非标准(非 RGB)样式的文本,你如何期望从中返回 RGB 颜色? - user2140173
2个回答

1
感谢AndASM对这个问题的出色描述。我正在编写一个使用Win32::OLE库读取Word文档的Perl程序。我的目标是以不同的格式输出文档,当我遇到这些索引值时,我陷入了深深的困境。在得到正确的指导后,我最终在Perl中构建了一个哈希查找来处理这些索引。我去掉了看起来无用的十六进制字符串(比如&H00字节),并构建了一个搜索字符串,通过这个哈希映射传递时返回RGB值。
my %indexedColors = (
    "ff0000" => [0,0,0],
    "dcffff" => [255,255,255],
    "dcf2ff" => [242,242,242],
    "dcd9ff" => [217,217,217],
    "dcbfff" => [191,191,191],
    "dca6ff" => [166,166,166],
    "dc80ff" => [128,128,128],
    "ddffff" => [0,0,0],
    "ddff80" => [127,127,127],
    "ddffa6" => [89,89,89],
    "ddffbf" => [64,64,64],
    "ddffd9" => [38,38,38],
    "ddfff2" => [13,13,13],
    "deffff" => [238,236,225],
    "dee6ff" => [221,217,195],
    "debfff" => [196,188,150],
    "de80ff" => [148,138,84],
    "de40ff" => [74,68,42],
    "de1aff" => [29,27,17],
    "dfffff" => [31,73,125],
    "dfff33" => [198,217,241],
    "dfff66" => [141,179,226],
    "dfff99" => [84,141,212],
    "dfbfff" => [23,54,93],
    "df80ff" => [15,36,62],
    "d4ffff" => [79,129,189],
    "d4ff33" => [219,229,241],
    "d4ff66" => [184,204,228],
    "d4ff99" => [149,179,215],
    "d4bfff" => [54,95,145],
    "d480ff" => [36,64,97],
    "d5ffff" => [192,80,77],
    "d5ff33" => [242,219,219],
    "d5ff66" => [229,184,183],
    "d5ff99" => [217,149,148],
    "d5bfff" => [148,54,52],
    "d580ff" => [99,36,35],
    "d6ffff" => [155,187,89],
    "d6ff33" => [221,217,195],
    "d6ff66" => [214,227,188],
    "d6ff99" => [194,214,155],
    "d6bfff" => [118,146,60],
    "d680ff" => [79,98,40],
    "d7ffff" => [128,100,162],
    "d7ff33" => [229,223,236],
    "d7ff66" => [204,192,217],
    "d7ff99" => [178,161,199],
    "d7bfff" => [95,73,122],
    "d780ff" => [64,49,82],
    "d8ffff" => [75,172,198],
    "d8ff33" => [218,238,243],
    "d8ff66" => [182,221,232],
    "d8ff99" => [146,205,220],
    "d8bfff" => [49,132,155],
    "d880ff" => [33,88,104],
    "d9ffff" => [247,150,70],
    "d9ff33" => [253,233,217],
    "d9ff66" => [251,212,180],
    "d9ff99" => [250,191,143],
    "d9bfff" => [227,108,10],
    "d980ff" => [152,72,6],
);

希望没有可怜的灵魂需要深入微软的向后兼容性,但以防万一。


1
我无法快速地通过谷歌找到相关资料,但如果我没记错的话,Word将返回三种可能的数据格式以表示字体颜色。
RGB 格式
如果高位字节为 &H00,则剩下的三个字节分别代表红、绿和蓝。这是您熟悉并已处理的格式。
自动颜色
如果值为 &HFF000000(也称为 -16777216),则颜色设置为自动,并通常为黑色。否则,它会使用文档的默认颜色。
神秘的第三种负数格式
如果高位字节的高位半字节为 &HD,也就是说,十六进制数字的第一位为 D,则使用 Word 的颜色方案格式。
例如,您可能会得到&D500FFFF。在我们的示例中,第二个半字节&H5与枚举WdThemeColorIndex中的一个值相匹配。如果您创建一个翻译表,将此枚举转换为MsoThemeColorSchemeIndex枚举,则可以在文档的ActiveDocument.DocumentTheme.ThemeColorScheme集合中查找基本颜色。您问为什么有两个具有不同索引号的枚举表示同一件事情?好问题!继续...
然而,这并不是故事的结尾!还有那最后三个剩余字节需要担心!下一个是高字的低字节,我认为很容易。我相信它总是&H00。如果您遇到该字节的其他值...祝您好运。
最后两个字节表示使值变暗或变亮的百分比(分别)。其中&FF或255表示没有变化,&h00表示100%。在颜色选择器中看到类似“强调 2,更亮 60%”之类的内容时也是如此。顺便说一下,这将是&HD500FF66,其中5是强调 2 的索引,&H66是较轻字节中的60%。
因此,这里有一个不考虑更亮和更暗值的函数:
Public Function GetBasicRGB(color As Long) As String
  Dim colorIndexLookup
  Dim colorIndex As Integer
  Dim finalColor As Long
  colorIndexLookup = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 2, 1, 4, 3)
  colorIndex = colorIndexLookup( _
      ((color And &HF000000) / &H1000000) _
      + LBound(colorIndexLookup))
  finalColor = ActiveDocument.DocumentTheme.ThemeColorScheme(colorIndex)
  GetBasicRGB = "rgb(" & (finalColor And &HFF) & "," & _
      (finalColor / &H100 And &HFF) & "," & _
      ((finalColor And &HFF0000) / &H10000) & ")"
End Function

为了考虑颜色的轻重,我认为您需要将RGB值转换为HSL值,然后通过%较轻或较暗来修改L组件。最后再转换回RGB。但是我现在不想去弄清楚这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接