Lettura di file Excel da C #


233

Esiste una libreria gratuita o open source per leggere i file Excel (.xls) direttamente da un programma C #?

Non deve essere troppo elaborato, basta selezionare un foglio di lavoro e leggere i dati come stringhe. Finora ho usato la funzione di testo Esporta in Unicode di Excel e ho analizzato il file risultante (delimitato da tabulazioni), ma vorrei eliminare il passaggio manuale.

Risposte:


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

Questo è quello che di solito uso. È un po 'diverso perché di solito applico un AsEnumerable () alla modifica delle tabelle:

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

in quanto ciò mi consente di utilizzare LINQ per cercare e creare strutture dai campi.

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

Se sembra che Seleziona in questo approccio cerchi di indovinare il tipo di dati della colonna e di forzare quel tipo di dati indovinato. Ad esempio, se hai una colonna con valori per lo più doppi, non ti piacerà passare x.Field <stringa>, ma aspetta x.Field <doppio>. È vero?
Kevin Le - Khnle,

1
Ho appena cercato su MSDN. Sembra che <T> sia solo usato per tentare di trasmettere il contenuto della colonna a un tipo. In questo esempio e solo il cast dei dati nelle colonne in stringhe. Se si desidera un doppio, è necessario chiamare double.Parse (x.Field <string> ("Cost") o qualcosa del genere. Il campo è un metodo di estensione per DataRow e sembra che non ci siano versioni non generiche.
Robin Robinson,

L'aggiunta di double.Parse alla query Linq rallenta di molto?
Tipo anonimo

23
Nota che se stai leggendo xlsx, devi usare questa stringa di connessione invece:string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName)
Andreas Grech

7
Purtroppo il driver Jet.OLEDB non è compatibile a 64 bit; dovrai passare al target x86 anziché a qualsiasi CPU (se vuoi ancora procedere con questo metodo). In alternativa, installa il driver ACE a 64 bit e modifica la stringa conn per utilizzare questo driver (come indicato da Andreas) - microsoft.com/en-us/download/…
Duncan

83

Se sono solo semplici dati contenuti nel file Excel, puoi leggere i dati tramite ADO.NET. Vedi le stringhe di connessione elencate qui:

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

-Ryan

Aggiornamento: quindi puoi semplicemente leggere il foglio di lavoro tramite qualcosa di simile select * from [Sheet1$]


1
In questo modo è di gran lunga il più veloce.
StingyJack,

17
Certo che non è vero, Stingy. Devi passare al setaccio tutti i dati e scrivere codice DB scadente (crea i tuoi modelli a mano, mappa colonne su proprietà, yadda yadda). Il modo più veloce è lasciare che altri poveri SOB facciano questo per te . Ecco perché le persone usano i framework invece di scrivere tutto dal basso verso l'alto.

12
Metodo senza valore! Tronca le colonne di testo a 255 caratteri durante la lettura. Attenzione! Vedi: stackoverflow.com/questions/1519288/… Il motore ACE fa la stessa cosa!
Triynko,

5
Tenere presente che l'utilizzo di ADO.NET per leggere i dati da exel richiede l'installazione ridistribuibile del motore di database di Microsoft Access o Microsoft Access.
zihotki,

3
Il driver indovinerà anche i tipi di colonne in base alle prime diverse righe. Se si dispone di una colonna con quelli che sembrano numeri interi nelle prime righe, si verificherà un errore quando si colpisce un non intero (ad esempio un float, una stringa)
Brian Low

27

L'approccio ADO.NET è rapido e semplice, ma presenta alcune stranezze di cui dovresti essere a conoscenza, in particolare per quanto riguarda la gestione dei DataTypes.

Questo eccellente articolo ti aiuterà a evitare alcune insidie ​​comuni: http://blog.lab49.com/archives/196


Hai risposto alla mia domanda (sotto forma di un commento sopra).
Kevin Le - Khnle,

22

Questo è quello che ho usato per 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
il foglio di lavoro non è definito ... mi sembra un po 'strano dopo aver definito chiaramente tutto il resto.
Jeremy Holovacs,

21

Che ne dici di Excel Data Reader?

http://exceldatareader.codeplex.com/

Ci ho usato la rabbia, in un ambiente di produzione, per estrarre grandi quantità di dati da una varietà di file Excel in SQL Server Compact. Funziona molto bene ed è piuttosto robusto.


2
Sarò il secondo lettore di dati Excel; ha anche portato all'utilissima libreria di test basati sui dati di Excel, che utilizza l'attributo TestCaseSource di NUnit 2.5 per rendere i test basati sui dati usando fogli di calcolo Excel incredibilmente facili. Fai attenzione che Resharper non supporta ancora TestCaseSource, quindi devi usare il runner NUnit.
David Keaveny,

