3

I am writing an Excel app that will read and write specified values from an Excel file, and display them to the user. However, when I try to read from a cell which has a Number Format or a function typed 'hh:min' (Hour:Min) I cannot obtain that value how exactly I want.

Here is my code...

ws[dateTimePicker1.Value.Day + 1].get_Range("F" + i.ToString(), Type.Missing);
    if (range.Value2 != null)  
        val += " - " + range.Value2.ToString();   //Sets FXX to val
    lbHK1.Items.Add(val);

Where...

  • ws = my worksheet
  • dateTimePicker1 = my date time picker which helps me decide which file will be opened
  • i = is an integer that helps me decide Row number of that cell
  • range = is an object created from Microsoft.Office.Interop.Excel.Range

In my example, when i = 11, F11 is the cell that contains the time value which is 06:30 (in Excel, fx : 06:30:00). However, when I try to get that value, it returns a double type such as 0.263888888888889

How can I get the value formatted correctly as it is displayed in Excel, rather than a meaningless double value?

wattostudios
  • 8,666
  • 13
  • 43
  • 57
msharpp
  • 31
  • 1
  • 2

3 Answers3

5

Excel stores times internally as doubles containing decimal fractions of a 24-hour day: so 6:30 AM would be 0.2708333

Charles Williams
  • 23,121
  • 5
  • 38
  • 38
  • It's interesting because when I get the value type by GetType() method it says it is a double value type. Either way, so how am I going to solve that problem then? Can you type a simple code here? – msharpp Mar 13 '11 at 17:22
5

When dealing with Excel dates, the date can either be stored as a string representation of a date, or it may be an OA date (OLE Automation Date). I've found that checking for both types is the safest route when parsing Excel dates.

Here's an extension method I wrote for the conversion:

/// <summary>
/// Sometimes the date from Excel is a string, other times it is an OA Date:
/// Excel stores date values as a Double representing the number of days from January 1, 1900.
/// Need to use the FromOADate method which takes a Double and converts to a Date.
/// OA = OLE Automation compatible.
/// </summary>
/// <param name="date">a string to parse into a date</param>
/// <returns>a DateTime value; if the string could not be parsed, returns DateTime.MinValue</returns>
public static DateTime ParseExcelDate( this string date )
{
    DateTime dt;
    if( DateTime.TryParse( date, out dt ) )
    {
        return dt;
    }

    double oaDate;
    if( double.TryParse( date, out oaDate ) )
    {
        return DateTime.FromOADate( oaDate );
    }

    return DateTime.MinValue;
}

In your example, the usage would be:

TimeSpan time = f11Value.ParseExcelDate().TimeOfDay;
Metro Smurf
  • 37,266
  • 20
  • 108
  • 140
2

Excel stores time in fractions of a day, 12:00 will be stored as 0.5 since 12/24 = 1/2 = 0.5

To get the hours you have to multiply the excel time by 24 and then round the result to an integer.

To get the minutes (since a day has 1440 minutes) you have to multiply the value by 1440, this will give you the minutes passed since 00:00, you'll need to divide by 60 and work over the remainder of the operation to get the time in minutes.

Here's a snippet:

string parseExcelHour(string cellInput){

    double excelHour = 0;

    try{
        excelHour = Double.Parse(cellInput);
    }catch { }

    int hour = (int) (excelHour * 24);// with the int cast you get only an integer.
    int min = (int) (excelHour * 1440 % 60); //mod (%) takes only the remainder and then the cast to int will round the number

    return (hour < 10? "0":"") + hour + ":" + (min < 10? "0":"") + min; //will print HH:mm
}
Cheloide
  • 793
  • 6
  • 21
  • Good effort and works in some cases. Unfortunately it doesn't parse all times correctly. I had 17:05 come back as 17:4 – Shumii May 07 '16 at 06:46
  • @Shumii Since float and double operations are not precise, you can lose some data and get 29.999999 minutes instead of 30. – Cheloide Sep 26 '17 at 14:46