Comment créer un fichier Excel (.XLS et .XLSX) en C # sans installer Microsoft Office?

1893

Comment puis-je créer une feuille de calcul Excel avec C # sans exiger qu'Excel soit installé sur la machine qui exécute le code?

mistrmark
la source
Le message "... sans installer Ms Office?" une partie de la question semble très peu professionnelle. Vous pouvez générer n'importe quel type de fichier à partir d'un programme C # (avec un fichier xlsou l' xlsxun d'eux). Il n'est pas obligatoire qu'un programme sur votre ordinateur puisse le lire (disons, binaire).
Mike
30
@Mike La pièce "sans exiger qu'Excel soit installé" n'a rien à voir avec le fait d'être professionnel. Il s'agit de dépendances. Le texte original de la question était libellé comme suit: "Idéalement, j'aimerais avoir l'open source, donc je n'ai pas à ajouter de dépendances tierces à mon code, et je voudrais éviter d'utiliser Excel directement pour créer le fichier (en utilisant OLE Automation.) " Il est regrettable que la question ait été radicalement simplifiée.
Tony
5
En supposant que vous essayiez de faire quelque chose sans bibliothèque ou code externe, je ne peux pas parler pour le fichier xls, mais pour les fichiers xlsx, pourquoi ne pas commencer par en prendre un existant, le renommer en fichier zip et en explorer le contenu? Un peu d'ingénierie inverse vous en dira beaucoup. Il existe plusieurs fichiers xml et fichiers rels différents dans les différents dossiers et sous-dossiers. Essayez d'explorer cela et voyez si c'est quelque chose que vous pouvez répliquer ou voyez si vous pouvez trouver de la documentation sur les différents espaces de nom / schémas xml.
Alexander Ryan Baggett
@AlexanderRyanBaggett Cela a été extrêmement utile! Je suis tombé sur cet article tout en travaillant sur la génération automatique de rapports et en explorant les documents en tant qu'archive zip fournissant un peu d'informations sur ce qui se passe dans la création d'un fichier de document.
SentientFlesh

Réponses:

1055

Vous pouvez utiliser une bibliothèque appelée ExcelLibrary. Il s'agit d'une bibliothèque open source gratuite publiée sur Google Code:

ExcelLibrary

Cela semble être un port de PHP ExcelWriter que vous avez mentionné ci-dessus. Il n'écrira pas encore au nouveau format .xlsx, mais ils travaillent sur l'ajout de cette fonctionnalité dans.

C'est très simple, petit et facile à utiliser. De plus, il dispose d'un DataSetHelper qui vous permet d'utiliser DataSets et DataTables pour travailler facilement avec des données Excel.

ExcelLibrary semble ne fonctionner que pour l'ancien format Excel (fichiers .xls), mais pourrait ajouter la prise en charge à l'avenir pour les nouveaux formats 2007/2010.

Vous pouvez également utiliser EPPlus , qui ne fonctionne que pour les fichiers au format Excel 2007/2010 (fichiers .xlsx). Il y a aussi NPOI qui fonctionne avec les deux.

Il y a quelques bogues connus avec chaque bibliothèque comme indiqué dans les commentaires. Dans l'ensemble, EPPlus semble être le meilleur choix au fil du temps. Il semble également être mis à jour et documenté plus activement.

En outre, comme indiqué par @ АртёмЦарионов ci-dessous, EPPlus prend en charge les tableaux croisés dynamiques et ExcelLibrary peut avoir une certaine prise en charge ( problème de tableau croisé dynamique dans ExcelLibrary )

Voici quelques liens pour référence rapide:
ExcelLibrary - GNU Lesser GPL
EPPlus - GNU Lesser General Public License (LGPL)
NPOI - Apache License

Voici un exemple de code pour ExcelLibrary:

Voici un exemple prenant des données d'une base de données et en créant un classeur. Notez que le code ExcelLibrary est la seule ligne en bas:

//Create the data set and table
DataSet ds = new DataSet("New_DataSet");
DataTable dt = new DataTable("New_DataTable");

//Set the locale for each
ds.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;
dt.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;

//Open a DB connection (in this example with OleDB)
OleDbConnection con = new OleDbConnection(dbConnectionString);
con.Open();

//Create a query and fill the data table with the data from the DB
string sql = "SELECT Whatever FROM MyDBTable;";
OleDbCommand cmd = new OleDbCommand(sql, con);
OleDbDataAdapter adptr = new OleDbDataAdapter();

adptr.SelectCommand = cmd;
adptr.Fill(dt);
con.Close();

//Add the table to the data set
ds.Tables.Add(dt);

//Here's the easy part. Create the Excel worksheet from the data set
ExcelLibrary.DataSetHelper.CreateWorkbook("MyExcelFile.xls", ds);

