Tạo tệp Excel trong ASP.NET [đã đóng]


99

Tôi sắp thêm một phần vào ứng dụng ASP.NET (mã VB.NET) sẽ cho phép người dùng lấy dữ liệu trả về cho họ dưới dạng tệp Excel, tệp này tôi sẽ tạo dựa trên dữ liệu cơ sở dữ liệu. Mặc dù có một số cách để làm điều này, nhưng mỗi cách đều có những hạn chế riêng. Làm thế nào sẽ bạn trả lại dữ liệu? Tôi đang tìm kiếm thứ gì đó sạch sẽ và đơn giản nhất có thể.


Câu trả lời:


131

CSV

Ưu điểm:

  • Đơn giản

Nhược điểm:

  • Nó có thể không hoạt động ở các ngôn ngữ khác hoặc trong các cấu hình Excel khác nhau (tức là dấu phân tách Danh sách)
  • Không thể áp dụng định dạng, công thức, v.v.

HTML

Ưu điểm:

  • Vẫn khá đơn giản
  • Hỗ trợ định dạng và công thức đơn giản

Nhược điểm:

  • Bạn phải đặt tên tệp là xls và Excel có thể cảnh báo bạn về việc mở tệp Excel không phải gốc
  • Một trang tính cho mỗi sổ làm việc

OpenXML (Office 2007 .XLSX)

Ưu điểm:

  • Định dạng Excel gốc
  • Hỗ trợ tất cả các tính năng của Excel
  • Không yêu cầu bản cài đặt Excel
  • Có thể tạo bảng tổng hợp
  • Có thể được tạo bằng dự án nguồn mở EPPlus

Nhược điểm:

  • Khả năng tương thích hạn chế bên ngoài Excel 2007 (không phải là vấn đề ngày nay)
  • Phức tạp trừ khi bạn đang sử dụng thành phần của bên thứ ba

SpreadSheetML (XML định dạng mở)

Ưu điểm:

  • Đơn giản so với các định dạng Excel gốc
  • Hỗ trợ hầu hết các tính năng của Excel: định dạng, kiểu, công thức, nhiều trang tính trên mỗi sổ làm việc
  • Excel không cần cài đặt để sử dụng nó
  • Không cần thư viện của bên thứ ba - chỉ cần viết ra xml của bạn
  • Tài liệu có thể được mở bằng Excel XP / 2003/2007

Nhược điểm:

  • Thiếu tài liệu tốt
  • Không được hỗ trợ trong các phiên bản Excel cũ hơn (trước năm 2000)
  • Chỉ ghi, trong đó khi bạn mở nó và thực hiện các thay đổi từ Excel, nó sẽ được chuyển đổi sang Excel gốc.

XLS (được tạo bởi thành phần bên thứ ba)

Ưu điểm:

  • Tạo tệp Excel gốc với tất cả các định dạng, công thức, v.v.

Nhược điểm:

  • Chi phí tiền
  • Thêm phụ thuộc

COM Interop

Ưu điểm:

  • Sử dụng thư viện Microsoft gốc
  • Đọc hỗ trợ cho các tài liệu gốc

Nhược điểm:

  • Rất chậm
  • Vấn đề phụ thuộc / đối sánh phiên bản
  • Các vấn đề về đồng thời / tính toàn vẹn dữ liệu để sử dụng web khi đọc
  • Rất chậm
  • Các vấn đề về tỷ lệ để sử dụng web (khác với đồng thời): cần tạo nhiều phiên bản ứng dụng Excel nặng trên máy chủ
  • Yêu cầu Windows
  • Tôi đã đề cập rằng nó chậm?

1
Ràng buộc "Chỉ ghi" được đề cập cho SpreadsheetML hoàn toàn không phải là một vấn đề, vì bạn có thể lưu tệp excel dưới dạng SpreadsheetML nếu muốn.
Brian

1
SpreadsheetML có thể làm hỏng Excel 2003 nếu bạn tạo các tệp lớn bằng nó. Đừng tin tưởng nó: /
Brian

2
Bạn có thể Lưu trở lại tệp SpreadsheetML tốt trong Office 2002 và 2003. Không cần Lưu theo yêu cầu. SpreadsheetML không thể lưu trữ macro, biểu đồ, đồ họa và một số tỷ lệ khác và kết thúc, bao gồm các tính năng mới của Office 2007 (ví dụ: hơn 3 định dạng có điều kiện). Vì XML dài dòng nên việc nén SpreadsheetML trước khi gửi từ máy chủ (sử dụng SharpZipLib là một tùy chọn) hoạt động rất tốt để giảm thời gian tải xuống - thực ra, cần lưu ý rằng dù sao thì OpenXML cũng được lưu trữ trong vùng chứa ZIP. @Brian: Tôi sử dụng SpreadsheetML phức tạp trong phạm vi 50-100MB hàng ngày mà không gặp sự cố.
richardtallent

