【问题标题】:.NET DataTable is mangling date field from an Excel file.NET DataTable 正在从 Excel 文件中修改日期字段
【发布时间】:2014-01-07 12:49:02
【问题描述】:

我现在正在为工作编写大量的提取转换加载代码。为了更容易从 SSIS 中读取用户生成的 Excel 电子表格中的数据,我编写了一个小库,它从 Excel 文件中读取列标题布局,并将数据转储到 MS SQL 数据库中的表中,该表具有与 Excel 文件相同的架构。到目前为止它运行良好,但我遇到了一些奇怪的问题。

(是的,我知道 SSIS 本身就支持这样的东西。我选择的方法有技术原因,解释它们超出了本文的范围。)

问题在于,对于某些输入文件,任何包含日期信息的列都会被破坏。例如,当我执行导入时,日期字符串12/09/2013 被修改为41617Dec 9, 2013 9:19:58 AM 变为 41617.388866。我正在检查它是否试图将12/09/2013 视为数学方程式,但(12/09)/2013 = 6.62361。此外,我检查了此电子表格上的单元格格式以及其他一些导入日期字段且没有错误的其他格式,并且在任何地方都是相同的 - 自定义、mm/dd/yyyy。

这里最大的问题是,由于我编写的过程的性质,一切都取决于我在运行时不知道文件的结构。我可以即时转换数据,但我不知道如何从41617 向后工作到12/09/2013

DateTime.TryParse 也无济于事:

DateTime dt;
DateTime.TryParse("41617", out dt);
Console.WriteLine(dt.ToString());

输出

1/1/0001 12:00:00 AM

这是我遇到问题的电子表格的剥离、去标识化副本的链接:View / Download from Google Drive

我正在使用 OLE DB 连接字符串从 Excel (2007) 文件中读取数据:

"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FilePath + ";Extended Properties = \"Excel 12.0 XML; HDR=YES; IMEX=1\";"

使用互操作类不是一种选择。它们没有在服务器上设置,作为承包商,我不太可能让 IT 进行设置。

然后,我使用 OleDbCommand(),它只针对 Excel 工作表运行 SELECT *,并用结果填充 DataSet。

这让我很困惑,如果能提供任何帮助,我将不胜感激。

【问题讨论】:

    标签: c# .net excel oledb etl


    【解决方案1】:

    尝试使用

    DateTime.FromOADate(value)
    

    【讨论】:

    • 感谢您发布这个 - 这是一个更清洁的解决方案......但我很高兴 Rik 发布了他的答案,因为背景真的很有趣!
    • 请记住,对于 1899-12-31 和 1900-03-01 之间的日期,它将关闭 1。
    【解决方案2】:

    编辑 我实际上建议使用Joe's answer(我之前还不知道)。请记住,对于 1899-12-31 和 1900-03-01 之间的日期,它将关闭 1。 我在这里留下我的答案以提供一些背景信息。

    Excel 将日期存储为从 1900 年 1 月 1 日(第 1 天)开始经过的天数,但它将 1900 年视为闰年。 (由于 Lotus 123 的一个错误,他们希望与之兼容)所以 1900 年 2 月 28 日之后的日期有额外的一天。

    我们心爱的 Joel Spolsky 几年前写信 an article 提到了这一点。

    您可以使用此方法将整数 Excel 日期转换为 DateTime

    public static DateTime ConvertFromExcelDate(int excelDate)
    {
        if (excelDate > 59) excelDate--; // 59 == februari 29
        return (new DateTime(1899,12,31)).AddDays(excelDate); // 19000101 == 1, so 18991231 == 0
    }
    

    请务必在您的代码中清楚地记录这一点,因为这肯定会在将来为不熟悉此问题的人提出问题。

    【讨论】:

    • 好的 - 我们在这里做一些事情......我的目标值是 12/09/2013,但是 new DateTime(1900, 1, 1).AddDays(41617) 返回 12/11/ 2013 - 我可以安全地假设我可以从这些列的整数值中减去 2(1 代表闰日,1 代表 1 月 1 日本身的值)?
    • 查看我的编辑。我确定您不必正确处理 1900 年 3 月 1 日之前的日期,您只需减去 2。
    • 为了学究气,经过一点实验,我发现Excel实际上将0视为1900年1月0日,.NET Framework无法处理,所以1899年12月31日是正确的开始日期。您的功能非常完美 - 非常感谢您的宝贵时间!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多