Domanda

Sto per aggiungere una sezione a un'app ASP.NET (codice VB.NET dietro) che consentirà a un utente di ottenere i dati restituiti come file Excel, che genererò in base ai dati del database. Mentre ci sono diversi modi per farlo, ognuno ha i suoi svantaggi. In che modo tu restituiresti i dati? Sto cercando qualcosa che sia il più pulito e semplice possibile.

È stato utile?

Soluzione

CSV

Pro:

  • semplice

Contro:

  • Potrebbe non funzionare in altre impostazioni locali o in diverse configurazioni di Excel (ad es. separatore di elenco)
  • Impossibile applicare formattazione, formule, ecc.

HTML

Pro:

  • Ancora piuttosto semplice
  • Supporta formule e formule semplici

Contro:

  • Devi nominare il file come xls ed Excel potrebbe avvisarti dell'apertura di un file Excel non nativo
  • Un foglio di lavoro per cartella di lavoro

OpenXML (Office 2007 .XLSX)

Pro:

  • Formato nativo di Excel
  • Supporta tutte le funzionalità di Excel
  • Non richiede una copia di installazione di Excel
  • Può generare tabelle Pivot
  • Può essere generato utilizzando il progetto open source EPPlus

Contro:

  • Compatibilità limitata al di fuori di Excel 2007 (non dovrebbe essere un problema al giorno d'oggi)
  • Complicato a meno che non si stia utilizzando un componente di terze parti

SpreadSheetML (formato aperto XML)

Pro:

  • Semplice rispetto ai formati nativi di Excel
  • Supporta la maggior parte delle funzionalità di Excel: formattazione, stili, formule, più fogli per cartella di lavoro
  • Excel non deve essere installato per usarlo
  • Non sono necessarie librerie di terze parti: basta scrivere il tuo xml
  • I documenti possono essere aperti da Excel XP / 2003/2007

Contro:

  • Mancanza di buona documentazione
  • Non supportato nelle versioni precedenti di Excel (precedente al 2000)
  • Sola scrittura, in quanto una volta aperto e apportato modifiche da Excel viene convertito in Excel nativo.

XLS (generato da un componente di terze parti)

Pro:

  • Genera file Excel nativo con tutti i formati, le formule, ecc.

Contro:

  • Costo in denaro
  • Aggiungi dipendenze

Interoperabilità COM

Pro:

  • Utilizza librerie Microsoft native
  • Leggi il supporto per i documenti nativi

Contro:

  • Molto lento
  • Problemi di corrispondenza dipendenza / versione
  • Problemi di concorrenza / integrità dei dati per l'uso del Web durante la lettura
  • Molto lento
  • Problemi di ridimensionamento per uso Web (diversi dalla concorrenza): è necessario creare molte istanze di app Excel pesanti sul server
  • Richiede Windows
  • Ho già detto che è lento?

Altri suggerimenti

Puoi generare i dati come celle di una tabella html, attaccare un'estensione .xls o .xlsx ed Excel li aprirà come se fosse un documento nativo . Puoi persino eseguire alcuni calcoli di formattazione e formula limitati in questo modo, quindi è molto più potente di CSV. Inoltre, l'output di una tabella html dovrebbe essere abbastanza facile da fare da una piattaforma web come ASP.Net;)

Se hai bisogno di più fogli di lavoro o fogli di lavoro con nome nella cartella di lavoro di Excel, puoi fare qualcosa di simile tramite uno schema XML chiamato SpreadSheetML . Questo non è non il nuovo formato fornito con Office 2007, ma qualcosa di completamente diverso che funziona fino a Excel 2000. Il modo più semplice per spiegare come funziona è con un esempio:

<?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 proviene da una 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();
}

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

Questo è un wrapper gratuito per SpreadML - funziona alla grande.

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

In base alle risposte fornite e alla consultazione con i colleghi, sembra che la soluzione migliore sia generare un file XML o tabelle HTML e spingerlo verso il basso come allegato. L'unica modifica raccomandata dai miei colleghi è che i dati (ovvero le tabelle HTML) possono essere scritti direttamente nell'oggetto Response, eliminando così la necessità di scrivere un file, che può essere problematico a causa di problemi con le autorizzazioni, I / O contesa e garantendo che si verifichi lo spurgo programmato.

Ecco uno snippet del codice ... Non l'ho ancora controllato e non ho fornito tutto il codice chiamato, ma penso che rappresenti bene l'idea.

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

poiché Excel capisce l'HTML, puoi semplicemente scrivere i dati come una tabella HTML in un file temporaneo con estensione .xls, ottenere il FileInfo per il file e soffiarlo indietro 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 si desidera evitare il file temporaneo, è possibile scrivere su un flusso in memoria e riscrivere i byte invece di utilizzare WriteFile

se si omette l'intestazione della lunghezza del contenuto, è possibile riscrivere direttamente l'html, ma questo potrebbe non funzionare sempre correttamente in tutti i browser

Preferisco personalmente il metodo XML. Restituirò i dati dal database in un set di dati, li salverò in XMl, quindi creerò un file xslt che contiene una regola di trasformazione che formatterà un documento corretto e una semplice trasformazione XML finirà il lavoro. La parte migliore di questo è che puoi formattare celle, formattare in modo condizionale, impostare intestazioni e piè di pagina e persino impostare intervalli di stampa.

L'ho fatto un paio di volte e ogni volta il modo più semplice era semplicemente restituire un file CSV (Comma Separated Value). Excel lo importa perfettamente ed è relativamente veloce da eseguire.

esportiamo i dati da un datagrid per eccellere continuamente. Convertendolo in HTML, quindi scrivendo in un file 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()

L'unico gotcha con questo metodo era che molte delle nostre griglie avevano pulsanti o collegamenti in esse, quindi ne hai bisogno anche tu:

'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

L'ho scoperto da qualche parte, funziona bene.

Raccomando bibliotecario di generazione excel open source gratuito basato su OpenXML

Mi ha aiutato diversi mesi fa.

Ecco un rapporto che estrae da una procedura memorizzata. I risultati vengono esportati in Excel. Utilizza ADO anziché ADO.NET e il motivo per cui è questa linea

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

Fa la maggior parte del lavoro e non è disponibile in 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 si riempie un GridView di dati è possibile utilizzare questa funzione per ottenere i dati in formato HTML, ma indicando che il browser è un file 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

Evita semplicemente l'interoperabilità COM tramite lo spazio dei nomi Microsoft.Office.Interop. È così dannatamente lento, inaffidabile e non scalabile. Non applicabile ai masochisti.

Puoi creare file Excel ben formattati usando questa libreria abbastanza facilmente: http://officehelper.codeplex.com/ documentazione .

Non è necessario che Microsoft Office sia installato sul server web!

CSV è il modo più semplice. Il più delle volte è collegato a Excel. Altrimenti devi usare le API di automazione o il formato XML. Le API e XML non sono così difficili da usare.

Informazioni sulla generazione di XML per Excel

O seguo il percorso CSV (come descritto sopra), o più spesso in questi giorni, utilizzo Infragistics NetAdvantage per generare il file. (La stragrande maggioranza delle volte in cui Infragistics è in gioco, stiamo solo esportando un UltraWebGrid esistente, che è essenzialmente una soluzione a LOC solo se sono necessarie ulteriori modifiche di formattazione. Potremmo anche generare manualmente un file Excel / BIFF, ma raramente è necessario.)

amico, in .net credo che potresti avere un componente che potrebbe farlo, ma in asp classico l'ho già fatto creando una tabella html e cambiando il tipo mime della pagina in vnd / msexcel. Immagino che se usi un gridview e cambi il tipo mime, forse dovrebbe funzionare, perché gridview è una tabella html.

L'unico modo a prova di proiettile per evitare il " Sembra che questi numeri siano memorizzati come testo " i triangoli verdi devono usare il formato Open XML. Vale la pena usarlo, solo per evitare gli inevitabili triangoli verdi.

