views:

855

answers:

7

I have a .NET WinForms textbox for a phone number field. After allowing free-form text, I'd like to format the text as a "more readable" phone number after the user leaves the textbox. (Outlook has this feature for phone fields when you create/edit a contact)

  • 1234567 becomes 123-4567
  • 1234567890 becomes (123) 456-7890
  • (123)456.7890 becomes (123) 456-7890
  • 123.4567x123 becomes 123-4567 x123
  • etc
A: 

I don't know of any way other than doing it yourself by possibly making some masks and checking which one it matches and doing each mask on a case by case basis. Don't think it'd be too hard, just time consuming.

Davy8
A: 

My guess is that you could accomplish this with a conditional statement to look at the input and then parse it into a specific format. But I'm guessing there is going to be a good amount of logic to investigate the input and format the output.

Mitchel Sellers
+2  A: 

A fairly simple-minded approach would be to use a regular expression. Depending on which type of phone numbers you're accepting, you could write a regular expression that looks for the digits (for US-only, you know there can be 7 or 10 total - maybe with a leading '1') and potential separators between them (period, dash, parens, spaces, etc.).

Once you run the match against the regex, you'll need to write the logic to determine what you actually got and format it from there.

EDIT: Just wanted to add a very basic example (by no means is this going to work for all of the examples you posted above). Geoff's suggestion of stripping non-numeric characters might help out a bit depending on how you write your regex.

Regex regex = new Regex(@"(?<areaCode>([\d]{3}))?[\s.-]?(?<leadingThree>([\d]{3}))[\s.-]?(?<lastFour>([\d]{4}))[x]?(?<extension>[\d]{1,})?");
string phoneNumber = "701 123-4567x324";

Match phoneNumberMatch = regex.Match(phoneNumber);
if(phoneNumberMatch.Success)
{
   if (phoneNumberMatch.Groups["areaCode"].Success)
   {
      Console.WriteLine(phoneNumberMatch.Groups["areaCode"].Value);
   }
   if (phoneNumberMatch.Groups["leadingThree"].Success)
   {
      Console.WriteLine(phoneNumberMatch.Groups["leadingThree"].Value);
   }
   if (phoneNumberMatch.Groups["lastFour"].Success)
   {
      Console.WriteLine(phoneNumberMatch.Groups["lastFour"].Value);
   }
   if (phoneNumberMatch.Groups["extension"].Success)
   {
      Console.WriteLine(phoneNumberMatch.Groups["extension"].Value);
   }
}
muloh
+1  A: 

I think the easiest thing to do is to first strip any non-numeric characters from the string so that you just have a number then format as mentioned in this question

Geoff
I thought about stripping any non-numeric characters and then formatting, but I don't think that works so well for the extension case (123.4567x123)
Shawn Miller
+1  A: 

I thought about stripping any non-numeric characters and then formatting, but I don't think that works so well for the extension case (123.4567x123)

Shawn Miller
+1  A: 

Lop off the extension then strip the non-numeric character from the remainder. Format it then add the extension back on.

Start: 123.4567x123
Lop: 123.4567
Strip: 1234567
Format: 123-4567
Add: 123-4567 x123
Dennis Williamson
A: 

This works for me. Worth checking performance if you are doing this in a tight loop...

public static string FormatPhoneNumber(string phone)
{
    phone = Regex.Replace(phone, @"[^\d]", "");
    if (phone.Length == 10)
     return Regex.Replace(phone,
                          "(?<ac>\\d{3})(?<pref>\\d{3})(?<num>\\d{4})",
                          "(${ac}) ${pref}-${num}");
    else if ((phone.Length < 16) && (phone.Length > 10))
     return Regex.Replace(phone,
                          "(?<ac>\\d{3})(?<pref>\\d{3})(?<num>\\d{4})(?<ext>\\d{1,5})", 
                          "(${ac}) ${pref}-${num} x${ext}");
    else
     return string.Empty;

}

dividius