用于从SpreadsheetML文件中读取日期的现有API?

时间:2011-01-20 03:32:33

标签: c# excel openxml openxml-sdk spreadsheetml

Office Open XML SDK或第三方是否存在现有API以正确读取SpreadsheetML / .xlsx文件中的日期?

由于有太多的变量影响检测值是一个日期(numFmtId +自定义数字格式),然后将日期序列转换为DateTime值(标准,向后兼容,以及1904-超向后兼容的工作簿) ),这似乎是合乎逻辑的,这是SDK提供的东西,或者至少有人会有一个现有的代码片段来处理。

我正在使用C#,但任何语言的解决方案都可以。

2 个答案:

答案 0 :(得分: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);
    }

答案 1 :(得分:0)

我以前从未阅读过Date,但我想你必须将你正在阅读的单元格上的样式索引与x:numFmts元素中的日期样式索引进行比较,你可以在x:cellStyle。我知道office 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是一个双精度数。我知道在将日期插入我们的Excel文档之前,我们将DateTime转换为OADate,所以我想使用FromOADate方法可以正常工作。

对于执行这些功能的任何API,我不知道任何能执行您想要的功能,但我希望它将包含在SDK的未来版本中。