条件格式化与硬停止的颜色渐变

我有一个Excel表中有一个正负值的数据列。 我希望能够做的是应用条件格式(颜色渐变)从深绿色到浅绿色的正值,浅红色到深红色的负值。

但是,我似乎无法做到这一点。 如果我应用一个条件格式,例如最大值为零,零点为浅绿色,那么所有的负值也会变成浅绿色。 有没有办法使一个条件格式只适用一定的价值,而不是超越? 我可以类似地为负值创build条件格式,但是同样会将正值显示为浅红色。 如果我在同一张纸上,则具有最高优先级的胜者将获胜。

更新 :尽pipe这真的很难看,但我决定试图找出哪些单元格大于0(或者实际上是一个中点值,在这种情况下是1.33 ),哪些单元格更低,并将单元格引用明确地设置为这些单元格。 所以我尝试像这样定义的条件格式(正绿色标尺):

 <x:conditionalFormatting sqref="$E$5 $E$6 $E$10 $E$13 $E$15 $E$17 $E$18 $E$19 $E$22 $E$24 $E$25..." xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> <x:cfRule type="colorScale" priority="1"> <x:colorScale> <x:cfvo type="num" val="1.13330279612636" /> <x:cfvo type="num" val="1.91050388235334" /> <x:color rgb="d6F4d6" /> <x:color rgb="148621" /> </x:colorScale> </x:cfRule> </x:conditionalFormatting> 

像这样(负面的红色标尺):

 <x:conditionalFormatting sqref="$E$4 $E$7 $E$8 $E$9 $E$11 $E$12 $E$14 $E$16 $E$20 $E$21 $E$23 $E$26 $E$28 $E$29 $E$30..." xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> <x:cfRule type="colorScale" priority="1"> <x:colorScale> <x:cfvo type="num" val="0.356101709899376" /> <x:cfvo type="num" val="1.13330279612636" /> <x:color rgb="985354" /> <x:color rgb="f4dddd" /> </x:colorScale> </x:cfRule> </x:conditionalFormatting> 

这工作很好! 直到你尝试sorting的点(我在这张表上有一个自动filter),并且把单元格赋值搞砸了。 所以,现在我的值大于1.33 ,应该(并且)已经应用了绿色渐变规则,但是现在被红色渐变引用(因此最终呈现为淡红色)。

我尝试了相对和绝对单元格引用(即减去$ ),但似乎也没有工作。

我一直无法find一种方法来使用默认的Excel条件格式的工作。 可以在VBA中创build自己的条件格式化algorithm,以启用此function,但是:

 Sub UpdateConditionalFormatting(rng As Range) Dim cell As Range Dim colorValue As Integer Dim min, max As Integer min = WorksheetFunction.min(rng) max = WorksheetFunction.max(rng) For Each cell In rng.Cells If (cell.Value > 0) Then colorValue = (cell.Value / max) * 255 cell.Interior.Color = RGB(255 - colorValue, 255, 255 - colorValue) ElseIf (cell.Value < 0) Then colorValue = (cell.Value / min) * 255 cell.Interior.Color = RGB(255, 255 - colorValue, 255 - colorValue) End If Next cell End End Sub 

上面的代码将生成以下配色scheme,并且可以很容易地进行修改,以适应您想要的任何调色板:

渐变条件格式

您可以在macros中使用此代码,或将其放入Worksheet_Change事件并自动更新(请注意,在Worksheet_Change事件处理程序中安装时将失去撤消function):

 Sub Worksheet_Change(ByVal Target As Range) UpdateConditionalFormatting Range("A1:A21") End Sub 

我认为这将是相对容易的,但它花了更多的思想,并不是一个优雅的解决scheme。

假设你有vba背景,我会给你使用的方法 – 如果你需要编程的帮助,留下评论,我会提供支持。

假设:范围是sorting最小最大或最大 – 最小'这不会工作,否则

编写一个表格级别的macros,更新计算或select – 只要你想条件格式更新

在这个macros中,您将确定数据范围的上限和下限以及中点的位置

所以在上面的图片是

 LB = A1 UP = A21 MP = A11 