La création du fichier Excel est aussi simple que cela. Vous pouvez également créer manuellement des fichiers Excel, mais la fonctionnalité ci-dessus m'a vraiment impressionné.

Mike Webb
la source
247
ExcelLibrary a été remplacé par l'exceptionnel EPPlus - epplus.codeplex.com . Jan le met à jour régulièrement. Je l'ai utilisé et c'est l'un des meilleurs projets open source avec lesquels nous avons travaillé.
Mark A
3
Il convient de noter qu'ExcelLibrary a beaucoup de problèmes de performances lorsqu'il s'agit de grands ensembles de données (plus de 5000 lignes avec beaucoup de colonnes). En train de faire une lourde modification de la base de code au travail afin que nous puissions l'utiliser dans un projet.
rossisdead
EPPlus semble beaucoup moins bogué qu'ExcelLibrary, MAIS il s'agit de GPL et donc seulement d'une solution pour les projets open source.
Seth
6
Qu'en est-il de ClosedXML ? Je pourrai être utile dans vos projets.
Amadeus Sánchez
589

Si vous êtes satisfait du format xlsx, essayez mon projet GitHub, EPPlus . Cela a commencé avec la source d'ExcelPackage, mais aujourd'hui c'est une réécriture totale. Il prend en charge les plages, le style des cellules, les graphiques, les formes, les images, les plages nommées, le filtre automatique et beaucoup d'autres choses.

Jan Källman
la source
77
La licence est désormais LGPL, les notes de version sont disponibles ici: epplus.codeplex.com/releases/view/79802
Simon D
13
Les exemples étaient utiles. J'ai pu changer mon code en utilisant la bibliothèque Microsoft Interop (horriblement lente) en cette bibliothèque (version 4.x) en quelques heures. Mon benchmark écrit un fichier avec deux onglets et environ 750 000 cellules. En utilisant MS Interop, cela a pris 13 minutes. En utilisant EPPlus, cela a pris 10 secondes, une accélération d'environ 80x. Très heureux!
Paul Chernoch
3
Pour plus de clarté dans ce fil, la LGPL permet de relier le logiciel sans que la partie infectieuse de la GPL ne se produise. Vous avez seulement besoin d'ouvrir les modifications que vous apportez à ClosedXml ou si vous placez directement le code source (au lieu de référencer les assemblys ClosedXml) à l'intérieur de votre application, vous devez ouvrir votre application.
Chris Marisic
4
@Paul Chernoch: Nous remplissons très rapidement les grandes feuilles Excel avec interop. Le secret est de faire une mise à jour groupée. Créez un objet [,] bloc, remplissez-le, puis écrivez cette matrice dans Excel à la fois: excelWorksheet.get_Range (range) .Value2 = block;
Marc Meketon
2
Il semble que la licence passe de LGPL à la licence Polyform Noncommercial 1.0.0
Luke
175

Et qu'en est-il de l'utilisation d'Open XML SDK 2.0 pour Microsoft Office?

Quelques avantages:

  • Ne nécessite pas l'installation d'Office
  • Fabriqué par Microsoft = documentation MSDN décente
  • Une seule DLL .Net à utiliser dans le projet
  • Le SDK est livré avec de nombreux outils comme diff, validateur, etc.

Liens:

Sogger
la source
3
Il est important de noter que la DLL pour cela est un peu plus de 5 Mo et limitée aux formats Office 2007. Mais certainement la solution la plus simple et la plus rapide qui fonctionne pour moi.
Josh Brown
18
Juste un avertissement que la v2.5 est sortie et peut être téléchargée ici .
Snuffleupagus
10
Le SDK modélise le XML en classes, de sorte que chaque balise XML est mappée à une balise, puis vous devez créer correctement la hiérarchie des classes (chaque instance a une collection d'instances / balises enfants). Cela signifie que vous devez connaître la structure XML d'un fichier Excel, ce qui est très compliqué. Il est beaucoup plus facile d'utiliser un wrapper tel que EPPlus, mentionné ci-dessus, ce qui simplifie les choses.
Tsahi Asher
2
Un excellent échantillon de Microsoft Open XML SDK - Open XML Writer peut être trouvé sur polymathprogrammer.com/2012/08/06/… Ou voir la solution Stack Overflow stackoverflow.com/questions/11370672/…
Greg
4
J'ai trouvé que l'Open XML Writer de Microsoft Open XML SDK était génial. En utilisant les solutions ci-dessus, (en particulier l'exemple de Vincent Tom (Poly Math)), il est facile de créer un écrivain qui diffuse à travers de grands ensembles de données et écrit des enregistrements d'une manière similaire et pas trop complexe à ce que vous feriez pour CSV; mais que vous écrivez plutôt du xml. Open XML est l'état d'esprit dans lequel Microsoft considère qu'il s'agit de nouveaux formats Office. Et vous pouvez toujours les renommer des fichiers .xslx en .zip si vous avez envie de fouiller dans leur contenu XML.
Greg
167

J'ai utilisé avec succès les projets open source suivants:

  • ExcelPackage pour les formats OOXML (Office 2007)

  • NPOI pour le format .XLS (Office 2003). NPOI 2.0 (Beta) prend également en charge XLSX.

Jetez un œil à mes articles de blog:

Création de feuilles de calcul Excel .XLS et .XLSX en C #

NPOI avec tableau Excel et graphique dynamique

Leniel Maccaferri
la source
6
Une note sur NPOI - Les références de ligne et de colonne sont basées sur zéro. Fonctionne bien pour remplir un modèle existant.
John M
108

Vous pouvez utiliser OLEDB pour créer et manipuler des fichiers Excel. Vérifiez ceci: lire et écrire Excel en utilisant OLEDB .

Exemple typique:

using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\temp\\test.xls;Extended Properties='Excel 8.0;HDR=Yes'"))
{
  conn.Open();
  OleDbCommand cmd = new OleDbCommand("CREATE TABLE [Sheet1] ([Column1] string, [Column2] string)", conn);
  cmd.ExecuteNonQuery();
}

EDIT - Quelques liens supplémentaires:

Panos
la source
4
Quelqu'un peut-il confirmer si cela fonctionne lors de l'exécution en x64? Je suis sûr que Jet ne fonctionne que si votre application est compilée ou s'exécute en mode 32 bits.
Lamar
2
Je viens de tester cette connexion et elle a échoué sur un Windows Server 2008 R2 x64 RC, il semble qu'il faille installer le pilote Office System 2007: Composants de connectivité des données [ microsoft.com/downloads/…
Chris Richner
25
Soyez très prudent avec cela - c'est un gros fléau laid (par exemple, il devine parfois un type de colonne et rejette toutes les données qui ne correspondent pas).
dbkk
9
Il faut être très prudent si vous utilisez cette méthode. Je l'ai trouvé très floconneux pour des données qui ne sont pas dans un format parfait.
Kenny Mann
9
En tant que personne qui a dû utiliser OleDb dans un grand projet, je dis de rester loin de lui! Il est parfois impossible de récupérer une valeur de cellule simplement parce qu'il ne pouvait pas comprendre le format. Il n'a pas d'opération de suppression. Il fonctionne de manière totalement différente et imprévisible, même avec le moindre changement de fournisseur. Je dirais optez pour une solution commerciale éprouvée.
Caner Öncü
80

La solution commerciale, SpreadsheetGear for .NET, le fera.

Vous pouvez voir des exemples ASP.NET (C # et VB) en direct ici et télécharger une version d'évaluation ici .

Avertissement: je possède SpreadsheetGear LLC

Joe Erickson
la source
10
Vous avez un excellent produit, mais je pense que beaucoup de gens ici attendent des solutions gratuites. Cela pourrait expliquer les votes négatifs.
md1337
65

Quelques options que j'ai utilisées:

Si XLSX est un must: ExcelPackage est un bon début mais s'est éteint lorsque le développeur a cessé de travailler dessus. ExML a repris à partir de là et a ajouté quelques fonctionnalités. ExML n'est pas une mauvaise option, je l'utilise toujours sur quelques sites de production.

Cependant, pour tous mes nouveaux projets, j'utilise NPOI , le port .NET d' Apache POI . NPOI 2.0 (Alpha) prend également en charge XLSX.

Nate
la source
Soyez prudent avec ExcelPackage si vous devez prendre en charge XLS. J'ai eu du mal avec et j'ai finalement opté pour ExcelLibrary.
Jeremy
Définitivement vrai. ExcelPackage / ExML n'est une bonne option que si vous avez besoin du support XLSX.
Nate
5
Notez qu'ExcelPackage a un successeur: EPPlus ( epplus.codeplex.com ) qui prend en charge XLSX. Ma seule préoccupation, par rapport à NPOI par exemple, est la performance, par exemple quand il y a beaucoup de colonnes.
Pragmateek
63

Une option extrêmement légère peut être d'utiliser des tableaux HTML. Créez simplement des balises head, body et table dans un fichier et enregistrez-le en tant que fichier avec une extension .xls. Il existe des attributs spécifiques à Microsoft que vous pouvez utiliser pour styliser la sortie, y compris les formules.

Je me rends compte que vous ne codez peut-être pas cela dans une application Web, mais voici un exemple de la composition d'un fichier Excel via un tableau HTML. Cette technique peut être utilisée si vous codez une application console, une application de bureau ou un service.

virgule oublié
la source
6
C'est tellement ad hoc mais ça marche (sans parler d'Excel émettant un avertissement à l'ouverture) et c'est si simple, ça mérite d'avoir une place comme solution. Mais seulement pour montrer que vous pouvez exporter un fichier Excel :))
Luka Ramishvili
3
Cette solution a bien fonctionné pour moi, notez simplement que vous ne pouvez pas utiliser l'extension .xlsx
Jill
Certaines personnes de mon organisation ne peuvent pas ouvrir les fichiers Excel créés de cette manière dans Office 2010 et versions ultérieures. Je ne sais pas quel est le problème, mais j'ai dû rouler ma propre implémentation OpenXML. (voir la réponse de Sogger)
Kristen Hammack
49

Si vous créez des fichiers Excel 2007/2010, essayez ce projet open source: https://github.com/closedxml/closedxml

Il fournit un moyen orienté objet de manipuler les fichiers (similaire à VBA) sans faire face aux tracas des documents XML. Il peut être utilisé par n'importe quel langage .NET comme C # et Visual Basic (VB).

ClosedXML vous permet de créer des fichiers Excel 2007/2010 sans l'application Excel. L'exemple typique est la création de rapports Excel sur un serveur Web:

var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sample Sheet");
worksheet.Cell("A1").Value = "Hello World!";
workbook.SaveAs("HelloWorld.xlsx");
Armfoot
la source
9
J'ai essayé de l'utiliser dans un projet qui crée de très grandes feuilles Excel. Excellente bibliothèque, mais extrêmement médiocre en performances. Je viens de faire une comparaison pour le projet sur lequel je travaille: ClosedXML (v 0.53.3) a pris 92 489 ms tandis que EPPlus (v 2.9.03, pour les tests - nous ne pouvons pas l'utiliser parce que c'est la GPL) a pris 16 500 ms.
Druide
1
@Druid la licence est LGPL en supposant que vous ne modifiez pas le code source en ClosedXML, il est libre d'utiliser epplus.codeplex.com/license
Chris Marisic
48

Vous pouvez utiliser ExcelXmlWriter .

Ça fonctionne bien.

Petr Snobelt
la source
47

En fait, vous voudrez peut-être vérifier les classes d'interopérabilité disponibles en C # (par exemple Microsoft.Office.Interop.Excel. Vous dites non OLE (ce qui n'est pas le cas), mais les classes d'interopérabilité sont très faciles à utiliser. Consultez la documentation C # ici (Interop pour Excel commence le page 1072 du C # PDF).

Vous pourriez être impressionné si vous ne les avez pas essayés.

Veuillez être averti de la position de Microsoft à ce sujet:

Microsoft ne recommande pas actuellement et ne prend pas en charge l'automatisation des applications Microsoft Office à partir de toute application ou composant client sans assistance non interactif (y compris les services ASP, ASP.NET, DCOM et NT), car Office peut présenter un comportement instable et / ou blocage lorsque Office est exécuté dans cet environnement.

GEOCHET
la source
6
Mais vous devez vous assurer de disposer de tout manuellement, sinon vous
perdrez de la
8
@Ricky B: De plus, d'après mon expérience avec l'interopérabilité, il utilise Excel. Chaque fois que nous l'utilisions, si Excel n'était pas installé sur la machine, nous recevions des exceptions COM.
MagicKat
1
Avec l'OLE, même avec des mises au rebut très prudentes, il finit par fuir la mémoire ou se bloquer. C'est sans doute OK pour les applications / postes de travail assistés, mais pour les serveurs n'est pas recommandé (MS a un KB le déclarant). Pour notre serveur, nous le redémarrons tous les soirs. Encore une fois, cela fonctionne bien.
Jennifer Zouak
11
@Geoffrey: ah OK, vous allez me faire travailler pour ça :) -> support.microsoft.com/kb/257757 Microsoft ne recommande pas actuellement, et ne prend pas en charge, l'automatisation des applications Microsoft Office à partir de toute application non surveillée, non application client interactive ...
Jennifer Zouak
4
J'arrive à cette discussion après avoir lutté plus d'une semaine sur l'interopérabilité, et à moins que vos besoins ne soient très simples, cela ne fonctionnera pas. La prise en charge de la mise en forme de votre feuille de calcul est épouvantable, ce qui est sans doute la raison de la génération d'un fichier .xls et pas seulement d'un fichier plat .csv. Par exemple, avez-vous essayé de sortir plus de 911 caractères dans une cellule, ou avez-vous essayé de définir la largeur des cellules fusionnées de manière cohérente? Je l'ai, et je ne peux pas vous dire à quel point je déteste cette merde maintenant ... Rendez-vous service et allez avec l'une des bibliothèques gratuites mentionnées dans cette discussion.
md1337
34

Voici une bibliothèque entièrement gratuit C #, ce qui vous permet d' exporter à partir d' un DataSet, DataTableou List<>un véritable Excel 2007 .xlsx, en utilisant les bibliothèques OpenXML:

http://mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm

Le code source complet est fourni - gratuitement - avec des instructions et une application de démonstration.

Après avoir ajouté cette classe à votre application, vous pouvez exporter votre DataSet vers Excel en une seule ligne de code:

CreateExcelFile.CreateExcelDocument(myDataSet, "C:\\Sample.xlsx");

Ce n'est pas beaucoup plus simple que ça ...

Et il ne nécessite même pas la présence d'Excel sur votre serveur.

Mike Gledhill
la source
1
Cela semble un peu trompeur, car vous demandez un don pour obtenir toutes les fonctionnalités.
UrbanEsc
C'est en partie vrai: la version entièrement gratuite générera un fichier .xlsx parfait pour vous, et tout le code source est fourni. Si vous donnez 10 $ ou plus à l'un de ces deux organismes de bienfaisance (dont je ne reçois absolument rien), vous obtenez une "meilleure" version montrant comment faire le formatage, les dates, etc. Compte tenu du coût des produits tiers, je pense donner 10 $ à une bonne cause en vaut la peine!
Mike Gledhill
23

Vous voudrez peut-être jeter un œil à GemBox. .

Ils ont une version gratuite avec toutes les fonctionnalités mais limitée à 150 lignes par feuille et 5 feuilles par classeur, si cela correspond à vos besoins.

Je n'ai pas encore eu besoin de l'utiliser moi-même, mais cela semble intéressant.

ManiacZX
la source
21

Syncfusion Essential XlsIO peut le faire. Il ne dépend pas de Microsoft Office et prend également en charge spécifiquement différentes plates-formes.

Échantillon de code:

//Creates a new instance for ExcelEngine.
ExcelEngine excelEngine = new ExcelEngine();
//Loads or open an existing workbook through Open method of IWorkbooks
IWorkbook workbook = excelEngine.Excel.Workbooks.Open(fileName);
//To-Do some manipulation|
//To-Do some manipulation
//Set the version of the workbook.
workbook.Version = ExcelVersion.Excel2013;
//Save the workbook in file system as xlsx format
workbook.SaveAs(outputFileName);

Toute la suite de contrôles est disponible gratuitement via le programme de licence communautaire si vous êtes éligible (moins de 1 million USD de revenus). Remarque: je travaille pour Syncfusion.

Davis Jebaraj
la source
18

Bien,

vous pouvez également utiliser une bibliothèque tierce comme Aspose .

Cette bibliothèque a l'avantage de ne pas nécessiter l'installation d'Excel sur votre machine, ce qui serait idéal dans votre cas.

Dimi Toulakis
la source
Pour être plus précis, vous pouvez utiliser Aspose.Cells pour .NET afin de créer des fichiers Excel (XLS, XLSX) dans votre application .NET.
Shahzad Latif
9
Oui, si cela ne vous dérange pas de payer des frais de licence minimum de 999 $. Essayez la bibliothèque MikesKnowledgeBase ... qui est 999 $ moins cher que ça !!
Mike Gledhill
17

OpenXML est également une bonne alternative qui permet d'éviter l'installation de MS Excel sur le serveur.Le SDK Open XML 2.0 fourni par Microsoft simplifie la tâche de manipulation des packages Open XML et des éléments de schéma Open XML sous-jacents dans un package. L'interface de programmation d'application (XML) Open XML encapsule de nombreuses tâches courantes que les développeurs effectuent sur des packages Open XML.

Découvrez OpenXML: Alternative qui évite d'installer MS Excel sur le serveur

Sachin Dhir
la source
17

Les diverses bibliothèques XML Office 2003 disponibles fonctionnent assez bien pour les petits fichiers Excel. Cependant, je trouve que la taille d'un grand classeur enregistré au format XML pose problème. Par exemple, un classeur avec lequel je travaille qui serait de 40 Mo dans le nouveau format XLSX (et il est vrai qu'il est plus compact) devient un fichier XML de 360 ​​Mo.