Il metodo migliore che ho visto per i report Excel è quello di scrivere i dati in XML con estensione XML e trasmetterli ai client con il tipo di contenuto corretto. (Application / xls)

Funziona con qualsiasi rapporto che richiede una formattazione di base e ti consente di confrontare i fogli di calcolo esistenti utilizzando gli strumenti di confronto del testo.

Supponendo che ciò avvenga per una rete intranet, in cui è possibile impostare autorizzazioni e imporre IE, è possibile generare il lato client della cartella di lavoro con JScript / VBScript che guida Excel . Questo ti dà la formattazione nativa di Excel, senza il fastidio di provare ad automatizzare Excel sul server.

Non sono sicuro di raccomandare più questo approccio se non in scenari abbastanza di nicchia, ma era abbastanza comune durante i classici tempi d'oro di ASP.

Ovviamente puoi sempre scegliere componenti di terze parti. Personalmente, ho avuto una buona esperienza con Spire.XLS http: //www.e- iceblue.com/xls/xlsintro.htm

Il componente è abbastanza facile da usare all'interno dell'applicazione:

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

Uno dei problemi che ho riscontrato utilizzando una delle soluzioni suggerite sopra che sono simili a questa risposta è che se lo estrai come allegato (quella che ho trovato essere la soluzione più pulita per i browser non-ms), quindi aprilo in Excel 2000-2003, il suo tipo è una "Pagina Web di Excel" e non un documento Excel nativo.

Quindi devi spiegare agli utenti come utilizzare " Salva come tipo " da Excel per convertirlo in un documento Excel. Questo è un problema se gli utenti devono modificare questo documento e quindi ricaricarlo sul tuo sito.

La mia raccomandazione è di usare CSV. È semplice e se gli utenti lo aprono da Excel, Excel li richiede almeno di salvarlo nel suo formato nativo.

Vorrei solo creare un file CSV basato sui dati, perché lo vedo come il più pulito ed Excel ha un buon supporto per questo. Ma se hai bisogno di un formato più flessibile, sono sicuro che ci sono alcuni strumenti di terze parti per generare file Excel reali.

Ecco una soluzione per lo streaming del datatable come CSV. Veloce, pulito e facile e gestisce le virgole nell'input.

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

ha appena creato una funzione per esportare da un modulo web C # per eccellere nella speranza che aiuti gli altri

    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 è necessario utilizzare Excel anziché un file CSV, sarà necessario utilizzare l'automazione OLE su un'istanza di Excel nel server. Il modo più semplice per farlo è avere un file modello e riempirlo programmaticamente con i dati. Lo salvi in ??un altro file.

Punte:

  • Non farlo in modo interattivo. Chiedi all'utente di dare il via al processo e quindi pubblicare una pagina con il link al file. Ciò mitiga i potenziali problemi di prestazioni durante la generazione del foglio di calcolo.
  • Usa il modello come ho descritto prima. Semplifica la modifica.
  • Assicurati che Excel sia impostato per non visualizzare finestre di dialogo. Su un server Web questo bloccherà l'intera istanza di Excel.
  • Conserva l'istanza di Excel su un server separato, preferibilmente dietro un firewall, quindi non è esposta come potenziale falla di sicurezza.
  • Tieni d'occhio l'utilizzo delle risorse. Generare un foglio di calcolo sull'interfaccia di automazione OLE (i PIA sono solo degli spessori) è un processo piuttosto pesante. Se è necessario ridimensionarlo a volumi di dati elevati, potrebbe essere necessario essere in qualche modo intelligente con la propria architettura.

Alcuni degli approcci 'usa i tipi mime per indurre Excel ad aprire tabelle HTML' funzionerebbero se non ti dispiace che il formato del file sia un po 'di base. Questi approcci fob anche il lavoro pesante della CPU sul client. Se desideri un controllo granulare del formato del foglio di calcolo, dovrai probabilmente utilizzare Excel stesso per generare il file come descritto sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top