Удачи!

аюсь прочитать данные из файлов .xlsx, используя SharpZipLib для распаковки (в памяти) и чтения внутренних файлов XML. Все хорошо, но с распознаванием дат - они хранятся в юлианском формате, и мне нужно как-то распознать, является ли число датой или только числом. В другой теме (к сожалению, она умерла, и мне нужен быстрый ответ) Я кое-что узнал от Марка Бейкера, но этого все еще недостаточно ...

«Excel хранит даты в виде значения с плавающей запятой ... целочисленная часть - это количество дней с 01.01.1900 (или 01.01.1904 в зависимости от того, какой календарь используется), дробная часть - это доля дня (то есть временная часть) ... сделана немного более неловкой из-за того, что 1900 год считается високосным.

Единственное, что отличает данные от числа, это маска числового формата. Если вы можете прочитать маску формата, вы можете использовать ее для определения значения как даты, а не числа ... затем рассчитать значение даты / форматирование из базовой даты. "

«Но разве атрибут« s »для дат не всегда имеет значение« 1 »? Я знаю, что он определяет стиль, но, может быть,?)

Атрибут s ссылается на запись стиля xf в styles.xml, и это не всегда будет запись 1 для дат ... все зависит от того, сколько разных стилей используется в книге. Стиль xf, в свою очередь, ссылается на маску числового формата. Чтобы идентифицировать ячейку, содержащую дату, необходимо выполнить поиск в формате xf -> numberformat, а затем определить, является ли эта маска числового формата маской числового формата даты / времени (а не, например, в процентах или маске формата чисел учета)

"Еще один вопрос - я сейчас просматриваю содержимое style.xml и в разделе вижу такие элементы, как:" <xf numFmtId = "14" ... applyNumberFormat = "1" /> "," <xf numFmtId = "1" ... applyNumberFormat = "1" /> "и т. Д., Но нет раздела <numFmts> ... Существуют ли" стандартные "форматы? Или я что-то просто пропустил?"

Может кто-нибудь помочь мне? Заранее спасибо.

 mahe madhi30 мая 2014 г., 13:13
Вот список идентификаторов формата датыmsdn.microsoft.com/en-us/library/...

Ответы на вопрос(4)

Решение Вопроса

как часть элемента styleSheet

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
    <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
        <numFmts count="3">
            <numFmt numFmtId="164" formatCode="[$-414]mmmm\ yyyy;@" /> 
            <numFmt numFmtId="165" formatCode="0.000" /> 
            <numFmt numFmtId="166" formatCode="#,##0.000" /> 
        </numFmts>

РЕДАКТИРОВАТЬ

Я дважды проверил код читателя xlsx (прошло много времени с тех пор, как я углубился в эту часть библиотеки); и есть встроенные форматы. Коды числового формата (numFmtId) менее 164 являются «встроенными».

Список, который у меня есть, неполон:

0 = 'General';
1 = '0';
2 = '0.00';
3 = '#,##0';
4 = '#,##0.00';
5 = '$#,##0;\-$#,##0';
6 = '$#,##0;[Red]\-$#,##0';
7 = '$#,##0.00;\-$#,##0.00';
8 = '$#,##0.00;[Red]\-$#,##0.00';
9 = '0%';
10 = '0.00%';
11 = '0.00E+00';
12 = '# ?/?';
13 = '# ??/??';
14 = 'mm-dd-yy';
15 = 'd-mmm-yy';
16 = 'd-mmm';
17 = 'mmm-yy';
18 = 'h:mm AM/PM';
19 = 'h:mm:ss AM/PM';
20 = 'h:mm';
21 = 'h:mm:ss';
22 = 'm/d/yy h:mm';

37 = '#,##0 ;(#,##0)';
38 = '#,##0 ;[Red](#,##0)';
39 = '#,##0.00;(#,##0.00)';
40 = '#,##0.00;[Red](#,##0.00)';

44 = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)';
45 = 'mm:ss';
46 = '[h]:mm:ss';
47 = 'mmss.0';
48 = '##0.0E+0';
49 = '@';

27 = '[$-404]e/m/d';
30 = 'm/d/yy';
36 = '[$-404]e/m/d';
50 = '[$-404]e/m/d';
57 = '[$-404]e/m/d';

59 = 't0';
60 = 't0.00';
61 = 't#,##0';
62 = 't#,##0.00';
67 = 't0%';
68 = 't0.00%';
69 = 't# ?/?';
70 = 't# ??/??';
 brovar11 янв. 2011 г., 10:43
[после редактирования] Это все объясняет, спасибо.
 Mark Baker11 янв. 2011 г., 10:00
Вот где должны храниться numFmts. Была ли рабочая книга сгенерирована с использованием самого Excel? Если открыть файл в MS Excel, распознает ли он значения ячеек как даты?
 Mark Baker11 янв. 2011 г., 10:47
Извините за медленный, нерешительный ответ ... Прошло много времени с тех пор, как я просмотрел этот фрагмент кода, и я просто забыл о наборе "встроенных модулей". Ваш вопрос теперь побудил меня отследить других, которых у меня нет в списке.
 Mark Baker11 янв. 2011 г., 10:50
