如何创建CSV Excel文件c# ?

时间:2022-09-02 15:13:05

I'm looking for a class for creating CSV Excel files.

我在找一个创建CSV Excel文件的类。

Expected features:

预期的特点:

  • Extremely simple to use
  • 非常简单易用
  • Escapes commas and quotes so excel handles them fine
  • 转义逗号和引号,因此excel可以很好地处理它们
  • Exports date and datetimes in timezone-proof format
  • 以时间区域证明格式导出日期和日期时间

Do you know any class capable of this?

你知道有什么班能做到这一点吗?

13 个解决方案

#1


91  

Slightly different version I wrote using reflection for my needs. I had to export a list of objects to csv. In case someone wants to use it for future.

根据我的需要,我使用反射编写了稍微不同的版本。我必须向csv导出一个对象列表。以防有人想用它来做未来。

public class CsvExport<T> where T: class
    {
        public List<T> Objects;

        public CsvExport(List<T> objects)
        {
            Objects = objects;
        }

        public string Export()
        {
            return Export(true);
        }

        public string Export(bool includeHeaderLine)
        {

            StringBuilder sb = new StringBuilder();
            //Get properties using reflection.
            IList<PropertyInfo> propertyInfos = typeof(T).GetProperties();

            if (includeHeaderLine)
            {
                //add header line.
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    sb.Append(propertyInfo.Name).Append(",");
                }
                sb.Remove(sb.Length - 1, 1).AppendLine();
            }

            //add value for each property.
            foreach (T obj in Objects)
            {               
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    sb.Append(MakeValueCsvFriendly(propertyInfo.GetValue(obj, null))).Append(",");
                }
                sb.Remove(sb.Length - 1, 1).AppendLine();
            }

            return sb.ToString();
        }

        //export to a file.
        public void ExportToFile(string path)
        {
            File.WriteAllText(path, Export());
        }

        //export as binary data.
        public byte[] ExportToBytes()
        {
            return Encoding.UTF8.GetBytes(Export());
        }

        //get the csv value for field.
        private string MakeValueCsvFriendly(object value)
        {
            if (value == null) return "";
            if (value is Nullable && ((INullable)value).IsNull) return "";

            if (value is DateTime)
            {
                if (((DateTime)value).TimeOfDay.TotalSeconds == 0)
                    return ((DateTime)value).ToString("yyyy-MM-dd");
                return ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
            }
            string output = value.ToString();

            if (output.Contains(",") || output.Contains("\""))
                output = '"' + output.Replace("\"", "\"\"") + '"';

            return output;

        }
    }

Usage sample : (updated per comment)

用法示例:(每条评论更新一次)

CsvExport<BusinessObject> csv= new CsvExport<BusinessObject>(GetBusinessObjectList());
Response.Write(csv.Export());

#2


18  

Please forgive me

请原谅我

But I think a public open-source repository is a better way to share code and make contributions, and corrections, and additions like "I fixed this, I fixed that"

但是我认为公共开源存储库是一种更好的共享代码,贡献,修正和补充的方式比如"我修复了这个,我修复了那个"

So I made a simple git-repository out of the topic-starter's code and all the additions:

所以我用主题启动器的代码和所有添加的代码做了一个简单的git仓库:

https://github.com/jitbit/CsvExport

https://github.com/jitbit/CsvExport

I also added a couple of useful fixes myself. Everyone could add suggestions, fork it to contribute etc. etc. etc. Send me your forks so I merge them back into the repo.

我还添加了一些有用的修正。每个人都可以添加建议,分叉贡献等等。把你的分叉发给我,这样我就可以把它们合并回回购。

PS. I posted all copyright notices for Chris. @Chris if you're against this idea - let me know, I'll kill it.

PS.我为Chris贴了所有的版权通知。@Chris,如果你反对这个想法-让我知道,我会杀了它。

#3


11  

Another good solution to read and write CSV-files is filehelpers (open source).

另一个读写csv文件的好方法是filehelper(开源)。

#4


6  

How about using string.Join instead of all the foreach Loops?

如何使用字符串。连接而不是所有的foreach循环?

#5


6  

If anyone would like I converted this to an extension method on IEnumerable:

如果有人愿意,我把它转换成IEnumerable的扩展方法:

public static class ListExtensions
{
    public static string ExportAsCSV<T>(this IEnumerable<T> listToExport, bool includeHeaderLine, string delimeter)
    {
        StringBuilder sb = new StringBuilder();

        IList<PropertyInfo> propertyInfos = typeof(T).GetProperties();

        if (includeHeaderLine)
        {
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                sb.Append(propertyInfo.Name).Append(",");
            }
            sb.Remove(sb.Length - 1, 1).AppendLine();
        }

        foreach (T obj in listToExport)
        {
            T localObject = obj;

            var line = String.Join(delimeter, propertyInfos.Select(x => SanitizeValuesForCSV(x.GetValue(localObject, null), delimeter)));

            sb.AppendLine(line);
        }

        return sb.ToString();
    }

    private static string SanitizeValuesForCSV(object value, string delimeter)
    {
        string output;

        if (value == null) return "";

        if (value is DateTime)
        {
            output = ((DateTime)value).ToLongDateString();
        }
        else
        {
            output = value.ToString();                
        }

        if (output.Contains(delimeter) || output.Contains("\""))
            output = '"' + output.Replace("\"", "\"\"") + '"';

        output = output.Replace("\n", " ");
        output = output.Replace("\r", "");

        return output;
    }
}

#6


5  

great work on this class. Simple and easy to use. I modified the class to include a title in the first row of the export; figured I would share:

这门课做得很好。简单易用。我将类修改为在导出的第一行包含一个标题;算我想分享:

use:

使用:

CsvExport myExport = new CsvExport();
myExport.addTitle = String.Format("Name: {0},{1}", lastName, firstName));

class:

类:

public class CsvExport
{
    List<string> fields = new List<string>();

    public string addTitle { get; set; } // string for the first row of the export

    List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
    Dictionary<string, object> currentRow
    {
        get
        {
            return rows[rows.Count - 1];
        }
    }

    public object this[string field]
    {
        set
        {
            if (!fields.Contains(field)) fields.Add(field);
            currentRow[field] = value;
        }
    }

    public void AddRow()
    {
        rows.Add(new Dictionary<string, object>());
    }

    string MakeValueCsvFriendly(object value)
    {
        if (value == null) return "";
        if (value is Nullable && ((INullable)value).IsNull) return "";
        if (value is DateTime)
        {
            if (((DateTime)value).TimeOfDay.TotalSeconds == 0)
                return ((DateTime)value).ToString("yyyy-MM-dd");
            return ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
        }
        string output = value.ToString();
        if (output.Contains(",") || output.Contains("\""))
            output = '"' + output.Replace("\"", "\"\"") + '"';
        return output;

    }

    public string Export()
    {
        StringBuilder sb = new StringBuilder();

        // if there is a title
        if (!string.IsNullOrEmpty(addTitle))
        {
            // escape chars that would otherwise break the row / export
            char[] csvTokens = new[] { '\"', ',', '\n', '\r' };

            if (addTitle.IndexOfAny(csvTokens) >= 0)
            {
                addTitle = "\"" + addTitle.Replace("\"", "\"\"") + "\"";
            }
            sb.Append(addTitle).Append(",");
            sb.AppendLine();
        }


        // The header
        foreach (string field in fields)
        sb.Append(field).Append(",");
        sb.AppendLine();

        // The rows
        foreach (Dictionary<string, object> row in rows)
        {
            foreach (string field in fields)
                sb.Append(MakeValueCsvFriendly(row[field])).Append(",");
            sb.AppendLine();
        }

        return sb.ToString();
    }

    public void ExportToFile(string path)
    {
        File.WriteAllText(path, Export());
    }

    public byte[] ExportToBytes()
    {
        return Encoding.UTF8.GetBytes(Export());
    }
}

#7


4  

there's an open-source library for CSV which you can get using nuget: http://joshclose.github.io/CsvHelper/

有一个用于CSV的开源库,可以使用nuget: http://joshclose.github.io/CsvHelper/

#8


3  

I added ExportToStream so the csv didn't have to save to the hard drive first.

我添加了ExportToStream,这样csv就不必先保存到硬盘上。

public Stream ExportToStream()
{
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(Export(true));
    writer.Flush();
    stream.Position = 0;
    return stream;
}

#9


3  

I've added

我已经添加了

