Question

Je suis sur le point d'ajouter une section à une application ASP.NET (codebehind 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 façons de procéder, chacune a ses propres inconvénients. Comment voulez-vous renvoyer les données? Je cherche quelque chose d'aussi propre et franc que possible.

Était-ce utile?

La solution

CSV

Avantages:

  • Simple

Inconvénients:

  • Il se peut que cela ne fonctionne pas dans d'autres environnements locaux ou dans différentes configurations Excel (séparateur de liste, par exemple)
  • Impossible d'appliquer le formatage, les formules, etc.

HTML

Avantages:

  • Toujours aussi simple
  • Prend en charge le formatage simple et les formules

Inconvénients:

  • Vous devez nommer le fichier sous la forme xls et Excel peut vous avertir de l'ouverture d'un fichier Excel non natif
  • Une feuille de calcul par classeur

OpenXML (Office 2007 .XLSX)

Avantages:

  • Format natif Excel
  • Prend en charge toutes les fonctionnalités d'Excel
  • Ne pas demander une copie d'installation 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 en dehors d'Excel 2007 (cela ne devrait plus être un problème)
  • Compliqué sauf si vous utilisez un composant tiers

SpreadSheetML (format XML ouvert)

Avantages:

  • Simple comparé aux formats natifs Excel
  • Prend en charge la plupart des fonctionnalités d'Excel: mise en forme, styles, formules, plusieurs feuilles par classeur
  • Excel n'a pas besoin d'être installé pour l'utiliser
  • Aucune bibliothèque tierce requise - écrivez simplement votre xml
  • Les documents peuvent être ouverts avec Excel XP / 2003/2007

Inconvénients:

  • Manque de bonne documentation
  • Non pris en charge dans les anciennes versions d'Excel (antérieures à 2000)
  • En écriture seule, une fois que vous l'ouvrez et apportez des modifications à partir d'Excel, il est converti en Excel natif.

XLS (généré par un composant tiers)

Avantages:

  • Génère un fichier Excel natif avec tous les formulaires, formules, etc.

Inconvénients:

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

Interopérabilité COM

Avantages:

  • Utilise les bibliothèques Microsoft natives
  • Lecture du support des documents natifs

Inconvénients:

  • très lent
  • Problèmes de correspondance de dépendance / version
  • Problèmes de concurrence / intégrité des données pour une utilisation Web lors de la lecture
  • très lent
  • Problèmes de dimensionnement pour une utilisation Web (différents de la simultanéité): nécessité de créer de nombreuses instances d'une application Excel lourde sur le serveur
  • Nécessite Windows
  • Ai-je mentionné que c'est lent?

Autres conseils

Vous pouvez exporter les données sous forme de cellules de tableau html, coller une extension .xls ou .xlsx et Excel l'ouvrira comme s'il s'agissait d'un document natif. . Vous pouvez même effectuer des calculs de formule et de formatage limités de cette manière, ce qui en fait un outil beaucoup plus puissant que le format CSV. En outre, la sortie d'une table HTML devrait être assez facile à faire à partir d'une plate-forme Web telle que ASP.Net;)

Si vous avez besoin de plusieurs feuilles de calcul ou de feuilles de calcul nommées dans votre classeur Excel, vous pouvez faire quelque chose de similaire via 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 depuis Excel 2000. Le moyen le plus simple d'expliquer son fonctionnement consiste à utiliser 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> 

Si vous venez d'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();
}

À partir d'une 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);
        }
    }
}

C’est un wrapper gratuit autour de SpreadML - il fonctionne très bien.

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

Sur la base des réponses fournies et de la consultation de vos collègues, il apparaît que la meilleure solution consiste à générer un fichier XML ou des tableaux HTML et à le placer en pièce jointe. Le changement recommandé par mes collègues est que les données (c’est-à-dire les tableaux HTML) peuvent être écrites directement dans l’objet Response, éliminant ainsi la nécessité d’écrire un fichier, ce qui peut être gênant en raison de problèmes d’autorisations, contention et en veillant à ce que la purge soit programmée.

Voici un extrait du code ... Je n'ai pas encore vérifié cela et je n'ai pas fourni tout le code appelé, mais je pense que cela représente bien 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()

Comme Excel comprend le langage HTML, vous pouvez simplement écrire les données sous forme de tableau HTML dans un fichier temporaire avec une extension .xls, obtenir le FileInfo pour le fichier et le restaurer à l’aide de

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

si vous voulez éviter le fichier temporaire, vous pouvez écrire dans un flux en mémoire et réécrire les octets au lieu d'utiliser WriteFile

si l'en-tête content-length est omis, vous pouvez simplement écrire le code HTML directement, mais cela risque de ne pas fonctionner correctement dans tous les navigateurs

Personnellement, je préfère la méthode XML. Je vais renvoyer les données de la base de données dans un jeu de données, les enregistrer au format XMl, puis créer un fichier xslt contenant une règle de transformation permettant de formater un document approprié. Une simple transformation XML termine le travail. La meilleure partie de ce travail consiste à formater des cellules, à effectuer un formatage conditionnel, à configurer des en-têtes et des pieds de page et même à définir des plages d’impression.

Je l'ai fait plusieurs fois et à chaque fois, le moyen le plus simple était de simplement renvoyer un fichier CSV (valeurs séparées par des virgules). Excel l'importe parfaitement, et c'est relativement rapide à faire.

nous exportons les données d'une grille de données pour exceller tout le temps. Conversion en HTML puis écriture dans un fichier 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()

Le seul inconvénient de cette méthode est qu'un grand nombre de nos grilles comportaient des boutons ou des liens, vous en avez donc besoin aussi:

'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

J'ai trouvé que quelque part, ça marche bien.

Je recommande la bibliothèque gratuite de génération Excel opensource , basée sur OpenXML

.

Cela m'a aidé il y a plusieurs mois.

Voici un rapport extrait d'une procédure stockée. Les résultats sont exportés vers Excel. Il utilise ADO au lieu de ADO.NET et la raison pour laquelle cette ligne est

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

Il fait l'essentiel du travail et n'est pas disponible sur 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

Si vous remplissez un GridView avec des données, vous pouvez utiliser cette fonction pour obtenir les données au format HTML, mais en indiquant au navigateur qu'il s'agit d'un fichier 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

Il suffit d’éviter COM Interop via l’espace de noms Microsoft.Office.Interop. Il est tellement lent et peu fiable et indéchiffrable. Non applicable pour les masochistes.

Vous pouvez facilement créer des fichiers Excel au format agréable avec cette bibliothèque: http://officehelper.codeplex.com/ documentation .

Microsoft Office n'a pas besoin d'être installé sur le serveur Web!

Le format CSV est le moyen le plus simple. La plupart du temps, il est lié à Excel. Sinon, vous devez utiliser les API d'automatisation ou le format XML. Les API et XML ne sont pas si difficiles à utiliser.

Informations sur la génération de XML pour Excel

Je choisis la route CSV (comme décrit ci-dessus) ou, plus souvent, j'utilise Infragistics NetAdvantage pour générer le fichier. (La très grande majorité du temps où Infragistics est en jeu, nous exportons simplement un UltraWebGrid existant, qui est essentiellement une solution one-LOC sauf si des ajustements supplémentaires de formatage sont nécessaires. Nous pourrions également générer manuellement un fichier Excel / BIFF, mais il est rarement nécessaire de le faire.)

man, en .net, je suppose que vous pourriez avoir un composant qui pourrait le faire, mais en asp classique, je l’ai déjà fait en créant un tableau html et en modifiant le taper mime de la page en vnd / msexcel. Je suppose que si vous utilisez un gridview et changez le type mime, cela devrait peut-être fonctionner, car gridview est un tableau html.

Le seul moyen sûr d'éviter les "Il semble que ces chiffres soient stockés sous forme de texte". triangles verts consiste à utiliser le format Open XML. Cela vaut la peine de l’utiliser, pour éviter les inévitables triangles verts.

