VBA:使用默认颜色提取图表中线条的RGB值

Ali*_*ice 10 excel vba colors excel-vba

问题

我想知道如何读取图表中自动指定颜色的当前RGB值,即使这需要将颜色冻结到其当前值(而不是在主题更改时更新它们,重新排序系列等)

用例

我的实际用例是我想让数据标签与折线图中的线条/标记的颜色相匹配.如果我通过方案或显式RGB值明确设置系列的颜色,这很容易,例如

' assuming ColorFormat.Type = msoColorTypeRGB
s.DataLabels.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB= _
s.Format.Line.ForeColor.RGB
Run Code Online (Sandbox Code Playgroud)

但是,在自动分配系列颜色时执行此操作会生成白色标签.更具体地说,以下两个等式都成立

s.Format.Line.ForeColor.Type = msoColorTypeRGB 
s.Format.Line.ForeColor.RGB = RGB(255,255,255)  ' White
Run Code Online (Sandbox Code Playgroud)

然而,当然这条线不是白色的,而是来自主题的自动指定颜色.这表明颜色是自动分配的

s.Border.ColorIndex = xlColorIndexAutomatic
Run Code Online (Sandbox Code Playgroud)

我想有意义的是,颜色不会与问题系列一起存储.即使将索引存储到颜色方案中也通常不起作用,因为如果添加了另一个数据系列或有人重新排序数据,则Excel需要更改颜色.如果有某种方法可以自动识别当前的RGB值,我还是会喜欢它.

一个丑陋的解决方法

对于具有6个或更少条目的图表,一个简单的解决方法是利用主题颜色按顺序分配的事实,所以我可以做(例如)

chrt.SeriesCollection(1).DataLabels.Format.TextFrame2.TextRange.Font.Fill.ForeColor.ObjectThemeColor _
= msoThemeColorAccent1
Run Code Online (Sandbox Code Playgroud)

据推测,这可以扩展到TintAndShade一旦主题用尽后用于区分条目,但这是一个丑陋的黑客.

研究

有人(如何提取主题颜色)主要问同样的问题在这里,但它从来没有回答.有几个来源建议将已知主题颜色转换为RGB值的方法(例如此处此处),但这只是问题; 我不知道这种颜色是先验的,除了"这条线目前的颜色是什么".

Dav*_*ens 9

所以这很有趣.我使用所有默认值创建折线图,然后运行此过程:

在此输入图像描述

Sub getLineCOlors()
Dim cht As Chart
Dim srs As Series
Dim colors As String
Dim pt As Point

Set cht = ActiveSheet.ChartObjects(1).Chart

For Each srs In cht.SeriesCollection
    With srs.Format.Line
    colors = colors & vbCrLf & srs.Name & " : " & _
            .ForeColor.RGB
    End With

Next

Debug.Print "Line Colors", colors

End Sub
Run Code Online (Sandbox Code Playgroud)

然后立即窗口显示:

Line Colors   
Series1 : 16777215
Series2 : 16777215
Series3 : 16777215
Run Code Online (Sandbox Code Playgroud)

但事实显然并非如此.很明显,它们都是不同的颜色.如果,而不是.RGB.ObjectThemeColor,那么我得到所有0,通过观察图表,这同样也是明显错误的!

Line Colors   
Series1 : 0
Series2 : 0
Series3 : 0
Run Code Online (Sandbox Code Playgroud)

现在这里有趣的地方:

如果在创建图表后我更改了系列颜色(或者通过分配给相同的ThemeColors而保持不变),则该函数显示有效的RGB:

Line Colors   
Series1 : 5066944
Series2 : 12419407
Series3 : 5880731
Run Code Online (Sandbox Code Playgroud)

就像Excel(和PowerPoint /等)在线图上完全无法识别自动分配的颜色一样.一旦指定了颜色,它就可以读取颜色.

注意:折线图是挑剔的,因为你没有a .Fill,而是a .Format.Line.ForeColor(和.BackColor)和IIRC也有一些其他的怪癖,就像你可以选择一个单独的并改变它的填充颜色,然后这会影响视觉上一个线段的外观等...

这仅限于折线图吗? 也许.我过去的经历说"可能",虽然我无法说这是一个错误,但它肯定是一个错误.

如果我在柱形图上运行类似的过程 - 再次仅使用自动分配的默认颜色,

Sub getCOlumnColors()

Dim cht As Chart
Dim srs As Series
Dim colors As String
Dim pt As Point

Set cht = ActiveSheet.ChartObjects(2).Chart

For Each srs In cht.SeriesCollection

    With srs.Format.Fill
    colors = colors & vbCrLf & srs.Name & " : " & _
            .ForeColor.RGB
    End With

Next

Debug.Print "Column Colors", colors

End Sub
Run Code Online (Sandbox Code Playgroud)

然后我得到看似有效的RGB值:

Column Colors 
Series1 : 12419407
Series2 : 5066944
Series3 : 5880731
Run Code Online (Sandbox Code Playgroud)

但是:它仍然无法识别有效ObjectThemeColor.如果我改变.RGB那么这个输出:

Column Colors 
Series1 : 0
Series2 : 0
Series3 : 0
Run Code Online (Sandbox Code Playgroud)

因此,基于这些观察,肯定无法访问自动分配的颜色格式的ObjectThemeColor和/或.RGB属性.

正如蒂姆·威廉姆斯所证实的那样,早在2005年这是一个错误,至少与RGB有关,可能是这个错误随着ObjectThemeColor等转移到了Excel 2007+ ......它不太可能被解决了时间很快,所以我们需要一个黑客解决方案:)

更新的解决方案

结合上面的两种方法!将每个系列从行转换为xlColumnClustered,然后从中查询颜色属性.Fill,然后将系列图表类型更改回其原始状态.这可能比尝试利用顺序索引更可靠(如果用户重新排序系列,则根本不可靠,例如,"Series1"在索引3处,等等)

Sub getLineColors()
Dim cht As Chart
Dim chtType As Long
Dim srs As Series
Dim colors As String

Set cht = ActiveSheet.ChartObjects(1).Chart

For Each srs In cht.SeriesCollection
    chtType = srs.ChartType
    'Temporarily turn this in to a column chart:
    srs.ChartType = 51
    colors = colors & vbCrLf & srs.Name & " : " & _
            srs.Format.Fill.ForeColor.RGB
    'reset the chart type to its original state:
    srs.ChartType = chtType
Next

Debug.Print "Line Colors", colors

End Sub
Run Code Online (Sandbox Code Playgroud)