那么你只需要使用两个渐变w / an if语句你说中点不会是精确的,所以if语句将决定中点是属于上限还是下限

然后只是:

 Range(LB:MP).Select .......apply traditional conditional format 1 (CF1) Range(MP+1:UP).Select .......apply traditional conditional format 2 (CF2) or Range(LB:MP-1).Select .......apply traditional conditional format 1 Range(MP:UP).Select .......apply traditional conditional format 2 

我不会使用白色作为MP颜色,但是在CF1中,如果它是红色范围,我将使用浅红色至深红色,而CF2浅绿色至深绿色

– – – – – – – – – – – – – – – – – – – 编辑 – – – – – – —————————

我只是读你的sorting困境。

另一个解决scheme,我曾经使用,再次如果您需要编码支持,我可以尝试寻找我的旧代码

我对RGB使用了一个简单的回归(如果你只是去G或R,就更简单了),来为每个值实际分配一个颜色编号

 MP = (0,1,0) UP = (0,255,0) MP-1 = (1,0,0) LB = (255,0,0) 

如果逻辑与上面一样,再次使用相同的图表macros和MP

然后我只是遍历单元格和应用颜色

 if cellVal < MP then CellVal*Mr+Br 'r for red, M & B for slope & intercept if cellVal > MP then CellVal*Mg+Bg 'g for green, M & B for slope & intercept 

如果还不清楚,请告诉我,如果您需要帮助,可以提供相关代码。

-E

编辑2:

你可以,而且我会推荐,而不是遍历整个范围,只遍历可见范围 – 这将加速更多,你可以添加触发器到你的表/数据集的sort / filter命令 – 它如果您想要根据您的所有数据或仅仅是可见的数据来select色谱,那么您也可以自由select,而后者则可以做一些“酷”的事情,比如看上面的第95百分位,仍然看到颜色的差异,因为他们很可能都是G 250-255,难以辨别

在对我之前的回答发表评论之后,我不认为使用colorScale是可能的,因为您需要两个缩放比例或四个颜色(两者都不允许)。 你可以通过使用带公式的条件格式来创build你自己的。

使用这种方法,您可以使其工作,而无需VBA和任何分类或编辑工作表仍然工作。

我一起敲了一个(非常)粗糙的例子,说明这可能是如何工作的。 它有点粗糙,它会为每个值创build一个新的条件格式; 你可能更喜欢创build一个你感兴趣的范围(也许使用百分比),但这是一个起点。

