Can I format NULL values in string.Format? - c#

I was wondering if there's a syntax for formatting NULL values in string.Format, such as what Excel uses
For example, using Excel I could specify a format value of {0:#,000.00;-#,000.00,NULL}, which means display the numeric value as number format if positive, number format in parenthesis if negative, or NULL if the value is null
string.Format("${0:#,000.00;(#,000.00);NULL}", someNumericValue);
Edit
I'm looking for formatting NULL/Nothing values for all data types, not just numeric ones.
My example is actually incorrect because I mistakenly thought Excel used the 3rd parameter if the value was NULL, but it's actually used when the value is 0. I'm leaving it in there because it's the closest thing I can think of to what I was hoping to do.
I am hoping to avoid the null coalescing operator because I am writing log records, and the data is not usually a string
It would be much easier to write something like
Log(string.Format("Value1 changes from {0:NULL} to {1:NULL}",
new object[] { oldObject.SomeValue, newObject.SomeValue }));
than to write
var old = (oldObject.SomeValue == null ? "null" : oldObject.SomeValue.ToString());
var new = (newObject.SomeValue == null ? "null" : newObject.SomeValue.ToString());
Log(string.Format("Value1 changes from {0} to {1}",
new object[] { old, new }));

You can define a custom formatter that returns "NULL" if the value is null and otherwise the default formatted string, e.g.:
foreach (var value in new[] { 123456.78m, -123456.78m, 0m, (decimal?)null })
{
string result = string.Format(
new NullFormat(), "${0:#,000.00;(#,000.00);ZERO}", value);
Console.WriteLine(result);
}
Output:
$123.456,78
$(123.456,78)
$ZERO
$NULL
Custom Formatter:
public class NullFormat : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type service)
{
if (service == typeof(ICustomFormatter))
{
return this;
}
else
{
return null;
}
}
public string Format(string format, object arg, IFormatProvider provider)
{
if (arg == null)
{
return "NULL";
}
IFormattable formattable = arg as IFormattable;
if (formattable != null)
{
return formattable.ToString(format, provider);
}
return arg.ToString();
}
}

I don't think there's anything in String.Format that will let you specify a particular format for null strings. A workaround is to use the null-coalescing operator, like this:
const string DefaultValue = "(null)";
string s = null;
string formatted = String.Format("{0}", s ?? DefaultValue);

Is this what you want?
string test;
test ?? "NULL"

It looks like String.Format for .NET acts the same way as Excel, i.e., you can use ; separator for positive, negative, and 0 values, but not NULL: http://msdn.microsoft.com/en-us/library/0c899ak8.aspx#SectionSeparator.
You will probably just have to handle the null value manually:
if (myval == null)
// handle
else
return String.Format(...);

You could use an extension method:
public static string ToDataString(this string prm)
{
if (prm == null)
{
return "NULL";
}
else
{
return "'" + prm.Replace("'", "''") + "'";
}
}
Then in your code you can do:
string Field1="Val";
string Field2=null;
string s = string.Format("Set Value:{0}, NullValue={1}",Field1.ToDataString(), Field2.ToDataString());

Related

How to replace string.empty to "0"

Just like the title says.
I've tried doing str.Replace("","0"); but it gave me error because oldValue has zero length.
Is it possible to replace string.Empty into something?
Edit:
I am maintaining a program and I encountered that the program was calling a method that'll return a string then be converted to Int32.
int x = Convert.toInt32(Method1());
public string Method1()
{
string retString = string.Empty;
//Do Something
return retString
}
You can simply return "0" for null, zero length or whitespace string using this one-liner:
return String.IsNullOrWhiteSpace(str) ? "0" : str;
String.Replace takes two string arguments oldValue and newValue. You specified the newValue 0 however an empty string is not legal for the oldValue.
try below code :-
str.Replace(" ","0");
or you can just assign "0" to emptry string as below :-
if(str == string.Empty)
{
str = "0";
}
or making it simple :-
String.IsNullOrWhiteSpace(str) ? "0" : str;
You can't replace empty string within the string, but you can replace, say, spaces, e.g.
str = str.Replace(" ", "0"); // providing str is not null
Or you can substitute empty string with "0":
if (String.IsNullOrEmpty(str))
str = "0";
When parsing string into int you can do something like that:
int x = String.IsNullOrEmpty(str) ? 0 : Convert.ToInt32(str);
In method() you can do:
return String.IsNullOrEmpty(retString) ? "0" : retString;
If you want to check if the value is empty and then set the value to zero, otherwise use the default value you can use an inline if like so:
return string.IsNullOrWhiteSpace(retString ) ? "0" : retString;
If you know that str is empty then you may use star="a"
If you want to check then write statement in if condition.
After your edit:
To convert an empty string to 0, and parse a non-empty string as an integer, I wouldn't deal with a "0" at all, but combine the two in a single method. For example:
int Parse(string s, int d = 0) {
if (string.IsNullOrEmpty(s))
return d;
return int.Parse(s);
}
Try This...
public string Method1()
{
string retString = string.Empty;
//Do Something
return string.IsNullOrEmpty(retString)?"0":retString;
}
It is not possible to replace string.Empty by "0". It will throw ArgumentException.
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll.
Additional information: String cannot be of zero length.
You can try following code:
if(retString == string.Empty)
{
retString = "0";
}
It sounds like your best option would be int.TryParse, if you encounter a string that can't be set to a valid value, it will set it to the default value for an integer (0) as well as returning a boolean so you can know this has happened.
int myInt;
if(!int.TryParse(myStringVariable, out myInt))
{
//Invalid integer you can put something here if you like but not needed
//myInt has been set to zero
}
//The same code without the if statement, still sets myInt
int.TryParse(myStringVariable, out myInt);

