具有纯色填充颜色的 C# EPPlus 数据栏条件格式



我正在生成涉及几列百分比数据的 excel 报告。由于报告用于演示目的,因此我想通过使用带有实心填充的数据条格式化百分比数据来使它们看起来不错。不知何故,这被证明是非常困难的,因为 EPPlus 中没有直接设置数据栏的固体填充,但我还是得出了这篇文章中的答案:

实心数据条和数据条最小值的手动和编码版本之间的外观不一致

但是,无论我多么努力地尝试编辑应用程序的代码,我只有一列最终以实心填充,其余的都是渐变。即使我将问题中的节点更改为如下所示的节点列表:

var cfNodes = xdoc.SelectNodes("/default:worksheet/default:conditionalFormatting/default:cfRule", nsm);
foreach(XmlNode cfNode in cfNodes)
{
cfNode.AppendChild(extLstCf);
}

以及工作表元素:

var wsNodes = xdoc.SelectNodes("/default:worksheet", nsm);
foreach(XmlElement wsNode in wsNodes)
{
wsNode.AppendChild(extLstWs);
}

我还尝试使用 xml 更改<sqref>参数,但这仍然没有涵盖我的所有数据栏列。我认为必须在 xml 中更改一些东西才能完成我想要的,但我不知道要寻找什么......

好的伙计们 我花了几天时间,但我终于想通了。可能有一种更简单的方法可以做到这一点,但到目前为止,这就是我让它为我工作的方式:

需要在工作表级别节点追加工作表 xml 扩展列表节点,该节点包括工作表包含的数字数据栏元素,并且每个元素都需要具有实心填充 I 的gradient = 0。例如,我的工作表包含两个数据栏,所以我的看起来像这样:

var extLstWs = xdoc.CreateNode(XmlNodeType.Element, "extLst", xdoc.DocumentElement.NamespaceURI);
extLstWs.InnerXml = @"<ext uri=""{78C0D931-6437-407d-A8EE-F0AAD7539E65}"" 
xmlns:x14=""http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"">
<x14:conditionalFormattings>
<x14:conditionalFormatting xmlns:xm=""http://schemas.microsoft.com/office/excel/2006/main"">
<x14:cfRule type=""dataBar"" id=""{3F3F0E19-800E-4C9F-9CAF-1E3CE014ED86}"">
<x14:dataBar minLength=""0"" maxLength=""100"" gradient=""0"">
<x14:cfvo type=""num"">
<xm:f>0</xm:f>
</x14:cfvo>
<x14:cfvo type=""num"">
<xm:f>100</xm:f>
</x14:cfvo>
<x14:negativeFillColor rgb=""FFFF0000""/><x14:axisColor rgb=""FF000000""/>
</x14:dataBar>
</x14:cfRule>
<xm:sqref>A1:A20</xm:sqref>
</x14:conditionalFormatting>
<x14:conditionalFormatting xmlns:xm=""http://schemas.microsoft.com/office/excel/2006/main"">
<x14:cfRule type=""dataBar"" id=""{3F3F0E19-800E-4C9F-9CAF-1E3CE014ED86}"">
<x14:dataBar minLength=""0"" maxLength=""100"" gradient=""0"">
<x14:cfvo type=""num"">
<xm:f>0</xm:f>
</x14:cfvo><x14:cfvo type=""num"">
<xm:f>200</xm:f>
</x14:cfvo><x14:negativeFillColor rgb=""FFFF0000""/>
<x14:axisColor rgb=""FF000000""/>
</x14:dataBar>
</x14:cfRule>
<xm:sqref>B1:B20</xm:sqref>
</x14:conditionalFormatting>
</x14:conditionalFormattings>
</ext>";
var wsNode = xdoc.SelectSingleNode("/default:worksheet", nsm);
wsNode.AppendChild(extLstWs);

请注意我是如何在其中获得两个<x14:conditionalFormattings>子节点的,每个数据条一个。

其次,需要在<cfRule>节点下附加条件格式规则节点的另一个扩展列表,每个数据栏也有一个。我能够使用 foreach 循环来查找工作表中的所有数据栏,并将相同的 xml 附加到每个数据栏,如下所示:

var cfNodes = xdoc.SelectNodes("/default:worksheet/default:conditionalFormatting/default:cfRule", nsm);
foreach (XmlNode cfnode in cfNodes)
{
var extLstCfNormal = xdoc.CreateNode(XmlNodeType.Element, "extLst", xdoc.DocumentElement.NamespaceURI);
extLstCfNormal.InnerXml = @"<ext uri=""{B025F937-C7B1-47D3-B67F-A62EFF666E3E}"" 
xmlns:x14=""http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"">
<x14:id>{3F3F0E19-800E-4C9F-9CAF-1E3CE014ED86}</x14:id></ext>";
cfnode.AppendChild(extLstCfNormal);
}

完成上述操作后,我终于能够显示带有实心填充的所有数据栏。

