Lecture de fichiers Excel à partir de C #


233

Existe-t-il une bibliothèque gratuite ou open source pour lire les fichiers Excel (.xls) directement à partir d'un programme C #?

Il n'a pas besoin d'être trop sophistiqué, il suffit de sélectionner une feuille de calcul et de lire les données sous forme de chaînes. Jusqu'à présent, j'ai utilisé la fonction de texte Exporter vers Unicode d'Excel et analysé le fichier résultant (délimité par des tabulations), mais j'aimerais éliminer l'étape manuelle.

Réponses:


153
var fileName = string.Format("{0}\\fileNameHere", Directory.GetCurrentDirectory());
var connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=Excel 8.0;", fileName);

var adapter = new OleDbDataAdapter("SELECT * FROM [workSheetNameHere$]", connectionString);
var ds = new DataSet();

adapter.Fill(ds, "anyNameHere");

DataTable data = ds.Tables["anyNameHere"];

C'est ce que j'utilise habituellement. C'est un peu différent car je colle habituellement un AsEnumerable () lors de l'édition des tables:

var data = ds.Tables["anyNameHere"].AsEnumerable();

car cela me permet d'utiliser LINQ pour rechercher et construire des structures à partir des champs.

var query = data.Where(x => x.Field<string>("phoneNumber") != string.Empty).Select(x =>
                new MyContact
                    {
                        firstName= x.Field<string>("First Name"),
                        lastName = x.Field<string>("Last Name"),
                        phoneNumber =x.Field<string>("Phone Number"),
                    });

Si semble que le Select dans cette approche essaie de deviner le type de données de la colonne et de forcer sur ce type de données deviné. Par exemple, si vous avez une colonne avec principalement des valeurs doubles, cela ne vous plaira pas de passer x.Field <chaîne>, mais attend x.Field <double>. Est-ce vrai?
Kevin Le - Khnle

1
Je viens de le rechercher sur MSDN. On dirait que le <T> est juste utilisé pour tenter de convertir le contenu de la colonne en un type. Dans cet exemple, et simplement en convertissant les données des colonnes en chaînes. Si vous vouliez un double, vous devez appeler double.Parse (x.Field <string> ("Cost") ou quelque chose comme ça. Le champ est une méthode d'extension pour DataRow et il semble qu'il n'y ait pas de versions non génériques.
Robin Robinson

L'ajout d'un double.Parse à la requête Linq le ralentit-il beaucoup?
Type anonyme

23
Notez que si vous lisez xlsx, vous devez utiliser cette chaîne de connexion à la place:string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName)
Andreas Grech

7
Malheureusement, le pilote Jet.OLEDB n'est pas compatible 64 bits; vous devrez passer à la cible x86 plutôt qu'à N'importe quel CPU (si vous voulez continuer avec cette méthode). Vous pouvez également installer le pilote ACE 64 bits et modifier la chaîne de connexion pour utiliser ce pilote (comme indiqué par Andreas) - microsoft.com/en-us/download/…
Duncan

83

S'il ne s'agit que de données simples contenues dans le fichier Excel, vous pouvez lire les données via ADO.NET. Voir les chaînes de connexion répertoriées ici:

http://www.connectionstrings.com/?carrier=excel2007 ou http://www.connectionstrings.com/?carrier=excel

-Ryan

Mise à jour: alors vous pouvez simplement lire la feuille de calcul via quelque chose comme select * from [Sheet1$]


1
Cette voie est de loin la plus rapide.
StingyJack

17
Bien sûr, ce n'est pas vrai, Stingy. Vous devez passer au crible toutes les données et écrire du code DB merdique (fabriquer à la main vos modèles, mapper les colonnes aux propriétés, yadda yadda). Le moyen le plus rapide est de laisser un autre pauvre SOB faire cela pour vous . C'est pourquoi les gens utilisent des frameworks au lieu de tout écrire de bas en haut.