Nếu có khả năng bạn sẽ phải xuất một lượng lớn dữ liệu, bạn nên xuất dưới dạng CSV. Ngoài SpreadsheetML, khó có thể tạo ra một giải pháp hiệu quả với bất kỳ định dạng nào khác. HTML có thể được viết và đọc một cách hiệu quả, nhưng bạn cần đặc tả thêm để hữu ích. Cả HTML và SpreadsheetML đều có các vấn đề khác liên quan đến các tệp lớn như Brian đã đề cập trong nhận xét của mình. Vì vậy, nếu bạn chỉ cần kết xuất dữ liệu đơn giản với CSV.
JohannesH

2
@pomarc: Nó có thể đơn giản, nhưng nó không sạch. Người dùng muốn có tệp Excel và bạn cung cấp cho họ tệp HTML có phần mở rộng giả mạo.
Heinzi

38

Bạn có thể xuất dữ liệu dưới dạng các ô trong bảng html, dán một .xlshoặc một .xlsxphần mở rộng vào đó và Excel sẽ mở nó như thể nó là một tài liệu gốc. Bạn thậm chí có thể thực hiện một số tính toán định dạng và công thức hạn chế theo cách này, vì vậy nó mạnh hơn nhiều so với CSV. Ngoài ra, việc xuất một bảng html phải khá dễ thực hiện từ một nền tảng web như ASP.Net;)

Nếu bạn cần nhiều trang tính hoặc trang tính được đặt tên trong Sổ làm việc Excel của mình, bạn có thể làm điều gì đó tương tự thông qua một lược đồ XML được gọi SpreadSheetML. Đây không phải là định dạng mới được cung cấp với Office 2007, mà là một cái gì đó hoàn toàn khác hoạt động từ trước đến nay như Excel 2000. Cách dễ nhất để giải thích cách hoạt động của nó là với một ví dụ:

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?> 
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
        xmlns:o="urn:schemas-microsoft-com:office:office"
        xmlns:x="urn:schemas-microsoft-com:office:excel"
        xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
        xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
      <Author>Your_name_here</Author>
      <LastAuthor>Your_name_here</LastAuthor>
      <Created>20080625</Created>
      <Company>ABC Inc</Company>
      <Version>10.2625</Version>
</DocumentProperties>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
        <WindowHeight>6135</WindowHeight>
        <WindowWidth>8445</WindowWidth>
        <WindowTopX>240</WindowTopX>
        <WindowTopY>120</WindowTopY>
        <ProtectStructure>False</ProtectStructure>
        <ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>

<Styles>
      <Style ss:ID="Default" ss:Name="Normal">
            <Alignment ss:Vertical="Bottom" />
            <Borders />
            <Font />
            <Interior />
            <NumberFormat />
            <Protection />
      </Style>
</Styles>

<Worksheet ss:Name="Sample Sheet 1">
<Table ss:ExpandedColumnCount="2" x:FullColumns="1" x:FullRows="1" ID="Table1">
<Column ss:Width="150" />
<Column ss:Width="200" />
<Row>
      <Cell><Data ss:Type="Number">1</Data></Cell>
      <Cell><Data ss:Type="Number">2</Data></Cell>
</Row>
<Row>
      <Cell><Data ss:Type="Number">3</Data></Cell>
      <Cell><Data ss:Type="Number">4</Data></Cell>
</Row>
<Row>
      <Cell><Data ss:Type="Number">5</Data></Cell>
      <Cell><Data ss:Type="Number">6</Data></Cell>
</Row>
<Row>
      <Cell><Data ss:Type="Number">7</Data></Cell>
      <Cell><Data ss:Type="Number">8</Data></Cell>
</Row>
</Table>
</Worksheet>

<Worksheet ss:Name="Sample Sheet 2">
<Table ss:ExpandedColumnCount="2" x:FullColumns="1" x:FullRows="1" ID="Table2">
<Column ss:Width="150" />
<Column ss:Width="200" />
<Row>
      <Cell><Data ss:Type="String">A</Data></Cell>
      <Cell><Data ss:Type="String">B</Data></Cell>
</Row>
<Row>
      <Cell><Data ss:Type="String">C</Data></Cell>
      <Cell><Data ss:Type="String">D</Data></Cell>
</Row>
<Row>
      <Cell><Data ss:Type="String">E</Data></Cell>
      <Cell><Data ss:Type="String">F</Data></Cell>
</Row>
<Row>
      <Cell><Data ss:Type="String">G</Data></Cell>
      <Cell><Data ss:Type="String">H</Data></Cell>
</Row>
</Table>
</Worksheet>
</Workbook> 

12
bạn có thể đổi tên tệp bằng một mở rộng .xml và thêm vào: <? mso-application progid = "Excel.Sheet"?> chỉ sau <? xml version = "1.0"?> theo cách này, các cửa sổ nhận biết rằng tệp là một Tệp Excel, sẽ cung cấp cho nó biểu tượng bên phải, sẽ mở ra excel khi bạn nhấp vào tệp và Excel sẽ không phàn nàn rằng định dạng và nội dung tệp không khớp. tạm biệt.
pomarc

1
@pomarc Nhược điểm của điều đó là các chương trình nhập tệp excel khác sẽ không nhận ra nó. Nhưng sau đó, họ có thể sẽ không phân tích cú pháp xml.
Joel Coehoorn

1
Tôi đã sử dụng kỹ thuật này khá thành công. Đây sẽ là khuyến nghị của tôi - bẩn đơn giản và rất hiệu quả.
NealB

Hai vấn đề tiềm ẩn (YMMV) với dữ liệu dạng bảng HTML được che dưới dạng tệp XLS: (1) Microsoft Excel sẽ tự động cắt bỏ các khoảng trắng và số 0 ở đầu; và (2) Microsoft Excel 2010 cảnh báo người dùng khi mở tệp XLS chứa dữ liệu dạng bảng HTML. Giải pháp cho # 1 dường như là creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (nếu dấu cách / số 0 ở đầu là quan trọng và cần được giữ lại).
iokevins,

Chỉ để làm rõ, trong khi tôi đã đề cập đến bảng HTML, điểm chính của câu trả lời này là SpreadsheetML, không chỉ là dữ liệu dạng bảng HTML. Excel coi nó là bản địa.
Joel Coehoorn

16

Nếu đến từ DataTable :

public static void DataTabletoXLS(DataTable DT, string fileName)
{
    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.Charset = "utf-16";
    HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
    HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.xls", fileName));
    HttpContext.Current.Response.ContentType = "application/ms-excel";

    string tab = "";
    foreach (DataColumn dc in DT.Columns)
    {
        HttpContext.Current.Response.Write(tab + dc.ColumnName.Replace("\n", "").Replace("\t", ""));
        tab = "\t";
    }
    HttpContext.Current.Response.Write("\n");

    int i;
    foreach (DataRow dr in DT.Rows)
    {
        tab = "";
        for (i = 0; i < DT.Columns.Count; i++)
        {
            HttpContext.Current.Response.Write(tab + dr[i].ToString().Replace("\n", "").Replace("\t", ""));
            tab = "\t";
        }
        HttpContext.Current.Response.Write("\n");
    }
    HttpContext.Current.Response.End();
}

Từ Gridview :

public static void GridviewtoXLS(GridView gv, string fileName)
{
    int DirtyBit = 0;
    int PageSize = 0;
    if (gv.AllowPaging == true)
    {
        DirtyBit = 1;
        PageSize = gv.PageSize;
        gv.AllowPaging = false;
        gv.DataBind();
    }

    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.Charset = "utf-8";
    HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
    HttpContext.Current.Response.AddHeader(
        "content-disposition", string.Format("attachment; filename={0}.xls", fileName));
    HttpContext.Current.Response.ContentType = "application/ms-excel";

    using (StringWriter sw = new StringWriter())
    using (HtmlTextWriter htw = new HtmlTextWriter(sw))
    {
        //  Create a table to contain the grid
        Table table = new Table();

        //  include the gridline settings
        table.GridLines = gv.GridLines;

        //  add the header row to the table
        if (gv.HeaderRow != null)
        {
            Utilities.Export.PrepareControlForExport(gv.HeaderRow);
            table.Rows.Add(gv.HeaderRow);
        }

        //  add each of the data rows to the table
        foreach (GridViewRow row in gv.Rows)
        {
            Utilities.Export.PrepareControlForExport(row);
            table.Rows.Add(row);
        }

        //  add the footer row to the table
        if (gv.FooterRow != null)
        {
            Utilities.Export.PrepareControlForExport(gv.FooterRow);
            table.Rows.Add(gv.FooterRow);
        }

        //  render the table into the htmlwriter
        table.RenderControl(htw);

        //  render the htmlwriter into the response
        HttpContext.Current.Response.Write(sw.ToString().Replace("£", ""));
        HttpContext.Current.Response.End();
    }

    if (DirtyBit == 1)
    {
        gv.PageSize = PageSize;
        gv.AllowPaging = true;
        gv.DataBind();
    }
}

private static void PrepareControlForExport(Control control)
{
    for (int i = 0; i < control.Controls.Count; i++)
    {
        Control current = control.Controls[i];
        if (current is LinkButton)
        {
            control.Controls.Remove(current);
            control.Controls.AddAt(i, new LiteralControl((current as LinkButton).Text));
        }
        else if (current is ImageButton)
        {
            control.Controls.Remove(current);
            control.Controls.AddAt(i, new LiteralControl((current as ImageButton).AlternateText));
        }
        else if (current is HyperLink)
        {
            control.Controls.Remove(current);
            control.Controls.AddAt(i, new LiteralControl((current as HyperLink).Text));
        }
        else if (current is DropDownList)
        {
            control.Controls.Remove(current);
            control.Controls.AddAt(i, new LiteralControl((current as DropDownList).SelectedItem.Text));
        }
        else if (current is CheckBox)
        {
            control.Controls.Remove(current);
            control.Controls.AddAt(i, new LiteralControl((current as CheckBox).Checked ? "True" : "False"));
        }

        if (current.HasControls())
        {
            Utilities.Export.PrepareControlForExport(current);
        }
    }
}