Pour autant que mes recherches m'ont mené, il existe deux packages commerciaux qui permettent la sortie vers les anciens formats de fichiers binaires. Elles sont:

Ni sont bon marché (500USD et 800USD respectivement, je pense). mais les deux fonctionnent indépendamment d'Excel lui-même.

Ce que je serais curieux de savoir, c'est le module de sortie Excel pour OpenOffice.org. Je me demande s'ils peuvent être portés de Java vers .Net.

biozinc
la source
Celui-ci fonctionne à la fois sur .net et java, et n'est pas cher. SmartXLS smartxls.com
liya
15

J'ai récemment utilisé FlexCel.NET et l' ai trouvé comme une excellente bibliothèque! Je ne dis pas cela à propos de trop de produits logiciels. Inutile de donner l'intégralité de l'argumentaire de vente ici, vous pouvez lire toutes les fonctionnalités sur leur site Web.

C'est un produit commercial, mais vous obtenez la source complète si vous l'achetez. Je suppose donc que vous pourriez le compiler dans votre assemblage si vous le vouliez vraiment. Sinon, c'est juste un assemblage supplémentaire pour xcopy - pas de configuration ou d'installation ou quelque chose comme ça.

Je ne pense pas que vous trouverez un moyen de le faire sans les bibliothèques tierces car le framework .NET, évidemment, n'a pas de support intégré pour cela et OLE Automation est juste un monde de difficultés.

