Generazione di un file Excel in ASP.NET [chiuso]


99

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


Risposte:


131

CSV

Professionisti:

  • Semplice

Contro:

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

HTML

Professionisti:

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

Professionisti:

  • Formato Excel nativo
  • Supporta tutte le funzionalità di Excel
  • Non è necessaria 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 tu non stia utilizzando un componente di terze parti

SpreadSheetML (formato XML aperto)

Professionisti:

  • 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 ha bisogno di 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 (pre-2000)
  • Sola scrittura, in quanto una volta aperto e apportato modifiche da Excel, viene convertito in Excel nativo.

XLS (generato da componenti di terze parti)

Professionisti:

  • Genera file Excel nativo con tutte le formattazioni, formule, ecc.

Contro:

  • Costo denaro
  • Aggiungi dipendenze

COM Interop

Professionisti:

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

Contro:

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

1
Il vincolo di "sola scrittura" menzionato per SpreadsheetML non è del tutto un problema, poiché puoi salvare un file Excel come SpreadsheetML se lo desideri.
Brian il

1
SpreadsheetML potrebbe bloccarsi in Excel 2003 se crei file di grandi dimensioni con esso. Non fidarti: /
Brian

2
È possibile salvare nuovamente in un file SpreadsheetML in Office 2002 e 2003. Non è richiesto alcun salvataggio con nome. SpreadsheetML non è in grado di memorizzare macro, grafici, grafici e poche altre quote, comprese le nuove funzionalità di Office 2007 (ad esempio, più di 3 formati condizionali). Poiché XML è dettagliato, Zipping SpreadsheetML prima dell'invio dal server (utilizzando SharpZipLib è un'opzione) funziona alla grande per ridurre i tempi di download - in realtà, va detto che OpenXML è comunque memorizzato in un contenitore ZIP. @Brian: uso quotidianamente un complesso SpreadsheetML nell'intervallo 50-100 MB senza problemi di crash.
richardtallent

Se esiste la possibilità che tu debba esportare grandi quantità di dati, dovresti esportare come CSV. A parte SpreadsheetML, è più difficile realizzare una soluzione performante con uno qualsiasi degli altri formati. L'HTML può essere scritto e letto in modo efficiente, ma necessita di ulteriori specifiche da parte tua per essere utile. Sia HTML che SpreadsheetML hanno altri problemi relativi ai file di grandi dimensioni, come menzionato da Brian nel suo commento. Quindi, se hai solo bisogno di una semplice esportazione dei dati, usa CSV.
JohannesH

2
@pomarc: potrebbe essere semplice, ma non è pulito. L'utente vuole un file Excel e tu gli dai un file HTML con un'estensione falsa.
Heinzi

38

Puoi produrre i dati come celle di tabella html, attaccare un'estensione .xlso .xlsxsu di esso ed Excel lo aprirà come se fosse un documento nativo. Puoi persino eseguire formattazioni limitate e calcoli di formule 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 all'interno della tua cartella di lavoro di Excel, puoi fare qualcosa di simile tramite uno schema XML chiamato SpreadSheetML. Questo non è il nuovo formato fornito con Office 2007, ma qualcosa di completamente diverso che funziona fin da 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> 

12
potresti rinominare il file con un'estensione .xml e aggiungere questo: <? mso-application progid = "Excel.Sheet"?> subito dopo <? xml version = "1.0"?> in questo modo Windows riconosce che il file è un File Excel, gli darà l'icona giusta, aprirà Excel quando fai clic sul file ed Excel non si lamenterà del fatto che il formato del file e il contenuto non corrispondono. addio.
pomarc

1
@pomarc Lo svantaggio è che altri programmi che importano file Excel non lo riconosceranno. Ma poi, probabilmente non analizzerebbero comunque l'xml.
Joel Coehoorn

1
Ho usato questa tecnica con successo. Questa sarebbe la mia raccomandazione: semplice e molto efficace.
NealB

Due potenziali problemi (YMMV) con i dati tabulari HTML mascherati come file XLS: (1) Microsoft Excel taglierà automaticamente gli spazi iniziali e gli zeri; e (2) Microsoft Excel 2010 avvisa l'utente quando apre un file XLS contenente dati tabulari HTML. La soluzione al numero 1 sembra essere creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (se gli spazi / zeri iniziali sono significativi e devono essere conservati).
iokevins

