Подтвердить что ты не робот

Диапазон С# Open XML 2.0 NumberFormatId

Работа с Open XML 2.0 с использованием С# для анализа больших файлов excel. Проблема, с которой я столкнулась, - это ядро, которое я обрабатываю, не имеет DataType. Затем я проверяю NumberFormatId, чтобы определить, является ли оно десятичным, числом или датой. Я ищу точный диапазон NumberFormatId для чисел/десятичных знаков и дат. Они, кажется, повсюду, некоторые числа/десятичные знаки имеют форматы 189,212,214,305 и даты, имеющие значения 185, 194, 278 и т.д. Кто-нибудь знает, определяет ли спецификация этих диапазонов?

Отредактировано - Дополнительная информация

Ниже приведен пример формата чисел 194 из файла style.xml внутри папки xl.

Листы excel из разных регионов мира, поэтому я думаю, что числовые форматы разные, но перекрываются ли они? Будет ли numFmtId 194 быть чем-то иным, чем дата в разных настройках культуры?

Ниже показано, как я конвертирую c.CellValues ​​как "40574" в даты, но проблема в том, как узнать, является ли "40574" датой, а не цифрой?

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

В настоящее время я делаю это, проверяя, нет ли DataType, чем проверка CellFormat, но есть проблемы, когда некоторые из NumberFormatId не находятся в моей проверке.

    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

Edit

В моем обновленном сообщении я забыл опубликовать значение, которое я нашел в файле style.xml:

<numFmt numFmtId="323" formatCode="mmm/yy;@"/>

Итак, с этим мой вопрос будет в том, как я могу получить formatCode и проанализировать его, чтобы определить, является ли это датой?

Ниже приведен вывод из окна немедленного отладки в формате format 323

{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"
4b9b3361

Ответ 1

Списки значений идентификаторов форматов

Ниже приведен список параметров формата (источник)

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  @

Hower, в этом списке указаны только несколько форматов. В соответствии с этим сообщением: Чтение дат из файлов OpenXml Excel, формат с идентификационным значением менее 164 встроен. Вы также можете найти более длинный список форматов.

Проверка значений идентификаторов форматов в файле xlsx

Для форматов с большими значениями ID вы можете найти их определения внутри самого файла. Чтобы увидеть их, вы должны открыть его с помощью архива zip-архива и найти файл styles.xml в каталоге xl. В качестве альтернативы откройте этот файл xlsx с помощью Open XML SDK 2.0 Productivity Tools и перейдите к этому файлу /xl/styles.xml/x:StyleSheet node.

В этом разделе вы должны иметь возможность видеть форматы, определенные в документе, вместе с присвоенными им значениями идентификаторов. Часть с форматами должна выглядеть примерно так:

...
<x:numFmts count="1">
    <x:numFmt numFmtId="166" formatCode="yy/mm/dd;@" />
</x:numFmts>
...

Если посмотреть на форматы, сохраненные здесь, кажется, что id vlaues может быть специфичным для файла xlsx, поэтому, возможно, одно и то же значение ID может использоваться для определения разных форматов в двух разных файлах xlsx. Однако для встроенных форматов они предопределены, поэтому они должны быть одинаковыми во всех файлах.

Если вам нужна помощь в поиске этих форматов в вашем файле или дополнительной информации, сообщите мне.

ИЗМЕНИТЬ

Вы также можете найти дополнительную информацию о форматах чисел в этом документе: http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.numberingformat.aspx.

EDIT II

Вы можете использовать этот код для получения словаря, содержащего все форматы, определенные в файле xlsx:

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;
}

Если вы хотите проверить, является ли какая-либо из них датой, я предполагаю, что простой способ проверки того, является ли формат кода (значение в словаре, созданным методом, который я опубликовал), содержит мм и yy.