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

发布于 2024-10-13 02:30:02 字数 252 浏览 4 评论 0 原文

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

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

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

Is there an existing API in Office Open XML SDK or a 3rd party to properly read dates from a SpreadsheetML / .xlsx file?

Since there are so many variables that affect detecting when a value is a date (numFmtId + custom number formats) and then converting the date serial to a DateTime value (standard, backwards compatible, and 1904-super-backwards-compatible workbooks), it seems logical that this is something the SDK would provide or at least someone would have an existing code snippet to handle.

I'm using C# but a solution for any language would be fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野味少女 2024-10-20 02:30:02

看起来还没有任何专门针对此目的的东西。这是我想出的例程。

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

Looks like there isn't anything out there already specific to this purpose. Here's the routine I came up with.

/// <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);
    }
九歌凝 2024-10-20 02:30:02

我以前从未读取过日期,但我想您必须将正在读取的单元格上的样式索引与 x:numFmts 元素中的日期样式索引进行比较,您将在x:cellStyle中查找。我知道 Office 2010 在单元格上有一个日期数据类型指示器,其中 因此,如果您使用该版本,查找数据是否会更容易是否是一个日期。这就是 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,我不知道是否有任何 API 可以执行您想要的操作,但我希望它将包含在 SDK 的未来版本中。

I have never read a Date in before, but I'd imagine you would have to compare the style index on the cell you are reading to the date style index in the x:numFmts element, which you would find in the x:cellStyle. I know office 2010 has a date data type indicator on the cell where <x:c t='d'> so if you are using that version it would be a lot easier to find if the data is a date or not. This is what it would look like in Office 2010:

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

To convert the data into a DateTime I believe all you have to do is a DateTime.FromOADate(cellvalue) where cellValue is a double. I know we convert a DateTime to an OADate before inserting dates into our excel documents so I'd imagine using the FromOADate method would work fine.

As far as any API's to do these functions, I am not aware of any that will perform what you want, but I wish it would be included in future versions of the SDK.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文