首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C#开放XML2.0 NumberFormatId范围

C#开放XML2.0 NumberFormatId范围
EN

Stack Overflow用户
提问于 2012-08-02 15:48:38
回答 1查看 35.2K关注 0票数 22

使用OpenXML2.0使用c#解析大型excel文件。我遇到的问题是我解析的单元格没有DataType,然后检查NumberFormatId以确定它是十进制、数字还是日期。我在寻找数字/小数和日期的确切NumberFormatId范围。他们似乎到处都是一些数字/小数格式为189,212,214,305,日期的值为185,194,278等。有人知道规范是否定义了这些范围吗?

编辑-更多信息

下面是xl文件夹中style.xml文件中194的数字格式的示例。

excel表格来自世界不同的地区,所以我认为数字格式是不同的,但是它们重叠吗?numFmtId 194不是不同文化背景下的约会吗?

下面是我如何将像"40574“这样的c.CellValues转换成日期,但问题是如何知道"40574”是否是日期而不是数字?

代码语言:javascript
运行
复制
 DateTime.FromOADate(Convert.ToDouble(c.CellValue.Text));

目前,我通过检查是否没有DataType来完成此任务,而不是检查CellFormat,但是当一些NumberFormatId不在我的检查中时,会出现一些问题。

代码语言:javascript
运行
复制
    private Object FormatCellValue(Cell c, SharedStringTable ssTable, CellFormats cellFormats)
            {
                if (c.CellValue != null)
                {
                    // If there is no data type, this must be a string that has been formatted as a number
                    if (c.DataType == null)
                    {
                        CellFormat cf;
                        if (c.StyleIndex == null)
                        {
                            cf = cellFormats.Descendants<CellFormat>().ElementAt<CellFormat>(0);
                        }
                        else
                        {
                            cf = cellFormats.Descendants<CellFormat>().ElementAt<CellFormat>(Convert.ToInt32(c.StyleIndex.Value));
                        }


                        if ((cf.NumberFormatId >= 14 && cf.NumberFormatId <= 22) ||
                            (cf.NumberFormatId >= 165 && cf.NumberFormatId <= 180) || 
                                cf.NumberFormatId == 278 || cf.NumberFormatId == 185 || cf.NumberFormatId == 196 || 
                                cf.NumberFormatId == 217 || cf.NumberFormatId == 326) // Dates
                        {

                            try
                            {

                                DateTime dt;
                                dt = DateTime.FromOADate(Convert.ToDouble(c.CellValue.Text));

...CODE CONTINUES

编辑

在我更新的帖子中,我忘记了在style.xml文件中找到的值:

代码语言:javascript
运行
复制
<numFmt numFmtId="323" formatCode="mmm/yy;@"/>

因此,我的问题是如何获得formatCode并解析它以确定它是否是一个日期?

下面是数字格式323的即时调试窗口的输出。

代码语言:javascript
运行
复制
{DocumentFormat.OpenXml.Spreadsheet.CellFormat}
    base {DocumentFormat.OpenXml.OpenXmlCompositeElement}: {DocumentFormat.OpenXml.Spreadsheet.CellFormat}
    Alignment: {DocumentFormat.OpenXml.Spreadsheet.Alignment}
    ApplyAlignment: "1"
    ApplyBorder: "1"
    ApplyFill: "1"
    ApplyFont: "1"
    ApplyNumberFormat: "1"
    ApplyProtection: "1"
    BorderId: "64"
    ExtensionList: null
    FillId: "0"
    FontId: "83"
    FormatId: "37992"
    LocalName: "xf"
    NumberFormatId: "323"
    PivotButton: null
    Protection: {DocumentFormat.OpenXml.Spreadsheet.Protection}
    QuotePrefix: "1"
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-14 17:47:30

格式ID值列表

下面是格式选项列表(来源)

代码语言:javascript
运行
复制
ID  Format Code
0   General
1   0
2   0.00
3   #,##0
4   #,##0.00
9   0%
10  0.00%
11  0.00E+00
12  # ?/?
13  # ??/??
14  d/m/yyyy
15  d-mmm-yy
16  d-mmm
17  mmm-yy
18  h:mm tt
19  h:mm:ss tt
20  H:mm
21  H:mm:ss
22  m/d/yyyy H:mm
37  #,##0 ;(#,##0)
38  #,##0 ;[Red](#,##0)
39  #,##0.00;(#,##0.00)
40  #,##0.00;[Red](#,##0.00)
45  mm:ss
46  [h]:mm:ss
47  mmss.0
48  ##0.0E+0
49  @

但是,这些列表只指定了几种格式。根据这篇文章:从OpenXml Excel文件中读取日期,ID值小于164个的格式是内置的。您还可以在那里找到更长的格式列表。

检查xlsx文件中的ID值格式

对于ID值更大的格式,可以在文件本身中找到它们的定义。为了查看它们,您应该使用zip归档浏览器打开它,并在xl目录中找到文件。或者,用/xl/styles.xml/x:StyleSheet打开这个xlsx文件,并导航到该文件的开放的XMLSDK2.0生产力工具节点。

在该部分中,您应该能够看到文档中定义的格式以及分配给它们的ID值。格式部分应该类似于以下内容:

代码语言:javascript
运行
复制
...
<x:numFmts count="1">
    <x:numFmt numFmtId="166" formatCode="yy/mm/dd;@" />
</x:numFmts>
...

在这里保存的格式中,id vlaue似乎可以特定于xlsx文件,因此可能相同的ID值可以用于在两个不同的xlsx文件中定义不同的格式。但是,对于构建的int格式,它们是预先定义的,所以在所有文件中都应该是相同的。

如果您需要帮助在您的文件或其他信息中找到这种格式,请告诉我。

编辑

您还可以在本文档中找到有关数字格式的更多信息:http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.numberingformat.aspx

编辑II

可以使用此代码获得包含xlsx文件中定义的所有格式的字典:

代码语言:javascript
运行
复制
private Dictionary<uint, String> BuildFormatMappingsFromXlsx(String fileName)
{
    Dictionary<uint, String> formatMappings = new Dictionary<uint, String>();

    using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
    {
        var stylePart = document.WorkbookPart.WorkbookStylesPart;

        var numFormatsParentNodes = stylePart.Stylesheet.ChildElements.OfType<NumberingFormats>();

        foreach (var numFormatParentNode in numFormatsParentNodes)
        {
            var formatNodes = numFormatParentNode.ChildElements.OfType<NumberingFormat>();
            foreach (var formatNode in formatNodes)
            {
                formatMappings.Add(formatNode.NumberFormatId.Value, formatNode.FormatCode);
            }
        }
    }

    return formatMappings;
}

如果您想检查其中任何一个是日期,我想一种简单的方法是验证格式代码(由我发布的方法创建的字典中的值)是否包含mmyy子字符串。

票数 46
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11781210

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档