Solo per chiarimento, mentre ho menzionato le tabelle HTML, il punto principale di questa risposta è SpreadsheetML, che è più di semplici dati tabulari HTML. Excel lo vede come nativo.
Joel Coehoorn

16

Se proviene da un 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);
        }
    }
}

1
Solo il codice che mi serviva, grazie. :)
Kjensen

Scott, cosa significa il simbolo della sterlina ("£")? E se ne avessi bisogno? Qualche altro personaggio pericoloso?
Piotr Owsiak

PERFETTO. Proprio quello di cui avevo bisogno.
Brad Bruce

il segno £ è in realtà solo qualcosa di cui avevo bisogno per uno dei miei clienti. puoi tirarlo fuori.
SpoiledTechie.com

Due potenziali problemi (YMMV) con i dati tabulari HTML mascherati come file XLS: (1) Microsoft Excel taglierà automaticamente gli spazi iniziali e gli zeri; e (2) Microsoft Excel 2010 avvisa l'utente quando apre un file XLS contenente dati tabulari HTML. La soluzione al numero 1 sembra essere creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (se gli spazi / zeri iniziali sono significativi e devono essere conservati). Anche i file di dati CSV soffrono del numero 1 quando vengono aperti in Microsoft Excel.
iokevins


5

Sulla base delle risposte fornite e della consultazione con i colleghi, sembra che la soluzione migliore sia generare un file XML o tabelle HTML e inviarlo come allegato. L'unica modifica consigliata dai miei colleghi è che i dati (cioè le tabelle HTML) possono essere scritti direttamente nell'oggetto Response, eliminando così la necessità di scrivere un file, che può essere fastidioso a causa di problemi di permessi, I / O contesa e garantire che si verifichi l'eliminazione programmata.

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

2
Dan, sei sulla strada giusta. E raccomando decisamente SpreadsheetML rispetto a HTML - spazio di respiro per il futuro, poiché il supporto HTML è limitato in modo frustrante. Ma con HTML, SpreadsheetML e OpenXML, le dimensioni dei file possono essere piuttosto grandi e non verranno compressi con gzip dal server. OpenXML richiede un contenitore ZIP con più file all'interno, e SpreadsheetML e HTML sono entrambi molto più veloci da scaricare se prima comprimi i file e invii lo zip come allegato. Usa SharpZipLib e invia in streaming ad esso invece che direttamente a Response.
richardtallent

4

poiché Excel comprende 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 rimandarlo 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 l'intestazione della lunghezza del contenuto viene omessa puoi semplicemente riscrivere l'html direttamente, ma questo potrebbe non funzionare sempre correttamente in tutti i browser


2
Due potenziali problemi (YMMV) con i dati tabulari HTML mascherati come file XLS: (1) Microsoft Excel taglierà automaticamente gli spazi iniziali e gli zeri; e (2) Microsoft Excel 2010 avvisa l'utente quando apre un file XLS contenente dati tabulari HTML. La soluzione al numero 1 sembra essere creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (se gli spazi / zeri iniziali sono significativi e devono essere conservati).
iokevins

3

Personalmente preferisco il metodo XML. Restituirò i dati dal database in un dataset, lo salverò in XMl, quindi creo un file xslt che contiene una regola di trasformazione che formatterà un documento appropriato e una semplice trasformazione XML finirà il lavoro. La parte migliore di questo è che puoi formattare celle, eseguire la formattazione condizionale, impostare intestazioni e piè di pagina e persino impostare intervalli di stampa.


2

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


Un potenziale problema (YMMV) con i dati CSV: Microsoft Excel ridurrà automaticamente gli spazi
iniziali

2

esportiamo i dati da un datagrid per eccellere tutto il tempo. Convertendolo in HTML e poi 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 problema con questo metodo era che molte delle nostre griglie contenevano pulsanti o collegamenti, quindi anche tu hai bisogno di questo:

'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

Ho scoperto che da qualche parte funziona bene.


2
Due potenziali problemi (YMMV) con i dati tabulari HTML mascherati come file XLS: (1) Microsoft Excel taglierà automaticamente gli spazi iniziali e gli zeri; e (2) Microsoft Excel 2010 avvisa l'utente quando apre un file XLS contenente dati tabulari HTML. La soluzione al numero 1 sembra essere creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (se gli spazi / zeri iniziali sono significativi e devono essere conservati).
iokevins


2

Ecco un report che attinge da una stored procedure. I risultati vengono esportati in Excel. Utilizza ADO invece di ADO.NET e il motivo è questa linea

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

