在 C# 中创建 .csv 文件

发布于 2024-09-15 03:02:23 字数 234 浏览 6 评论 0原文

好吧,我想用 C# 创建一个 .csv 文件。我环顾四周,发现很多人都在使用 system.IO.memorystream 和 system.io.streamwriter。

问题是这样的:我有一个网络应用程序。我想让用户能够导出到 Excel。问题是,Excel 无法安装在服务器上(不要问)。我希望能够为报告编写 .csv 工作表导出。现在,所有报告的报告标题和数据都将有所不同(循环将解决此问题)。有人有例子或更好的资源供我参考吗?

Alright I want to create a .csv file in C#. I have been looking around and noticed a lot of people are using the system.IO.memorystream and system.io.streamwriter.

The problem is this: I have a web application. I want to give the user the ability to export to excel. Problem is, Excel cannot be installed on the server (don't ask). I want to be able to write an .csv sheet export for a report. Now, the reports headers and data will be different for all of the reports (looping through will solve this). Anybody have an example or better resources for me to go through?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

赠意 2024-09-22 03:02:55

这是用于创建 csv 文件的函数:

 private async Task<string> WriteCSV<ViewModel>(IEnumerable<ViewModel> viewModels, string path)
            {
                Type itemType = typeof(ViewModel);
                var props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                    .OrderBy(p => p.Name);

                var blobName = string.Empty;

                using (var ms = new MemoryStream())
                {

                    using (var writer = new System.IO.StreamWriter(ms))
                    {
                        writer.WriteLine(string.Join(", ", props.Select(p => p.Name)));

                        foreach (var item in viewModels)
                        {

                            writer.WriteLine(string.Join(", ", props.Select(p => p.GetValue(item, null))));
                        }
    }

 }
    }

否则您可以参考以下链接:

https://travelcodingnlotsmore.wordpress.com/2013/06/06/creating-csv-file-from-data-in-list-object-in- c/

This is the function used to create csv file:

 private async Task<string> WriteCSV<ViewModel>(IEnumerable<ViewModel> viewModels, string path)
            {
                Type itemType = typeof(ViewModel);
                var props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                    .OrderBy(p => p.Name);

                var blobName = string.Empty;

                using (var ms = new MemoryStream())
                {

                    using (var writer = new System.IO.StreamWriter(ms))
                    {
                        writer.WriteLine(string.Join(", ", props.Select(p => p.Name)));

                        foreach (var item in viewModels)
                        {

                            writer.WriteLine(string.Join(", ", props.Select(p => p.GetValue(item, null))));
                        }
    }

 }
    }

Otherwise you can refer below link:

https://travelcodingnlotsmore.wordpress.com/2013/06/06/creating-csv-file-from-data-in-list-object-in-c/

残花月 2024-09-22 03:02:52

如果您不介意使用第 3 方库并且 LGPL 许可证可以在如果您的项目,那么 FileHelpers 就是一个很棒的工具。

If you don't mind using a 3rd party library and the LGPL license is okay in your project, then FileHelpers is a great tool for this.

吝吻 2024-09-22 03:02:49

创建 CSV 文件确实没有什么神奇之处。 CSV 文件的唯一问题是没有真正的标准,大多数导入者只会为导入过程实现一种特定行为。如果运气好的话,你会得到一些能猜得比较好的东西。

生成 CSV 文件只需打印行即可。至于实际细节,请熟悉一下:

http://en.wikipedia.org/wiki/逗号分隔值

也就是说,如果您想要导出到 Excel,您可以使用 Microsoft 的 OOXML SDK:

http://msdn.microsoft.com/en-us/library/bb448854.aspx

OOXML SDK 是一个 C# 库,可用于在服务器。 Brian Jones 博客是有关如何使用此库的重要资源:

http://blogs.msdn。 com/b/brian_jones/

There is really no magic in creating a CSV file. The only problem with CSV files is that there is not really a standard, and most importers will just implement one particular behavior for the import process. If you are lucky, you will get something that can guess relatively well.

Generating the CSV file is just a matter of printing the lines. As for the actual details, familiarize yourself with:

http://en.wikipedia.org/wiki/Comma-separated_values

That being said, if what you want is to export to Excel, you could use Microsoft's OOXML SDK:

http://msdn.microsoft.com/en-us/library/bb448854.aspx

The OOXML SDK is a C# library that you can use to generate Excel files on the server. The Brian Jones blog is a great resource on how to use this library:

http://blogs.msdn.com/b/brian_jones/

好菇凉咱不稀罕他 2024-09-22 03:02:47

仅当您使用 Office Interop 时才需要 Excel。使用 StringWriter,您只需创建一个文件并添加一些响应信息。仅在打开文件时才需要 Excel。

Excel is only required if you are using Office Interop. Using StringWriter, you are simply going to create a file and add some response information. Excel is only required when opening the file.

碍人泪离人颜 2024-09-22 03:02:44

您应该能够很好地使用使用 System.IO.MemoryStream 和 System.IO.StreamWriter 的示例。

您无需将 MemoryStream 写入文件,而是将其作为 ASP.NET 中的 ResponseStream 返回(确保设置了适当的标头值,以便浏览器知道它正在下载文件)。

You should be able to use the examples using System.IO.MemoryStream and System.IO.StreamWriter just fine.

Instead of writing the MemoryStream out to a file, you would return it as the ResponseStream in ASP.NET (making sure that you set the appropriate header values so the browser knows that it's downloading a file).

后来的我们 2024-09-22 03:02:41
private void WriteItem<T>(StreamWriter sr, T item)
{
    string itemString = item.ToString();
    if(itemString.IndexOfAny(new char[] { '"', ',', '\n', '\r' }) != -1)//skip test and always escape for different speed/filesize optimisation
    {
        sr.Write('"');
        sr.Write(itemString.Replace("\"", "\"\""));
        sr.Write('"');
    }
    else
        sr.Write(itemString);
}
private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
    bool first = true;
    foreach(T item in line)
    {
        if(!first)
            sr.Write(',');
        first = false;
        WriteItem(sr, item);
    }
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
    bool first = true;
    foreach(IEnumerable<T> line in allLines)
    {
        if(!first)
            sr.Write('\n');
        first = false;
        WriteLine(sr, line);
    }
}
private void WriteCSV<T>(HttpResponse response, IEnumerable<IEnumerable<T>> allLines)
{
    response.ContentType = "text/csv";
    WriteCSV(response.Output, allLines);
}

还值得发送带有推荐文件名的内容处置标头。

编辑:最近,在需要在枚举中的项目之间间隔操作的情况下(例如上面的逗号和换行符),我更喜欢保留一个不断检查的布尔值,而是直接处理枚举器,然后将第一个元素与其余元素分开处理。我开始这样做是为了提高效率,但后来发现它是第一个项目不同的代码路径的更好表达。因此,我现在将上面的内容写为:

private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
  using(var en = line.GetEnumerator())
  if(en.MoveNext())
  {
    WriteItem(sr, en.Current);
    while(en.MoveNext())
    {
      sr.Write(',');
      WriteItem(sr, en.Current);
    }
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
    using(var en = allLines.GetEnumerator())
    if(en.MoveNext())
    {
      WriteLine(sr, en.Current);
      while(en.MoveNext())
      {
        sr.Write('\n');
        WriteLine(sr, en.Current);
      }
    }
}
private void WriteItem<T>(StreamWriter sr, T item)
{
    string itemString = item.ToString();
    if(itemString.IndexOfAny(new char[] { '"', ',', '\n', '\r' }) != -1)//skip test and always escape for different speed/filesize optimisation
    {
        sr.Write('"');
        sr.Write(itemString.Replace("\"", "\"\""));
        sr.Write('"');
    }
    else
        sr.Write(itemString);
}
private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
    bool first = true;
    foreach(T item in line)
    {
        if(!first)
            sr.Write(',');
        first = false;
        WriteItem(sr, item);
    }
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
    bool first = true;
    foreach(IEnumerable<T> line in allLines)
    {
        if(!first)
            sr.Write('\n');
        first = false;
        WriteLine(sr, line);
    }
}
private void WriteCSV<T>(HttpResponse response, IEnumerable<IEnumerable<T>> allLines)
{
    response.ContentType = "text/csv";
    WriteCSV(response.Output, allLines);
}

It can be worth also sending a content-disposition header with a recommended filename.

Edit: Of late, with cases where one needs to interspace an action between items in an enumeration (like the comma and newline above), I've preferred that rather keeping a boolean that keeps being checked, I handle the enumerator directly, and then handle the first element separate from the rest. I started doing this as a micro-opt in a efficiency-push but have grown to just find it a better expression of a code-path that differs for the first item. As such, I'd now write the above as:

private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
  using(var en = line.GetEnumerator())
  if(en.MoveNext())
  {
    WriteItem(sr, en.Current);
    while(en.MoveNext())
    {
      sr.Write(',');
      WriteItem(sr, en.Current);
    }
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
    using(var en = allLines.GetEnumerator())
    if(en.MoveNext())
    {
      WriteLine(sr, en.Current);
      while(en.MoveNext())
      {
        sr.Write('\n');
        WriteLine(sr, en.Current);
      }
    }
}
携君以终年 2024-09-22 03:02:35

这是我通常采取的方法。但可能不是最有效的。

        /// <summary>
    /// Generates the contents of the log file.
    /// </summary>
    /// <returns>The contents of the log file.</returns>
    internal string GenerateLogFile()
    {
        StringBuilder csvExport = new StringBuilder();
        csvExport.AppendLine(Resources.CSVHeader);

        foreach (DataRow row in this.logEntries.Rows)
        {
            csvExport.AppendLine(
                string.Format(
                "\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\", \"{9}\"",
                row[ColumnNames.LogTime], row[ColumnNames.Field1], row[ColumnNames.Field2], row[ColumnNames.Field3], row[ColumnNames.Field4], row[ColumnNames.Field5], row[ColumnNames.Field6], row[ColumnNames.Field7], row[ColumnNames.Field8], row[ColumnNames.Field9]));
        }

        return csvExport.ToString();
    }

    /// <summary>
    /// Adds the CSV file to the response.
    /// </summary>
    /// <param name="csvExportContents">The contents of the CSV file.</param>
    internal void DisplayLogFile(string csvExportContents)
    {
        byte[] data = new ASCIIEncoding().GetBytes(csvExportContents);

        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.ContentType = "APPLICATION/OCTET-STREAM";
        HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=Export.csv");
        HttpContext.Current.Response.OutputStream.Write(data, 0, data.Length);
        HttpContext.Current.Response.End();
    }

