Pergunta

Estou prestes a adicionar uma seção para um aplicativo ASP.NET (VB.NET codebehind) que permitirá que um usuário para obter dados retornados a eles como um arquivo do Excel, que vai gerar com base em dados de banco de dados. Embora existam várias maneiras de fazer isso, cada um tem suas próprias desvantagens. Como seria você retornar os dados? Eu estou procurando algo que é tão limpo e simples quanto possível.

Foi útil?

Solução

CSV

Pros:

  • Simples

Contras:

  • Pode não funcionar em outros locais ou em diferentes configurações do Excel (ou seja, separador de lista)
  • Não é possível aplicar a formatação, fórmulas, etc

HTML

Pros:

  • Ainda bem simples
  • Suporta formatação simples e fórmulas

Contras:

  • Você tem que nomear o arquivo como xls e Excel pode avisá-lo sobre a abertura de um arquivo Excel não nativa
  • Uma planilha por pasta de trabalho

OpenXML (Office 2007 .xlsx)

Pros:

  • formato nativo Excel
  • Suporta todos os Excel apresenta
  • Não requerem uma cópia de instalação do Excel
  • É possível gerar tabelas dinâmicas
  • Pode ser gerado usando projeto de código aberto EPPlus

Contras:

  • compatibilidade limitada fora Excel 2007 (não deve ser um problema hoje em dia)
  • Complicated menos que você esteja usando um componente de terceiros

SpreadsheetML (formato XML aberto)

Pros:

  • simples em comparação com formatos nativos do Excel
  • suporta a maioria dos recursos do Excel: formatação, estilos, fórmulas, várias folhas por livro
  • Excel não precisa ser instalado para usá-lo
  • Não há bibliotecas de terceiros necessário - basta escrever o seu xml
  • Os documentos podem ser abertos pelo Excel XP / 2003/2007

Contras:

  • A falta de uma boa documentação
  • Não suportado em versões mais antigas do Excel (pré-2000)
  • Write-only, em que uma vez que você abri-lo e fazer alterações de Excel é convertido em Excel nativa.

XLS (gerado pelo componente de terceiros)

Pros:

  • Gerar arquivo nativo Excel com toda a formatação, fórmulas, etc.

Contras:

  • dinheiro Custo
  • Adicionar dependências

COM Interop

Pros:

  • Usa bibliotecas nativas da Microsoft
  • Suporte de leitura para documentos nativos

Contras:

  • Muito lento
  • questões
  • Dependência / versão de harmonização
  • Concorrência / problemas de integridade de dados para uso da web quando leitura
  • Muito lento
  • Escala questões para o uso da web (diferente da concorrência): necessidade de criar várias instâncias de aplicativo pesado Excel no servidor
  • Requer o Windows
  • Eu mencionei que ele é lento?

Outras dicas

Você pode enviar os dados como células de tabela HTML, furar um .xls ou extensão .xlsx sobre ele, e Excel irá abri-lo como se fosse um documento nativa. Você pode até mesmo fazer alguns cálculos de formatação limitadas e fórmula dessa maneira, por isso é muito mais poderoso do CSV. Além disso, a saída de uma tabela html deve ser muito fácil de fazer a partir de uma plataforma web como ASP.Net;)

Se você precisar de várias planilhas ou planilhas nomeados dentro de sua pasta de trabalho Excel, você pode fazer algo semelhante através de um esquema XML chamado SpreadSheetML. Esta é não o novo formato que acompanha o Office 2007, mas algo completamente diferente que as obras já em Excel 2000. A maneira mais fácil de explicar como ele funciona é com um exemplo:

<?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> 

Se vindo de um 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();
}

A partir de um 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);
        }
    }
}

Este é um wrapper livre em torno SpreadML - ele funciona muito bem.

http://www.carlosag.net/Tools/ExcelXmlWriter/

