Skip to content

Fix phone number format: escaped dashes misidentified as grouping chars; decimal cast in special format classes#1710

Merged
tonyqus merged 2 commits into
masterfrom
copilot/fix-npoi-phone-number-format
Mar 1, 2026
Merged

Fix phone number format: escaped dashes misidentified as grouping chars; decimal cast in special format classes#1710
tonyqus merged 2 commits into
masterfrom
copilot/fix-npoi-phone-number-format

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 1, 2026

DataFormatter incorrectly formats phone numbers like ###\-###\-#### as 1-234-56-7-890 instead of 123-456-7890, and SSNFormat/ZipPlusFourFormat/PhoneFormat throw InvalidCastException when FormatRawCellContents passes a decimal value.

Changes

  • DataFormatter.cs — alternate grouping detection: Run alternateGrouping.Match() against the original format string (before cleanFormatForNumber strips backslashes). After stripping, ###\-###\-#### becomes ###-###-#### and the regex incorrectly captures - as an alternate grouping separator. Matching on the raw string avoids this because the backslash breaks the [#0]{3} contiguity requirement.

  • Format.cs — decimal cast fix: Replace (double)obj with Convert.ToDouble(obj, CultureInfo.InvariantCulture) in SSNFormat, ZipPlusFourFormat, and PhoneFormat, consistent with DecimalFormat. The direct cast throws when obj is a decimal, which is what FormatRawCellContents produces.

DataFormatter formatter = new DataFormatter(CultureInfo.GetCultureInfo("en-US"));

// Previously produced "1-234-56-7-890"
formatter.FormatRawCellContents(1234567890, -1, "###\\-###\\-####");  // → "123-456-7890"

// Previously threw InvalidCastException
formatter.FormatRawCellContents(1234567890, -1, "[<=9999999]###\\-####;\\(###\\)\\ ###\\-####");  // → "(123) 456-7890"
Original prompt

This section details on the original issue you should resolve

<issue_title>Bug: NPOI does not format simple phone number format correctly</issue_title>
<issue_description>### 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);</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…s grouping chars, fix decimal cast in SSN/Zip/Phone format classes

Co-authored-by: tonyqus <772561+tonyqus@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix NPOI phone number formatting issue Fix phone number format: escaped dashes misidentified as grouping chars; decimal cast in special format classes Mar 1, 2026
@tonyqus tonyqus added this to the NPOI 2.8.0 milestone Mar 1, 2026
@tonyqus tonyqus marked this pull request as ready for review March 1, 2026 16:45
@tonyqus tonyqus merged commit 4200c63 into master Mar 1, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NPOI does not format simple phone number format correctly

2 participants