12
Méthode sans valeur! Tronque les colonnes de texte à 255 caractères lors de la lecture. Il faut se méfier! Voir: stackoverflow.com/questions/1519288/… Le moteur ACE fait la même chose!
Triynko

5
Sachez que l'utilisation d'ADO.NET pour lire des données à partir d'Exel nécessite l'installation de Microsoft Access ou du moteur de base de données Microsoft Access Redistributable.
zihotki

3
Le pilote devinera également les types de colonnes en fonction des premières lignes. Si vous avez une colonne avec ce qui ressemble à des entiers dans les premières lignes, vous rencontrerez une erreur lorsque vous frappez un non-entier (par exemple un flottant, une chaîne)
Brian Low

27

L'approche ADO.NET est rapide et facile, mais elle a quelques bizarreries que vous devez connaître, en particulier en ce qui concerne la façon dont les DataTypes sont traités.

Cet excellent article vous aidera à éviter certains pièges courants: http://blog.lab49.com/archives/196


Vous avez répondu à ma question (sous forme de commentaire ci-dessus).
Kevin Le - Khnle

22

Voici ce que j'ai utilisé pour Excel 2003:

Dictionary<string, string> props = new Dictionary<string, string>();
props["Provider"] = "Microsoft.Jet.OLEDB.4.0";
props["Data Source"] = repFile;
props["Extended Properties"] = "Excel 8.0";

StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> prop in props)
{
    sb.Append(prop.Key);
    sb.Append('=');
    sb.Append(prop.Value);
    sb.Append(';');
}
string properties = sb.ToString();

using (OleDbConnection conn = new OleDbConnection(properties))
{
    conn.Open();
    DataSet ds = new DataSet();
    string columns = String.Join(",", columnNames.ToArray());
    using (OleDbDataAdapter da = new OleDbDataAdapter(
        "SELECT " + columns + " FROM [" + worksheet + "$]", conn))
    {
        DataTable dt = new DataTable(tableName);
        da.Fill(dt);
        ds.Tables.Add(dt);
    }
}

2
la feuille de calcul n'est pas définie ... me semble un peu étrange après avoir clairement défini tout le reste.
Jeremy Holovacs

21

Que diriez-vous d'Excel Data Reader?

http://exceldatareader.codeplex.com/

J'y ai utilisé de la colère, dans un environnement de production, pour extraire de grandes quantités de données d'une variété de fichiers Excel dans SQL Server Compact. Cela fonctionne très bien et c'est plutôt robuste.


2
Je seconde le lecteur de données Excel; il a également conduit à la bibliothèque Excel Data Driven Tests, incroyablement utile, qui utilise l'attribut TestCaseSource de NUnit 2.5 pour rendre les tests basés sur les données à l'aide de feuilles de calcul Excel ridiculement faciles. Attention, Resharper ne prend pas encore en charge TestCaseSource, vous devez donc utiliser le runner NUnit.
David Keaveny

Malheureusement, il y a des problèmes avec cette bibliothèque que nous venons de rencontrer. Premièrement, nous avons eu quelques champs de devises qui sortent sous forme de dates. Deuxièmement, il se bloque si le classeur contient des feuilles vides. Donc, bien qu'il ait été très facile à intégrer, nous réévaluons maintenant s'il faut continuer à utiliser cette bibliothèque. Il ne semble pas être activement développé.
Ian1971

Il suppose également la présence de certains éléments facultatifs dans le fichier xlsx qui l'empêchent de lire les données s'ils sont absents.
RichieHindle

Nous rencontrons des problèmes avec les fichiers Excel provenant de SQL Server Reporting Services. Ils ne fonctionnent tout simplement pas, sauf si vous les ouvrez et les enregistrez (même non modifiés). @RichieHindle: de quels éléments optionnels parlez-vous (en espérant que cela pourrait m'aider avec mes fichiers Excel SSRS)?
Peter

@Peter: Je pense que c'était un <dimension>élément manquant <worksheet>qui me causait des problèmes.
RichieHindle

16

Voici du code que j'ai écrit en C # en utilisant .NET 1.1 il y a quelques années. Je ne sais pas si ce serait exactement ce dont vous avez besoin (et ce n'est peut-être pas mon meilleur code :)).

using System;
using System.Data;
using System.Data.OleDb;

namespace ExportExcelToAccess
{
    /// <summary>
    /// Summary description for ExcelHelper.
    /// </summary>
    public sealed class ExcelHelper
    {
        private const string CONNECTION_STRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=<FILENAME>;Extended Properties=\"Excel 8.0;HDR=Yes;\";";

        public static DataTable GetDataTableFromExcelFile(string fullFileName, ref string sheetName)
        {
            OleDbConnection objConnection = new OleDbConnection();
            objConnection = new OleDbConnection(CONNECTION_STRING.Replace("<FILENAME>", fullFileName));
            DataSet dsImport = new DataSet();

            try
            {
                objConnection.Open();

                DataTable dtSchema = objConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

                if( (null == dtSchema) || ( dtSchema.Rows.Count <= 0 ) )
                {
                    //raise exception if needed
                }

                if( (null != sheetName) && (0 != sheetName.Length))
                {
                    if( !CheckIfSheetNameExists(sheetName, dtSchema) )
                    {
                        //raise exception if needed
                    }
                }
                else
                {
                    //Reading the first sheet name from the Excel file.
                    sheetName = dtSchema.Rows[0]["TABLE_NAME"].ToString();
                }

                new OleDbDataAdapter("SELECT * FROM [" + sheetName + "]", objConnection ).Fill(dsImport);
            }
            catch (Exception)
            {
                //raise exception if needed
            }
            finally
            {
                // Clean up.
                if(objConnection != null)
                {
                    objConnection.Close();
                    objConnection.Dispose();
                }
            }


            return dsImport.Tables[0];
            #region Commented code for importing data from CSV file.
            //              string strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +"Data Source=" + System.IO.Path.GetDirectoryName(fullFileName) +";" +"Extended Properties=\"Text;HDR=YES;FMT=Delimited\"";
            //
            //              System.Data.OleDb.OleDbConnection conText = new System.Data.OleDb.OleDbConnection(strConnectionString);
            //              new System.Data.OleDb.OleDbDataAdapter("SELECT * FROM " + System.IO.Path.GetFileName(fullFileName).Replace(".", "#"), conText).Fill(dsImport);
            //              return dsImport.Tables[0];

            #endregion
        }

        /// <summary>
        /// This method checks if the user entered sheetName exists in the Schema Table
        /// </summary>
        /// <param name="sheetName">Sheet name to be verified</param>
        /// <param name="dtSchema">schema table </param>
        private static bool CheckIfSheetNameExists(string sheetName, DataTable dtSchema)
        {
            foreach(DataRow dataRow in dtSchema.Rows)
            {
                if( sheetName == dataRow["TABLE_NAME"].ToString() )
                {
                    return true;
                }   
            }
            return false;
        }
    }
}

Je ne pourrais pas être plus d'accord avec Cherian. Ce code a de nombreuses années ... avant même que je sois compétent avec Resharper :)
hitec

2
Le code est moche, mais il montre comment obtenir les noms des feuilles, super!
Sam



8

J'ai fait beaucoup de lecture à partir de fichiers Excel en C # il y a quelque temps, et nous avons utilisé deux approches:

  • L'API COM, où vous accédez directement aux objets Excel et les manipulez via des méthodes et des propriétés
  • Le pilote ODBC qui permet d'utiliser Excel comme une base de données.

Cette dernière approche était beaucoup plus rapide: la lecture d'un grand tableau de 20 colonnes et 200 lignes prendrait 30 secondes via COM et une demi-seconde via ODBC. Je recommanderais donc l'approche de la base de données si vous n'avez besoin que des données.

À votre santé,

Carl



6

Je veux montrer une méthode simple pour lire le fichier xls / xlsx avec .NET. J'espère que ce qui suit vous sera utile.

 DataTable privé ReadExcelToTable (chemin de chaîne)    
 {

     //Chaîne de connexion

     string connstring = "Provider = Microsoft.ACE.OLEDB.12.0; Data Source =" + path + "; Extended Properties = 'Excel 8.0; HDR = NO; IMEX = 1';";  
     //Le même nom 
     // string connstring = Provider = Microsoft.JET.OLEDB.4.0; Data Source = "+ path + //"; Extended Properties = 'Excel 8.0; HDR = NO; IMEX = 1'; "; 

     en utilisant (OleDbConnection conn = new OleDbConnection (connstring))
     {
        conn.Open ();
        // Obtenir le nom de toutes les feuilles
        DataTable sheetsName = conn.GetOleDbSchemaTable (OleDbSchemaGuid.Tables, nouvel objet [] {null, null, null, "Table"});  

        // Obtenez le nom de la première feuille
        string firstSheetName = sheetsName.Rows [0] [2] .ToString (); 

        //Chaîne de requête 
        string sql = string.Format ("SELECT * FROM [{0}]", firstSheetName); 
        OleDbDataAdapter ada = new OleDbDataAdapter (sql, connstring);
        DataSet set = new DataSet ();
        ada.Fill (set);
        return set.Tables [0];   
   }
 }

Le code provient de l'article: http://www.c-sharpcorner.com/uploadfile/d2dcfc/read-excel-file-with-net/ . Vous pouvez en obtenir plus de détails.


2
Cela a été utile, en particulier la partie sur la lecture des noms de feuille.
martinstoeckli

4

Pas gratuit, mais avec le dernier Office, il y a une très belle API d'automatisation .Net. (il y a une API depuis longtemps mais c'était méchant COM) Vous pouvez faire tout ce que vous voulez / besoin dans le code pendant que l'application Office reste un processus d'arrière-plan caché.


3
@ Type anonyme J'ai lu la question et offrais une alternative utile à une implémentation OSS souhaitée ... parce que, eh bien, j'étais presque sûr qu'il n'y avait rien de disponible. Et, à en juger par la réponse acceptée, l'exigence d'installer Office n'est pas un problème.
xanadont

3

Pardonnez-moi si je suis hors de la base ici, mais n'est-ce pas à cela que servent les PIA Office ?


5
Oui, mais cela impliquerait la création d'une instance Excel.Application, le chargement du fichier xls, etc. Si l'exigence est purement de lire certaines données du fichier, il est beaucoup plus facile et beaucoup plus léger d'utiliser l'une des méthodes ADO.NET décrites dans les autres réponses.
Adam Ralph

Trop lent, en utilisant Office PIA comme ligne de base, tout le reste est plus rapide - même en utilisant simplement un tableau d'objets transmis à partir de la propriété .Value2. Qui utilise toujours le PIA.
Type anonyme

3

Dernièrement, en partie pour améliorer LINQ .... J'ai utilisé l'API d'automatisation d'Excel pour enregistrer le fichier en tant que feuille de calcul XML, puis obtenir le traitement de ce fichier à l'aide de LINQ to XML.


Je soupçonne que vous pouvez le protéger contre Excel, mais pas contre l'homme avec le compilateur ... comme n'importe quoi ... ce ne sont que des octets.
kenny

@gsvirdi, postez une question séparée sur la sécurité des fichiers Excel, cette question porte sur les performances.
Type anonyme


3

SmartXLS est un autre composant de feuille de calcul Excel qui prend en charge la plupart des fonctionnalités des graphiques Excel, des moteurs de formules et peut lire / écrire le format openxml excel2007.



2

Je recommande la bibliothèque FileHelpers qui est une bibliothèque .NET gratuite et facile à utiliser pour importer / exporter des données depuis EXCEL, des enregistrements de longueur fixe ou délimités dans des fichiers, des chaînes ou des flux + Plus.

La section de documentation de la liaison de données Excel http://filehelpers.sourceforge.net/example_exceldatalink.html