В остальной части моего кода, когда я проверяю, является ли маска формата форматом даты или времени, я проверяю наличие любых символов ymdHis в маске формата; но обратите внимание на любой из этих символов в имени цвета (например, «#, ## 0; [Cyan] (#, ## 0)») или любые маски формата, которые начинаются с «_» или «0».
 brovar11 янв. 2011 г., 10:02
Да, и ячейки форматируются как даты (если я добавлю туда число, например 40180, оно также преобразует его в дату).

Вы начинаете с захвата "s" или StyleIndex. Обратите внимание на дату в числовом формате ниже (40667):

<row r="1">
  <c r="A1" s="1">
    <v>40667</v>
  </c>
</row>

Атрибут «s» в узлах ячеек указывает на начинающийся с нуля массив узлов styles.xml, начинающийся с 0. Это ключ к поиску формата даты, если он есть, который сопоставляется с необработанными числовыми данными даты. Вы видите s = 1, который указывает на 2-й узел xf в следующем разделе style.xml форматирования ячейки вашей книги Excel:

   <cellXfs count="2">
     <xf numFmtId="0" ... />
     <xf numFmtId="14" ... />
   </cellXfs>

Во втором узле вы видите значение numFmtId = "14". Это число FormatID. Он говорит вам, что это идентификатор, необходимый для определения того, в каком номере должна быть представлена ​​ваша дата. Но это число указывает на два возможных места для формата даты. Если его число находится в диапазоне 14-22, это встроенный стиль для даты. Если он выходит за пределы этого диапазона, его (возможно) пользовательский формат даты добавляется владельцем файла Excel. Вы не будете знать, пока не проверите оба места.

В первом случае, если это значение 14-22, вам нужно будет сопоставить его с одним из предварительно созданных форматов даты, которые есть в каждом файле excel (mm-dd-yy и т. Д.). Вы можете найти эту таблицу в OpenXML SDK. Вот пример тех с numFmtId, сопоставленным со встроенными форматами даты ....

14  mm-dd-yy
15  d-mmm-yy
16  d-mmm
17  mmm-yy
18  h:mm AM/PM

На данный момент вы знаете дату и формат, в котором она будет представлена. Если это не одно из этих значений, скорее всего, это пользовательское число. И теперь вам нужно снова найти в файле styles.xml узел стиля с соответствующим значением numFmtId. Эти узлы будут содержать пользовательский формат даты следующим образом:

    <numFmts count="2">
        <numFmt numFmtId="164" formatCode="mm/yyyy;@" /> 
        <numFmt numFmtId="165" formatCode="0.000" /> 
        <numFmt numFmtId="166" formatCode="#,##0.000" /> 
    </numFmts>

Обратите внимание, что если ваш numFmtId был 164, вы нашли его пользовательский формат даты. Таким образом, чтобы поймать все эти сумасшедшие форматы даты, пользовательские и встроенные, лучше всего поддерживать диапазон допустимых «форматов» в виде строк, найти ваш formatCode и посмотреть, соответствует ли он одному из приемлемых в вашем коде.

Удачи!

которые индексируют cellXfs в таблице стилей. Каждый элемент cellXfs содержит набор атрибутов. Наиболее важным является NumberFormatID. Если его значение находится в диапазоне 14-22, это «стандартная» дата. Если он попадает в диапазон 165–180, это «форматированная» дата, которая будет иметь соответствующий атрибут NumberingFormat.

Стандартная дата

[x: c r = "A2" s = "2"] [x: v] 38046 [/ x: v] [/ x: c]

[x: xf numFmtId = "14" fontId = "0" fillId = "0" borderId = "0" xfId = "0" applyNumberFormat = "1" /] (порядковый номер 2)

Дата в формате

[x: c r = "A4" s = "4"] [x: v] 38048 [/ x: v] [/ x: c]

[x: xf numFmtId = "166" fontId = "0" fillId = "0" borderId = "0" xfId = "0" applyNumberFormat = "1" /] (порядковый номер 4)

[x: numFmt numFmtId = "166" formatCode = "m / d; @" /]

Этот код извлекает список идентификаторов стилей, которые соответствуют этим форматам даты.

  private void GetDateStyles()
  {
     //
     // The only way to tell dates from numbers is by looking at the style index. 
     // This indexes cellXfs, which contains NumberFormatIds, which index NumberingFormats.
     // This method creates a list of the style indexes that pertain to dates.
     WorkbookStylesPart workbookStylesPart = (WorkbookStylesPart) UriPartDictionary["/xl/styles.xml"];
     Stylesheet styleSheet = workbookStylesPart.Stylesheet;
     CellFormats  cellFormats = styleSheet.CellFormats;

     int i = 0;
     foreach (CellFormat cellFormat in cellFormats)
     {
        uint numberFormatId = cellFormat.NumberFormatId;
        if ((numberFormatId >= 14 && numberFormatId <= 22) 
        || (numberFormatId >= 165u && numberFormatId <= 180u))
        {
           _DateStyles.Add(i.ToString());
        }
        i++;
     }
 mahe madhi06 июн. 2014 г., 08:24
ссылка: MSDN не задокументировано должным образом. Но POI утверждает, что то же самое вссылка: Issue, Официального подтверждения в ECMA пока нет. Насколько я знаю.
 Borysław Bobulski12 апр. 2013 г., 14:12
Хорошо. Я уже знаю. _document = SpreadsheetDocument.Open (filePath, true); UriPartDictionary = BuildUriPartDictionary (_document);stackoverflow.com/a/13607098/907732
 Borysław Bobulski12 апр. 2013 г., 14:01
Как получить UriPartDictionary?

14" считался "форматом короткой даты Windows", поскольку в Австралии этот формат будет отображать дату как "dd / mm / yy", а не "mm / dd / yy".

Ваш ответ на вопрос