OWC11 Date Formatting Ignored - c#

I am creating an Excel document using owc11. I am providing the dates in dd/mm/yyyy format. I am doing something like this in the code:
for (..looping through results..)
{
Range c = EmailStats.putCellValue(sheet, row, 1, val);
c.set_NumberFormat("dd/mm/yyyy");
}
private static Range putCellValue(Worksheet sheet, int row, int col, String val)
{
Range cell = (Range) sheet.Cells[row, col];
cell.set_Value(XlRangeValueType.xlRangeValueDefault, val);
return cell;
}
Now when for the val argument I set the date format as "dd/mm/yyyy" or not set it at all, the behaviour I get is mm/dd/yyyy from the 1st of a month up and till the 12th and then it swaps back to dd/mm/yyyy. So owc11 thinks that it knows better and swaps the days and month around (like in the US format) and when it is over the 12th date it sticks to the UK format.
Val is declared as String because it may not always be a date. It may be a date, a day, a user name, group name etc depending on how we group/sort our data. Also it may be a selection of days.
After experimenting a while I figured out that the only way to solve this is to use the universal date format of yyyy/mm/dd. However that may create other integration problems. So I was hoping that there may be a way to enforce the dd/mm/yyyy format, so please any suggestions are welcome.

Try to set val as not string. Try assign val as DateTime.
cell.set_Value(XlRangeValueType.xlRangeValueDefault, val);

Related

Input string was not in a correct format while reading date from excel

I am trying to upload an excel sheet. Now I am getting an error for the date column. I was able to fix it up to this point base on some suggestions here. This is the date format on the excel 20/4/2020
But I couldn't figure it out from this point. I kept getting. I was able to get the Value from the excel sheet and stored in string date
Input string was not in a correct format.
at System.Number.ThrowOverflowOrFormatException(ParsingStatus status,
TypeCode type) at System.Double.Parse(String s)
Here is my code below
//be on the first column [r,c]
int row = 2;
for (int i = 2; i <= noOfRow; i++) //start from the second row
{
if (!string.IsNullOrEmpty(workSheet.Cells[i, 3].Text))
{
string date = workSheet.Cells[i, 3].Value.ToString();
try
{
double d = double.Parse(date);//Error is coming from here
DateTime conv = DateTime.FromOADate(d);
}
catch (Exception ex)
{}
}
}
I will appreciate if someone can help me out
Thanks
The problem occurs because value in the variable date = "11/5/2020" is not a double value. It is a DateTime value. To fix you problem you should use the next code to convert value in the date variable into DateTime value:
DateTime d = DateTime.ParseExact(date, "d/M/yyyy", CultureInfo.InvariantCulture);
Method DateTime.ParseExact allows you to set the format of the parsed date.
The above code worked for me the day you shared with me. But now I am
getting this error {"String '6/3/2020 12:00:00 AM' was not recognized
as a valid DateTime."} I have tried implementing almost everything on
stackoverflow.
If date string in your excel file can be in different formats, then you can use overload of the method DateTime.ParseExact that supports specifying several parse formats. For example:
string[] formats = {"d/M/yyyy", "d/M/yyyy hh:mm:ss tt"};
DateTime d = DateTime.ParseExact(date, formats, CultureInfo.InvariantCulture, DateTimeStyles.None);
Here is complete sample that demostrates this overload of the method DateTime.ParseExact.

Convert time-formatted column in excel to C# DateTime

I am currently using the Excel C# libraries (Microsoft.Office.Interop.Excel) to read an excel spreadsheet into my C# application.
I initially tried to read all the cells as their raw data, but found that Date-formatted cells were giving me a 5-digit integer, and time-formatted cells were returning a decimal. So I then found out that you can use a date-conversion method built into Excel's C# library, like so:
DateTime excelDate = (DateTime)ExcelCalcValue.ExcelDateToDateTime(workbook, Double.Parse(cell.Value.ToString()));
output = excelDate.ToString("yyyy-MM-dd HH:mm");
Through debugging my application with various test sheets, I have been able to record the various format strings that cells return when they are formatted in different ways. These are below:
(WorksheetCell.CellFormat.FormatString)
Times
[$-F400]h:mm:ss\\ AM/PM
hh:mm:ss;#
h:mm:ss;#
[$-409]hh:mm:ss\\ AM/PM;#
[$-409]h:mm:ss\\ AM/PM;#
Dates
m/d/yy
[$-F800]dddd\\,\\ mmmm\\ dd\\,\\ yyyy
dd/mm/yyyy;#
dd/mm/yy;#
d/m/yy;#
d\\.m\\.yy;#
yyyy\\-mm\\-dd;#
[$-809]dd\\ mmmm\\ yyyy;#
[$-809]d\\ mmmm\\ yyyy;#
Using these, I can now reliably determine the formatting style of a cell in excel. Using the earlier code, I can detect a date-formatted cell and return the proper data in DateTime format. However, I cannot see an equivalent function for converting time-formatted cells.
I get a result of 0.58368055555555554 when I read a cell time-formatted as [$-F400]h:mm:ss\\ AM/PM. I have absolutely no idea how to convert this into a DateTime, or indeed what this float represents.
Can anyone suggest a method of converting time-formatted excel cells (which are stored as a strange float) into the correct DateTime variable?
As FrankPI said, use DateTime.FromOADate(). You would use this function with the raw data from an Excel cell - there is no need to parse the format.
Excel encodes its dates and times in a double. The integral portion represents the days after January 1, 1900. The fraction part represents the time since midnight of the day referenced. For example:
1.5 is January 1, 1900 # Noon
and
41507.25 = August 21, 2013 # 6:00 am
Refer to the MSDN docs on this function for more information:
http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx
The "strange float" can probably be converted too a DateTime via the DateTime.FromOADate() method. Actually, it is the number of days since January, 1, 1900 with the time as fractions, e. g. 0.04236 = 1/24 + 1/(24 * 60) for 1:01 am.
I wrote this function to handle a date input from Excel into C#. It handles a number of data type possibilities for a date cell:
/// <summary>
/// Returns DateTime?
/// Excel dates are double values, and sometimes, they're typical dd/mm/yyyy dates.
/// This function handles both possibilities, and the possibility of a blank date input.
/// ///
/// </summary>
/// <param name="inputDate"></param>
/// <returns></returns>
private static DateTime? ResolveExcelDateInput(string inputDate)
{
double incomingDate = 0;
DateTime incomingDateDate = new DateTime();
// If the incoming date is a double type, parse it into DateTime
if (Double.TryParse(inputDate, out incomingDate))
{
return DateTime.FromOADate(incomingDate);
}
// IF the incoming date value is a date type, parse it.
var parseDateResult = DateTime.TryParse(inputDate, out incomingDateDate);
if(parseDateResult)
{
// If the parse is successful return the date
return incomingDateDate;
}
else
{
// If the parse isn't successful; check if this a blank value and set to a default value.
if(string.IsNullOrWhiteSpace(inputDate))
{
return new DateTime(1901, 1, 1);
}
else
{
// Otherwise return null value so that is then handled by the validation logic.
// log a validation result because inputDate is likely an invalid string value that has nothing to do with dates.
return null;
}
}
}
If you want that either date value is in double format or in date format it converts it to date format then try to use following code. datestringvalue should be your input value.
DateTime dateNow = DateTime.Now;
DateTime formatedDate = DateTime.TryParse("datestringvalue", out dateNow) ? Convert.ToDateTime("datestringvalue") : DateTime.FromOADate(Convert.ToDouble("datestringvalue"));

How to remove year from datetime object?

I have a gridview that is bound to a datatable from a db. One of the columns is a datetime field which I got to read in shortdate mode (mm/dd/yyyy). However, I was wondering if there was any easy to remove the year from the date time either in the cell or at the time of display.
//Convert the "date" column to only appear in mm/dd format
foreach (GridViewRow row in GridView1.Rows)
{
String myS = row.Cells[2].Text;
DateTime dt = DateTime.Parse(row.Cells[2].Text);
row.Cells[2].Text = dt.ToShortDateString();
}
Use the standard ToString date formatter, with capital MM meaning "month month" and lower-case dd "day day"
row.Cells[2].Text = dt.ToString("MM/dd");
The answer really depends on if you want to support I18N/L10N. If you're interested in your date coming out something like "June 15" in en-US or "15. juni" in da-DK, you could use:
row.Cells[2].Text = dt.ToString("M");
If, on the other hand, you're interested in your date always coming out "06/15", regardless of culture, you can use:
row.Cells[2].Text = dt.ToString("MM/dd");
As far as I can tell, there's no internationalized standard date/time format for Month/Day, but you can check out the full list of standard formats for yourself at MSDN - Standard Date and Time Format Strings.

how can i assign only year say 2011 in a datetime variable in c#

I have a asp Text box as
where the user will fill only a year value, For this value I have Datetime type Property in c# application and Date type column in DB. So I want to convert that txtYear.Text to DateTime But it will only hold and/or show the year. Please help me in this situation.
A DateTime object will always hold a complete DateTime value, you can't use it to store a year only. (what use would that be anyway?) Besides, the datatype of a "year" is int, not DateTime.
So, I'd like to suggest changing your property to datatype int, both in your code and database.
To display just the year use the format "yyyy".
string s = "2011";
DateTime d = new DateTime(int.Parse(s), 1, 1);
Console.WriteLine(d.ToString("yyyy"));
Console.WriteLine(d);
You have to specify the format of the DateTime value you are manipulating:
String dateTimeFormat = "yyyy";
To show only a part of the DateTime value use the following:
dateTimeValue.ToString(dateTimeFormat);
To read a String value that represents a year into a DateTime use the following:
DateTime.ParseExact(stringValue, dateTimeFormat, CultureInfo.InvariantCulture);
DateTime.ParseExact Method (String, String, IFormatProvider) converts the specified string representation of a date and time to its DateTime equivalent using the specified format and culture-specific format information. The format of the string representation must match the specified format exactly.
DateTime.ToString Method converts the value of the current DateTime object to its equivalent string representation.
Rather than applying any string manipulating function make use of Year property. Check the documentation on the msdn by visiting below link.
DateTime.Year Property
A DateTime always has a full date component. When you create the DateTime instance, you'll need to assign a month and day, but you can ignore them in your usage.
DateTime d = new DateTime(int.Parse(txtYear.Text, 1, 1);
txtYear.Text = d.ToString("yyyy");
Even better would be not to use a DateTime but just use int. If you have only a year, you only need an int.
i assume the text box name is txYear
DateTime dt = new DateTime (Convert.ToInt32(txYear.text),1,1)
save this dt value in database
If you want only the year, why don't you make it of type smallint?
Anyway if you do really want to make it an year,
DateTime x = new DateTime(Convert.ToInt32(txtYear.text), 1, 1);
But make sure you validate that txtYear.text actually does have a valid year.
That is how I did and it worked.
string format = "yyyy";
var CurrentYear = DateTime.Now.ToString(format);

DataTable filter expression with DateTime and less-or-equal operator problem

I have the following code:
DataTable t = new DataTable();
t.Locale = CultureInfo.InvariantCulture;
t.Columns.Add("Date", typeof(DateTime));
DateTime today = DateTime.Now;
DateTime yesterday = today.AddDays(-1);
DateTime tomorow = today.AddDays(1);
t.Rows.Add(yesterday);
t.Rows.Add(today);
t.Rows.Add(tomorow);
string filter = string.Format(CultureInfo.InvariantCulture,
"Date >= #{0}# AND Date <= #{1}#", yesterday, tomorow);
t.DefaultView.RowFilter = filter;
foreach (DataRowView v in t.DefaultView)
Console.WriteLine(v["date"]);
I'm expecting that the filtered t.DefaultView now contains all three "days". But for some reason the last date from the range isn't included. It seems <= operator for DateTime type works like a <.
Where is the problem? Is that a bug? Any suggestions how to overcome that?
Update.
Got some responses about DateTime type and comparison operators. Thanks.
But now I want to direct attention to filter expression.
Ok, say I have the folloving loop:
foreach (DataRow r in t.Rows)
{
DateTime date = (DateTime)r["Date"];
if (yesterday <= date && date <= tomorow)
Console.WriteLine(date);
}
This loop should show the same result like
foreach (DataRowView v in t.DefaultView)
Console.WriteLine(v["date"]);
from the previous example, yes? No! Here <= works as I'm expecting and the result is all three days. Why?
Update #2: solution.
As Joe has noted - the problem is about fractions of a second.
If I format upper and lower bounds with Round-trip date/time pattern (to preserve fractions of a second) - everything works just fine:
string filter = string.Format(CultureInfo.InvariantCulture,
"Date >= '{0}' AND Date <= '{1}'",
yesterday.ToString("o", CultureInfo.InvariantCulture),
tomorow.ToString("o", CultureInfo.InvariantCulture));
The date comparison takes the time into account. So, for instance, "today at midday" is greater than just "today". If you use DateTime.Now, the time is included. So, if DateTime.Now is "today at midday", then tomorrow = today.AddDays(1) is less than "tomorrow at 3PM"... So you need to ignore the time part of the date. You can do that by formatting the date without the time. Also, if you want to check that a date is "less or equal than tomorrow" (regardless of the time), check that it is "strictly less than the day after tomorrow" :
string filter = string.Format(CultureInfo.InvariantCulture,
"Date >= #{0:MM/dd/yyyy}# AND Date < #{1:MM/dd/yyyy}#",
yesterday,
tomorrow.AddDays(1));
The code you posted in your update is not equivalent to the row filter.
Your row filter formats the date using the general format for the current culture. This probably does not include fractions of a second - therefore unless you happen to call DateTime.Now on a second boundary, your tomorrow value will be some fractions of a second beyond the range specified by the filter.
I.e. if your tomorrow value is '2009-12-23 01:02:03.456', your row filter is only taking values up to and including '2009-12-23 01:02:03', a few fractions of a second before the value specified by tomorrow.
If you only want to compare dates, you should use DateTime.Date to truncate the time component from your dates (and use DateTime.Today rather than DateTime.Now for the current date).
Try with
DateTime today = DateTime.Today;
if does not solve, check whether your date field contains time also. there lies your problem.
Update: your second comment.
when you compare with DateTime.Now e.g. Date <= 21.12.2009 14:35:35, it will take all before 14:35 hours and will ignore later rows. Hope this helps you.
See following article to get more idea
http://dotnetguts.blogspot.com/2007/06/understanding-datetime-and-timespan-in.html

Categories

Resources