Skip to content

Bug: NPOI does not format simple phone number format correctly #1668

@ConnorGlacken

Description

@ConnorGlacken

NPOI Version

2.7.3

File Type

  • XLSX
  • XLS
  • DOCX
  • XLSM
  • OTHER

Upload the Excel File

Not really needed, but here's a spreadsheet with 2 different phone number formats, one works and one doesn't: Formatting_Issue_Test.xls

Reproduce Steps

Use DataFormatter.FormatCellValue() or DataFormatter.FormatRawCellContents() to format a 10 digit numeric value with the following phone number format: "###-###-####" or "###\\-###\\-####" as Excel provides it.

Cell B3 in the uploaded example .xls file has an example of the issue.

Issue Description

When creating the number format for "###-###-####" the DataFormatter.CreateNumberFormat method incorrectly identifies this format string as using '-' as an alternate grouping character and updates the format accordingly. This leads to the final output looking like this: "1-234-56-7-890".

You can test this quickly by adding a test like this to TestDataFormatter.cs

[Test]
public void TestPhoneNumberFormat()
{
    DataFormatter formatter = new DataFormatter(CultureInfo.GetCultureInfo("en-US"));

    Assert.AreEqual("(123) 456-7890", formatter.FormatRawCellContents(1234567890, -1, "[<=9999999]###\\-####;\\(###\\)\\ ###\\-####"));
    Assert.AreEqual("123-456-7890", formatter.FormatRawCellContents(1234567890, -1, "###\\-###\\-####")); // returns 1-234-56-7-890
}

Note: This unit test also identifies a bug in DataFormatter.FormatRawCellContents when using SSNFormat, ZipPlusFourFormat, or PhoneFormat.

FormatRawCellContents converts the value to a decimal before calling Format:
result = numberFormat.Format(decimal.Parse(textValue));

But the Format methods of SSNFormat, ZipPlusFourFormat, and PhoneFormat all attempt to cast to a double, which throws an exception:
var result = ((double)obj).ToString(df, culture);

I updated these lines to use Convert.ToDouble the way DecimalFormat does in order to fix this:
var result = Convert.ToDouble(obj, CultureInfo.InvariantCulture).ToString(df, culture);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions