I have a small question.
I have to get only the Ship date "July 17, 2015" from the string. lets say this is my code:
string result = "";
foreach (HtmlElement el in webBrowser1.Document.GetElementsByTagName("div"))
if (el.GetAttribute("className") == "not-annotated hover")
{
result = el.InnerText;
textBox2.Text = result;
}
Now this is the output:
string result = "";
string date = "";
foreach (HtmlElement el in webBrowser1.Document.GetElementsByTagName("div"))
if (el.GetAttribute("className") == "not-annotated hover")
{
result = el.InnerText;
date = Regex.Match(result ,
String.Format(#"{0}\s(?<words>[\w\s]+)\s{1}", "Ship Date:", "Country:"),
RegexOptions.IgnoreCase).Groups["words"].Value;
textBox2.Text = date ;
}
It seems as if your div is an outer div, you need the one which displays the ship-date only. That would be the safest/easiest approach.
However, if all you have is that large string, you could split by new-line characters and get the date from the line which starts with Ship date:
string[] lines = result.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
string dateString = lines
.FirstOrDefault(l => l.Trim().StartsWith("Ship date", StringComparison.InvariantCultureIgnoreCase));
DateTime shipDate;
if (dateString != null)
{
string[] formats = new[] { "MMMM dd, yyyy" };
string datePart = dateString.Split(':').Last().Trim();
bool validShipDate = DateTime.TryParseExact(
datePart,
formats,
DateTimeFormatInfo.InvariantInfo,
DateTimeStyles.None,
out shipDate);
if (validShipDate)
Console.WriteLine(shipDate);
}
From the Output text that you have shared,
string result = "";
foreach (HtmlElement el in webBrowser1.Document.GetElementsByTagName("div"))
if (el.GetAttribute("className") == "not-annotated hover")
{
result = el.InnerText;
if (result.IndexOf("Ship Date") == 0) //Ship Date text is present in the string
{
//since the string format is Ship Date: July 17, 2015 -
//we can assume : as a delimiter and split the text
string[] splitText = result.Split(':');
string date = splitText[1].Trim(); //this will give the date portion alone
}
textBox2.Text = result;
}
Hope this helps.
NOTE: This logic will work only if the Ship Date string in the HTML is received in the same format as specified in your Output sample
Related
when i am try to change date format from csv file 3/1/2021-3/31/2021 to Mar-01-2021-Mar-31-2021 getting error please help me solve the issue.
foreach (DataRow dr in dtDataTable.Rows)
{
for (int i = 0; i < dtDataTable.Columns.Count; i++)
{
if (ListInputDateColumns.Contains(dtDataTable.Columns[i].ColumnName))
{
if(dtDataTable.Columns[i].ColumnName == "Period")
{
sw.Write(dr[i] = Convert.ToDateTime(dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).ToString("MMM-dd-yyyy-MMM-dd-yyyy"));//Here i am getting error
}
else
{
sw.Write(dr[i] = Convert.ToDateTime(dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).ToString("MMM-dd-yyyy hh:mm:ss tt"));
}
//sw.Write(dr[i].ToString());
}
else
{
sw.Write(dr[i].ToString());
}
//sw.Write(dr[i].ToString());
sw.Write(",");
}
sw.Write(sw.NewLine);
}
sw.Close();
}
}
You have to parse that string by splitting it by the delimiter and then parse each token to DateTime. Then you can convert it back to string with the desired format:
string targetFormat = "MMM-dd-yyyy";
string s = " 3/1/2021-3/31/2021";
string[] tokens = s.Split('-');
if(tokens.Length == 2)
{
bool validFrom = DateTime.TryParse(tokens[0], CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime fromDate);
bool validTo = DateTime.TryParse(tokens[1], CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime toDate);
if (validFrom && validTo)
{
string result = $"{fromDate.ToString(targetFormat, CultureInfo.InvariantCulture)}-{toDate.ToString(targetFormat, CultureInfo.InvariantCulture)}";
}
}
OK, we can do this in one line of code if you want, but it gets pretty ugly as far as readability goes. For a one liner, simply change this line:
sw.Write(dr[i] = Convert.ToDateTime(dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).ToString("MMM-dd-yyyy-MMM-dd-yyyy"));//Here i am getting error
to
sw.Write(dr[i] = Convert.ToDateTime((dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).Substring(0, (dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).IndexOf('-'))).ToString("MMM-dd-yyyy") + "-" + Convert.ToDateTime((dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).Substring((dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).IndexOf('-') + 1)).ToString("MMM-dd-yyyy");
but for maintainability, I would recommend creating a quick method for parsing "Period" like this
string ParsePeriod(string period)
{
DateTime from = Convert.ToDateTime(period.Substring(0, period.IndexOf('-')));
DateTime to = Convert.ToDateTime(period.Substring(period.IndexOf('-') + 1));
return from.ToString("MMM-dd-yyyy") + "-" + to.ToString("MMM-dd-yyyy");
}
then call it like this by changing this:
sw.Write(dr[i] = Convert.ToDateTime(dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()]).ToString("MMM-dd-yyyy-MMM-dd-yyyy"));//Here i am getting error
to this:
sw.Write(dr[i] = ParsePeriod(Convert.ToString(dtDataTable.Rows[i][dtDataTable.Columns[i].ColumnName.ToString()])));
I trust this solves your problem. ;-)
C# is kicking my butt...
I have a text file I'm splitting in hopes to insert into SQL. I need a swift shove in the right direction!
An excerpt from the file I am capturing is below and I am splitting on " - "
2020-06-25-13.23.04.220000 - Running MRP for Site
I can split the two parts just fine.
console_output
But can't seem to get the date into a format that is valid for my SQL insert. I think, but could be completely wrong that I need to reformat this date string using some REPLACE commands.
If I try and use DateTime.ParseExact using my non-working code below I receive a System.FormatException:String was not recognized as valid on my DateTime.ParseExact line.
foreach (string line in lines)
{
if (line.Contains("Running MRP for Site"))
{
List<string> s = new List<string>(
line.Split(new string[] { " - " }, StringSplitOptions.None));
Console.WriteLine(s[0].ToString());
Console.WriteLine(s[1].ToString());
string format = "yyyy-MM-dd-hh:mm:ss:ffffff";
string date = s[0].ToString().Replace('.', ':');
DateTime dt = DateTime.ParseExact(date, format, CultureInfo.InvariantCulture);
/*
if (conn.State != ConnectionState.Open)
{
conn = new SqlConnection { ConnectionString = Properties.Settings.Default.ConnectionString };
conn.Open();
}
{
String query = #"INSERT INTO
It's the hh. That's a 12-hour clock. You need HH for a 24-hour clock. See Custom date and time format strings - the "HH" custom format specifier.
Here it is in the form of a unit test that takes the input string and verifies that the result is correct (although perhaps crudely.)
[TestMethod]
public void ParseDateTimeTest()
{
var input = "2020-06-25-13.23.04.220000 - Running MRP for Site";
var firstSegment = input.Split(new string[] { " - " }, StringSplitOptions.None)[0];
string format = "yyyy-MM-dd-HH.mm.ss.ffffff";
var parsed = DateTime.ParseExact(firstSegment, format, CultureInfo.InvariantCulture);
Assert.AreEqual(13, Math.Truncate((parsed - new DateTime(2020, 6, 25)).TotalHours));
}
I have a CSV file which goes like this:
1,01/01/2001,a
2,19/09/2013,as
3,12/05/2016,asd
4,13/05/2016,asdf
5,12/12/2012,asdfg
6,05/02/2006,asdfgh
7,06/03/2011,asdfghj
I want to sort and display the dates in chronological order but I can't seem to get my code to sort it out. However, my code is able to display the dates according to the format in the CSV file.
If the CSV file is like this:
01/01/2001
19/09/2013
12/05/2016
13/05/2016
12/12/2012
05/02/2006
06/03/2011
Then, it works just fine.
The following is my code:
string parts = new StreamReader(#"C:\input.txt").ReadToEnd();
string[] file = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < file.Length; i++)
{
string[] data = file[i].Split(new string[] { "," }, StringSplitOptions.None);
string[] dates = new string[] { data[1].ToString() };
//var date = dates.OrderBy(x => DateTime.Parse(x)).ToList();
var date = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
foreach (string s in date)
{
sb.AppendLine(s + "<br />");
Label1.Text = sb.ToString();
}
}
I have tested this code using both DateTime.Parse and DateTime.ParseExact on the CSV file, but they didn't work.
I'm really new to LINQ query and this is my first time using it. I would really appreciate it if there is an explanation provided on what's wrong with my code.
You are sorting an array (dates) that always contains one date (because you create it each time from a single line in a loop). Then you add this line to the label's text.
You have to create a collection that contains all the dates, before you sort it.
string parts = new StringReader(#"C:\input.txt").ReadToEnd();
string[] lines = parts.Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
List<string> dates = new List<string>();
for (int i = 0; i < lines.Length; i++)
{
string[] data = lines[i].Split(new string[] { "," }, StringSplitOptions.None);
dates.Add(data[1]);
}
var datesSorted = dates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
foreach (string s in datesSorted)
{
sb.AppendLine(s + "<br />");
}
Label1.Text = sb.ToString();
It may required to select the values in Date format first then order it
Try
var date = dates.Select(x => DateTime.ParseExact(x, "dd/MM/yyyy", null)).OrderBy(t => t).ToList();
foreach (DateTime s in date)
{
sb.AppendLine(s.ToString("dd/MM/yyyy") + "<br />");
}
Label1.Text = sb.ToString();
Need to move the Label1 Text assigning after foreach
Please first put your dates into a Collection, for example a List or Array, and then sort the Collection. Default sort order is ascending
List<string> unsortedDates = new List<string>();
string parts = new StreamReader(#"C:\input.txt").ReadToEnd();
string[] file = parts.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < file.Length; i++)
{
string[] data = file[i].Split(new string[] { "," }, StringSplitOptions.None);
unsortedDates.Add(data[1]);
}
var sortedDatesAscending = unsortedDates.OrderBy(x => DateTime.ParseExact(x, "dd/MM/yyyy", null));
foreach (string s in sortedDatesAscending)
{
sb.AppendLine(s + "<br />");
Label1.Text = sb.ToString();
}
so I understand how to make global values and the fact that 1. you shouldn't do it and 2. you cannot use a value that was created in a different "context" however, I'm not sure how to correct this problem in my case. I think it will make sense if you read my code
//read in Load Query TestCSV
var sourcePath = #"D:\\Load Query test.csv"; //What is the inital CSV
var delimiter = ",";
var firstLineContainsHeaders = true; //CSV has headers
//creates temp file which takes less time than loading into memory
var tempPath = Path.Combine(#"D:", Path.GetRandomFileName());
var lineNumber = 0;
var splitExpression = new Regex(#"(" + delimiter + #")(?=(?:[^""]|""[^""]*"")*$)");
using (var writer = new StreamWriter(tempPath))
using (var reader = new StreamReader(sourcePath))
{
string line = null;
string[] headers = null;
if (firstLineContainsHeaders)
{
line = reader.ReadLine();
lineNumber++;
if (string.IsNullOrEmpty(line)) return; // file is empty;
headers = splitExpression.Split(line).Where(s => s != delimiter).ToArray();
writer.WriteLine(line); // write the original header to the temp file.
}
var i = 0; //used in 2nd while loop later
string lines = null;//used in next using statement
while ((line = reader.ReadLine()) != null)
{
lineNumber++;
var columns = splitExpression.Split(line).Where(s => s != delimiter).ToArray();
//make sure you always have the same number of columns in a line
if (headers == null) headers = new string[columns.Length];
if (columns.Length != headers.Length) throw new InvalidOperationException(string.Format("Line {0} is missing one or more columns.", lineNumber));
string badDate = "Date entered incorrectly"; //used in next while loop
// this while loop will read in the user input dateTime and use that to get the column from the PI server.
//if the date time is entered incorrectly it will tell the user to try to input the datetime again
while (i==0)
{
Console.WriteLine("Enter date, ex:16 Jun 8:30 AM 2008, Press enter when done"); //instruct the user in how to enter the date
string userInput = Console.ReadLine(); //read in the date the user enters
string format = "dd MMM h:mm tt yyyy"; //how the system will read the date entered
DateTime dateTime;
//if date is entered correctly, parse it, grab the parsed value dateTime and exit loop
if (DateTime.TryParseExact(userInput, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
i = 1; //set the flag to exit while loop
}
//if input is bad return "Date entered incorrectly and run the loop again
else
{
Console.WriteLine(badDate);
i=0; //set the flag to run the loop again
}
}
var del = ","; //used in next using statement
var SplitExpression = new Regex(#"(" + del + #")(?=(?:[^""]|""[^""]*"")*$)"); //used in next using statement
//Use the dateTime from the previous while loop and use it to add each point in "testpts.csv" to "Load Query Test.csv"
using (StreamReader tags = new StreamReader(#"D:\\testpts.csv"))
{
// string userInput = Console.ReadLine();
string format = "dd MMM h:mm tt yyyy";
DateTime.TryParseExact(userInput, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime);
lines = tags.ReadLine();
var columns1 = SplitExpression.Split(lines).Where(s => s != del).ToArray();
var point = PIPoint.FindPIPoint(piServer, lines);
var value = point.RecordedValue(dateTime);
string returnXml = string.Format(#"<value=""{0}"" />", value);
columns[15] = columns[15].Replace("0", returnXml); //column the point should be placed in (in Load Query Test.csv)
}
//if statement that will replace any extra 0 testpt values with column 13 values
if (columns[15].Contains("0"))
{
columns[15] = columns[15].Replace("0", columns[13]);
}
writer.WriteLine(string.Join(delimiter, columns));
}
}
File.Delete(sourcePath); //delete the original csv
File.Move(tempPath, sourcePath); //replace the old csv with edited one
Console.ReadLine();
I'm getting the error in the using statement:
using (StreamReader tags = new StreamReader(#"D:\\testpts.csv"))
{
// string userInput = Console.ReadLine();
string format = "dd MMM h:mm tt yyyy";
DateTime.TryParseExact(userInput, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime);
lines = tags.ReadLine();
var columns1 = SplitExpression.Split(lines).Where(s => s != del).ToArray();
var point = PIPoint.FindPIPoint(piServer, lines);
var value = point.RecordedValue(dateTime);
string returnXml = string.Format(#"<value=""{0}"" />", value);
columns[15] = columns[15].Replace("0", returnXml); //column the point should be placed in (in Load Query Test.csv)
}
In this case the dateTime and userInput values are obviously out of context. I need them created in the previous while loop however because I want the user to be able to enter the correct date only once and ensure that it is entered correctly to make sure the script will actually pull data.
Please let me know if there is another way I can order my code or how I can make userInput and dateTime global. Thank you
Your problem lies in the "dateTime" variable. "userInput" is fine, the inner using statement has access to the scope of its outer using statement, because the inner one is part of the outer's scope.
The problem is with "dateTime" - the variable is declared inside a while loop, and there is a using block afterwards - after the variable is not available anymore, because the scope was disposed - which references a non existent variable.
Solution: move the declaration of your dateTime variable out of the while. Say, a line before the while's definition.
Without critisizing your code to much ... here an answer. You should be able to walk yourself from here on
Split the declaration of the variable with it's assignment
string userInput = Console.ReadLine();
to
string userInput;
userInput = Console.ReadLine();
Move the declarations (the first line) outside of the outer Loop.
Edit: Please, also have a look at Properties (you may call them
globals)
I'm having trouble with format my cells to Date.
FileInfo info = new FileInfo(path);
using (ExcelPackage package = new ExcelPackage(info))
{
ExcelWorksheet ws = package.Workbook.Worksheets.Add(sheetName);
ws.Cells[3, 1].Style.Numberformat.Format = "yyyy-mm-dd";
ws.Cells["A3"].Formula = "=DATE(2014,10,5)";
}
Output from this in Excel: 41 917,00
Why is this not working?
I agree with Yosoyke. You're probably targeting the wrong cells. You can try:
ws.Cells["A3"].Style.Numberformat.Format = "yyyy-mm-dd";
ws.Cells["A3"].Formula = "=DATE(2014,10,5)";
worksheet.Cells["YOURDATECELL_OR_YOURDATECELLRANGE"].Style.Numberformat.Format = "mm-dd-yy";
if you use the formula mentioned by taraz. do add worksheet.Calculate() in the end.
reference
https://epplus.codeplex.com/wikipage?title=About%20Formula%20calculation
Or instead of using formula, Alternative approach
private static decimal GetExcelDecimalValueForDate(DateTime date)
{
DateTime start = new DateTime(1900, 1, 1);
TimeSpan diff = date - start;
return diff.Days + 2;
}
Reference
worksheet.Cells["A2"].Value = GetExcelDecimalValueForDate(Convert.ToDateTime('2016-04-29'));
worksheet.Cells["A2"].Style.Numberformat.Format = "mm-dd-yy";//or m/d/yy h:mm
By Default when excel saves a date field it saves it as numFormatId 14(Look at the xml files in the xls). This ensure the date formats correctly in any country when the file is opened.
In Epplus mm-dd-yy translates to numFormatId 14 for excel.
This will ensure that when the file is opened in any country the date will be formatted correctly based on the country's short date settings.
Also noticed m/d/yy h:mm formats correctly for any country.
var dateColumns = from DataColumn d in dt.Columns
where d.DataType == typeof(DateTime) || d.ColumnName.Contains("Date")
select d.Ordinal + 1;
foreach (var dc in dateColumns)
{
worksheet.Cells[2, dc, rowCount + 2, dc].Style.Numberformat.Format = "mm/dd/yyyy hh:mm:ss AM/PM";
}
it will format all the columns with header Date to specific format given/ provided
I was having the same problem with my CSV to be transformed. I was able to do this in a little different manner.
private string ConvertToExcel(string CSVpath, string EXCELPath)
{
try
{
string Filename = System.IO.Path.GetFileNameWithoutExtension(CSVpath);
string DirectoryName = System.IO.Path.GetDirectoryName(CSVpath);
EXCELPath = DirectoryName + "\\" + Filename + ".xlsx";
string worksheetsName = "Report";
bool firstRowIsHeader = false;
var format = new OfficeOpenXml.ExcelTextFormat();
format.Delimiter = '|';
format.EOL = "\n";
using (OfficeOpenXml.ExcelPackage package = new OfficeOpenXml.ExcelPackage(new System.IO.FileInfo(EXCELPath)))
{
string dateformat = "m/d/yy h:mm";
//string dateformat = System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
OfficeOpenXml.ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(worksheetsName);
worksheet.Cells["A1"].LoadFromText(new System.IO.FileInfo(CSVpath), format, OfficeOpenXml.Table.TableStyles.Medium2, firstRowIsHeader);
worksheet.Column(3).Style.Numberformat.Format = dateformat;
worksheet.Column(5).Style.Numberformat.Format = dateformat;
worksheet.Column(6).Style.Numberformat.Format = dateformat;
worksheet.Column(20).Style.Numberformat.Format = dateformat;
worksheet.Column(21).Style.Numberformat.Format = dateformat;
worksheet.Column(22).Style.Numberformat.Format = dateformat;
package.Save();
}
}
catch (Exception ex)
{
//DAL.Operations.Logger.LogError(ex);
Console.WriteLine(ex);
Console.Read();
}
return EXCELPath;
}
Generic solution which takes IEnumerable (data) it loops through the properties of the generic object finds which is of DateType or nullableDate Type and applies formatting:
//set the list of dateColumns which will be used to formate them
List<int> dateColumns = new List<int>();
//get the first indexer
int datecolumn = 1;
//loop through the object and get the list of datecolumns
foreach (var PropertyInfo in data.FirstOrDefault().GetType().GetProperties())
{
//check if property is of DateTime type or nullable DateTime type
if (PropertyInfo.PropertyType == typeof(DateTime) || PropertyInfo.PropertyType == typeof(DateTime?))
{
dateColumns.Add(datecolumn);
}
datecolumn++;
}
// Create the file using the FileInfo object
var file = new FileInfo(outputDir + fileName);
//create new excel package and save it
using (var package = new ExcelPackage())
{
//create new worksheet
var worksheet = package.Workbook.Worksheets.Add("Results");
// add headers
worksheet.Cells["A1"].LoadFromCollection(data, true);
//format date field
dateColumns.ForEach(item => worksheet.Column(item).Style.Numberformat.Format = "dd-mm-yyyy");
// auto size columns
worksheet.Cells.AutoFitColumns();
//save package
package.SaveAs(file);
}
You can try, If you want using AM/PM
worksheet.Cells[1].Style.Numberformat.Format = "dd/MM/yyyy HH:mm:ss AM/PM";
Following on from the very good Generic solution which takes IEnumerable.. answer we had to go a step further and display different date formatting for different properties. Fro example some columns needed to be displayed as dd/MM/yyyy and others as dd/MM/yyyy hh:mm.
So we added a DisplayFormat annotation with a DataFormatString (representing a DateTime format) to our properties like this:
using System.ComponentModel.DataAnnotations;
...
[DisplayName("Download Date")]
[DisplayFormat(DataFormatString = "dd/MM/yyyy hh:mm")]
public string DownloadDate { get; set; }
...
And then borrowing from Generic solution which takes IEnumerable.. we pulled out the date format string from the DisplayFormat annotation when iterating the properties of the data object:
public void FormatDateColumns(ExcelWorksheet worksheet, IEnumerable<IResult> data)
{
// Dictionary 'key' contains the Index of the column that contains DateTime data
// Dictionary 'value' contains the DateTime format for that column
Dictionary<int, string> dateColumns = new Dictionary<int, string>();
int dateColumnIndex = 1;
// find all the DateTime/DateTime? columns in the data object
foreach (var PropertyInfo in data.FirstOrDefault().GetType().GetProperties())
{
if (PropertyInfo.PropertyType == typeof(DateTime) || PropertyInfo.PropertyType == typeof(DateTime?))
{
string dateTimeFormat = Constants.DefaultDateTimeFormat;
// attempt to get a DataFormatString from a DisplayFormat annotation which may be decorating the Property
// looking for an annotation something like [DisplayFormat(DataFormatString = "dd-MM-yyyy hh:mm")]
if (PropertyInfo.CustomAttributes != null)
{
var dislayFormatAttribute = PropertyInfo.CustomAttributes.Where(x => x.AttributeType.Name == "DisplayFormatAttribute").FirstOrDefault();
if (dislayFormatAttribute != null && dislayFormatAttribute.NamedArguments != null && dislayFormatAttribute.NamedArguments.Count > 0)
{
var displayFormatArg = dislayFormatAttribute.NamedArguments.First();
if (displayFormatArg != null && displayFormatArg.TypedValue != null && displayFormatArg.TypedValue.Value != null)
{
// NOTE: there is probably an easier way to get at this value?
dateTimeFormat = displayFormatArg.TypedValue.Value.ToString();
}
}
}
dateColumns.Add(dateColumnIndex, dateTimeFormat);
}
dateColumnIndex++;
}
if (dateColumns.Count > 0)
{
// apply the formatting
dateColumns.ToList().ForEach(item => worksheet.Column(item.Key).Style.Numberformat.Format = item.Value);
}
}
I wanted to add that the setting of the format was the solution for me. But, I could not get it to work until I set the value property to a DateTime object and not a string. That was the key to making it all work.
I had a similar issue, and even though I was correctly setting the date and applying the proper number format to the cell containing the date, I was seeing the numeric representation of the date.
Turns out that after that, I applied a style, that effectively reset my format.
The code was something like:
ws.Cells["A3"].Style.Numberformat.Format =
System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
ws.Cells["A3"].Value = New DateTime(2021, 10, 15, 23, 16, 0).ToOADate();
and later, I had:
ws.Cells("A3").StyleName = colStyle //colstyle is a style created earlier
To fix that, I needed to apply the NumberFormat.Format after setting the style.
Make sure your cell width is large enough to display your date! This is the problem if the cell displays ### symbols.
A simple fix for this is to autofit the cell width in your worksheet:
ws.Cells.AutoFitColumns();
Complete example with passing a DateTime object:
ws.Cells[3, 1].Style.Numberformat.Format = "yyyy-mm-dd";
ws.Cells[3, 1].Value = new DateTime(2014,10,5);
ws.Cells.AutoFitColumns();
For advanced formatting, look at https://support.microsoft.com/en-us/office/number-format-codes-5026bbd6-04bc-48cd-bf33-80f18b4eae68.
Keep in mind NOT to localize reserved characters of the numberformat code into another language: Write yyyy for the year, not jjjj. If you want to format a number and want the decimal separator, write 0.00, not 0,00.
(Posted this as I keep stumbling over this problem and this question is the first search result.)
Some news:
ws.Cells["A3"].Style.Numberformat.Format = "[$-en-US]yyyy-mmm-dd";
ws.Cells["A3"].Formula = "=DATE(2014,10,5)";