.Net中的Excel样式条件数字格式

我需要使用Excel条件格式string在.Net应用程序中格式化数字。 对于那些不熟悉它们的人来说,Excel格式string看起来像这样:

[>=2]#,##0.0;[<=-2]-#,##0.0;#,##0.00 

…应该被解释为“对于大于2的数字使用第一格式,对于低于-2的数字使用第二格式,对于其他任何情况使用第三格式”。

在我继续构build我自己的自定义格式stringparsing器之前,有没有人知道在.Net中是否有类似这样的东西,我可以使用? 我知道有格式化string的分隔符,但是据我所知,似乎没有考虑到“是负数/正数/零”的情况。

你将不得不自己实现格式化,但是你可以使用接口IFormatProviderICustomFormatter来挂接到.NET现有的格式化框架。

这是一个如何做到这一点的例子。 一个ConditionalFormatter类被创build,它由几个ConditionalFormat对象组成。 ConditionalFormat类具有PredicateFormatConditionalFormatter将按顺序search所有ConditionalFormat对象,并在Predicate为true的位置查找第一个对象,并使用关联的Format 。 格式化程序使用字母“Z”作为格式string。

 class ConditionalFormat<T> where T : IFormattable { public Func<T, Boolean> Predicate { get; set; } public String Format { get; set; } public static readonly Func<T, Boolean> Tautology = _ => true; } class ConditionalFormatter<T> : Collection<ConditionalFormat<T>>, IFormatProvider, ICustomFormatter where T : IFormattable { public const String FormatString = "Z"; readonly CultureInfo cultureInfo; public ConditionalFormatter(IEnumerable<ConditionalFormat<T>> conditionalFormats) : this(conditionalFormats, null) { } public ConditionalFormatter(IEnumerable<ConditionalFormat<T>> conditionalFormats, CultureInfo cultureInfo) : base(conditionalFormats.ToList()) { this.cultureInfo = cultureInfo; } public Object GetFormat(Type formatType) { return formatType == typeof(ICustomFormatter) ? this : null; } public String Format(String format, Object arg, IFormatProvider formatProvider) { if (arg.GetType() != typeof(T)) return HandleOtherFormats(format, arg); var formatUpperCase = format.ToUpperInvariant(); if (formatUpperCase != FormatString) return HandleOtherFormats(format, arg); var value = (T) arg; foreach (var conditionalFormat in this) if (conditionalFormat.Predicate(value)) return ((IFormattable) value).ToString(conditionalFormat.Format, cultureInfo); throw new InvalidOperationException(String.Format("No format matching value {0}.", value)); } String HandleOtherFormats(String format, Object arg) { var formattable = arg as IFormattable; if (formattable != null) return formattable.ToString(format, this.cultureInfo); else if (arg != null) return arg.ToString(); else return String.Empty; } } 

该类是通用的,你将不得不创build一个匹配你想格式化的types的实例。 这里是一个使用Double的例子:

 var conditionalFormatter = new ConditionalFormatter<Double>( new[] { new ConditionalFormat<Double> { Predicate = d => -2 < d && d < 2, Format = "#,##0.00" }, new ConditionalFormat<Double> { Predicate = ConditionalFormat<Double>.Tautology, Format = "#,##0.0" }, } ); var value = 1234.5678; var formattedValue = String.Format(conditionalFormatter, "Value is {0:Z}", value); 

另一个有趣的解决scheme是:有一个名为SmartFormat的库包含一个条件格式器。

你的例子的语法是:

 var output = Smart.Format("{0:>=2?{0:#,##0.0}|<=-2?{0:-#,##0.0}|{0:#,##0.00}}", value); 

有关语法的解释,请参阅ConditionalFormatter 。

但是,如果您想要支持上面提到的确切的Excel语法,则可以下载SmartFormat源代码并修改ConditionalFormatter以支持您的语法。 它使用正则expression式来parsing每个(condition) ,所以很容易修改。

你需要写if / else if语句。 没有直接的办法

 string numberToFormat = //state your number here string FormattedString = null; if(numberToFormat >2) { //Format 1 //eg FormattedString = String.Format("{0:0.00}", numberToFormat); } else if(numberToFormat < -2) { //Format 2 } else { // Format Default } 

这是最短的路。 但是,当然你可以得到你自己的条件格式化程序。