2011-01-20 2 views
2

Существует ли существующий API в Office Open XML SDK или сторонней стороне для правильного чтения дат из файла SpreadsheetML/.xlsx?Существующий API для чтения дат из файлов SpreadsheetML?

Поскольку существует так много переменных, которые влияют на обнаружение, когда значение является датой (numFmtId + форматы пользовательских номеров), а затем преобразование даты в значение DateTime (стандартное, обратное совместимое и совместимое с 1904-супер-назад рабочие книги), представляется логичным, что это то, что предоставил SDK, или, по крайней мере, у кого-то есть существующий фрагмент кода для обработки.

Я использую C#, но решение для любого языка будет в порядке.

ответ

1

Похоже, что нет ничего особенного для этой цели. Вот рутина, с которой я столкнулся.

/// <summary> 
/// Represents the formula used for converting date serial values stored within the workbook into DateTime instances. 
/// </summary> 
/// <remarks> 
/// Information on date serial conversion is available here: http://www.documentinteropinitiative.com/implnotes/ISO-IEC29500-2008/001.018.017.004.001.000.000.aspx 
/// </remarks> 
public enum XlsxDateCompatibility 
{ 
    /// <summary> 
    /// Standard dates are based on December 30, 1899 and are considered "Standard 1900" dates. 
    /// </summary> 
    StandardBase1900, 

    /// <summary> 
    /// Excel for Windows backwards compatible dates are based on December 31, 1899 are are considered "Backwards compatible 1900" dates. 
    /// </summary> 
    BackwardsCompatibleBase1900, 

    /// <summary> 
    /// Excel for Macintos backwards compatible dates are based on January 1, 1904 and are considered "1904" dates. 
    /// </summary> 
    BackwardsCompatibleBase1904 
} 

    private static readonly IDictionary<XlsxDateCompatibility, DateTime> _dateSerialBaseDates 
     = new Dictionary<XlsxDateCompatibility, DateTime> 
      { 
       {XlsxDateCompatibility.StandardBase1900, new DateTime(1899, 12, 30)}, 
       {XlsxDateCompatibility.BackwardsCompatibleBase1900, new DateTime(1899, 12, 31)}, 
       {XlsxDateCompatibility.BackwardsCompatibleBase1904, new DateTime(1904, 1, 1)} 
      }; 

    public static DateTime DateSerialToDateTime(double dateSerial, XlsxDateCompatibility dateCompatibility) 
    { 

     // special case for dateCompaitility 1900, Excel thinks 1900 is a leap year 
     // http://support.microsoft.com/kb/214019 
     if (dateCompatibility == XlsxDateCompatibility.BackwardsCompatibleBase1900 && dateSerial >= 61.0) 
     { 
      dateSerial -= 1; 
     } 

     DateTime baseDate;   
     if (!_dateSerialBaseDates.TryGetValue(dateCompatibility, out baseDate)) 
     { 
      baseDate = _dateSerialBaseDates[XlsxDateCompatibility.StandardBase1900]; 
     } 
     return baseDate.AddDays(dateSerial); 
    } 
0

Я никогда не читал дату раньше, но я бы предположил, что вам придется сравнить индекс стиля в ячейке, которую вы читаете, с индексом стиля даты в элементе x:numFmts, который вы найдете в x:cellStyle. Я знаю, что в офисе 2010 есть индикатор типа данных даты в ячейке, где <x:c t='d'>, поэтому, если вы используете эту версию, было бы намного легче найти, являются ли данные датой или нет. Это то, что это будет выглядеть как в Office 2010:

<x:c r="C4" t="d"> 
    <x:v>1976-11-22T08:30Z</x:v> 
</x:c> 

Для преобразования данных в DateTime Я считаю, все, что вам нужно сделать, это DateTime.FromOADate(cellvalue) где CellValue является двойной. Я знаю, что мы конвертируем DateTime в OADate, прежде чем вставлять даты в наши документы excel, поэтому я бы предположил, что использование метода FromOADate будет работать нормально.

Что касается любых функций API для выполнения этих функций, я не знаю о том, что будет выполнять то, что вы хотите, но я бы хотел, чтобы он был включен в будущие версии SDK.

+0

благодарит за комментарии. Я уже спросил и получил хорошие ответы на вопросы об определении дат и технических подробностей о том, как их читать. На самом деле это намного сложнее, чем показывает ваш ответ. У меня достаточно информации для написания пользовательского кода для чтения дат сейчас, но мне внезапно пришла в голову мысль, что это должна быть общая проблема, и был удивлен, что я не смог найти какой-либо существующий код для его обработки. –

+0

@Samuel - Да, мой ответ - это взгляд в 50 000 футов, как я могу начать решать, как идентифицировать даты в Excel, но вы определенно правы, говоря, что это сложнее, чем то, что я написал. Если вам посчастливилось понять это, мне бы очень хотелось увидеть код, так как найти ответы на основные вопросы Open XML SDK сложно. – amurra

+1

Когда я закончил, я отправлю проект. Я просто сделал с конвертером xlsx в DataSet, используя обработку стиля SAX из Open XML SDK. –