EMP
la source
15

J'ai écrit un code simple pour exporter un ensemble de données vers Excel sans utiliser d'objet Excel en utilisant System.IO.StreamWriter.

Vous trouverez ci-dessous le code qui lira toutes les tables de l'ensemble de données et les écrira les feuilles une par une. J'ai pris l'aide de cet article .

public static void exportToExcel(DataSet source, string fileName)
{
        const string endExcelXML = "</Workbook>";
        const string startExcelXML = "<xml version>\r\n<Workbook " +
                 "xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n" +
                 " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n " +
                 "xmlns:x=\"urn:schemas-    microsoft-com:office:" +
                 "excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:" +
                 "office:spreadsheet\">\r\n <Styles>\r\n " +
                 "<Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n " +
                 "<Alignment ss:Vertical=\"Bottom\"/>\r\n <Borders/>" +
                 "\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>" +
                 "\r\n <Protection/>\r\n </Style>\r\n " +
                 "<Style ss:ID=\"BoldColumn\">\r\n <Font " +
                 "x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n " +
                 "<Style     ss:ID=\"StringLiteral\">\r\n <NumberFormat" +
                 " ss:Format=\"@\"/>\r\n </Style>\r\n <Style " +
                 "ss:ID=\"Decimal\">\r\n <NumberFormat " +
                 "ss:Format=\"0.0000\"/>\r\n </Style>\r\n " +
                 "<Style ss:ID=\"Integer\">\r\n <NumberFormat " +
                 "ss:Format=\"0\"/>\r\n </Style>\r\n <Style " +
                 "ss:ID=\"DateLiteral\">\r\n <NumberFormat " +
                 "ss:Format=\"mm/dd/yyyy;@\"/>\r\n </Style>\r\n " +
                 "</Styles>\r\n ";
        System.IO.StreamWriter excelDoc = null;
        excelDoc = new System.IO.StreamWriter(fileName);

        int sheetCount = 1;
        excelDoc.Write(startExcelXML);
        foreach (DataTable table in source.Tables)
        {
            int rowCount = 0;
            excelDoc.Write("<Worksheet ss:Name=\"" + table.TableName + "\">");
            excelDoc.Write("<Table>");
            excelDoc.Write("<Row>");
            for (int x = 0; x < table.Columns.Count; x++)
            {
                excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
                excelDoc.Write(table.Columns[x].ColumnName);
                excelDoc.Write("</Data></Cell>");
            }
            excelDoc.Write("</Row>");
            foreach (DataRow x in table.Rows)
            {
                rowCount++;
                //if the number of rows is > 64000 create a new page to continue output
                if (rowCount == 64000)
                {
                    rowCount = 0;
                    sheetCount++;
                    excelDoc.Write("</Table>");
                    excelDoc.Write(" </Worksheet>");
                    excelDoc.Write("<Worksheet ss:Name=\"" + table.TableName + "\">");
                    excelDoc.Write("<Table>");
                }
                excelDoc.Write("<Row>"); //ID=" + rowCount + "
                for (int y = 0; y < table.Columns.Count; y++)
                {
                    System.Type rowType;
                    rowType = x[y].GetType();
                    switch (rowType.ToString())
                    {
                        case "System.String":
                            string XMLstring = x[y].ToString();
                            XMLstring = XMLstring.Trim();
                            XMLstring = XMLstring.Replace("&", "&");
                            XMLstring = XMLstring.Replace(">", ">");
                            XMLstring = XMLstring.Replace("<", "<");
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                           "<Data ss:Type=\"String\">");
                            excelDoc.Write(XMLstring);
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.DateTime":
                            //Excel has a specific Date Format of YYYY-MM-DD followed by  
                            //the letter 'T' then hh:mm:sss.lll Example 2005-01-31T24:01:21.000
                            //The Following Code puts the date stored in XMLDate 
                            //to the format above
                            DateTime XMLDate = (DateTime)x[y];
                            string XMLDatetoString = ""; //Excel Converted Date
                            XMLDatetoString = XMLDate.Year.ToString() +
                                 "-" +
                                 (XMLDate.Month < 10 ? "0" +
                                 XMLDate.Month.ToString() : XMLDate.Month.ToString()) +
                                 "-" +
                                 (XMLDate.Day < 10 ? "0" +
                                 XMLDate.Day.ToString() : XMLDate.Day.ToString()) +
                                 "T" +
                                 (XMLDate.Hour < 10 ? "0" +
                                 XMLDate.Hour.ToString() : XMLDate.Hour.ToString()) +
                                 ":" +
                                 (XMLDate.Minute < 10 ? "0" +
                                 XMLDate.Minute.ToString() : XMLDate.Minute.ToString()) +
                                 ":" +
                                 (XMLDate.Second < 10 ? "0" +
                                 XMLDate.Second.ToString() : XMLDate.Second.ToString()) +
                                 ".000";
                            excelDoc.Write("<Cell ss:StyleID=\"DateLiteral\">" +
                                         "<Data ss:Type=\"DateTime\">");
                            excelDoc.Write(XMLDatetoString);
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Boolean":
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                        "<Data ss:Type=\"String\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Int16":
                        case "System.Int32":
                        case "System.Int64":
                        case "System.Byte":
                            excelDoc.Write("<Cell ss:StyleID=\"Integer\">" +
                                    "<Data ss:Type=\"Number\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Decimal":
                        case "System.Double":
                            excelDoc.Write("<Cell ss:StyleID=\"Decimal\">" +
                                  "<Data ss:Type=\"Number\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.DBNull":
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                  "<Data ss:Type=\"String\">");
                            excelDoc.Write("");
                            excelDoc.Write("</Data></Cell>");
                            break;
                        default:
                            throw (new Exception(rowType.ToString() + " not handled."));
                    }
                }
                excelDoc.Write("</Row>");
            }
            excelDoc.Write("</Table>");
            excelDoc.Write(" </Worksheet>");
            sheetCount++;
        }


        excelDoc.Write(endExcelXML);
        excelDoc.Close();
    }