1
Chỉ cần mã tôi cần, cảm ơn. :)
Kjensen

Scott, cái gì với dấu thăng ("£")? Nếu tôi cần thì sao? Có nhân vật nào nguy hiểm không?
Piotr Owsiak

HOÀN HẢO. Đúng thứ tôi cần.
Brad Bruce

bảng hiệu £ thực sự chỉ là thứ tôi cần cho một trong những khách hàng của mình. bạn có thể lấy nó ra.
SpoiledTechie.com

Hai vấn đề tiềm ẩn (YMMV) với dữ liệu dạng bảng HTML được che dưới dạng tệp XLS: (1) Microsoft Excel sẽ tự động cắt bỏ các khoảng trắng và số 0 ở đầu; và (2) Microsoft Excel 2010 cảnh báo người dùng khi mở tệp XLS chứa dữ liệu dạng bảng HTML. Giải pháp cho # 1 dường như là creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (nếu dấu cách / số 0 ở đầu là quan trọng và cần được giữ lại). Tệp dữ liệu CSV cũng bị xếp hạng 1 khi mở trong Microsoft Excel.
iokevins,


5

Dựa trên các câu trả lời được đưa ra và tham khảo ý kiến ​​của đồng nghiệp, có vẻ như giải pháp tốt nhất là tạo tệp XML hoặc các bảng HTML và đẩy nó xuống dưới dạng tệp đính kèm. Một thay đổi được các đồng nghiệp của tôi đề xuất là dữ liệu (tức là các bảng HTML) có thể được ghi trực tiếp vào đối tượng Phản hồi, do đó loại bỏ nhu cầu ghi ra tệp, điều này có thể gây rắc rối do các vấn đề về quyền, I / O tranh chấp và đảm bảo rằng quá trình thanh lọc theo lịch trình xảy ra.

Đây là một đoạn mã ... Tôi chưa kiểm tra điều này và tôi chưa cung cấp tất cả mã được gọi, nhưng tôi nghĩ nó thể hiện tốt ý tưởng.

    Dim uiTable As HtmlTable = GetUiTable(groupedSumData)

    Response.Clear()

    Response.ContentType = "application/vnd.ms-excel"
    Response.AddHeader("Content-Disposition", String.Format("inline; filename=OSSummery{0:ddmmssf}.xls", DateTime.Now))

    Dim writer As New System.IO.StringWriter()
    Dim htmlWriter As New HtmlTextWriter(writer)
    uiTable.RenderControl(htmlWriter)
    Response.Write(writer.ToString)

    Response.End()

2
Dan, bạn đang đi đúng hướng. Và tôi chắc chắn khuyên bạn nên sử dụng SpreadsheetML thay vì HTML - chỗ thở cho tương lai, vì hỗ trợ HTML bị hạn chế một cách đáng ngạc nhiên. Nhưng với HTML, SpreadsheetML và OpenXML, kích thước tệp có thể khá lớn và sẽ không được máy chủ nén. OpenXML yêu cầu một vùng chứa ZIP với nhiều tệp bên trong và SpreadsheetML và HTML đều tải xuống nhanh hơn nhiều nếu bạn nén chúng trước và gửi zip dưới dạng tệp đính kèm. Sử dụng SharpZipLib và truyền trực tuyến đến nó thay vì trực tiếp tới Phản hồi.
richardtallent

4

vì Excel hiểu HTML nên bạn chỉ có thể ghi dữ liệu ra dưới dạng bảng HTML vào tệp tạm thời có phần mở rộng .xls, lấy FileInfo cho tệp và thổi lại bằng cách sử dụng

Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fi.Name);
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fi.FullName);
Response.End();

nếu bạn muốn tránh tệp tạm thời, bạn có thể ghi vào luồng trong bộ nhớ và ghi lại các byte thay vì sử dụng WriteFile

nếu tiêu đề độ dài nội dung bị bỏ qua, bạn chỉ có thể viết lại html trực tiếp, nhưng điều này có thể không hoạt động chính xác mọi lúc trong tất cả các trình duyệt


2
Hai vấn đề tiềm ẩn (YMMV) với dữ liệu dạng bảng HTML được che dưới dạng tệp XLS: (1) Microsoft Excel sẽ tự động cắt bỏ các khoảng trắng và số 0 ở đầu; và (2) Microsoft Excel 2010 cảnh báo người dùng khi mở tệp XLS chứa dữ liệu dạng bảng HTML. Giải pháp cho # 1 dường như là creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (nếu dấu cách / số 0 ở đầu là quan trọng và cần được giữ lại).
iokevins,

3