大部分工作是通过以下两种方法完成的。 我已经给他们添加了一些总结评论,如果他们需要更多的解释,只是让我知道。

 /// <summary> /// Adds a conditional format to the sheet based on the value passed in /// </summary> /// <param name="value">The value going into the cell</param> /// <param name="minValue">The minimum value in the whole range of values going into the sheet</param> /// <param name="maxValue">The maximum value in the whole range of values going into the sheet</param> /// <param name="ignoreRangeLowValue">The lowest value in the mid-point. A value greater than or equal to this and less than or equal to the ignoreRangeHighValue will be unstyled</param> /// <param name="ignoreRangeHighValue">The highest value in the mid-point. A value greater than or equal to the ignoreRangeLowValue and less than or equal to this value will be unstyled</param> /// <param name="lowValuesMinColor">The colour of the lowest value below the mid-point</param> /// <param name="lowValuesMaxColor">The colour of the highest value below the mid-point</param> /// <param name="highValuesMinColor">The colour of the lowest value above the mid-point</param> /// <param name="highValuesMaxColor">The colour of the highest value above the mid-point</param> /// <param name="differentialFormats">A DifferentialFormats object to add the formats to</param> /// <param name="conditionalFormatting">A ConditionalFormatting object to add the conditional formats to</param> private static void AddConditionalStyle(decimal value, decimal minValue, decimal maxValue, decimal ignoreRangeLowValue, decimal ignoreRangeHighValue, System.Drawing.Color lowValuesMinColor, System.Drawing.Color lowValuesMaxColor, System.Drawing.Color highValuesMinColor, System.Drawing.Color highValuesMaxColor, DifferentialFormats differentialFormats, ConditionalFormatting conditionalFormatting) { System.Drawing.Color fillColor; if (value >= ignoreRangeLowValue && value <= ignoreRangeHighValue) return; if (value > ignoreRangeHighValue) { fillColor = GetColour(value, ignoreRangeHighValue, maxValue, highValuesMinColor, highValuesMaxColor); } else { fillColor = GetColour(value, minValue, ignoreRangeLowValue, lowValuesMinColor, lowValuesMaxColor); } DifferentialFormat differentialFormat = new DifferentialFormat(); Fill fill = new Fill(); PatternFill patternFill = new PatternFill(); BackgroundColor backgroundColor = new BackgroundColor() { Rgb = fillColor.Name }; patternFill.Append(backgroundColor); fill.Append(patternFill); differentialFormat.Append(fill); differentialFormats.Append(differentialFormat); ConditionalFormattingOperatorValues op = ConditionalFormattingOperatorValues.Between; Formula formula1 = null; Formula formula2 = null; if (value > maxValue) { op = ConditionalFormattingOperatorValues.GreaterThanOrEqual; formula1 = new Formula(); formula1.Text = value.ToString(); } else if (value < minValue) { op = ConditionalFormattingOperatorValues.LessThanOrEqual; formula1 = new Formula(); formula1.Text = value.ToString(); } else { formula1 = new Formula(); formula1.Text = (value - 0.05M).ToString(); formula2 = new Formula(); formula2.Text = (value + 0.05M).ToString(); } ConditionalFormattingRule conditionalFormattingRule = new ConditionalFormattingRule() { Type = ConditionalFormatValues.CellIs, FormatId = (UInt32Value)formatId++, Priority = 1, Operator = op }; if (formula1 != null) conditionalFormattingRule.Append(formula1); if (formula2 != null) conditionalFormattingRule.Append(formula2); conditionalFormatting.Append(conditionalFormattingRule); } /// <summary> /// Returns a Color based on a linear gradient /// </summary> /// <param name="value">The value being output in the cell</param> /// <param name="minValue">The minimum value in the whole range of values going into the sheet</param> /// <param name="maxValue">The maximum value in the whole range of values going into the sheet</param> /// <param name="minColor">The color of the low end of the scale</param> /// <param name="maxColor">The color of the high end of the scale</param> /// <returns></returns> private static System.Drawing.Color GetColour(decimal value, decimal minValue, decimal maxValue, System.Drawing.Color minColor, System.Drawing.Color maxColor) { System.Drawing.Color val; if (value < minValue) val = minColor; else if (value > maxValue) val = maxColor; else { decimal scaleValue = (value - minValue) / (maxValue - minValue); int r = (int)(minColor.R + ((maxColor.R - minColor.R) * scaleValue)); int g = (int)(minColor.G + ((maxColor.G - minColor.G) * scaleValue)); int b = (int)(minColor.B + ((maxColor.B - minColor.B) * scaleValue)); val = System.Drawing.Color.FromArgb(r, g, b); } return val; } 

