【问题标题】:DateTime from XLS to C# conversion failureDateTime 从 XLS 到 C# 转换失败
【发布时间】:2012-08-24 08:36:16
【问题描述】:

我正在使用 Office 2003 文档 (.xls) 开发 VS2008 .NET3.5。我正在使用 Microsoft.Office.Interop.Excel 访问文档。

这很适合我的目的,但每当我尝试获取日期时都会失败。

我使用的方式是最常见的:

object date= xlWorkSheet.get_Range("E" + i, "E" + i).Value2;
double doubleDate = double.Parse(date);
DateTime finallyDate = DateTime.FromOADate(doubleDate);

我存储的日期是 1961 年 1 月 12 日(意大利语表示 12 月 1 日,如果我打开 excel,它会告诉我 1961 年 12 月 1 日)。

当我运行我的应用程序时,恰好 double 的值变为 15011.0,而 finallyDate 值是 2/4/1941 时,这是不对的!

我该如何解决这个问题?有什么方法可以转换(也可以手动)该 15011 号码?

谢谢!!

【问题讨论】:

  • 在解析之前,date 本身的值究竟是什么? (鉴于date 被声明为object...,我很惊讶上面的代码甚至可以编译...)
  • @JonSkeet 使用 Excel 互操作(在可以使用动态的 C#4 之前)我认为所有内容都作为对象返回。要使用赋值运算符左侧的对象以外的任何对象,您需要根据需要在右侧进行强制转换
  • @JMK:当然,我对第一个语句没意见 - 但没有 double.Parse(object) 方法...
  • @JonSkeet 对不起,我没有看到,我只是测试了它,你当然是对的,它无法编译!
  • 单元格的值为:12/1/1961..

标签: c# excel date type-conversion


【解决方案1】:

对于你问题的第一部分,我该如何解决这个问题?

确保

  1. 文档已保存。
  2. 您正在访问正确的单元格。

对于问题的第二部分,有没有办法(也可以手动)转换 15011 号码?

15011 实际上是从 1-1-1900 的天数。我通常只是将提到的数字除以 365 来得到一个粗略的日期。你会问为什么粗糙?因为有些年份有 366 天,我们需要考虑闰年。

如果您需要使用序列号准确计算日期,您可能需要使用此处找到的方法。 http://naspinski.net/post/Translate-an-Excel-Serial-Date-into-a-C-DateTime.aspx

public DateTime ExcelSerialDateToDT(int nSerialDate)
 {
 int l = nSerialDate + 68569 + 2415019;
 int n = ((4 * l) / 146097);
 l = l - ((146097 * n + 3) / 4);
 int i = ((4000 * (l + 1)) / 1461001);
 l = l - ((1461 * i) / 4) + 31;
 int j = ((80 * l) / 2447);
 int nDay = l - ((2447 * j) / 80);
 l = (j / 11);
 int nMonth = j + 2 - (12 * l);
 int nYear = 100 * (n - 49) + i + l;

return DateTime.Parse(nMonth + "/" + nDay + "/" + nYear);
 } 

您可以在 Microsoft Office Excel 上阅读更多关于此行为的原因 http://www.codeproject.com/Articles/2750/Excel-serial-date-to-Day-Month-Year-and-vise-versa

【讨论】:

  • 嗨.. 文档已保存,我正在访问正确的单元格.. 如果我使用您建议的代码,我会得到与从 excel 获得的相同错误日期.. 我得到 2/4/ 1941 年 12/1/1961
  • 以上是静态 DateTime.FromOADate() 的一个相当糟糕的版本
【解决方案2】:

获取 Value 属性而不是 Value2,然后您将能够使用 Date 对象。您可能需要将其转换为 (DateTime)。

使用 Value2 得到的是 Date 的浮点值。

例如,看看我下面的电子表格,其中 A1 包含一个日期:

然后在 Excel 中,我添加对 Microsoft.Office.Interop.Excel 的引用,并像这样获取 Value 和 Value2 属性:

var excel = new Excel.Application();

var workbook = excel.Workbooks.Open(@"C:\Test\Test.xlsx");
var worksheet = (Excel.Worksheet)workbook.Sheets[1];

Excel.Range range = worksheet.get_Range("A1");

var rangeAsValue = range.Value;
var rangeAsValue2 = range.Value2;

Console.WriteLine(rangeAsValue);
Console.WriteLine(rangeAsValue2);

Console.ReadLine();

我得到这个输出:

有趣的是,如果您在 .Net 4.5 应用程序中尝试此操作,它仍然有效,但 var 的类型对于 rangeAsValue 和 rangeAsValue2 被解析为动态,并且您失去了智能感知。

【讨论】:

  • 嗨!我正在使用 Microsoft Excel 12.0 对象库...使用您的代码,我看不到 Value,而只能看到 Value2!
  • 我也在使用 12.0 库,并针对 .net 3.5 客户端框架,这对我有用。我需要添加的唯一 using 语句是 using Excel = Microsoft.Office.Interop.Excel;
  • 不知道为什么,但它仍然不会给出日期,而是给出一些数字...... :(
猜你喜欢
  • 2017-12-25
  • 1970-01-01
  • 1970-01-01
  • 2017-11-29
  • 1970-01-01
  • 2013-06-21
  • 1970-01-01
  • 2014-01-08
  • 2013-12-05
相关资源
最近更新 更多