Sfortunatamente, ci sono alcuni problemi con questa libreria che abbiamo appena riscontrato. In primo luogo abbiamo avuto alcuni campi di valuta che escono come date. In secondo luogo, si arresta in modo anomalo se la cartella di lavoro contiene fogli vuoti. Quindi, anche se è stato molto facile da integrare, ora stiamo rivalutando se continuare a utilizzare questa libreria. Non sembra essere sviluppato attivamente.
Ian1971,

Presuppone inoltre la presenza di alcuni elementi opzionali nel file xlsx che impediscono la lettura dei dati in caso di assenza.
RichieHindle,

Stiamo riscontrando problemi con i file Excel provenienti da SQL Server Reporting Services. Semplicemente non funzionano, a meno che tu non li apra e li salvi (anche inediti). @RichieHindle: di quali elementi opzionali stai parlando (sperando che questo mi possa aiutare con i miei file SSRS Excel)?
Peter,

@Peter: penso che sia stato un <dimension>elemento mancante a <worksheet>causare problemi per me.
RichieHindle

16

Ecco del codice che ho scritto in C # usando .NET 1.1 qualche anno fa. Non sono sicuro se questo sarebbe esattamente ciò di cui hai bisogno (e potrebbe non essere il mio miglior codice :)).

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

Non potrei essere più d'accordo Cherian. Questo codice ha molti anni ... prima ancora che fossi abile con Resharper :)
hitec

2
Il codice è brutto, ma mostra come ottenere i nomi dei fogli, fantastico!
Sam,



8

Qualche tempo fa ho letto molto dai file Excel in C # e abbiamo usato due approcci:

  • L'API COM, dove si accede direttamente agli oggetti di Excel e li manipola attraverso metodi e proprietà
  • Il driver ODBC che consente di utilizzare Excel come un database.

Quest'ultimo approccio è stato molto più veloce: la lettura di una grande tabella con 20 colonne e 200 righe richiederebbe 30 secondi tramite COM e mezzo secondo tramite ODBC. Quindi consiglierei l'approccio al database se tutto ciò di cui hai bisogno sono i dati.

Saluti,

Carl



6

Voglio mostrare un metodo semplice per leggere il file xls / xlsx con .NET. Spero che quanto segue possa esserti utile.

 Private DataTable ReadExcelToTable (percorso stringa)    
 {

     // Stringa di connessione

     string connstring = "Provider = Microsoft.ACE.OLEDB.12.0; Origine dati =" + percorso + "; Proprietà estese = 'Excel 8.0; HDR = NO; IMEX = 1';";  
     // lo stesso nome 
     // string connstring = Provider = Microsoft.JET.OLEDB.4.0; Origine dati = "+ percorso + //"; Proprietà estese = 'Excel 8.0; HDR = NO; IMEX = 1'; "; 

     using (OleDbConnection conn = new OleDbConnection (connstring))
     {
        conn.Open ();
        // Ottieni nome per tutti i fogli
        DataTableheetName = conn.GetOleDbSchemaTable (OleDbSchemaGuid.Tables, nuovo oggetto [] {null, null, null, "Table"});  

        // Ottieni il nome del primo foglio
        stringa firstSheetName =heetName.Rows [0] [2] .ToString (); 

        //Stringa della domanda 
        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];   
   }
 }

Il codice proviene dall'articolo: http://www.c-sharpcorner.com/uploadfile/d2dcfc/read-excel-file-with-net/ . Puoi ottenere maggiori dettagli da esso.


2
È stato utile, in particolare la parte sulla lettura dei nomi dei fogli.
martinstoeckli,

4

Non gratuito, ma con l'ultima versione di Office c'è un'API .Net di automazione molto bella. (C'è stata un'API per molto tempo ma è stata una brutta COM) Puoi fare tutto ciò che vuoi / hai bisogno nel codice mentre l'app di Office rimane un processo in background nascosto.


3
@ Tipo anonimo Ho letto la domanda e offrivo un'alternativa utile all'implementazione OSS desiderata ... perché, beh, ero abbastanza sicuro che non ci fosse nulla disponibile. E, a giudicare dalla risposta accettata, l'obbligo di installare Office non è un problema.
xanadont,

3

Perdonami se sono fuori base qui, ma non è questo a che cosa servono le PIA di Office ?


5
Sì, ma ciò implicherebbe la creazione di un'istanza Excel.Application, il caricamento del file xls, ecc. Se il requisito è puramente di leggere alcuni dati dal file, è molto più semplice e molto più leggero utilizzare uno dei metodi ADO.NET descritti nelle altre risposte.
Adam Ralph,

Troppo lento, usando la PIA di Office come base, tutto il resto è più veloce, anche solo usando un array Object passato dalla proprietà .Value2. Che sta ancora usando il PIA.
Tipo anonimo

3

