0

I am building a StringBuilder with a column of date type and appends their some dates with my format YYYY-MM-DD.

Later, I conver it to byte[] and then creates an .csv file from it:

public ActionResult DownloadUsersDates()
{
    string data = Encoding.UTF8.GetBytes(GetAllDates());
    var res = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
    return File(res, "text/csv", "DatesList.csv");
}

public string GetAllDates()
{
    var sb = new StringBuilder();
    const string separater = ",";
    const string columnEscaper = "\"";

    sb.Append("Date");

    //Doing some code...

    foreach (var item in myItems)
    {
         sb.Append(columnEscaper);
         sb.Append((item.BirthDate.ToString("yyyy-MM-dd"))); //returns dates of format: `YYYY-MM-DD`
         sb.Append(columnEscaper);
         sb.Append(separater);
         sb.Append("\r");
    }
}

The problem is that it changes my format and saves it as another format: DD/MM/YYYY.

I understand that I need somehow to change the column Format Cell. How can I do it?

Thanks in advance.

Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116
  • 2
    CSV's can't store additional info about localization, Office will present the dates in the local format. – Gusman Dec 01 '16 at 16:08
  • @Gusman is correct. Excel is the devil when it comes to csv files. – Asnivor Dec 01 '16 at 16:13
  • @Asnivor no it isn't. It's people that expect it to somehow guess what they actually want. In this case though, what Excel? This is an MVC method! Why save anything as Excel, or convert anything? – Panagiotis Kanavos Dec 01 '16 at 16:15
  • @MishaZaslavsy your code doesn't contain anything related to Excel at all. In fact, I see a hard-coded conversion to a local datetime string `BirthDate.ToString()`. It looks like you are hand-coding the conversion, generating a proper string, then turning it into bytes without a reason, then back to the very same string then send it to the browser. – Panagiotis Kanavos Dec 01 '16 at 16:17
  • @PanagiotisKanavos You are right, but actually it is a little code from a huge code. Actually I have about 20 columns. I just wrote the essence. – Misha Zaslavsky Dec 01 '16 at 16:19
  • @MishaZaslavsky there is still no Excel anywhere and you hard-code the local format. If you wanted `YYYY-MM-DD` you should use `AppendFormat("{0:yyyy-MM-dd}")`. In fact, you could avoid formatting, conversion problems if you *did* create an Excel file from your list of items with a library like EPPlus – Panagiotis Kanavos Dec 01 '16 at 16:21
  • Do you still have a problem after this change? If you do, please post code that actually reproduces the problem – Panagiotis Kanavos Dec 01 '16 at 16:35
  • 1
    Open with notepad. It's excel doing the format.(I believe) – Trey Dec 01 '16 at 16:09
  • 1
    Have you tried specifying a format provider? `ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);` – ColinM Dec 01 '16 at 19:51
  • @ColinM `yyyy-MM-dd` isn't affected by the locale, it only contains numbers. – Panagiotis Kanavos Dec 02 '16 at 08:44
  • Thanks for the info @PanagiotisKanavos – ColinM Dec 02 '16 at 08:55
  • 1
    @MishaZaslavsky did you mean that when you *import* the file into Excel, you see dates in the local date format? That's normal, not a conversion. The date value is the same. If you want to change the style, [create a real Excel file](http://stackoverflow.com/questions/32837808/how-do-i-export-to-excel/32838151#32838151) with EPPlus and [specify the NumberFormat you want](http://stackoverflow.com/questions/9859610/how-to-set-column-type-when-using-epplus) – Panagiotis Kanavos Dec 02 '16 at 09:00
  • @PanagiotisKanavos Yes, that's what I mean. And yes I found NumberFormat before I wrote this question but it seems that I should use a Worksheet object and change it parameter. But in my code I just using string, can I append to the string some command that will do the work as NumberFormat? Or I just have to do it another way in xlsx file and not csv? – Misha Zaslavsky Dec 02 '16 at 09:05
  • 1
    @MishaZaslavsky your question asks something *completely* different. And CSV has no format, or types, it's just a text file with commas. `NumberFormat` is a property of Excel sheets, not text files like csv. Check the links in the previous comment – Panagiotis Kanavos Dec 02 '16 at 09:07
  • @PanagiotisKanavos Then I explained bad my question. But thanks. I thought like that. – Misha Zaslavsky Dec 02 '16 at 09:09