This the approach i normally take. Probably not the most efficient though.

        /// <summary>
    /// Generates the contents of the log file.
    /// </summary>
    /// <returns>The contents of the log file.</returns>
    internal string GenerateLogFile()
    {
        StringBuilder csvExport = new StringBuilder();
        csvExport.AppendLine(Resources.CSVHeader);

        foreach (DataRow row in this.logEntries.Rows)
        {
            csvExport.AppendLine(
                string.Format(
                "\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\", \"{9}\"",
                row[ColumnNames.LogTime], row[ColumnNames.Field1], row[ColumnNames.Field2], row[ColumnNames.Field3], row[ColumnNames.Field4], row[ColumnNames.Field5], row[ColumnNames.Field6], row[ColumnNames.Field7], row[ColumnNames.Field8], row[ColumnNames.Field9]));
        }

        return csvExport.ToString();
    }

    /// <summary>
    /// Adds the CSV file to the response.
    /// </summary>
    /// <param name="csvExportContents">The contents of the CSV file.</param>
    internal void DisplayLogFile(string csvExportContents)
    {
        byte[] data = new ASCIIEncoding().GetBytes(csvExportContents);

        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.ContentType = "APPLICATION/OCTET-STREAM";
        HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=Export.csv");
        HttpContext.Current.Response.OutputStream.Write(data, 0, data.Length);
        HttpContext.Current.Response.End();
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文