Harsha.Vaswani
la source
1
Comme le dit l'article, c'est du XML qu'Excel lira plutôt que d'être réellement un fichier XLS, ce qui signifie qu'il ne fonctionnera que dans Excel et pas dans d'autres programmes qui lisent des feuilles de calcul. Mais c'est probablement mieux que les réponses des tableaux HTML équivalents ici!
Rup
Prend en charge xlsx ? OpenXML ?
Kiquenet
14

Je veux juste ajouter une autre référence à une solution tierce qui résout directement votre problème: http://www.officewriter.com

(Avertissement: je travaille pour SoftArtisans, la société qui fabrique OfficeWriter)

Eisbaer
la source
12

Voici un moyen de le faire avec LINQ to XML, avec un exemple de code:

Importez et exportez rapidement des données Excel avec LINQ to XML

C'est un peu complexe, car vous devez importer des espaces de noms, etc., mais cela vous permet d'éviter toute dépendance externe.

(De plus, bien sûr, c'est VB .NET, pas C #, mais vous pouvez toujours isoler le truc VB .NET dans son propre projet pour utiliser les littéraux XML, et faire tout le reste en C #.)

Kyralessa
la source
12

Certains fournisseurs de composants tiers comme Infragistics ou Syncfusion offrent de très bonnes capacités d'exportation Excel qui ne nécessitent pas l'installation de Microsoft Excel.

Étant donné que ces fournisseurs fournissent également des composants de grille d'interface utilisateur avancés, ces composants sont particulièrement utiles si vous souhaitez que le style et la disposition d'une exportation Excel imitent l'état actuel d'une grille dans l'interface utilisateur de votre application.

Si votre exportation est destinée à être exécutée côté serveur en mettant l'accent sur les données à exporter et sans lien avec l'interface utilisateur, je choisirais l'une des options open source gratuites (par exemple ExcelLibrary).

J'ai déjà participé à des projets qui tentaient d'utiliser l'automatisation côté serveur sur la suite Microsoft Office. Sur la base de cette expérience, je déconseille fortement cette approche.

Simen S
la source
12
public class GridViewExportUtil
{
    public static void Export(string fileName, GridView gv)
    {
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.AddHeader(
            "content-disposition", string.Format("attachment; filename={0}", fileName));
        HttpContext.Current.Response.ContentType = "application/ms-excel";

        using (StringWriter sw = new StringWriter())
        {
            using (HtmlTextWriter htw = new HtmlTextWriter(sw))
            {
                //  Create a form to contain the grid
                Table table = new Table();

                //  add the header row to the table
                if (gv.HeaderRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.HeaderRow);
                    table.Rows.Add(gv.HeaderRow);
                }

                //  add each of the data rows to the table
                foreach (GridViewRow row in gv.Rows)
                {
                    GridViewExportUtil.PrepareControlForExport(row);
                    table.Rows.Add(row);
                }

                //  add the footer row to the table
                if (gv.FooterRow != null)
                {
                    GridViewExportUtil.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());
                HttpContext.Current.Response.End();
            }
        }
    }

    /// <summary>
    /// Replace any of the contained controls with literals
    /// </summary>
    /// <param name="control"></param>
    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())
            {
                GridViewExportUtil.PrepareControlForExport(current);
            }
        }
    }
}