2 Answers2

2

The problem is that it changes my format and saves it as another format: DD/MM/YYYY.

I believe this is incorrect. If you open the file in a text editor (not Excel) it will be yyyy-MM-dd.

Let's take this the following *.csv file:

enter image description here

This is how it renders in Excel 2016 in Australia.

enter image description here

Excel recognized that the string is a date and formats the cells according to your local settings. What you see will be different to what someone with differently setup Windows would see.

Let's change the column's formatting.

enter image description here

enter image description here

tymtam
  • 31,798
  • 8
  • 86
  • 126
  • This seems to be the only logical answer to a very vague question - that the OP misunderstood local date formatting for some kind of conversion. Of course, if the code actually generated an `xlsx` file eg with EPPlus, there would be no conversion issues and the file would be smaller – Panagiotis Kanavos Dec 02 '16 at 08:49
0

You can try this. I hope it is same as your need.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;


namespace ExportToCSV.Controllers
{    
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {                        
            byte[] data = Encoding.UTF8.GetBytes(GetAllDates());
            var res = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
            return File(res, "text/csv", "DatesList.csv");
        }

        public string GetAllDates()
        {
            var sb = new StringBuilder();
            sb.AppendLine("Date");

            foreach (var item in Clients.clients)
            { 
                sb.Append("'");              
                sb.Append((item.Dob.ToString("yyyy-MM-dd"))); //returns dates of format: `YYYY-MM-DD`             
                sb.Append("',");
                sb.Append("\n");
            }
            return sb.ToString();
        }

    }

    public class Clients
    {
        public string FirstName { set; get; }
        public string LastName { set; get; }
        public string Email { set; get; }
        public DateTime Dob { set; get; }
        public Clients(string firstname, string lastname, DateTime dob, string email)
        {
            this.FirstName = firstname;
            this.LastName = lastname;
            this.Dob = dob;
            this.Email = email;
        }

        public static List<Clients> clients = new List<Clients>
            {
                 new Clients ( "Adam",  "Bielecki",  DateTime.Parse("22-05-1986"),  "adamb@example.com" ),
                 new Clients (  "George1", "Smith",  DateTime.Parse("10-10-1990"),  "george@example.com" ),
                 new Clients (  "George2", "Smith",  DateTime.Parse("10-05-1992"),  "george@example.com" ),
                 new Clients (  "George3", "Smith",  DateTime.Parse("08-12-1998"),  "george@example.com" )
            };
    }
}
Kumar Akhil
  • 176
  • 7
  • This is a poor attempt & workaround without attempting to find out what the issue is. – ColinM Dec 01 '16 at 19:53
  • I edited my ans. I am trying to explain this solution by an example. I hope this will be same. – Kumar Akhil Dec 01 '16 at 20:24
  • I didn't call the lack of code a poor attempt, I called the usage of `Contains` and `Replace` a poor attempt. You're complicating a task, at the expense of performance, for a job that the framework already provides. https://msdn.microsoft.com/en-us/library/8tfzyc64(v=vs.110).aspx – ColinM Dec 01 '16 at 20:27
  • Thanks for point out. This is valuable suggestion for me.In future I will take care for the same. – Kumar Akhil Dec 01 '16 at 20:43
  • The `GetAllDates` method is exactly the same. What is this supposed to solve? The `clients` initialization actually *introduces* a conversion bug because it parses a local date format. – Panagiotis Kanavos Dec 02 '16 at 08:46
  • Since you've updated your code, can I ask exactly what the difference is between yours and the OP's code? – ColinM Dec 02 '16 at 23:46