Culture dependent NumberFormat for dates in C# VSTO Excel - c#

I'm relatively new to C# and I'm still learning a lot. I also searched stackoverflow for similar problems but got to a point where I'm stuck.
In my VSTO Excel project I'd like to output dynamic data coming from a database with a predefined number format per column also coming from the database. The user can define his own layout of the report. Everything is working just fine, I have just problems formatting the date value.
When it's about to output a date column, the format should be automatically be determined by the program instead of predefining it in the database as well. The date value gets already inserted in the Excel sheet as the decimal number it should be. Everything okay here. When I manually format it in Excel itself, it is displayed correctly.
But I want to format the date with C# like it would be formatted when I do it manually by clicking on the short date format in Excel. And it should work in every country, regardless in which language the office package was installed.
I'm working with a German installation and I expect the format to be "TT.MM.JJJJ". When formatting the column with this fixed string, it works perfectly (at least in Germany I guess).
It makes no difference if formatting it with
CurrentWorksheet.Columns[queryColumn.Position].NumberFormat = "TT.MM.JJJJ";
or
CurrentWorksheet.Columns[queryColumn.Position].NumberFormatLocal = "TT.MM.JJJJ";
Both end up in the same (correct) result. That the first line is working as well is the first thing which was unexpected for me, but that's not the main point. I tried to format it dynamically by replacing "TT.MM.JJJJ" with the following lines:
// Leads to dd.MM.yyyy
System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
// Fixed German culture still leads to dd.MM.yyyy
CultureInfo.CreateSpecificCulture("de-DE").DateTimeFormat.ShortDatePattern;
// MM/dd/yyyy - also not helpful
CultureInfo.InvariantCulture.DateTimeFormat.ShortDatePattern;
When using the first or second ShortDatePattern the date 27.08.2014 is shown as "dd.08.yyyy". Excel simply doesn't unterstand "dd" or "yyyy". I thought at least when using NumberFormat instead of NumberFormatLocal it would work, because it's the global format, but it doesn't. It feels like Microsoft has implemented the date formatting more complicated that it could be.
How would I determine the correct date pattern here?

The answer (it still is a kind of workaround) is pretty much found in another question:
How to set localized short-date format for a cell in Excel with C#?
There's just a very small difference I had to make in the method for constructing the ShortDatePattern (the Application parameter for DateFormatComponentCodes).
public static string ConstructExcelShortDatePattern()
{
var systemDateComponentCodes = new DateFormatComponentCodes();
var excelDateComponentCodes = new DateFormatComponentCodes(Globals.ThisAddIn.Application);
string systemShortDatePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
string excelShortDatePattern = systemShortDatePattern.Replace(systemDateComponentCodes.Year, excelDateComponentCodes.Year).Replace(systemDateComponentCodes.Month, excelDateComponentCodes.Month).Replace(systemDateComponentCodes.Day, excelDateComponentCodes.Day);
return excelShortDatePattern;
}
Thanks to Heinzi for finding a great answer and Jordan for providing such a useful class!

Related

String was not recognized as a valid DateTime from SQLite file

I have a program, that puts the .txt files to a database file (im using system.data.sqlite NuGET package). I have yyyy.MM.dd format set on my Pc, and it's used by the database too, however I still get the above mentioned error.
An additional info, that could help, is that when I set the table's appropriate column to a simple string it's working as normal, but as soon As I set it to date it gives me this exeption.
Can someone please help me?
You seem to be mixing up how a type is formatted into text with the type itself. If a column is typed as date, then its expecting a date, not a text conforming to whatever date format you have in mind.
Its the same is if you try to do the following:
DateTime date = "01.01.2020";
This won't compile, because string, nevermind if it represents a valid formatted date, and DateTime are two altogether different types.
If you are reading from a text file, you first need to convert the formatted string representations to their corresponding DateTime. See DateTime.TryParse method on how to do this. Once you have valid dates in your hands, try pushing those to the DB.

Is there any way to update only text of date picker content control, not the formatting detail?