Svolge 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

1

Se si riempie un GridView con i 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

Due potenziali problemi (YMMV) con i dati tabulari HTML mascherati come file XLS: (1) Microsoft Excel taglierà automaticamente gli spazi iniziali e gli zeri; e (2) Microsoft Excel 2010 avvisa l'utente quando apre un file XLS contenente dati tabulari HTML. La soluzione al numero 1 sembra essere creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (se gli spazi / zeri iniziali sono significativi e devono essere conservati).
iokevins

1

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




0

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 one-LOC a meno che non siano necessari ulteriori ritocchi di formattazione. Potremmo anche generare manualmente un file Excel / BIFF, ma raramente ce n'è bisogno.)


0

amico, in .net immagino 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é il gridview è una tabella html.


Due potenziali problemi (YMMV) con i dati tabulari HTML mascherati come file XLS: (1) Microsoft Excel taglierà automaticamente gli spazi iniziali e gli zeri; e (2) Microsoft Excel 2010 avvisa l'utente quando apre un file XLS contenente dati tabulari HTML. La soluzione al numero 1 sembra essere creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (se gli spazi / zeri iniziali sono significativi e devono essere conservati).
iokevins

0

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


0

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

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


0

Supponendo che questo sia per una intranet, in cui è possibile impostare autorizzazioni e imporre IE, è possibile generare la cartella di lavoro lato client 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 che consiglierei più questo approccio tranne che in scenari abbastanza di nicchia, ma era abbastanza comune durante i classici tempi d'oro dell'ASP.


0

Ovviamente puoi sempre optare per 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 della tua 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");

0

Uno dei problemi che ho riscontrato utilizzando una delle soluzioni suggerite sopra che sono simili a questa risposta è che se sposti il ​​contenuto 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 Excel" e non un documento Excel nativo.

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

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


Dovrai stare attento con CSV se i tuoi utenti sono sparsi in tutto il mondo. Qui in Germania la virgola viene utilizzata come separatore decimale e quindi il punto e virgola viene utilizzato come separatore di valori. Rende difficile creare un file leggibile in tutte le diverse culture. Pertanto il mio voto sarebbe per uno dei formati XML.
paul

0

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.


0

Ecco una soluzione che trasmette il 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();
}

-1

ho appena creato una funzione per esportare da un modulo Web C # per eccellere, sperando 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();
            }
        }
     }

-5

Se devi utilizzare Excel invece di un file CSV, dovrai utilizzare l'automazione OLE su un'istanza di Excel sul server. Il modo più semplice per farlo è disporre di un file modello e compilarlo programmaticamente con i dati. Lo salvi in ​​un altro file.

Suggerimenti:

  • Non farlo in modo interattivo. Chiedi all'utente di avviare il processo e quindi pubblicare una pagina con il collegamento al file. Questo mitiga potenziali problemi di prestazioni durante la generazione del foglio di calcolo.
  • Usa il modello come ho descritto prima. Rende più facile modificarlo.
  • Assicurati che Excel sia impostato per non visualizzare finestre di dialogo. Su un server web questo bloccherà l'intera istanza di Excel.
  • Mantieni l'istanza di Excel su un server separato, preferibilmente dietro un firewall, in modo che non venga esposta come potenziale falla di sicurezza.
  • Tieni d'occhio l'utilizzo delle risorse. La generazione di uno spreadhseet sull'interfaccia di automazione OLE (i PIA sono solo spessori su questo) è un processo abbastanza pesante. Se è necessario ridimensionarlo a volumi di dati elevati, potrebbe essere necessario essere in qualche modo intelligenti con la propria architettura.

Alcuni degli approcci "usa i tipi MIME per ingannare Excel nell'apertura di tabelle HTML" funzionerebbero se non ti dispiace che il formato del file sia un po 'basilare. Questi approcci trasferiscono anche il lavoro pesante della CPU sul client. Se desideri un controllo granulare sul formato del foglio di calcolo, probabilmente dovrai utilizzare Excel stesso per generare il file come descritto sopra.


Pessima idea fare automazione da un server web. Le alternative possono sembrare hack-ish, ma funzioneranno davvero molto meglio.
Joel Coehoorn,

Usiamo OLE lato server con Excel ed è un enorme problema sul retro. Se non fosse per il rischio per il nostro prodotto **, sceglieremmo un'altra soluzione. ** Meglio il diavolo che conosci ...
DaveE
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.