这是我的版本,如何为那些未能应用徐奥伟解决方案的人(像我一样......

public static Random Rnd = new Random();
public static string GenerateXlsId()
{
//{29BD882A-B741-482B-9067-72CC5D939236}
string id = string.Empty;
for (int i = 0; i < 32; i++)
if (Rnd.NextDouble() < 0.5)
id += Rnd.Next(0, 10);
else
id += (char)Rnd.Next(65, 91);
id = id.Insert(8, "-");
id = id.Insert(13, "-");
id = id.Insert(18, "-");
id = id.Insert(23, "-");
return id;
}
public static void FixDatabarsAtWorksheet(OfficeOpenXml.ExcelWorksheet eworksheet)
{
System.Xml.XmlNodeList databars = eworksheet.WorksheetXml.GetElementsByTagName("dataBar");
if (databars.Count > 0)
{
string conditional_formattings_str = string.Empty;
for (int i = 0; i < databars.Count; i++)
{
string temp_databar_id = GenerateXlsId();
databars[i].ParentNode.InnerXml += @"<extLst>
<ext uri=""{B025F937-C7B1-47D3-B67F-A62EFF666E3E}"" xmlns:x14=""http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"">
<x14:id>{" + temp_databar_id + @"}</x14:id>
</ext>
</extLst>";
//--
string temp_sqref = databars[i].ParentNode.ParentNode.Attributes["sqref"].Value;
string left_type = string.Empty;
string left_val = string.Empty;
string right_type = string.Empty;
string right_val = string.Empty;
string color = string.Empty;
Color databar_fill_color = Color.Empty;
Color databar_border_color = Color.Empty;
for (int j = 0; j < databars[i].ChildNodes.Count; j++)
if (databars[i].ChildNodes[j].LocalName == "cfvo" && databars[i].ChildNodes[j].Attributes["type"] != null)
{
if (string.IsNullOrEmpty(left_type))
left_type = databars[i].ChildNodes[j].Attributes["type"].Value;
else if (string.IsNullOrEmpty(right_type))
right_type = databars[i].ChildNodes[j].Attributes["type"].Value;
if (databars[i].ChildNodes[j].Attributes["val"] != null)
if (string.IsNullOrEmpty(left_val))
left_val = databars[i].ChildNodes[j].Attributes["val"].Value;
else if (string.IsNullOrEmpty(right_val))
right_val = databars[i].ChildNodes[j].Attributes["val"].Value;
}
else if (databars[i].ChildNodes[j].LocalName == "color")
{
color = databars[i].ChildNodes[j].Attributes["rgb"].Value;
int argb = Int32.Parse(color, System.Globalization.NumberStyles.HexNumber);
databar_fill_color = Color.FromArgb(argb);
databar_border_color = Color.FromArgb(255,
databar_fill_color.R - 50 < 0 ? databar_fill_color.R + 50 : databar_fill_color.R - 50,
databar_fill_color.G - 50 < 0 ? databar_fill_color.R + 50 : databar_fill_color.G - 50,
databar_fill_color.B - 50 < 0 ? databar_fill_color.R + 50 : databar_fill_color.B - 50);
}
string temp_conditional_formatting_template = @"<x14:conditionalFormatting xmlns:xm=""http://schemas.microsoft.com/office/excel/2006/main"">
<x14:cfRule type=""dataBar"" id=""{" + temp_databar_id + @"}"">
<x14:dataBar minLength=""" + (string.IsNullOrEmpty(left_val) ? "0" : left_val) + "" maxLength="" + (string.IsNullOrEmpty(right_val) ? "100" : right_val) + "" gradient="0" " + (databar_border_color.IsEmpty ? string.Empty : "border = "1"") + ">";
temp_conditional_formatting_template += Environment.NewLine + "<x14:cfvo type="" + (left_type.ToLower() == "min" ? "autoMin" : left_type) + "" />";
temp_conditional_formatting_template += Environment.NewLine + "<x14:cfvo type="" + (right_type.ToLower() == "max" ? "autoMax" : right_type) + "" />";
if (!databar_border_color.IsEmpty)
temp_conditional_formatting_template += Environment.NewLine + "<x14:borderColor rgb="" + BitConverter.ToString(new byte[] { databar_border_color.A, databar_border_color.R, databar_border_color.G, databar_border_color.B }).Replace("-", "") + "" />";
temp_conditional_formatting_template += Environment.NewLine + @"</x14:dataBar>
</x14:cfRule>
<xm:sqref>" + temp_sqref + @"</xm:sqref>
</x14:conditionalFormatting>";
conditional_formattings_str += temp_conditional_formatting_template;
}
databars[0].ParentNode.ParentNode.ParentNode.InnerXml += @"<extLst>
<ext uri=""{78C0D931-6437-407d-A8EE-F0AAD7539E65}"" xmlns:x14=""http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"">
<x14:conditionalFormattings>" + conditional_formattings_str + @" 
</x14:conditionalFormattings>
</ext>
</extLst>";
}
}

这么小的事情这么痛苦...哇��

附言MS,我讨厌您在将 XmlElements 插入父节点时跳过前缀值!

附言2.这使得任何其他条件格式消失...不知道为什么...天哪!

最新更新