作为一个例子,我创build了这个:

 static uint formatId = 0U; public static void CreateSpreadsheetWorkbook(string filepath) { SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument. Create(filepath, SpreadsheetDocumentType.Workbook); // Add a WorkbookPart to the document. WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); workbookpart.Workbook = new Workbook(); // Add a WorksheetPart to the WorkbookPart. WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>(); SheetData sheetData = new SheetData(); worksheetPart.Worksheet = new Worksheet(sheetData); // Add Sheets to the Workbook. Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook. AppendChild<Sheets>(new Sheets()); // Append a new worksheet and associate it with the workbook. Sheet sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "FormattedSheet" }; sheets.Append(sheet); WorkbookStylesPart stylesPart = workbookpart.AddNewPart<WorkbookStylesPart>(); stylesPart.Stylesheet = new Stylesheet(); Fills fills = new Fills() { Count = (UInt32Value)20U }; //this count is slightly out; we should calculate it really //this could probably be more efficient - we don't really need one for each value; we could put them in percentiles for example DifferentialFormats differentialFormats = new DifferentialFormats() { Count = (UInt32Value)20U }; ConditionalFormatting conditionalFormatting = new ConditionalFormatting() { SequenceOfReferences = new ListValue<StringValue>() { InnerText = "A1:A21" } }; for (decimal i = 1; i > -1.1M; i -= 0.1M) { AddConditionalStyle(i, -0.8M, 0.8M, 0M, 0M, System.Drawing.Color.FromArgb(152, 83, 84), System.Drawing.Color.FromArgb(244, 221, 221), System.Drawing.Color.FromArgb(214, 244, 214), System.Drawing.Color.FromArgb(20, 134, 33), differentialFormats, conditionalFormatting); } worksheetPart.Worksheet.Append(conditionalFormatting); stylesPart.Stylesheet.Append(differentialFormats); uint rowId = 1U; for (decimal i = 1; i > -1.1M; i -= 0.1M) { Cell cell = new Cell(); cell.DataType = CellValues.Number; cell.CellValue = new CellValue(i.ToString()); Row row = new Row() { RowIndex = rowId++ }; row.Append(cell); sheetData.Append(row); } workbookpart.Workbook.Save(); spreadsheetDocument.Close(); } 

其中创build一个电子表格,看起来像这样:

在这里输入图像说明

您也许可以使用cfvo上的numtypes将中点定义为具有白色的零点。 然后将min设置为红色,将max为绿色。

例如这样的东西

 <conditionalFormatting sqref="A1:A21"> <cfRule type="colorScale" priority="1"> <colorScale> <cfvo type="min" /> <cfvo type="num" val="0" /> <cfvo type="max" /> <color rgb="ff0000" /> <color rgb="ffffff" /> <color rgb="00ff00" /> </colorScale> </cfRule> </conditionalFormatting> 

给出的结果如下所示:

在这里输入图像说明

根据您的进一步意见,我发现您对使用3色渐变的特别关注是对“过渡”点缺乏区分。 我build议根据这个注意事项,你实际上在具有特定优先级的重叠部分上使用多组条件格式规则,如下所示:

假设我们正在查看A列,它将保存-100到100之间的数字。假设你想要任何东西-100或者更糟的是变成鲜红色,逐渐消散到接近0的光线。然后在+ .5至-5,你想要无色的白色。 然后在0附近应该变成浅绿色,在+100变成亮绿色。

首先,设置关于“0”部分的规则。 就像是:

 =ROUND(A1,0)=0 

使此规则适用于优先级,并将其设置为使单元格变为白色。 请注意,您也可以使用它来“远离”遥远的情况。 就像是:

 =OR(ROUND(A1,0)=0,ROUND(A1,0)>100,ROUND(A1,0)<-100) 

这个规则会使单元格变成0白色,并且在你想要的-100-> 100范围外变成白色。

然后应用第二个规则,其中包括您的渐变。 这将设置3种颜色,白色为0(即使您的硬编码“取整为0”规则将适用于上限,消除了数字0周围的渐变色),红色为-100,绿色为100。

在此基础上,范围在-100-> 100范围以外的任何数据都将是白色的,任何舍入到0的数据都将是白色的,而范围内的任何其他数字将从鲜红色到白色均匀地移动到鲜绿色。

我只是vba的新手,我认为这是一个有趣的问题。 我不确定这些规则如何适用于张贴“头脑风暴”的解决scheme,所以如果我正在踩脚趾,让我知道,我会删除我的答案,并学会避免在将来做。 谦虚介绍说:

你可以通过vba修改条件格式吗? 我会调查是否有可能做到这一点:阅读的格式化属性和vba条件格式对象似乎可以使用TintAndShade

规则1:颜色大于所需的中点单色绿色(通过公式)

规则#2:在单色红色的对面

规则#3:三维渐变 – >在vba中修改

修改它 – 删除颜色引用,但在你设置的地方添加一行

  .TintAndShade = .Gradient 

在IF内

 IF .Gradient < 0.3 Then .TintAndShade = 0.3 Else .TintAndShade = .Gradient End if 

(0.3是我的build议,至less在我的屏幕上,@ 0.3的色调与0.3的红色明显不同)