Cá nhân tôi thích phương pháp XML hơn. Tôi sẽ trả lại dữ liệu từ cơ sở dữ liệu trong Dataset, lưu nó vào XMl, sau đó tôi tạo một tệp xslt có chứa quy tắc chuyển đổi sẽ định dạng một tài liệu thích hợp và một phép biến đổi XML đơn giản sẽ hoàn thành công việc. Phần tốt nhất của điều này là bạn có thể định dạng ô, thực hiện định dạng có điều kiện, thiết lập đầu trang và chân trang, và thậm chí đặt phạm vi in.


2

Tôi đã thực hiện điều này một vài lần và mỗi lần, cách đơn giản nhất là trả về tệp CSV (Giá trị được phân tách bằng dấu phẩy). Excel nhập nó một cách hoàn hảo và nó tương đối nhanh.


Một vấn đề tiềm năng (YMMV) với dữ liệu CSV: Microsoft Excel sẽ cắt không gian và zeroes hàng đầu tự động
iokevins

2

chúng tôi xuất dữ liệu từ lưới dữ liệu để luôn xuất sắc. Chuyển nó sang HTML rồi ghi vào tệp excel

Response.ContentType = "application/vnd.ms-excel"
    Response.Charset = ""
    Response.AddHeader("content-disposition", "fileattachment;filename=YOURFILENAME.xls")
    Me.EnableViewState = False
    Dim sw As System.IO.StringWriter = New System.IO.StringWriter
    Dim hw As HtmlTextWriter = New HtmlTextWriter(sw)
    ClearControls(grid)
    grid.RenderControl(hw)
    Response.Write(sw.ToString())
    Response.End()

Điểm duy nhất với phương pháp này là rất nhiều lưới của chúng tôi có các nút hoặc liên kết trong đó, vì vậy bạn cũng cần điều này:

'needed to export grid to excel to remove link button control and represent as text
Private Sub ClearControls(ByVal control As Control)
    Dim i As Integer
    For i = control.Controls.Count - 1 To 0 Step -1
        ClearControls(control.Controls(i))
    Next i

    If TypeOf control Is System.Web.UI.WebControls.Image Then
        control.Parent.Controls.Remove(control)
    End If

    If (Not TypeOf control Is TableCell) Then
        If Not (control.GetType().GetProperty("SelectedItem") Is Nothing) Then
            Dim literal As New LiteralControl
            control.Parent.Controls.Add(literal)
            Try
                literal.Text = CStr(control.GetType().GetProperty("SelectedItem").GetValue(control, Nothing))
            Catch
            End Try
            control.Parent.Controls.Remove(control)
        Else
            If Not (control.GetType().GetProperty("Text") Is Nothing) Then
                Dim literal As New LiteralControl
                control.Parent.Controls.Add(literal)
                literal.Text = CStr(control.GetType().GetProperty("Text").GetValue(control, Nothing))
                control.Parent.Controls.Remove(control)
            End If
        End If
    End If
    Return
End Sub

Tôi thấy rằng ở đâu đó, nó hoạt động tốt.


2
Hai vấn đề tiềm ẩn (YMMV) với dữ liệu dạng bảng HTML được che dưới dạng tệp XLS: (1) Microsoft Excel sẽ tự động cắt bỏ các khoảng trắng và số 0 ở đầu; và (2) Microsoft Excel 2010 cảnh báo người dùng khi mở tệp XLS chứa dữ liệu dạng bảng HTML. Giải pháp cho # 1 dường như là creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (nếu dấu cách / số 0 ở đầu là quan trọng và cần được giữ lại).
iokevins,


2

Đây là một báo cáo lấy từ một quy trình được lưu trữ. Kết quả được xuất sang Excel. Nó sử dụng ADO thay vì ADO.NET và lý do tại sao dòng này

oSheet.Cells(2, 1).copyfromrecordset(rst1)

Nó thực hiện hầu hết các công việc và không có sẵn trong ado.net.

‘Calls stored proc in SQL Server 2000 and puts data in Excel and ‘formats it

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim cnn As ADODB.Connection
        cnn = New ADODB.Connection
        cnn.Open("Provider=SQLOLEDB;data source=xxxxxxx;" & _
          "database=xxxxxxxx;Trusted_Connection=yes;")

        Dim cmd As New ADODB.Command


        cmd.ActiveConnection = cnn


        cmd.CommandText = "[sp_TomTepley]"
        cmd.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
        cmd.CommandTimeout = 0
        cmd.Parameters.Refresh()


        Dim rst1 As ADODB.Recordset
        rst1 = New ADODB.Recordset
        rst1.Open(cmd)

        Dim oXL As New Excel.Application
        Dim oWB As Excel.Workbook
        Dim oSheet As Excel.Worksheet

        'oXL = CreateObject("excel.application")
        oXL.Visible = True
        oWB = oXL.Workbooks.Add
        oSheet = oWB.ActiveSheet

        Dim Column As Integer
        Column = 1

        Dim fld As ADODB.Field
        For Each fld In rst1.Fields

            oXL.Workbooks(1).Worksheets(1).Cells(1, Column).Value = fld.Name
            oXL.Workbooks(1).Worksheets(1).cells(1, Column).Interior.ColorIndex = 15
            Column = Column + 1

        Next fld

        oXL.Workbooks(1).Worksheets(1).name = "Tom Tepley Report"
        oSheet.Cells(2, 1).copyfromrecordset(rst1)
        oXL.Workbooks(1).Worksheets(1).Cells.EntireColumn.AutoFit()


        oXL.Visible = True
        oXL.UserControl = True

        rst1 = Nothing

        cnn.Close()
        Beep()

    End Sub