String.Format() not invoking custom formatter

I have a custom formatter specified, basically like this:
public class NotationNumericFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType_)
{
return (formatType_ == typeof(ICustomFormatter) ? this : null;
}
public string Format(string format_, object arg_, IFormatProvider formatProvider_)
{
if (!Equals(formatProvider_) || arg_ == null) // <-- I put a breakpoint here...
{
return;
}
// then a bunch of stuff happens here.
}
}
What's stumping me at the moment is, the following code:
// _myFormatter is a NotationNumericFormatter which gets instanced
// in the ctor of the class in question.
var result = string.Format(_myFormatter, (parameter_ ?? "").ToString(), value_);
Which is never, ever, hitting the first line in my formatter's Format() method. What am I missing here? Is there some subtlety to string.Format that I'm missing?
If parameter does not have {0} then the formatter won't break point
this will breakpoint
var result = string.Format(_myFormatter, "{0}", value_);
this won't
var result = string.Format(_myFormatter, "", value_);
When you call String.Format(IFormatProvider provider , String format , params Object[] args ) the second parameter format hast to specified as a valid format string i.e. it cannot be empty.
Try to set parameter_ to something like "{0}" then it should work.

Format decimal c# - Keep last zero

I have been searching for this but cannot seem to find the answer. I have the following decimals with the corresponding output that I want from String.Format
100.00 -> 100
100.50 -> 100.50
100.51 -> 100.51
My problem is that I cannot seem to find a format which will keep the 0 on the end of 100.50 as well as remove the 2 zeros from 100.
Any help is much appreciated.
EDIT
For some more clarity. I have variables of type decimal, they are only ever going to be 2 decimal places. Basically I want to display 2 decimal places if they exist or none, I don't want to display one decimal place in the case of 100.50 becoming 100.5
As far as I know, there is no such format. You will have to implement this manually, e.g.:
String formatString = Math.Round(myNumber) == myNumber ?
"0" : // no decimal places
"0.00"; // two decimal places
You can use this:
string s = number.ToString("0.00");
if (s.EndsWith("00"))
{
s = number.ToString("0");
}
Test if your number is an integer, and use according format :
string.Format((number % 1) == 0 ? "{0}": "{0:0.00}", number)
Ok, this hurts my eyes, but should give you what you want:
string output = string.Format("{0:N2}", amount).Replace(".00", "");
UPDATE: I like Heinzi's answer more.
This approach will achieve the desired result while applying the specified culture:
decimal a = 100.05m;
decimal b = 100.50m;
decimal c = 100.00m;
CultureInfo ci = CultureInfo.GetCultureInfo("de-DE");
string sa = String.Format(new CustomFormatter(ci), "{0}", a); // Will output 100,05
string sb = String.Format(new CustomFormatter(ci), "{0}", b); // Will output 100,50
string sc = String.Format(new CustomFormatter(ci), "{0}", c); // Will output 100
You can replace the culture with CultureInfo.CurrentCulture or any other culture to fit your needs.
The CustomFormatter class is:
public class CustomFormatter : IFormatProvider, ICustomFormatter
{
public CultureInfo Culture { get; private set; }
public CustomFormatter()
: this(CultureInfo.CurrentCulture)
{ }
public CustomFormatter(CultureInfo culture)
{
this.Culture = culture;
}
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (formatProvider.GetType() == this.GetType())
{
return string.Format(this.Culture, "{0:0.00}", arg).Replace(this.Culture.NumberFormat.NumberDecimalSeparator + "00", "");
}
else
{
if (arg is IFormattable)
return ((IFormattable)arg).ToString(format, this.Culture);
else if (arg != null)
return arg.ToString();
else
return String.Empty;
}
}
}

