99 votes

Génération d'un fichier Excel dans ASP.NET

Je suis sur le point d'ajouter une section à une application ASP.NET (code code VB.NET) qui permettra à un utilisateur de récupérer les données sous forme de fichier Excel, que je générerai en fonction des données de la base de données. Bien qu'il existe plusieurs manières de procéder, chacune a ses propres inconvénients. Comment renvoyez- vous les données? Je cherche quelque chose d'aussi propre et simple que possible.

132voto

Eduardo Molteni Points 23135

CSV

Pour:

  • Simple

Inconvénients:

  • Il peut ne pas fonctionner dans d'autres localités ou dans les différents Excel configurations (c'est à dire le séparateur de Liste)
  • Ne peut pas appliquer la mise en forme, formules, etc

HTML

Pour:

  • Encore assez Simple
  • Prend en charge simple formatage et formules

Inconvénients:

  • Vous avez le nom du fichier xls pour Excel peut vous avertir de l'ouverture d'un non natif fichier Excel
  • Une feuille de calcul par classeur

OpenXML (Office 2007 .XLSX)

Pour:

  • Natif format Excel
  • Prend en charge toutes les fonctionnalités d'Excel
  • Ne pas besoin d'une installation de copie d'Excel
  • Peut générer des tableaux croisés dynamiques
  • Peut être généré à l'aide d'un projet open source EPPlus

Inconvénients:

  • Compatibilité limitée à l'extérieur Excel 2007 (il ne devrait pas être un problème de nos jours)
  • Compliqué, sauf si vous utilisez des composants tiers

SpreadSheetML (format ouvert XML)

Pour:

  • Simple par rapport à Excel natif de formats
  • Supporte la plupart des fonctionnalités d'Excel: mise en forme, les styles, les formules, plusieurs feuilles par classeur
  • Excel n'a pas besoin d'être installé pour l'utiliser
  • Pas de bibliothèques tierces nécessaire - il suffit d'écrire votre xml
  • Les Documents peuvent être ouverts dans microsoft Excel XP/2003/2007

Inconvénients:

  • L'absence d'une bonne documentation
  • Pas pris en charge dans les versions antérieures d'Excel (avant 2000)
  • Écriture seule, qu'une fois que vous l'ouvrir et le modifier à partir d'Excel, il est converti en natif Excel.

XLS (produites par des tiers composant)

Pour:

  • Générer natif fichier Excel avec toutes les mise en forme, formules, etc.

Inconvénients:

  • Le coût de l'argent
  • Ajouter des dépendances

COM Interop

Pour:

  • Utilisant les bibliothèques Microsoft
  • Support en lecture pour les documents

Inconvénients:

  • Très lent
  • Dépendance/version correspondante questions
  • La simultanéité/problèmes d'intégrité des données pour l'utilisation du web lors de la lecture
  • Très lent
  • Des questions d'échelle pour une utilisation web (différente de la simultanéité): besoin de créer de nombreux cas de forte Excel application sur le serveur
  • Nécessite Windows
  • Ai-je mentionné que c'est lent?

40voto

Joel Coehoorn Points 190579

Vous pouvez exporter les données au format html des cellules de tableau, un bâton .xls ou .xlsx extension sur elle, et Excel s'ouvre comme s'il s'agissait d'un document natif. Vous pouvez même le faire de manière limitée, mise en forme et la formule de calculs de cette façon, il est donc beaucoup plus puissant que CSV. Aussi, la sortie d'un tableau html devrait être assez facile à faire à partir d'une plate-forme web comme ASP.Net ;)

Si vous avez besoin de plusieurs feuilles de calcul ou le nom des feuilles de calcul au sein de votre Classeur Excel, vous pouvez faire quelque chose de similaire par le biais d'un schéma XML appelé SpreadSheetML. Ce n'est pas le nouveau format fourni avec Office 2007, mais quelque chose de complètement différent qui fonctionne aussi loin que Excel 2000. La façon la plus simple pour expliquer comment il fonctionne, c'est avec un exemple:

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

16voto

SpoiledTechie.com Points 2541

si provenant d'une table de données.

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

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

7voto

rp. Points 9997

Ceci est un wrapper gratuit autour de SpreadML - cela fonctionne très bien.

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

5voto

Dan Coates Points 977

Basé sur les réponses données, et en consultation avec les collègues de travail, il apparaît que la meilleure solution est de générer un fichier XML ou HTML des tables et pousser vers le bas comme une pièce jointe. Le seul changement recommandé par mon co-travailleurs, c'est que les données (c'est à dire les tableaux HTML) peut être écrit directement à l'objet de Réponse, éliminant ainsi le besoin d'écrire un fichier, ce qui peut être problématique en raison de problèmes d'autorisations, I/O contention, et de veiller à ce que prévue purge se produit.

Voici un extrait du code... je n'ai pas vérifié encore, et je n'ai pas fourni tous les appelés de code, mais je pense que c'est l'idée.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X