1

Nếu bạn điền dữ liệu vào GridView, bạn có thể sử dụng chức năng này để lấy dữ liệu có định dạng HTML, nhưng cho trình duyệt biết đó là tệp excel.

 Public Sub ExportToExcel(ByVal fileName As String, ByVal gv As GridView)

        HttpContext.Current.Response.Clear()
        HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", fileName))
        HttpContext.Current.Response.ContentType = "application/ms-excel"

        Dim sw As StringWriter = New StringWriter
        Dim htw As HtmlTextWriter = New HtmlTextWriter(sw)
        Dim table As Table = New Table

        table.GridLines = gv.GridLines

        If (Not (gv.HeaderRow) Is Nothing) Then
            PrepareControlForExport(gv.HeaderRow)
            table.Rows.Add(gv.HeaderRow)
        End If

        For Each row As GridViewRow In gv.Rows
            PrepareControlForExport(row)
            table.Rows.Add(row)
        Next

        If (Not (gv.FooterRow) Is Nothing) Then
            PrepareControlForExport(gv.FooterRow)
            table.Rows.Add(gv.FooterRow)
        End If

        table.RenderControl(htw)

        HttpContext.Current.Response.Write(sw.ToString)
        HttpContext.Current.Response.End()

    End Sub


    Private Sub PrepareControlForExport(ByVal control As Control)

        Dim i As Integer = 0

        Do While (i < control.Controls.Count)

            Dim current As Control = control.Controls(i)

            If (TypeOf current Is LinkButton) Then
                control.Controls.Remove(current)
                control.Controls.AddAt(i, New LiteralControl(CType(current, LinkButton).Text))

            ElseIf (TypeOf current Is ImageButton) Then
                control.Controls.Remove(current)
                control.Controls.AddAt(i, New LiteralControl(CType(current, ImageButton).AlternateText))

            ElseIf (TypeOf current Is HyperLink) Then
                control.Controls.Remove(current)
                control.Controls.AddAt(i, New LiteralControl(CType(current, HyperLink).Text))

            ElseIf (TypeOf current Is DropDownList) Then
                control.Controls.Remove(current)
                control.Controls.AddAt(i, New LiteralControl(CType(current, DropDownList).SelectedItem.Text))

            ElseIf (TypeOf current Is CheckBox) Then
                control.Controls.Remove(current)
                control.Controls.AddAt(i, New LiteralControl(CType(current, CheckBox).Checked))

            End If

            If current.HasControls Then
                PrepareControlForExport(current)
            End If

            i = i + 1

        Loop

    End Sub

Hai vấn đề tiềm ẩn (YMMV) với dữ liệu dạng bảng HTML được che dưới dạng tệp XLS: (1) Microsoft Excel sẽ tự động cắt bỏ các khoảng trắng và số 0 ở đầu; và (2) Microsoft Excel 2010 cảnh báo người dùng khi mở tệp XLS chứa dữ liệu dạng bảng HTML. Giải pháp cho # 1 dường như là creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (nếu dấu cách / số 0 ở đầu là quan trọng và cần được giữ lại).
iokevins,

1

Chỉ cần tránh COM Interop qua không gian tên Microsoft.Office.Interop. Nó quá chậm và không đáng tin cậy và không thể điều chỉnh được. Không áp dụng cho người bạo dâm.



0

CSV là cách dễ dàng nhất. Hầu hết thời gian nó được liên kết với Excel. Nếu không, bạn phải sử dụng các API tự động hóa hoặc định dạng XML. Các API và XML không khó sử dụng.

Thông tin về cách tạo XML cho Excel


0

Tôi đi theo tuyến CSV (như được mô tả ở trên), hoặc thường xuyên hơn vào những ngày này, tôi sử dụng Infragistics NetAdvantage để tạo tệp. (Phần lớn thời gian khi Infragistics đang hoạt động, chúng tôi chỉ xuất một UltraWebGrid hiện có, về cơ bản là giải pháp một-LOC trừ khi cần chỉnh sửa thêm định dạng. Chúng tôi cũng có thể tạo tệp Excel / BIFF theo cách thủ công, nhưng hiếm khi cần thiết.)


0

người đàn ông, trong .net tôi đoán bạn có thể có một thành phần có thể làm điều đó, nhưng trong asp cổ điển, tôi đã thực hiện nó tạo một bảng html và thay đổi kiểu mime của trang thành vnd / msexcel. Tôi đoán rằng nếu bạn sử dụng chế độ xem lưới và thay đổi kiểu mime có lẽ nó sẽ hoạt động, vì chế độ xem lưới là một bảng html.


