2010-08-20 4 views
7

Хорошо, я хочу создать CSV-файл на C#. Я смотрю вокруг и замечаю, что многие люди используют system.IO.memorystream и system.io.streamwriter.Создайте CSV-файл в C#

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

+0

После прочтения. Все, что мне действительно нужно сделать, это цикл и вывод данных, разделенных запятыми, с/n в конце строки и продолжением цикла до завершения ... сохранить файл как .csv, а затем закрыть поток ... правильно? – Tom

+0

Вам также необходимо установить тип содержимого, и если в базе данных может содержаться символ '' ',', 'или символ новой строки, вам также необходимо его избежать. Код для этого в моем ответе. –

ответ

13

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

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

Откуда CSVHeader? – RealityDysfunction

+0

Я не вижу, как бы сбрасывались значения, которые могли бы содержать '' '. –

+0

@RealityDysfunction Я предполагаю, что это файл resx. Для примера было бы более полезно иметь строковый литерал. – MrBoJangles

4

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

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

3

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

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

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

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

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

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

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

+0

Для этого нужен Excel на сервере? – Tom

+0

Вам не нужен Excel на сервере для запуска SDK OOXML. Фактически, вы даже можете запустить его в системе Linux с помощью Mono. –

4

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

3

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

+1

Я люблю FileHelpers! Эта простая и быстрая библиотека упрощает превращение плоских файлов в объекты. Он также может объектно ориентировать объекты в текстовые файлы. И это быстро. И у него есть мастер, который поможет вам. Ура! –

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

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

Смежные вопросы