I am working on one word add-in application in which I have several date picker content controls, setting the text value in to this content control also changes the format of it as per system date format.
I am setting up the DateDisplayFormat and DateDisplayLocale explicitly still it is showing date value as per system date format.
ContentControl.Range.Text = "21-12-16";
ContentControl.DateDisplayFormat ="yy-M-d";
ContentControl.DateDisplayLocale =
Microsoft.Office.Interop.Word.WdLanguageID.wdSimplifiedChinese;
My system date format : MM/dd/yyyy
-Actual result : 16-12-21 (MM/dd/yyyy)
-Expected result : 21-12-16 (yy-M-d)
I believe the problem comes from the ambiguity of Range.Text = 16-12-21.
This can be interpreted either way, as the year 2016 or as the year 2021. Word does rely on the Windows System settings for things like interpreting what a date should be, rather than anything local. I thought, perhaps switching the order of the format and data entry might have an influence, but it does not.
Simply provide a four-digit year, which is standard good-practice every since people realized the potential "millenium" problems back in the 1990's, and there's no issue. There's also no issue when someone uses the DatePicker in the UI. So...
ContentControl.Range.Text = "2021-12-16";
ContentControl.DateDisplayFormat ="yy-M-d";
ContentControl.DateDisplayLocale =
Microsoft.Office.Interop.Word.WdLanguageID.wdSimplifiedChinese;

EPPlus load custom value

I have cell which contains value
7.11.2014
in custom format
dd/mm/yyyy
so in excel it looks like
07/11/2014
when i load it via EPPLus
cellValue = sheet.Cells[row, column].Value.ToString();
it loads the General format value, which is
41950
How can i load the Value 07/11/2014 or other date format with i can work ?
Thank you
Looking over some similar code that I've done before, all you'll need to do is to use DateTime.Parse() and it should come out exactly how you want it.
As I mentioned in the comments Excel saves the actual dates as being a number of days from its epoch date of 1/1/1900 (hence why you keep seeing 41950). .NET code will accept that, and will convert it to the correct date.
OK i got it, this code works
long serialDate = long.Parse(sheet.Cells[r, c].Value.ToString());
cellValue = DateTime.FromOADate(serialDate).ToString("dd-MM-yyyy");
Thank you for help :)

Format c# dateTime to local string format

I have a DateTime C# object (in a Unity script, targeted for an Android device). I want to retrieve a string representation via .toString() (so w/o any special formatting parameter), which is supposed to deliver a short form like "10/5/2014 9.17 PM". If I now run it on an Android device with the locale set to e.g. German, just the time will be converted correctly, while the date stays in US format (so "10/5/2014 21.17" instead of "5.10.2014 21.17").
Am I doing something wrong here, or maybe don't I understand the whole thing at all ;-)
Your assumption about DateTime.ToString is correct. The following code prints 05.10.2014 13:26:36:
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
DateTime time = DateTime.Now;
Console.WriteLine(time.ToString());
I'd check what the value of Thread.CurrentThread.CurrentCulture.ToString() is in your environment and ensure that Unity sets it correctly. If it doesn't, you would have to do it yourself.

C# to Excel set custom date display and value

Given a certain date, I want to set the value of a cell with a DateTime object, but without the "Time" information. For example, for today the value would just be "29/06/2012" and not "29/06/2012 16:54:36".
Concerning the display, for today's date I want it to be written like this (it is in french, I don't know how it would be in english): "29 juin" and not "29/06/2012".
How can I achieve this?
EDIT : I just took a look at the display formatting I need in Excel, it is "jj mmmm" ("dd mmmm" in C#). But the cell, though taking the value, does not take the formatting. Here is a piece of code:
cell.Value = string.Format("{0:dd/MM/yyyy}", DateTime.Now);
cell.NumberFormat = "jj mmmm";
I also tried:
cell.Value = DateTime.Now;
cell.NumberFormat = "jj mmmm";
In that case, the display formatting is OK, but the cell value contains the Time information, which is not OK.
See this StackOverflow question, and my answer to it. It will allow you to set the custom format for the cell directly in the excel sheet, from there you just need to research what the different date format strings are.
That is only helpful if you are using excel automation though.
Otherwise, formatting the DateTime.ToString output will be better. Once again, researching the different DateStringFormatting options will be helpful to you.
Final option. Directly change the template, not using automation. Goto the cell and manually change the cell format until the display is what you want. This does not change the actual data, just its display.
UPDATE
There are two specific issues to deal with.
Issue one is making sure excel recognizes that this IS a date. To that end, make certain that the date data itself is formatted en-US. Why, because Microsoft is dumb, and doesn't recognize international date formats.
Issue two is the display format for the cell. For a 3 letter abbreviation of the month, use the string d mmm. If you want the full month name, use d-mmmm.
I was testing and noted that excel refused to treat 29/06/2012 16:54:36 as a date, but it accepted 06/29/2012 16:54:36 without an issue. As I said, microsoft is dumb.
just change DateTime.Now to DateTime.Date and the time will be zero'd out
DateTime has a method called ToShortDateString
// Displays Fri 29 Aug
Console.WriteLine(date1.ToString("ddd d MMM", CultureInfo.CreateSpecificCulture("fr-FR")));
This would be a good resource for you: msdn custom date and time format strings

Categories