Hai vấn đề tiềm ẩn (YMMV) với dữ liệu dạng bảng HTML được che dưới dạng tệp XLS: (1) Microsoft Excel sẽ tự động cắt bỏ các khoảng trắng và số 0 ở đầu; và (2) Microsoft Excel 2010 cảnh báo người dùng khi mở tệp XLS chứa dữ liệu dạng bảng HTML. Giải pháp cho # 1 dường như là creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (nếu dấu cách / số 0 ở đầu là quan trọng và cần được giữ lại).
iokevins,

0

Cách duy nhất để tránh hình tam giác màu xanh lục "Có vẻ như những số này được lưu trữ dưới dạng văn bản" là sử dụng định dạng Open XML. Nó là giá trị sử dụng nó, chỉ để tránh các tam giác màu xanh lá cây không thể tránh khỏi.


0

Phương pháp tốt nhất mà tôi đã thấy cho các báo cáo excel là viết dữ liệu ra bằng XML với phần mở rộng XML và truyền trực tuyến cho khách hàng với kiểu nội dung chính xác. (ứng dụng / xls)

Điều này hoạt động cho bất kỳ báo cáo nào yêu cầu định dạng cơ bản và cho phép bạn so sánh với các bảng tính hiện có bằng cách sử dụng các công cụ so sánh văn bản.


0

Giả sử điều này là dành cho mạng nội bộ, nơi bạn có thể đặt quyền và ủy quyền cho IE, bạn có thể tạo phía máy khách sổ làm việc với JScript / VBScript điều khiển Excel . Điều này cung cấp cho bạn định dạng Excel gốc mà không gặp rắc rối khi cố gắng tự động hóa Excel trên máy chủ.

Tôi không chắc mình còn thực sự đề xuất phương pháp này nữa ngoại trừ trong các trường hợp khá thích hợp, nhưng nó khá phổ biến trong thời hoàng kim ASP cổ điển.


0

Tất nhiên bạn luôn có thể sử dụng các thành phần của bên thứ ba. Cá nhân tôi đã có một trải nghiệm tốt với Spire.XLS http://www.e-iceblue.com/xls/xlsintro.htm

Thành phần này khá dễ sử dụng trong ứng dụng của bạn:

        Workbook workbook = new Workbook();

        //Load workbook from disk.
        workbook.LoadFromFile(@"Data\EditSheetSample.xls");
        //Initailize worksheet
        Worksheet sheet = workbook.Worksheets[0];

        //Writes string
        sheet.Range["B1"].Text = "Hello,World!";
        //Writes number
        sheet.Range["B2"].NumberValue = 1234.5678;
        //Writes date
        sheet.Range["B3"].DateTimeValue = System.DateTime.Now;
        //Writes formula
        sheet.Range["B4"].Formula = "=1111*11111";

        workbook.SaveToFile("Sample.xls");

0

Một trong những vấn đề tôi đã gặp phải khi sử dụng một trong các giải pháp được đề xuất ở trên tương tự như câu trả lời này là nếu bạn đẩy nội dung ra dưới dạng tệp đính kèm (điều tôi thấy là giải pháp sạch nhất cho các trình duyệt không phải ms) , sau đó mở nó trong Excel 2000-2003, kiểu của nó là "Trang web Excel" chứ không phải tài liệu Excel gốc.

Sau đó, bạn phải giải thích cho người dùng cách sử dụng "Save as type" từ bên trong Excel để chuyển nó thành tài liệu Excel. Đây là một khó khăn nếu người dùng cần chỉnh sửa tài liệu này và sau đó tải lại nó lên trang web của bạn.

Khuyến nghị của tôi là sử dụng CSV. Nó đơn giản và nếu người dùng mở nó từ bên trong Excel, thì ít nhất Excel sẽ nhắc họ lưu nó ở định dạng gốc.


Bạn sẽ cần phải cẩn thận với CSV nếu người dùng của bạn sống rải rác trên khắp thế giới. Ở Đức, dấu phẩy được sử dụng làm dấu phân cách thập phân và vì vậy dấu chấm phẩy được dùng làm dấu phân tách giá trị. Gây khó khăn cho việc tạo một tệp có thể đọc được ở tất cả các nền văn hóa khác nhau. Do đó, phiếu bầu của tôi sẽ dành cho một trong các định dạng XML.
paul

0

Tôi sẽ chỉ tạo tệp CSV dựa trên dữ liệu, vì tôi thấy đó là tệp sạch nhất và Excel có hỗ trợ tốt cho nó. Nhưng nếu bạn yêu cầu một định dạng linh hoạt hơn, tôi chắc chắn rằng có một số công cụ của bên thứ 3 để tạo tệp excel thực.


0