Ultimamente, in parte per migliorare su LINQ .... Ho usato l'API di automazione di Excel per salvare il file come foglio di calcolo XML e quindi ottenere il processo utilizzando LINQ to XML.


Sospetto che tu possa proteggerlo da Excel, ma non dall'uomo con il compilatore ... come qualsiasi cosa ... sono solo byte.
Kenny,

@gsvirdi, pubblica una domanda separata sulla sicurezza dei file Excel, questa domanda riguarda le prestazioni.
Tipo anonimo


3

SmartXLS è un altro componente del foglio di calcolo Excel che supporta la maggior parte delle funzionalità di grafici Excel, motori di formule e può leggere / scrivere il formato openxml excel2007.



2

Consiglio la Libreria FileHelpers che è una libreria .NET gratuita e facile da usare per importare / esportare dati da EXCEL, record a lunghezza fissa o delimitati in file, stringhe o stream + Altro.

La sezione documentazione di Excel Data Link http://filehelpers.sourceforge.net/example_exceldatalink.html


1
Non ti deluderò, ma di recente ho iniziato a utilizzare FileHelpers e sono rimasto scioccato da quanto ... schifoso. Ad esempio, l'unico modo per mappare le colonne in un CSV alle proprietà ... mi scusi, CAMPI, di un modello è quello di creare i campi nell'ordine delle colonne . Non ti conosco, ma non farei affidamento su una stranezza del compilatore per una delle considerazioni di progettazione più centrali del mio framework f8king.


2

SpreadsheetGear è fantastico. Sì, è una spesa, ma rispetto al giocherellare con queste altre soluzioni, vale il costo. È veloce, affidabile, molto completo e devo dire che dopo aver utilizzato questo prodotto nel mio lavoro di software a tempo pieno per oltre un anno e mezzo, il loro supporto clienti è fantastico!


Difficile da giustificare quando ci sono tanti modi semplici ed efficaci (gratuiti) di leggere e scrivere su Excel.
Tipo anonimo

2

La soluzione che abbiamo usato, doveva:

  • Consenti lettura / scrittura di file prodotti da Excel
  • Sii veloce nelle prestazioni (non come usare le COM)
  • Essere indipendenti da MS Office (necessario per essere utilizzabili senza client con MS Office installato)
  • Sii libero o open source (ma sviluppato attivamente)

Esistono diverse opzioni, ma abbiamo trovato NPoi (porta .NET del lungo progetto Java open source Poi esistente ) per essere il migliore: http://npoi.codeplex.com/

Inoltre, consente di lavorare con i formati di file .doc e .ppt


2

Se sono solo dati tabulari. Consiglierei gli aiutanti dei dati di file di Marcos Melli che possono essere scaricati qui .



1

potresti scrivere un foglio di calcolo Excel che carica un determinato foglio di calcolo Excel e lo salva come CSV (anziché farlo manualmente).

allora potresti automatizzarlo da c #.

e una volta che è in CSV, il programma c # può farlo.

(Inoltre, se qualcuno ti chiede di programmare in Excel, è meglio fingere di non sapere come)

(modifica: ah sì, rob e ryan hanno entrambi ragione)



1

Ho appena fatto un progetto demo veloce che ha richiesto la gestione di alcuni file Excel. Il componente .NET del software GemBox era adeguato alle mie esigenze. Ha una versione gratuita con alcune limitazioni.

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


Cordiali saluti: L'ho provato e non ha soddisfatto la mia necessità di poter leggere un file crittografato.
Chad,

1

Excel Package è un componente open-source (GPL) per la lettura / scrittura di file Excel 2007. L'ho usato su un piccolo progetto e l'API è semplice. Funziona solo con XLSX (Excel 200 e), non con XLS.

Il codice sorgente sembra anche ben organizzato e facile da aggirare (se hai bisogno di espandere la funzionalità o risolvere problemi minori come ho fatto io).

All'inizio, ho provato l'approccio ADO.Net (stringa di connessione di Excel), ma era pieno di attacchi dannosi - ad esempio se la seconda riga contiene un numero, restituirà ints per tutti i campi nella colonna sottostante e rilascerà silenziosamente tutti i dati non va bene.


1

Usiamo ClosedXML in sistemi piuttosto grandi.

  • Gratuito
  • Facile da installare
  • Codifica diretta
  • Supporto molto reattivo
  • Il team di sviluppatori è estremamente aperto a nuovi suggerimenti. Spesso nuove funzionalità e correzioni di bug vengono implementate nella stessa settimana

1

Take.ioIl foglio di calcolo farà questo lavoro per te e gratuitamente. Dai un'occhiata a questo .


Questa è una piccola libreria davvero fantastica. Converte tutto in Elenchi di elenchi di stringhe, il che va bene per il tipo di lavoro di cui avevo bisogno.
Drewmate,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.