?? operator in system.DBNull

Is there an operator or built in function to simplyfy this:
myVal = object1.object2.something(a,b).dataColumn.toString()==""?object1.object2.something(a,b).dataColumn.toString():"-";
I know i can do something like:
string str = object1.object2.something(a,b).dataColumn.toString();
myVal =str==""?"-":str;
but I have many objects and I want to avoid it:
string str1 = object1.object2.something(a,b).dataColumn1.toString();
myVal1==""?str1:"-"
string str2 = object1.object2.something(a,b).dataColumn2.toString();
myVal2==""?str2:"-"
:
string strN = object1.object2.something(a,b).dataColumnN.toString();
myValN==""?strN:"-"
I can also create a function:
private string CheckNull(object dataColumn){
return dataColumn == System.DBNull?"-":dataColumn.toString();
}
myVal1 = CheckNull(object1.object2.something1(a,b).dataColumn.toString())
myVal2 = CheckNull(object1.object2.something2(a,b).dataColumn.toString())
myVal3 = CheckNull(object1.object2.something3(a,b).dataColumn.toString())
The easiest way is to use the ?? operator but the problem is that 'dataColumn' is not compatible with ?? because sometimes returns a system.DBNull instead of a null. Look at the immediate window output:
System.DBNull??"-"
'System.DBNull' is a 'type', which is not valid in the given context
null??"-"
"-"
I wonder if there is some (string) function or operator that can return "-" if dataColumn.toString()=="" without an if..then (because I would have to make many if..then for all of them. Otherwise I rather use the function approach shown above.
string str = object1.object2.something(a,b).dataColumn.toString().if("","-");
How about:
public static class StringHelper {
public static string ValueOrDash(this string value) {
return string.IsNullOrEmpty(value) ? "-" : value;
}
}
Then you can just do:
myVal = object1.object2.something(a,b).DataColumn.ToString().ValueOrDash();
Or better yet:
public static class StringHelper {
public static string ValueOrWhatever(this string value, string defaultValue) {
return string.IsNullOrEmpty(value) ? defaultValue : value;
}
}
myVal = object1.object2.something(a,b).DataColumn.ToString().ValueOrWhatever("-");
If the underlying object is always either a string or DbNull, you could use the as cast operator:
private string CheckNull(object dataColumn){
return dataColumn == (dataColumn as string)??"-":dataColumn;
}
This will also return "-" if the value is an integer for example or some other type.
It's not clear from your code, but if these values are coming from DataRows you could use the new (.NET 3.5) DataRowExtensions.Field function, which will return null instead of DbNull.
You could write an extension method to call on the dataColumn. It wouldn't functionally be much different than your CheckNull method, though.
Or in your first example with str1, str2, strN and such, is there a reason you can't reuse str1 for each? I see you have a method call in your long line of code, you wouldn't want to waste the time running that more often than you need to (especially if it's going to result in the same output every time).

how to do this conversion?

string mvi = Moneys.GetValue(8) as string;
if (mvi == null)
// I am getting exception Here if its null?
money.Currency= Convert.ToDecimal("");
else
// Currency is Decimal
money.Currency= Convert.ToDecimal(mvi);
// I am getting exception Here if its null?
money.Currency= Convert.ToDecimal("");
Can anybody tell me how to do this?
Empty string is not convertible to decimal. You could perform a check like this
if (string.IsNullOrEmpty(mvi))
{
money.Currency = 0M;
}
else
{
decimal temp = 0M;
if (decimal.TryParse(mvi, out temp))
{
money.Currency = temp;
}
else
{
// you have an invalid input, handle
}
}
Here's my version of Anthony Pegram's answer:
string mvi = Moneys.GetValue(8) as string;
money.Currency = 0M;
if (!String.IsNullOrEmpty(mvi))
if (!Decimal.TryParse(mvi, out money.Currency))
throw new FormatException("mvi");
On the whole, it looks quite a bit like the one Alex made, only it treats empty as zero and shows more error-handling.
You can use TryParse instead of Convert.ToDecimal():
decimal theValue;
string mvi = Moneys.GetValue(8) as string;
Decimal.TryParse( mvi, out theValue );
alternatively, you can use the null coallescing operator to handle nulls preemtively:
var theValue = Convert.ToDecimal( mvi ?? "0" );
In both cases, however, you have to decide what to do if the value coming in is not a valid decimal.
http://msdn.microsoft.com/en-us/library/hf9z3s65.aspx
I think you want Convert.ToDecimal("0.0"); otherwise you get a EDIT: ArgumentNullException

Categories