Đây là một giải pháp truyền dữ liệu ra dưới dạng CSV. Nhanh chóng, sạch sẽ và dễ dàng và nó xử lý dấu phẩy trong đầu vào.

public static void ExportToExcel(DataTable data, HttpResponse response, string fileName)
{
    response.Charset = "utf-8";
    response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
    response.Cache.SetCacheability(HttpCacheability.NoCache);
    response.ContentType = "text/csv";
    response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);

    for (int i = 0; i < data.Columns.Count; i++)
    {
       response.Write(data.Columns[i].ColumnName);
       response.Write(i == data.Columns.Count - 1 ? "\n" : ",");
    }        
    foreach (DataRow row in data.Rows)
    {
        for (int i = 0; i < data.Columns.Count; i++)
        {
            response.Write(String.Format("\"{0}\"", row[i].ToString()));
            response.Write(i == data.Columns.Count - 1 ? "\n" : ",");
        }
    }

    response.End();
}

-1

vừa tạo một hàm để xuất từ ​​một biểu mẫu web C # sang excel hy vọng nó sẽ giúp ích cho những người khác

    public void ExportFileFromSPData(string filename, DataTable dt)
    {
        HttpResponse response = HttpContext.Current.Response;

        //clean up the response.object
        response.Clear();
        response.Buffer = true;
        response.Charset = "";

        // set the response mime type for html so you can see what are you printing 
        //response.ContentType = "text/html";
        //response.AddHeader("Content-Disposition", "attachment;filename=test.html");

        // set the response mime type for excel
        response.ContentType = "application/vnd.ms-excel";
        response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
        response.ContentEncoding = System.Text.Encoding.UTF8;
        response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());

        //style to format numbers to string
        string style = @"<style> .text { mso-number-format:\@; } </style>";
        response.Write(style);

        // create a string writer
        using (StringWriter sw = new StringWriter())
        {
            using (HtmlTextWriter htw = new HtmlTextWriter(sw))
            {
                // instantiate a datagrid
                GridView dg = new GridView();
                dg.DataSource = dt;
                dg.DataBind();

                foreach (GridViewRow datarow in dg.Rows)
                {
                    //format specific cell to be text 
                    //to avoid 1.232323+E29 to get 1232312312312312124124
                    datarow.Cells[0].Attributes.Add("class", "text");
                }

                dg.RenderControl(htw);
                response.Write(sw.ToString());
                response.End();
            }
        }
     }

-5

Nếu bạn phải sử dụng Excel thay vì tệp CSV, bạn sẽ cần sử dụng tự động hóa OLE trên một phiên bản Excel là máy chủ. Cách dễ nhất để làm điều này là có một tệp mẫu và điền dữ liệu vào nó theo chương trình. Bạn lưu nó vào một tệp khác.

Lời khuyên:

  • Đừng làm điều đó một cách tương tác. Yêu cầu người dùng bắt đầu quá trình và sau đó đăng một trang có liên kết đến tệp. Điều này giảm thiểu các vấn đề về hiệu suất tiềm ẩn trong khi tạo bảng tính.
  • Sử dụng mẫu như tôi đã mô tả trước đây. Nó làm cho nó dễ dàng hơn để sửa đổi nó.
  • Đảm bảo rằng Excel được đặt để không bật lên hộp thoại. Trên máy chủ web, điều này sẽ treo toàn bộ phiên bản excel.
  • Giữ phiên bản Excel trên một máy chủ riêng biệt, tốt nhất là sau tường lửa, để nó không bị lộ ra như một lỗ hổng bảo mật tiềm ẩn.
  • Theo dõi việc sử dụng tài nguyên. Tạo một tập tin trải rộng qua giao diện tự động hóa OLE (PIA chỉ là một phần nhỏ về điều này) là một quá trình khá nặng nề. Nếu bạn cần mở rộng quy mô này thành khối lượng dữ liệu cao, bạn có thể cần phải thông minh một chút với kiến ​​trúc của mình.

Một số phương pháp 'sử dụng kiểu mime để đánh lừa excel mở bảng HTML' sẽ hoạt động nếu bạn không ngại định dạng của tệp là một chút cơ bản. Những cách tiếp cận này cũng ngăn chặn công việc nặng nhọc của CPU đối với máy khách. Nếu bạn muốn kiểm soát chi tiết định dạng của bảng tính, bạn có thể sẽ phải sử dụng chính Excel để tạo tệp như được mô tả ở trên.


Ý tưởng tồi khi tự động hóa từ một máy chủ web. Các lựa chọn thay thế có vẻ như hack-ish, nhưng chúng thực sự sẽ hoạt động tốt hơn nhiều.
Joel Coehoorn 29/09/08

Chúng tôi sử dụng OLE phía máy chủ với Excel và đó là một vấn đề lớn ở mặt sau. Nếu không vì rủi ro cho sản phẩm của chúng tôi **, chúng tôi sẽ sử dụng một giải pháp khác. ** Tốt hơn bạn nên biết ma quỷ ...
DaveE
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.