Salut, cette solution consiste à exporter votre vue de grille vers votre fichier Excel, cela pourrait vous aider

Gaurav
la source
7
Non, cela génère du HTML marqué comme un fichier Excel plutôt que comme un vrai fichier Excel. Oui, Excel lui-même ouvrira cela, mais d'autres programmes qui utilisent des feuilles de calcul - y compris la visionneuse Excel gratuite de Microsoft, par exemple - ne l'accepteront pas. Vous feriez mieux de créer un vrai fichier Excel en utilisant l'une des bibliothèques ici.
Rup
Vous devez également utiliser System.Net.Mime.ContentDisposition pour générer le texte d'en-tête de disposition de contenu plutôt qu'une chaîne ajoutée - qui s'adaptera correctement aux noms de fichiers contenant des espaces, etc.
Rup
12

Vous pouvez créer des fichiers Excel bien formatés à l'aide de cette bibliothèque: http://officehelper.codeplex.com/documentation
Voir l'exemple ci-dessous:

using (ExcelHelper helper = new ExcelHelper(TEMPLATE_FILE_NAME, GENERATED_FILE_NAME))
{
    helper.Direction = ExcelHelper.DirectionType.TOP_TO_DOWN;
    helper.CurrentSheetName = "Sheet1";
    helper.CurrentPosition = new CellRef("C3");

    //the template xlsx should contains the named range "header"; use the command "insert"/"name".
    helper.InsertRange("header");

    //the template xlsx should contains the named range "sample1";
    //inside this range you should have cells with these values:
    //<name> , <value> and <comment>, which will be replaced by the values from the getSample()
    CellRangeTemplate sample1 = helper.CreateCellRangeTemplate("sample1", new List<string> {"name", "value", "comment"}); 
    helper.InsertRange(sample1, getSample());

    //you could use here other named ranges to insert new cells and call InsertRange as many times you want, 
    //it will be copied one after another;
    //even you can change direction or the current cell/sheet before you insert

    //typically you put all your "template ranges" (the names) on the same sheet and then you just delete it
    helper.DeleteSheet("Sheet3");
}        

