Создать.csv-файл на языке C#

хорошо я хочу создать .csv-файл на C#. Я осматривался и заметил, что многие люди используют эту систему.ИО.memorystream и система.Ио.streamwriter.

проблема в следующем: у меня есть веб-приложение. Я хочу дать пользователю возможность экспортировать в excel. Проблема в том, что Excel не может быть установлен на сервере (не спрашивайте). Я хочу иметь возможность писать .экспорт листов csv для отчета. Теперь заголовки и данные отчетов будут отличаться для всех отчетов (петля через решит это). У кого-нибудь есть пример или лучшие ресурсы для меня?

7 ответов


это подход, который я обычно принимаю. Хотя, наверное, не самый эффективный.

        /// <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();
    }

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);
}

также может стоить отправить заголовок Content-disposition с рекомендуемым именем файла.

Edit: в последнее время, в случаях, когда нужно поместить действие между элементами в перечислении (например, запятая и новая строка выше), я предпочел бы, чтобы вместо того, чтобы держать логическое значение, которое продолжает проверяться, я обрабатываю перечислитель напрямую, а затем обрабатываю первый элемент отдельно от остальных. Я начал делать это как микро-опт в эффективности-толчок, но вырос до просто найдите лучшее выражение пути кода, который отличается для первого элемента. Как таковой, я бы сейчас написал выше как:

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);
      }
    }
}

вы должны иметь возможность использовать примеры, используя System.IO.MemoryStream и System.IO.StreamWriter просто отлично.

вместо того, чтобы записывать MemoryStream в файл, вы бы вернули его как ResponseStream в ASP.NET (убедитесь, что вы установили соответствующие значения заголовка, чтобы браузер знал, что он загружает файл).


Excel требуется только при использовании Office Interop. Используя StringWriter, вы просто создадите файл и добавите некоторую информацию об ответе. В Excel требуется только при открытии файла.


в создании CSV-файла действительно нет магии. Единственная проблема с CSV-файлами заключается в том, что на самом деле нет стандарта, и большинство импортеров просто реализуют одно конкретное поведение для процесса импорта. Если Вам повезет, вы получите что-то, что может догадаться относительно хорошо.

создание файла CSV-это просто вопрос печати строк. Что касается фактических деталей, ознакомьтесь с:

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

при этом, если вы хотите экспортировать в Excel, вы можете использовать Microsoft OOXML SDK:

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

пакет OOXML SDK-это библиотека c#, которую можно использовать для создания файлов Excel на сервере. Блог Брайана Джонса-отличный ресурс о том, как использовать это библиотека:

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


Если вы не возражаете использовать стороннюю библиотеку и LGPL лицензия в порядке в вашем проекте, тогда FileHelpers является отличным инструментом для этого.


это функция, используемая для создания 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/