public void ExportToFile(string path, DataTable tabela)
{

     DataColumnCollection colunas = tabela.Columns;

     foreach (DataRow linha in tabela.Rows)
     {

           this.AddRow();

           foreach (DataColumn coluna in colunas)

           {

               this[coluna.ColumnName] = linha[coluna];

           }

      }
      this.ExportToFile(path);

}

Previous code does not work with old .NET versions. For 3.5 version of framework use this other version:

以前的代码不能使用旧的。net版本。3.5版本的框架使用其他版本:

        public void ExportToFile(string path)
    {
        bool abort = false;
        bool exists = false;
        do
        {
            exists = File.Exists(path);
            if (!exists)
            {
                if( !Convert.ToBoolean( File.CreateText(path) ) )
                        abort = true;
            }
        } while (!exists || abort);

        if (!abort)
        {
            //File.OpenWrite(path);
            using (StreamWriter w = File.AppendText(path))
            {
                w.WriteLine("hello");
            }

        }

        //File.WriteAllText(path, Export());
    }

#10


2  

Thanks a lot for that! I modified the class to:

非常感谢!我修改了这个类:

  • use a variable delimiter, instead of hardcoded in code
  • 使用变量分隔符,而不是硬编码在代码中
  • replacing all newLines (\n \r \n\r) in MakeValueCsvFriendly
  • 在MakeValueCsvFriendly中替换所有新行

Code:

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

    public class CsvExport
    {

        public char delim = ';';
        /// <summary>
        /// To keep the ordered list of column names
        /// </summary>
        List<string> fields = new List<string>();

        /// <summary>
        /// The list of rows
        /// </summary>
        List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();

        /// <summary>
        /// The current row
        /// </summary>
        Dictionary<string, object> currentRow { get { return rows[rows.Count - 1]; } }

        /// <summary>
        /// Set a value on this column
        /// </summary>
        public object this[string field]
        {
            set
            {
                // Keep track of the field names, because the dictionary loses the ordering
                if (!fields.Contains(field)) fields.Add(field);
                currentRow[field] = value;
            }
        }

        /// <summary>
        /// Call this before setting any fields on a row
        /// </summary>
        public void AddRow()
        {
            rows.Add(new Dictionary<string, object>());
        }

        /// <summary>
        /// Converts a value to how it should output in a csv file
        /// If it has a comma, it needs surrounding with double quotes
        /// Eg Sydney, Australia -> "Sydney, Australia"
        /// Also if it contains any double quotes ("), then they need to be replaced with quad quotes[sic] ("")
        /// Eg "Dangerous Dan" McGrew -> """Dangerous Dan"" McGrew"
        /// </summary>
        string MakeValueCsvFriendly(object value)
        {
            if (value == null) return "";
            if (value is INullable && ((INullable)value).IsNull) return "";
            if (value is DateTime)
            {
                if (((DateTime)value).TimeOfDay.TotalSeconds == 0)
                    return ((DateTime)value).ToString("yyyy-MM-dd");
                return ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
            }
            string output = value.ToString();
            if (output.Contains(delim) || output.Contains("\""))
                output = '"' + output.Replace("\"", "\"\"") + '"';
            if (Regex.IsMatch(output,  @"(?:\r\n|\n|\r)"))
                output = string.Join(" ", Regex.Split(output, @"(?:\r\n|\n|\r)"));
            return output;
        }

        /// <summary>
        /// Output all rows as a CSV returning a string
        /// </summary>
        public string Export()
        {
            StringBuilder sb = new StringBuilder();

            // The header
            foreach (string field in fields)
                sb.Append(field).Append(delim);
            sb.AppendLine();

            // The rows
            foreach (Dictionary<string, object> row in rows)
            {
                foreach (string field in fields)
                    sb.Append(MakeValueCsvFriendly(row[field])).Append(delim);
                sb.AppendLine();
            }

            return sb.ToString();
        }

        /// <summary>
        /// Exports to a file
        /// </summary>
        public void ExportToFile(string path)
        {
            File.WriteAllText(path, Export());
        }

        /// <summary>
        /// Exports as raw UTF8 bytes
        /// </summary>
        public byte[] ExportToBytes()
        {
            return Encoding.UTF8.GetBytes(Export());

        }

    }

#11


1  

You can also use ADO to do this: http://weblogs.asp.net/fmarguerie/archive/2003/10/01/29964.aspx

您还可以使用ADO来实现这一点:http://weblogs.asp.net/fmarguerie/archive/2003/10/01/29964.aspx

#12


1  

The original class have a problem, and that is if you want to add a new column, you will receive KeyNotFoundException on Export method. For example:

原始类有一个问题,那就是如果您想添加一个新的列,您将接收到Export方法的KeyNotFoundException。例如:

static void Main(string[] args)
{
    var export = new CsvExport();

    export.AddRow();
    export["Region"] = "New York, USA";
    export["Sales"] = 100000;
    export["Date Opened"] = new DateTime(2003, 12, 31);

    export.AddRow();
    export["Region"] = "Sydney \"in\" Australia";
    export["Sales"] = 50000;
    export["Date Opened"] = new DateTime(2005, 1, 1, 9, 30, 0);
    export["Balance"] = 3.45f;  //Exception is throwed for this new column

    export.ExportToFile("Somefile.csv");
}

To solve this, and using the @KeyboardCowboy idea of ​​using reflection, I modified the code to allow add rows that do not have the same columns. You can use instances of anonymous classes. For example:

为了解决这个问题,并使用了使用反射的@KeyboardCowboy概念,我修改了代码,允许添加没有相同列的行。您可以使用匿名类的实例。例如:

static void Main(string[] args)
{
    var export = new CsvExporter();

    export.AddRow(new {A = 12, B = "Empty"});
    export.AddRow(new {A = 34.5f, D = false});

    export.ExportToFile("File.csv");
}

You can download the source code here CsvExporter. Feel free to use and modify.

您可以在这里下载csvexports的源代码。请随意使用和修改。

Now, if all rows you want to write are of the same class, I created the generic class CsvWriter.cs, which has a better performance RAM usage and ideal for writing large files.Plus it lets you add formatters to the data type you want. An example of use:

现在,如果要编写的所有行都属于同一个类,我创建了通用类CsvWriter。cs,具有更好的性能RAM使用,非常适合编写大型文件。此外,它还允许向所需的数据类型添加格式化程序。使用一个例子:

class Program
{
    static void Main(string[] args)
    {
        var writer = new CsvWriter<Person>("Persons.csv");

        writer.AddFormatter<DateTime>(d => d.ToString("MM/dd/yyyy"));

        writer.WriteHeaders();
        writer.WriteRows(GetPersons());

        writer.Flush();
        writer.Close();
    }

    private static IEnumerable<Person> GetPersons()
    {
        yield return new Person
            {
                FirstName = "Jhon", 
                LastName = "Doe", 
                Sex = 'M'
            };

        yield return new Person
            {
                FirstName = "Jhane", 
                LastName = "Doe",
                Sex = 'F',
                BirthDate = DateTime.Now
            };
        }
    }


    class Person
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public char Sex  { get; set; }

        public DateTime BirthDate { get; set; }
    }

#13


0  

You need only 1 function to do this. Only you have to do is to make a folder in your solution explorer and store the csv file there and then export that file to the user.

只需要一个函数。您只需在解决方案资源管理器中创建一个文件夹,并在其中存储csv文件,然后将该文件导出给用户。

As in my case I have a folder downloads. First I export all my content to that directory and then exporting it to the user. For response.end handling, I used the ThreadAbortException. So it is a 100% genuine and working function in my solution.

在我的例子中,我有一个文件夹下载。首先,我将所有内容导出到该目录,然后将其导出到用户。为响应。结束处理,我使用了ThreadAbortException。所以在我的解中它是一个100%真实的工作函数。

protected void lnkExport_OnClick(object sender, EventArgs e)
{

    string filename = strFileName = "Export.csv";

    DataTable dt = obj.GetData();  

// call the content and load it into the datatable

    strFileName = Server.MapPath("Downloads") + "\\" + strFileName;

// creating a file in the downloads folder in your solution explorer

    TextWriter tw = new StreamWriter(strFileName);

// using the built in class textwriter for writing your content in the exporting file

    string strData = "Username,Password,City";

// above line is the header for your exported file. So add headings for your coloumns in excel(.csv) file and seperate them with ","

    strData += Environment.NewLine;

// setting the environment to the new line

    foreach (DataRow dr in dt.Rows)
    {
       strData += dr["Username"].ToString() + "," + dr["Password"].ToString() + "," +      dr["City"].ToString();
       strData += Environment.NewLine;
    }

// everytime when loop execute, it adds a line into the file
    tw.Write(strData);

// writing the contents in file
    tw.Close();

// closing the file
    Response.Redirect("Downloads/" + filename);

// exporting the file to the user as a popup to save as....
}

#1


91  

Slightly different version I wrote using reflection for my needs. I had to export a list of objects to csv. In case someone wants to use it for future.

根据我的需要,我使用反射编写了稍微不同的版本。我必须向csv导出一个对象列表。以防有人想用它来做未来。

public class CsvExport<T> where T: class
    {
        public List<T> Objects;

        public CsvExport(List<T> objects)
        {
            Objects = objects;
        }

        public string Export()
        {
            return Export(true);
        }

        public string Export(bool includeHeaderLine)
        {

            StringBuilder sb = new StringBuilder();
            //Get properties using reflection.
            IList<PropertyInfo> propertyInfos = typeof(T).GetProperties();

            if (includeHeaderLine)
            {
                //add header line.
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    sb.Append(propertyInfo.Name).Append(",");
                }
                sb.Remove(sb.Length - 1, 1).AppendLine();
            }

            //add value for each property.
            foreach (T obj in Objects)
            {               
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    sb.Append(MakeValueCsvFriendly(propertyInfo.GetValue(obj, null))).Append(",");
                }
                sb.Remove(sb.Length - 1, 1).AppendLine();
            }

            return sb.ToString();
        }

        //export to a file.
        public void ExportToFile(string path)
        {
            File.WriteAllText(path, Export());
        }

        //export as binary data.
        public byte[] ExportToBytes()
        {
            return Encoding.UTF8.GetBytes(Export());
        }

        //get the csv value for field.
        private string MakeValueCsvFriendly(object value)
        {
            if (value == null) return "";
            if (value is Nullable && ((INullable)value).IsNull) return "";

            if (value is DateTime)
            {
                if (((DateTime)value).TimeOfDay.TotalSeconds == 0)
                    return ((DateTime)value).ToString("yyyy-MM-dd");
                return ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
            }
            string output = value.ToString();

            if (output.Contains(",") || output.Contains("\""))
                output = '"' + output.Replace("\"", "\"\"") + '"';

            return output;

        }
    }

Usage sample : (updated per comment)

用法示例:(每条评论更新一次)

CsvExport<BusinessObject> csv= new CsvExport<BusinessObject>(GetBusinessObjectList());
Response.Write(csv.Export());

#2


18  

Please forgive me

请原谅我

But I think a public open-source repository is a better way to share code and make contributions, and corrections, and additions like "I fixed this, I fixed that"

但是我认为公共开源存储库是一种更好的共享代码,贡献,修正和补充的方式比如"我修复了这个,我修复了那个"

So I made a simple git-repository out of the topic-starter's code and all the additions:

所以我用主题启动器的代码和所有添加的代码做了一个简单的git仓库:

https://github.com/jitbit/CsvExport

https://github.com/jitbit/CsvExport

I also added a couple of useful fixes myself. Everyone could add suggestions, fork it to contribute etc. etc. etc. Send me your forks so I merge them back into the repo.

我还添加了一些有用的修正。每个人都可以添加建议,分叉贡献等等。把你的分叉发给我,这样我就可以把它们合并回回购。

PS. I posted all copyright notices for Chris. @Chris if you're against this idea - let me know, I'll kill it.

PS.我为Chris贴了所有的版权通知。@Chris,如果你反对这个想法-让我知道,我会杀了它。

#3


11  

Another good solution to read and write CSV-files is filehelpers (open source).

另一个读写csv文件的好方法是filehelper(开源)。

#4


6  

How about using string.Join instead of all the foreach Loops?

如何使用字符串。连接而不是所有的foreach循环?

#5


6  

If anyone would like I converted this to an extension method on IEnumerable:

如果有人愿意,我把它转换成IEnumerable的扩展方法:

public static class ListExtensions
{
    public static string ExportAsCSV<T>(this IEnumerable<T> listToExport, bool includeHeaderLine, string delimeter)
    {
        StringBuilder sb = new StringBuilder();

        IList<PropertyInfo> propertyInfos = typeof(T).GetProperties();

        if (includeHeaderLine)
        {
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                sb.Append(propertyInfo.Name).Append(",");
            }
            sb.Remove(sb.Length - 1, 1).AppendLine();
        }

        foreach (T obj in listToExport)
        {
            T localObject = obj;

            var line = String.Join(delimeter, propertyInfos.Select(x => SanitizeValuesForCSV(x.GetValue(localObject, null), delimeter)));

            sb.AppendLine(line);
        }

        return sb.ToString();
    }

    private static string SanitizeValuesForCSV(object value, string delimeter)
    {
        string output;

        if (value == null) return "";

        if (value is DateTime)
        {
            output = ((DateTime)value).ToLongDateString();
        }
        else
        {
            output = value.ToString();                
        }

        if (output.Contains(delimeter) || output.Contains("\""))
            output = '"' + output.Replace("\"", "\"\"") + '"';

        output = output.Replace("\n", " ");
        output = output.Replace("\r", "");

        return output;
    }
}

#6


5  

great work on this class. Simple and easy to use. I modified the class to include a title in the first row of the export; figured I would share:

这门课做得很好。简单易用。我将类修改为在导出的第一行包含一个标题;算我想分享:

use:

使用:

CsvExport myExport = new CsvExport();
myExport.addTitle = String.Format("Name: {0},{1}", lastName, firstName));

class:

类:

public class CsvExport
{
    List<string> fields = new List<string>();

    public string addTitle { get; set; } // string for the first row of the export

    List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
    Dictionary<string, object> currentRow
    {
        get
        {
            return rows[rows.Count - 1];
        }
    }

    public object this[string field]
    {
        set
        {
            if (!fields.Contains(field)) fields.Add(field);
            currentRow[field] = value;
        }
    }

    public void AddRow()
    {
        rows.Add(new Dictionary<string, object>());
    }

    string MakeValueCsvFriendly(object value)
    {
        if (value == null) return "";
        if (value is Nullable && ((INullable)value).IsNull) return "";
        if (value is DateTime)
        {
            if (((DateTime)value).TimeOfDay.TotalSeconds == 0)
                return ((DateTime)value).ToString("yyyy-MM-dd");
            return ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
        }
        string output = value.ToString();
        if (output.Contains(",") || output.Contains("\""))
            output = '"' + output.Replace("\"", "\"\"") + '"';
        return output;

    }

    public string Export()
    {
        StringBuilder sb = new StringBuilder();

        // if there is a title
        if (!string.IsNullOrEmpty(addTitle))
        {
            // escape chars that would otherwise break the row / export
            char[] csvTokens = new[] { '\"', ',', '\n', '\r' };

            if (addTitle.IndexOfAny(csvTokens) >= 0)
            {
                addTitle = "\"" + addTitle.Replace("\"", "\"\"") + "\"";
            }
            sb.Append(addTitle).Append(",");
            sb.AppendLine();
        }


        // The header
        foreach (string field in fields)
        sb.Append(field).Append(",");
        sb.AppendLine();

        // The rows
        foreach (Dictionary<string, object> row in rows)
        {
            foreach (string field in fields)
                sb.Append(MakeValueCsvFriendly(row[field])).Append(",");
            sb.AppendLine();
        }

        return sb.ToString();
    }

    public void ExportToFile(string path)
    {
        File.WriteAllText(path, Export());
    }

    public byte[] ExportToBytes()
    {
        return Encoding.UTF8.GetBytes(Export());
    }
}

#7


4  

there's an open-source library for CSV which you can get using nuget: http://joshclose.github.io/CsvHelper/

有一个用于CSV的开源库,可以使用nuget: http://joshclose.github.io/CsvHelper/

#8


3  

I added ExportToStream so the csv didn't have to save to the hard drive first.

我添加了ExportToStream,这样csv就不必先保存到硬盘上。

public Stream ExportToStream()
{
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(Export(true));
    writer.Flush();
    stream.Position = 0;
    return stream;
}

#9


3  

I've added

我已经添加了

public void ExportToFile(string path, DataTable tabela)
{

     DataColumnCollection colunas = tabela.Columns;

     foreach (DataRow linha in tabela.Rows)
     {

           this.AddRow();

           foreach (DataColumn coluna in colunas)

           {

               this[coluna.ColumnName] = linha[coluna];

           }

      }
      this.ExportToFile(path);

}

