简体   繁体   English

C#-Excel日期未通过Value2中的日期序列

[英]C# - Excel date not passing date serial in Value2

I have an Excel sheet with a list of people's birthdays that reads like this: 我有一个Excel工作表,上面列出了人们的生日,内容如下:

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

Where the left column has a 'GENERAL' format, and the right column has a 'DATE' format. 左列为“ GENERAL”格式,右列为“ DATE”格式。 The intent is to have a windows service that will be reading this list of birthdays every day and send out any "Happy Birthday!" 目的是要有一个Windows服务,该服务将每天读取此生日列表并发送任何“生日快乐!”。 emails that apply. 适用的电子邮件。

This is the code I'm using for reading the excel data: 这是我用来读取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;
}

After searching around for a bit I learned that the correct way to get a date from Excel was to use the FromOADate method, which expects a double value in the form of 40599, for instance, to represent a date. 经过一番搜索后,我了解到从Excel获取日期的正确方法是使用FromOADate方法,该方法期望以40599的形式表示的double精度值表示日期。 The thing is however, that my Value2 is not returning that date serial, but instead the value in the format seen above, 12/07/1989, and as such I'm not able to use the 'proper way' of converting Excel dates. 但是,问题是,我的Value2并未返回该日期序列,而是以上面所示的格式(1989年12月7日)返回该值,因此我无法使用转换Excel日期的“正确方法” 。

I mean, sure, I can just use Value2 's string and parse that as a Date, but why is the value not being passed on properly in the first place? 我的意思是,可以,我只可以使用Value2的字符串并将其解析为Date,但是为什么不能首先正确传递该值呢?

I think you may be making this more complicated than it has to be. 我认为您可能会使事情变得比实际复杂。 If you are simply looking for a date from the cell… use a DateTime.TryParse(…) . 如果只是从单元格中查找日期,请使用DateTime.TryParse(…) You will have to do this any way as in Excel even if the column is set as a Date the user can pretty much type whatever they want. 即使将列设置为Date ,用户也可以使用Excel中的任何方式执行此操作,而用户几乎可以键入所需的任何内容。 The point being that you cannot depend on excel to return a VALID date, so simply check to see if it is valid and react appropriately. 关键是您不能依靠excel返回有效日期,因此只需检查它是否有效并做出适当反应即可。 The code below will do this. 下面的代码将执行此操作。

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

Hope this helps! 希望这可以帮助!

Edit for OP Answer 编辑OP答案

I am glad you found the problem you were having. 很高兴您发现您遇到的问题。 I must say however that I think you are still missing my point. 但是,我必须说,我认为您仍然不明白我的意思。 You cannot depend on an Excel Cell having a proper value. 您不能依赖具有适当值的Excel单元格。 In most cases, if you get values from excel cells and you want to use those values in your program for something other than strings, you MUST validate this value simply to prevent your code from crashing. 在大多数情况下,如果您从excel单元中获取值,并且想要在程序中将这些值用于除字符串之外的其他内容,则必须仅对此值进行验证,以防止代码崩溃。 In your fix… you are simply making sure the value in the excel cell is formatted properly. 在修复过程中……您只是要确保excel单元格中的值格式正确。 In the future, if you inadvertently type in the wrong format your program will crash. 将来,如果您不小心输入了错误的格式,则程序将崩溃。 This would be undesirable in any environment. 在任何环境下这都是不希望的。

Using your example of sending out a birthday email or eCard is trivial and not that important unless someone really wants their birthday eCard. 使用您发送生日电子邮件或eCard的示例很简单,而且并不重要,除非有人真的想要他们的生日eCard。 In this “birthday” case ignoring the invalid data is acceptable; 在这种“生日”情况下,忽略无效数据是可以接受的; however it may be nice to know why it didn't get sent. 但是,很高兴知道为什么没有发送。 In your current code you will be made aware of this situation by crashing. 在您当前的代码中,崩溃将使您意识到这种情况。 So you have to go and look for the invalid date if it's important enough and fix it in excel. 因此,您必须去寻找无效的日期(如果它足够重要),然后在excel中进行修复。

Given your description let's assume it WAS important enough to try and fix the invalid date. 根据您的描述,让我们假设它足够重要,可以尝试解决无效日期。 There are several issues that arise here. 这里出现几个问题。 As you said in your answer you had the MM/dd/YYYY(US) dates that were defaulting to the dd/MM/YYYY format ... In this case only “YOU” would know this. 如您在回答中所说,您的MM / dd / YYYY(US)日期默认为dd / MM / YYYY格式 ...在这种情况下,只有“ YOU”会知道。 If someone else typed in the date you could not possibly know if 03/10/1997 was correct or 10/03/1997 was correct as BOTH are valid dates. 如果其他人输入了日期,则您可能无法确定03/10/1997是正确的还是10/03/1997是正确的,因为两者都是有效日期。 In this case it would simply be the wrong birthday date, either typed in by you or another user. 在这种情况下,这可能是您或其他用户输入的错误的生日日期。 There is absolutely zero you can do to prevent this from happening as both dates are valid. 由于两个日期均有效,因此您可以采取绝对的措施来防止这种情况的发生。 If a large company makes this mistake, it may never be known until the customer complains that they are getting their birthday eCard on the wrong date. 如果一家大公司犯了这个错误,那么直到客户抱怨他们在错误的日期获取生日电子贺卡之前,它可能永远不会被知道。

Lastly, as I started, your current code has a bug and will crash if the date is in an invalid format. 最后,当我开始时,您当前的代码有一个错误,如果日期格式无效,它将崩溃。 The problem here is that YOU know this, and do not address this situation in your code. 这里的问题是您知道这一点,并且没有在代码中解决这种情况。 This is the wrong approach; 这是错误的方法。 fix your code so it doesn't crash. 修复您的代码,以免崩溃。

So after some debugging I realized what the problem was. 因此,经过一些调试,我意识到了问题所在。 I had entered MM/dd/YYYY (US) dates that were defaulting to the dd/MM/YYYY format instead. 我输入的MM/dd/YYYY (US)日期默认为dd/MM/YYYY格式。 And though the string was technically correct, the date itself was invalid of course, which is why no date serial was being passed. 尽管字符串在技术上是正确的,但日期本身当然是无效的,这就是为什么没有传递日期序列的原因。

Changing the date to match the correct format (or alternatively specifying the US convention for them) solved the problem. 更改日期以匹配正确的格式(或为它们指定美国惯例)可以解决此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM