2017-01-23 46 views
0

我有一个Excel工作表与人的生日列表,内容是这样的:C# - Excel中日期不及格日期序列中值2

Mary 08/17/1993 
John 01/23/1991 
Ann 12/07/1989 

凡左边栏有一个“常规”格式,而右列有'DATE'格式。意图是有一个windows服务,每天会读这份生日列表并发送任何“生日快乐!”适用的电子邮件。

这是我使用的代码读取Excel数据:

public static List<Tuple<string, DateTime>> getBirthdays() 
{ 
    List<Tuple<string, DateTime>> birthdays = new List<Tuple<string, DateTime>>(); 

    Excel.Application xlApp = new Excel.Application(); 
    Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(@"C:\Users\AGuaja\Desktop\birthdays.xlsx"); 
    Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1]; 
    Excel.Range xlRange = xlWorksheet.UsedRange; 

    int rowCount = xlRange.Rows.Count; 
    int colCount = xlRange.Columns.Count; 

    string user = String.Empty; 
    DateTime bday = DateTime.Now; 

    for (int i = 1; i <= rowCount; i++) 
    { 
     for (int j = 1; j <= colCount; j++) 
     { 
      if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null) 
      { 
       if (j == 1) 
        user = xlRange.Cells[i, j].Value2.ToString(); 
       else 
        bday = DateTime.FromOADate(double.Parse(xlRange.Cells[i, j].Value2)); 
      } 
     } 
     birthdays.Add(new Tuple<string, DateTime>(user, bday)); 
    } 

    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 

    Marshal.ReleaseComObject(xlRange); 
    Marshal.ReleaseComObject(xlWorksheet); 

    xlWorkbook.Close(); 
    Marshal.ReleaseComObject(xlWorkbook); 

    xlApp.Quit(); 
    Marshal.ReleaseComObject(xlApp); 

    return birthdays; 
} 

了一下才知道是正确的方式来获得的日期从Excel是使用FromOADate方法摸索之后,例如,其预期以40599的形式的double值表示日期。然而,我的Value2没有返回日期序列,而是上面看到的格式的值,12/07/1989,因此我无法使用转换Excel日期的“正确方法” 。

我的意思是,当然,我可以只使用Value2的字符串并将其解析为日期,但为什么该值无法正确传递?

+2

在你的Excel中,你是否将行格式化为DATE?如果你不是他们是 存储为文本值,你不会得到内部双值。 – dgorti

+0

@dgorti是的,我明确地确定了这一点,因为我认为那是原始问题,但那不是。 –

+0

明白了,你在你的文章中提到过。让我掀起一个样本,看看发生了什么 – dgorti

回答

1

我认为你可能会让它变得比它更复杂。如果您只是从单元格中寻找日期...请使用DateTime.TryParse(…)。即使列设置为Date,用户也可以按照Excel中的任何方式执行此操作,用户可以根据需要输入任意内容。问题是你不能依靠excel来返回一个有效日期,所以只需检查它是否有效并做出适当的反应。下面的代码将做到这一点。

DateTime cellDate; 
if (DateTime.TryParse(xlRange.Cells[i, j].Value, out cellDate)) { 
    Console.WriteLine("Valid Date: " + cellDate.ToLongDateString()); 
} 
else { 
    Console.WriteLine("Date Is Invalid: " + xlRange.Cells[i, j].Value); 
} 

希望这会有所帮助!

编辑为OP回答

我很高兴你找到你所遇到的问题。不过,我必须说,我认为你仍然错过了我的观点。 您不能依赖具有适当值的Excel单元格。在大多数情况下,如果您从Excel单元格中获取值并且想要在程序中使用这些值来获取除字符串之外的其他值,则必须验证此值,以防止代码崩溃。在你的修复中......你只是确保Excel单元格中的值格式正确。将来,如果您无意中输入错误的格式,您的程序将崩溃。这在任何环境中都是不可取的。

使用你的发送生日电子邮件或电子名片的例子是微不足道的,没有那么重要,除非有人真的想要他们的生日电子名片。在这个“生日”情况下,忽略无效数据是可以接受的;然而,它可能很高兴知道它为什么没有发送。在您当前的代码中,您将通过崩溃意识到这种情况。所以你必须去查找无效日期,如果它足够重要并在Excel中修复它。

根据您的描述,让我们假设它足够重要,以尝试修复无效日期。这里出现了几个问题。正如你在答案中所说的那样,你有MM/DD/YYYY(美国)日期,这些日期默认为dd/MM/YYYY格式 ......在这种情况下,只有“你”会知道这一点。如果其他人输入的日期不可能知道03/10/1997是否正确,或者10/03/1997是正确的,因为两者都是有效日期。在这种情况下,它只是错误的生日日期,无论是由您还是其他用户输入。当两个日期都有效时,你可以做的绝对零,以防止这种情况发生。如果一家大公司犯了这个错误,直到客户抱怨他们在错误的日期得到他们的生日电子名片才可能知道。

最后,当我开始时,您当前的代码有一个错误,并且如果日期格式无效将会崩溃。这里的问题是,你知道这一点,并没有解决你的代码中的这种情况。这是错误的方法;修复你的代码,使其不会崩溃。

+0

在Excel中的数据*假设*是可靠的,但你确实有一点。为了“良好实践”,我还可以添加另一个if语句试图进行转换,而不是使用'FromOADate'。如果没有其他答案出现,我会标记这一个,谢谢。 –

+0

你会将无效日期更改为? – JohnG

+0

可能没有添加条目。如果日期错误并且无法解析,那么该人不会得到生日快乐。 –

0

所以经过一些调试后,我意识到问题所在。我输入了MM/dd/YYYY(美国)的日期,而不是dd/MM/YYYY格式。尽管字符串在技术上是正确的,但是日期本身当然是无效的,这就是为什么没有日期序列被传递。

更改日期以匹配正确的格式(或者指定美国惯例为他们)解决了问题。

+0

请在我的回答中看到我添加的评论。 – JohnG