1
Je ne vais pas vous décevoir, mais j'ai récemment commencé à utiliser FileHelpers et j'ai été choqué de voir à quel point c'est merdique. Par exemple, la seule façon de mapper des colonnes dans un csv à des propriétés ... excusez-moi, FIELDS, d'un modèle est de créer les champs dans l'ordre des colonnes . Je ne sais pas pour vous, mais je ne compterais pas sur une bizarrerie du compilateur pour l'une des considérations de conception les plus centrales de mon framework f8king.


2

SpreadsheetGear est génial. Oui, c'est une dépense, mais par rapport au bidouillage avec ces autres solutions, cela en vaut le coût. Il est rapide, fiable, très complet et je dois dire qu'après avoir utilisé ce produit dans mon travail de logiciel à temps plein pendant plus d'un an et demi, leur support client est fantastique!


Difficile de justifier quand il existe de nombreuses façons simples et efficaces de lire et d'écrire dans Excel.
Type anonyme

2

La solution que nous avons utilisée devait:

  • Autoriser la lecture / écriture des fichiers produits par Excel
  • Soyez rapide dans les performances (pas comme l'utilisation des COM)
  • Être indépendant de MS Office (devait être utilisable sans que MS Office soit installé)
  • Être libre ou open source (mais activement développé)

Il y a plusieurs choix, mais nous avons trouvé que NPoi (le port .NET du projet open source Poi de Java existant depuis longtemps ) était le meilleur: http://npoi.codeplex.com/

Il permet également de travailler avec les formats de fichiers .doc et .ppt


2

S'il ne s'agit que de données tabulaires. Je recommanderais les assistants de données de fichiers de Marcos Melli qui peuvent être téléchargés ici .



1

vous pouvez écrire une feuille de calcul Excel qui charge une feuille de calcul Excel donnée et l'enregistre en tant que csv (plutôt que de le faire manuellement).

alors vous pouvez automatiser cela à partir de c #.

et une fois qu'il est en csv, le programme c # peut le bloquer.

(aussi, si quelqu'un vous demande de programmer en Excel, il vaut mieux faire comme si vous ne saviez pas comment)

(modifier: ah oui, rob et ryan ont tous les deux raison)



1

Je viens de faire un projet de démonstration rapide qui nécessitait la gestion de certains fichiers Excel. Le composant .NET du logiciel GemBox était adéquat pour mes besoins. Il a une version gratuite avec quelques limitations.

http://www.gemboxsoftware.com/GBSpreadsheet.htm


Pour info: je l'ai essayé et il ne répondait pas à mon besoin de pouvoir lire un fichier crypté.
Chad

1

Excel Package est un composant open source (GPL) pour lire / écrire des fichiers Excel 2007. Je l'ai utilisé sur un petit projet et l'API est simple. Fonctionne uniquement avec XLSX (Excel 200 et), pas avec XLS.

Le code source semble également bien organisé et facile à déplacer (si vous avez besoin d'étendre les fonctionnalités ou de résoudre des problèmes mineurs comme je l'ai fait).

Au début, j'ai essayé l'approche ADO.Net (chaîne de connexion Excel), mais elle était chargée de hacks désagréables - par exemple, si la deuxième ligne contient un nombre, elle renverra des entiers pour tous les champs de la colonne ci-dessous et supprimera silencieusement toutes les données ça ne va pas.


1

Nous utilisons ClosedXML dans des systèmes assez grands.

  • Libre
  • Facile à installer
  • Codage simple
  • Support très réactif
  • L'équipe de développeurs est extrêmement ouverte à de nouvelles suggestions. Souvent, de nouvelles fonctionnalités et corrections de bugs sont mises en œuvre au cours de la même semaine

1

Take.ioLe tableur fera ce travail pour vous, et sans frais. Jetez un oeil à cela .


Ceci est une petite bibliothèque vraiment géniale. Il convertit simplement tout en listes de listes de chaînes, ce qui est très bien pour le type de travail dont j'avais besoin.
Drewmate

0

Je viens d'utiliser ExcelLibrary pour charger une feuille de calcul .xls dans un DataSet. A très bien fonctionné pour moi.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.