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.
Réponses
Trop de publicités?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?
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>
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);
}
}
}
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()