Com base nas respostas dadas, e consultas com colegas de trabalho, parece que a melhor solução é gerar tanto um arquivo XML ou tabelas HTML e empurrá-lo para baixo como um anexo. A única mudança recomendado pelos meus colegas de trabalho é que os dados (ou seja, as tabelas HTML) pode ser escrito diretamente ao objeto Response, eliminando assim a necessidade de escrever um arquivo, que pode ser problemático devido a problemas de permissões, I / O contenção, e garantindo que purga programado ocorre.

Aqui está um trecho do código ... Eu não tenho verificado isso ainda, e eu não ter fornecido todo o código chamado, mas eu acho que ela representa bem a idéia.

    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()

desde Excel entende HTML você pode apenas escrever os dados como uma tabela HTML para um arquivo temporário com uma extensão .xls, obter o FileInfo para o arquivo, e explodi-lo de volta usando

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

Se você queria evitar o arquivo temporário, você pode escrever para um fluxo na memória e escrever os bytes de volta em vez de usar WriteFile

Se o cabeçalho Content-Length é omitido você poderia simplesmente escrever o html volta diretamente, mas isso pode não funcionar corretamente o tempo todo em todos os navegadores

Eu pessoalmente prefiro o método XML. Vou retornar os dados do banco de dados em um conjunto de dados, salve-o em XML, então eu criar um arquivo XSLT que contém uma regra de transformação que irá formatar um documento apropriado, e um XML simples transformar vai terminar o trabalho para cima. A melhor parte sobre isso, você pode formatar células, fazer a formatação condicional, cabeçalhos e rodapés de instalação, e até mesmo definir intervalos de impressão.

Já fiz isso algumas vezes e cada vez que a maneira mais fácil era simplesmente retornar um CSV (Comma Separated Value) de arquivos. importações do Excel-lo perfeitamente, e é relativamente rápido de fazer.

podemos exportar dados de um datagrid para excel o tempo todo. Convertê-lo para HTML, em seguida, escrever para um arquivo 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()

A única pegadinha com este método é que um monte de nossas redes tinha botões ou links neles assim que você precisa disso também:

'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

Eu descobri que em algum lugar, ele funciona bem.

Eu recomendo livre opensource geração excel libruary que é baseado no OpenXML

Ele me ajudou há vários meses.

Aqui está um relatório que puxa a partir de um procedimento armazenado. Os resultados são exportados para o Excel. Ele usa ADO em vez de ADO.NET e a razão por que é esta linha

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

Ele faz a maioria do trabalho e não está disponível em 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

Se você preencher um GridView com dados que você pode usar essa função para obter os dados formatadas em HTML, mas indicando o navegador é um arquivo 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

Apenas evitar interoperabilidade via Microsoft.Office.Interop namespace. É tão maldito lento e pouco confiável e unscalable. Não se aplica para masoquistas.

Você pode criar bem os arquivos do Excel usando esta biblioteca, muito facilmente formatado: http://officehelper.codeplex.com/ documentação .

Microsoft Office não precisa ser instalado no servidor web!

CSV é maneira mais fácil. Na maioria das vezes ela está ligada ao Excel. Caso contrário, você tem que usar as APIs de automação ou formato XML. As APIs e XML não que são difíceis de usar.

informações sobre XML geração para Excel

I quer ir a rota CSV (como descrito acima), ou mais frequentemente estes dias, eu uso Infragistics NetAdvantage para gerar o arquivo. (O próprio grande maioria das vezes, onde Infragistics está em jogo, nós estamos apenas exportar um UltraWebGrid existente, que é essencialmente uma solução one-LOC, a menos que são necessários ajustes de formatação extra. Poderíamos gerar manualmente um arquivo do Excel / BIFF, bem como, mas raramente há uma necessidade.)

homem, em .net eu acho que você poderia ter um componente que poderia fazer isso, mas em asp clássico que eu já ter feito isso criando uma tabela html e mudando o tipe mime da página para vnd / msexcel. Eu acho que se você usar um gridview e alterar o tipo de mime talvez ele deve funcionar, porque o gridview é uma tabela HTML.

A única maneira à prova de balas de evitar o "Parece que esses números são armazenados como texto" triângulos verdes é usar o formato Open XML. Vale a pena usá-lo, apenas para evitar os triângulos verdes inevitáveis.

