2010-08-20 66 views
7

Được rồi Tôi muốn tạo tệp .csv trong C#. Tôi đã nhìn xung quanh và nhận thấy rất nhiều người đang sử dụng system.IO.memorystream và system.io.streamwriter.Tạo tệp .csv trong C#

Vấn đề là: Tôi có một ứng dụng web. Tôi muốn cung cấp cho người dùng khả năng xuất sang excel. Vấn đề là, Excel không thể được cài đặt trên máy chủ (không hỏi). Tôi muốn có thể viết một trang xuất .csv cho một báo cáo. Bây giờ, các tiêu đề báo cáo và dữ liệu sẽ khác nhau đối với tất cả các báo cáo (lặp qua sẽ giải quyết vấn đề này). Bất cứ ai có một ví dụ hoặc nguồn lực tốt hơn cho tôi để đi qua?

+0

Sau khi đọc xung quanh. Tất cả những gì tôi thực sự cần làm là lặp qua và xuất dữ liệu được phân cách bằng dấu phẩy với/n ở cuối hàng và tiếp tục lặp lại cho đến khi hoàn tất ... lưu tệp dưới dạng .csv và sau đó đóng luồng ... đúng không? – Tom

+0

Bạn cũng cần phải đặt loại nội dung và nếu một biểu đồ có thể chứa ký tự '' ',', 'hoặc dòng mới bạn cần phải thoát khỏi nó. Mã cho câu trả lời của tôi là –

Trả lời

13

Cách tiếp cận này tôi thường thực hiện. Có lẽ không phải là hiệu quả nhất mặc dù.

 /// <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 xuất phát từ đâu? – RealityDysfunction

+0

Tôi không thấy các giá trị có thể chứa '" 'sẽ bị loại bỏ như thế nào. –

+0

@RealityDysfunction Tôi giả sử nó từ một tệp resx. Nó sẽ hữu ích hơn vì lợi ích của ví dụ để chỉ có một chuỗi chữ. – MrBoJangles

4

Bạn sẽ có thể sử dụng các ví dụ sử dụng System.IO.MemoryStreamSystem.IO.StreamWriter tốt.

Thay vì ghi MemoryStream ra tệp, bạn sẽ trả về nó như là ResponseStream trong ASP.NET (đảm bảo rằng bạn đặt giá trị tiêu đề thích hợp để trình duyệt biết rằng nó đang tải xuống tệp).

3

Thực sự không có phép thuật khi tạo tệp CSV. Vấn đề duy nhất với tệp CSV là không thực sự là tiêu chuẩn và hầu hết các nhà nhập khẩu sẽ chỉ thực hiện một hành vi cụ thể cho quá trình nhập. Nếu bạn may mắn, bạn sẽ nhận được một cái gì đó có thể đoán tương đối tốt.

Tạo tệp CSV chỉ là vấn đề in các dòng. Đối với các chi tiết thực tế, làm quen với:

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

Điều đó đang được nói, nếu những gì bạn muốn là để xuất khẩu sang Excel, bạn có thể sử dụng OOXML của Microsoft SDK:

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

Các OOXML SDK là một thư viện C# mà bạn có thể sử dụng để tạo các tệp Excel trên máy chủ. Blog Brian Jones là một nguồn lực lớn về cách sử dụng thư viện này:

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

+0

Tôi có cần Excel trên máy chủ cho điều này không? – Tom

+0

Bạn không cần Excel trên máy chủ để chạy OOXML SDK. Trong thực tế, bạn thậm chí có thể chạy nó trên một hệ thống Linux với Mono. –

4

Excel chỉ cần thiết nếu bạn đang sử dụng Office Interop. Sử dụng StringWriter, bạn chỉ cần tạo một tệp và thêm một số thông tin phản hồi. Excel chỉ được yêu cầu khi mở tệp.

3

Nếu bạn không nhớ sử dụng thư viện của bên thứ ba và giấy phép LGPL không sao trong dự án của bạn, thì FileHelpers là một công cụ tuyệt vời cho việc này.

+1

Tôi yêu FileHelpers! Thư viện đơn giản và nhanh chóng này biến các tệp phẳng thành các đối tượng dễ dàng. Nó cũng có thể biến các đối tượng thành các tệp văn bản phẳng theo cách hướng đối tượng. Và nó nhanh. Và nó có một thuật sĩ để giúp hướng dẫn bạn. Chúc mừng! –

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

Bạn cũng có thể gửi tiêu đề bố cục nội dung bằng tên tệp được đề xuất.

Chỉnh sửa: Trong trường hợp cần phải xen kẽ một hành động giữa các mục trong một liệt kê (như dấu phẩy và dòng mới ở trên), tôi thích thay vì giữ một boolean giữ kiểm tra, tôi xử lý điều tra trực tiếp, và sau đó xử lý phần tử đầu tiên tách biệt với phần còn lại. Tôi bắt đầu làm điều này như là một lựa chọn vi trong một đẩy hiệu quả nhưng đã phát triển để chỉ tìm thấy nó một biểu hiện tốt hơn của một con đường mã khác với mục đầu tiên.Như vậy, bây giờ tôi muốn viết ở trên như:

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

Đây là chức năng dùng để tạo ra tập tin 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)))); 
         } 
    } 

} 
    } 

Nếu không, bạn có thể tham khảo dưới đây liên kết:

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