où l'échantillon ressemble à ceci:

private IEnumerable<List<object>> getSample()
{
    var random = new Random();

    for (int loop = 0; loop < 3000; loop++)
    {
        yield return new List<object> {"test", DateTime.Now.AddDays(random.NextDouble()*100 - 50), loop};
    }
}
inconnu
la source
10

Le moyen le plus simple et le plus rapide pour créer un fichier Excel à partir de C # est d'utiliser l'Outil de productivité Open XML. L'outil de productivité Open XML est fourni avec l'installation du kit SDK Open XML. L'outil inverse l'ingénierie de tout fichier Excel en code C #. Le code C # peut ensuite être utilisé pour recréer ce fichier.

Un aperçu du processus impliqué est:

  1. Installez le SDK Open XML avec l'outil.
  2. Créez un fichier Excel en utilisant le dernier client Excel avec l'apparence souhaitée. Nommez-le DesiredLook.xlsx.
  3. Avec l'outil ouvert DesiredLook.xlsxet cliquez sur le bouton Reflect Code en haut. entrez la description de l'image ici
  4. Le code C # de votre fichier sera généré dans le volet droit de l'outil. Ajoutez-le à votre solution C # et générez des fichiers avec l'apparence souhaitée.

En prime, cette méthode fonctionne pour tous les fichiers Word et PowerPoint. En tant que développeur C #, vous apporterez ensuite des modifications au code pour répondre à vos besoins.

J'ai développé une application WPF simple sur github qui fonctionnera sur Windows à cet effet. Il existe une classe d'espace réservé appelée GeneratedClassoù vous pouvez coller le code généré. Si vous revenez en arrière une version du fichier, il générera un fichier Excel comme ceci:

entrez la description de l'image ici

Taterhead
la source
1
Je n'ai pas encore essayé cette solution Open XML SDK mais Wow, je vais certainement la vérifier. Je travaille avec des outils comme celui-ci depuis de nombreuses années et je ne connaissais pas celui-ci. J'ai publié mon propre simples logiciels libres pour convertir des fichiers XLSX avec .NET: github.com/TonyGravagno/NebulaXConvert
TonyG