O melhor método que eu vi para relatórios Excel está a escrever os dados em XML com uma extensão XML e transmiti-lo aos clientes com o tipo de conteúdo correto. (Application / xls)

Isso funciona para qualquer relatório que requer formatação básica, e permite-lhe comparar com planilhas existentes usando ferramentas de comparação de texto.

Assumindo que este é para uma intranet, onde você pode definir permissões e mandato IE, você pode gerar lado do cliente pasta de trabalho com JScript / VBScript condução Excel . Isto dá-lhe a formatação nativa Excel, sem o incômodo de tentar automatizar Excel no servidor.

Eu não tenho certeza eu realmente recomendo esta abordagem mais, exceto em bastante cenários de nicho, mas era bastante comum durante os tempos áureos ASP clássicas.

Pode, claro, sempre ir para uma componentes de terceiros. Pessoalmente, tenho tido uma boa experiência com Spire.XLS http: //www.e- iceblue.com/xls/xlsintro.htm

O componente é muito fácil de usar dentro de sua aplicação:

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

Um dos problemas Corri tenho todo usando uma das soluções sugeridas acima, que são semelhantes a esta resposta é que se você empurrar o conteúdo como um anexo (o que eu encontrei para ser a solução mais limpa para os não-ms navegadores), em seguida, abri-lo no Excel 2000-2003, seu tipo é uma "página da web Excel" e não um documento nativo Excel.

Então você tem que explicar aos usuários como usar "Salvar como tipo" de dentro Excel para convertê-lo para um documento Excel. Esta é uma dor, se os usuários precisam editar este documento e, em seguida, re-enviá-lo para o seu site.

A minha recomendação é usar CSV. É simples e se os usuários fazem abri-lo a partir de dentro do Excel, Excel, pelo menos, pede-lhes para salvá-lo em seu formato nativo.

Gostaria apenas de criar um arquivo CSV com base nos dados, porque eu vejo isso como a mais limpa e Excel tem um bom suporte para ele. Mas se você precisar de um formato mais flexível, eu tenho certeza que há algumas ferramentas de 3 para gerar excel verdadeira arquivos.

Aqui está uma solução a transmite o fora tabela de dados como um CSV. Rápido, limpo e fácil, e ele lida com vírgulas na entrada.

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

acabou de criar uma função para exportação a partir de um formulário web C # para excel espero que ajude outros

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

Se você tiver que usar o Excel em vez de um arquivo CSV que você vai precisar usar automação OLE em uma instância Excel um servidor. A maneira mais fácil de fazer isso é ter um arquivo de modelo e programaticamente preenchê-lo com os dados. Você salvá-lo em outro arquivo.

Dicas:

  • Não faça isso de forma interativa. Tem o pontapé de usuário fora do processo e, em seguida, postar uma página com o link para o arquivo. Isso reduz possíveis problemas de desempenho enquanto a planilha é gerada.
  • Use o modelo como eu descrevi antes. Ela torna mais fácil para modificá-lo.
  • Certifique-se de que o Excel está definido para não aparecer diálogos. Em um servidor web esta irá travar toda a instância excel.
  • Mantenha a instância do Excel em um servidor separado, de preferência atrás de um firewall, por isso não é exposto como uma potencial falha de segurança.
  • Fique de olho no uso de recursos. Gerando um spreadhseet sobre a interface de automação OLE (os da PIA são calços pouco mais este) é um processo bastante pesado. Se você precisa de escala isso para grandes volumes de dados que você pode precisar de ser um pouco inteligente com sua arquitetura.

Alguns dos 'uso mime-types para enganar excel em uma tabela HTML de abertura' abordagens iria funcionar se você não se importa o formato do arquivo a ser um pouco básico. Essas abordagens também fob a pesada CPU trabalho off para o cliente. Se você quer controle graned-fino sobre o formato da planilha que você provavelmente terá que usar o próprio Excel para gerar o arquivo como descrito acima.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top