La meilleure méthode que j'ai vue pour les rapports Excel consiste à écrire les données en XML avec une extension XML et à les diffuser vers les clients avec le type de contenu correct. (application / xls)

Cela fonctionne pour tout rapport nécessitant une mise en forme de base et vous permet de comparer des feuilles de calcul existantes à l'aide d'outils de comparaison de texte.

En supposant qu'il s'agisse d'un intranet, où vous pouvez définir des autorisations et mandater IE, vous pouvez générer le côté client du classeur avec JScript / VBScript pilotant Excel . Cela vous donne un formatage Excel natif, sans avoir à essayer d'automatiser Excel sur le serveur.

Je ne suis pas sûr de vraiment recommander cette approche, sauf dans des scénarios relativement créneaux, mais c'était assez courant lors des journées classiques d'ASP.

Vous pouvez bien sûr toujours utiliser des composants tiers. Personnellement, j'ai eu une bonne expérience avec Spire.XLS http: //www.e- iceblue.com/xls/xlsintro.htm

Le composant est assez facile à utiliser dans votre application:

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

Un des problèmes que j'ai rencontré en utilisant l'une des solutions suggérées ci-dessus, qui est similaire à cette réponse est que si vous transmettez le contenu en tant que pièce jointe (ce que j'ai trouvé être la solution la plus propre pour les navigateurs non-ms), puis ouvrez-le dans Excel 2000-2003, il est de type "page Web Excel". et non un document Excel natif.

Vous devez ensuite expliquer aux utilisateurs comment utiliser " Enregistrer sous le type " depuis Excel pour le convertir en document Excel. C’est difficile si les utilisateurs doivent modifier ce document, puis le télécharger à nouveau sur votre site.

Ma recommandation est d'utiliser le format CSV. C'est simple et si les utilisateurs l'ouvrent à partir d'Excel, Excel leur demande au moins de l'enregistrer dans son format natif.

Je créerais simplement un fichier CSV basé sur les données, car j’estime qu’il s’agissait du fichier le plus propre, et Excel est bien pris en charge. Mais si vous avez besoin d’un format plus flexible, je suis certain que certains outils tiers permettent de générer de véritables fichiers Excel.

Voici une solution qui diffuse le contenu en tant que fichier CSV. Rapide, propre et facile, il gère les virgules en entrée.

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

vient de créer une fonction permettant d'exporter à partir d'un formulaire Web C # pour espérer qu'elle aide les autres

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

Si vous devez utiliser Excel au lieu d'un fichier CSV, vous devrez utiliser l'automatisation OLE sur une instance Excel sur le serveur. Pour ce faire, le moyen le plus simple consiste à créer un fichier modèle et à le compléter par programme avec les données. Vous enregistrez dans un autre fichier.

Conseils:

  • Ne le faites pas de manière interactive. Demandez à l'utilisateur de lancer le processus, puis publiez une page avec le lien vers le fichier. Cela atténue les problèmes de performances potentiels lors de la génération du tableur.
  • Utilisez le modèle tel que décrit précédemment. Cela facilite la modification.
  • Assurez-vous qu'Excel est configuré pour ne pas ouvrir les boîtes de dialogue. Sur un serveur Web, cela suspendra toute l'instance Excel.
  • Conservez l'instance Excel sur un serveur distinct, de préférence derrière un pare-feu, afin d'éviter toute faille de sécurité.
  • Surveillez l'utilisation des ressources. Générer un spreadhseet sur l'interface d'automatisation OLE (les PIA ne sont que des casses dessus) est un processus assez lourd. Si vous devez adapter cela à des volumes de données élevés, vous devrez peut-être faire preuve d'une certaine intelligence dans votre architecture.

Certaines des approches "utiliser les types mime pour tromper parfaitement en ouvrant un tableau HTML" pourraient fonctionner si le format du fichier était un peu basique. Ces approches impliquent également que le processeur lourd travaille sur le client. Si vous souhaitez un contrôle précis du format de la feuille de calcul, vous devrez probablement utiliser Excel pour générer le fichier comme décrit ci-dessus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top