Previous code does not work with old .NET versions. For 3.5 version of framework use this other version:

以前的代码不能使用旧的。net版本。3.5版本的框架使用其他版本:

        public void ExportToFile(string path)
    {
        bool abort = false;
        bool exists = false;
        do
        {
            exists = File.Exists(path);
            if (!exists)
            {
                if( !Convert.ToBoolean( File.CreateText(path) ) )
                        abort = true;
            }
        } while (!exists || abort);

        if (!abort)
        {
            //File.OpenWrite(path);
            using (StreamWriter w = File.AppendText(path))
            {
                w.WriteLine("hello");
            }

        }

        //File.WriteAllText(path, Export());
    }

#10


2  

Thanks a lot for that! I modified the class to:

非常感谢!我修改了这个类:

  • use a variable delimiter, instead of hardcoded in code
  • 使用变量分隔符,而不是硬编码在代码中
  • replacing all newLines (\n \r \n\r) in MakeValueCsvFriendly
  • 在MakeValueCsvFriendly中替换所有新行

Code:

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

    public class CsvExport
    {

        public char delim = ';';
        /// <summary>
        /// To keep the ordered list of column names
        /// </summary>
        List<string> fields = new List<string>();

        /// <summary>
        /// The list of rows
        /// </summary>
        List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();

        /// <summary>
        /// The current row
        /// </summary>
        Dictionary<string, object> currentRow { get { return rows[rows.Count - 1]; } }

        /// <summary>
        /// Set a value on this column
        /// </summary>
        public object this[string field]
        {
            set
            {
                // Keep track of the field names, because the dictionary loses the ordering
                if (!fields.Contains(field)) fields.Add(field);
                currentRow[field] = value;
            }
        }

        /// <summary>
        /// Call this before setting any fields on a row
        /// </summary>
        public void AddRow()
        {
            rows.Add(new Dictionary<string, object>());
        }

        /// <summary>
        /// Converts a value to how it should output in a csv file
        /// If it has a comma, it needs surrounding with double quotes
        /// Eg Sydney, Australia -> "Sydney, Australia"
        /// Also if it contains any double quotes ("), then they need to be replaced with quad quotes[sic] ("")
        /// Eg "Dangerous Dan" McGrew -> """Dangerous Dan"" McGrew"
        /// </summary>
        string MakeValueCsvFriendly(object value)
        {
            if (value == null) return "";
            if (value is INullable && ((INullable)value).IsNull) return "";
            if (value is DateTime)
            {
                if (((DateTime)value).TimeOfDay.TotalSeconds == 0)
                    return ((DateTime)value).ToString("yyyy-MM-dd");
                return ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
            }
            string output = value.ToString();
            if (output.Contains(delim) || output.Contains("\""))
                output = '"' + output.Replace("\"", "\"\"") + '"';
            if (Regex.IsMatch(output,  @"(?:\r\n|\n|\r)"))
                output = string.Join(" ", Regex.Split(output, @"(?:\r\n|\n|\r)"));
            return output;
        }

        /// <summary>
        /// Output all rows as a CSV returning a string
        /// </summary>
        public string Export()
        {
            StringBuilder sb = new StringBuilder();

            // The header
            foreach (string field in fields)
                sb.Append(field).Append(delim);
            sb.AppendLine();

            // The rows
            foreach (Dictionary<string, object> row in rows)
            {
                foreach (string field in fields)
                    sb.Append(MakeValueCsvFriendly(row[field])).Append(delim);
                sb.AppendLine();
            }

            return sb.ToString();
        }

        /// <summary>
        /// Exports to a file
        /// </summary>
        public void ExportToFile(string path)
        {
            File.WriteAllText(path, Export());
        }

        /// <summary>
        /// Exports as raw UTF8 bytes
        /// </summary>
        public byte[] ExportToBytes()
        {
            return Encoding.UTF8.GetBytes(Export());

        }

    }

#11


1  

You can also use ADO to do this: http://weblogs.asp.net/fmarguerie/archive/2003/10/01/29964.aspx

您还可以使用ADO来实现这一点:http://weblogs.asp.net/fmarguerie/archive/2003/10/01/29964.aspx

#12


1  

The original class have a problem, and that is if you want to add a new column, you will receive KeyNotFoundException on Export method. For example:

原始类有一个问题,那就是如果您想添加一个新的列,您将接收到Export方法的KeyNotFoundException。例如:

static void Main(string[] args)
{
    var export = new CsvExport();

    export.AddRow();
    export["Region"] = "New York, USA";
    export["Sales"] = 100000;
    export["Date Opened"] = new DateTime(2003, 12, 31);

    export.AddRow();
    export["Region"] = "Sydney \"in\" Australia";
    export["Sales"] = 50000;
    export["Date Opened"] = new DateTime(2005, 1, 1, 9, 30, 0);
    export["Balance"] = 3.45f;  //Exception is throwed for this new column

    export.ExportToFile("Somefile.csv");
}

To solve this, and using the @KeyboardCowboy idea of ​​using reflection, I modified the code to allow add rows that do not have the same columns. You can use instances of anonymous classes. For example:

为了解决这个问题,并使用了使用反射的@KeyboardCowboy概念,我修改了代码,允许添加没有相同列的行。您可以使用匿名类的实例。例如:

static void Main(string[] args)
{
    var export = new CsvExporter();

    export.AddRow(new {A = 12, B = "Empty"});
    export.AddRow(new {A = 34.5f, D = false});

    export.ExportToFile("File.csv");
}

You can download the source code here CsvExporter. Feel free to use and modify.

您可以在这里下载csvexports的源代码。请随意使用和修改。

Now, if all rows you want to write are of the same class, I created the generic class CsvWriter.cs, which has a better performance RAM usage and ideal for writing large files.Plus it lets you add formatters to the data type you want. An example of use:

现在,如果要编写的所有行都属于同一个类,我创建了通用类CsvWriter。cs,具有更好的性能RAM使用,非常适合编写大型文件。此外,它还允许向所需的数据类型添加格式化程序。使用一个例子:

class Program
{
    static void Main(string[] args)
    {
        var writer = new CsvWriter<Person>("Persons.csv");

        writer.AddFormatter<DateTime>(d => d.ToString("MM/dd/yyyy"));

        writer.WriteHeaders();
        writer.WriteRows(GetPersons());

        writer.Flush();
        writer.Close();
    }

    private static IEnumerable<Person> GetPersons()
    {
        yield return new Person
            {
                FirstName = "Jhon", 
                LastName = "Doe", 
                Sex = 'M'
            };

        yield return new Person
            {
                FirstName = "Jhane", 
                LastName = "Doe",
                Sex = 'F',
                BirthDate = DateTime.Now
            };
        }
    }


    class Person
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public char Sex  { get; set; }

        public DateTime BirthDate { get; set; }
    }

#13


0  

You need only 1 function to do this. Only you have to do is to make a folder in your solution explorer and store the csv file there and then export that file to the user.

只需要一个函数。您只需在解决方案资源管理器中创建一个文件夹,并在其中存储csv文件,然后将该文件导出给用户。

As in my case I have a folder downloads. First I export all my content to that directory and then exporting it to the user. For response.end handling, I used the ThreadAbortException. So it is a 100% genuine and working function in my solution.

在我的例子中,我有一个文件夹下载。首先,我将所有内容导出到该目录,然后将其导出到用户。为响应。结束处理,我使用了ThreadAbortException。所以在我的解中它是一个100%真实的工作函数。

protected void lnkExport_OnClick(object sender, EventArgs e)
{

    string filename = strFileName = "Export.csv";

    DataTable dt = obj.GetData();  

// call the content and load it into the datatable

    strFileName = Server.MapPath("Downloads") + "\\" + strFileName;

// creating a file in the downloads folder in your solution explorer

    TextWriter tw = new StreamWriter(strFileName);

// using the built in class textwriter for writing your content in the exporting file

    string strData = "Username,Password,City";

// above line is the header for your exported file. So add headings for your coloumns in excel(.csv) file and seperate them with ","

    strData += Environment.NewLine;

// setting the environment to the new line

    foreach (DataRow dr in dt.Rows)
    {
       strData += dr["Username"].ToString() + "," + dr["Password"].ToString() + "," +      dr["City"].ToString();
       strData += Environment.NewLine;
    }

// everytime when loop execute, it adds a line into the file
    tw.Write(strData);

// writing the contents in file
    tw.Close();

// closing the file
    Response.Redirect("Downloads/" + filename);

// exporting the file to the user as a popup to save as....
}