Lectura de archivos de Excel desde C #

233

¿Existe una biblioteca gratuita o de código abierto para leer archivos de Excel (.xls) directamente desde un programa C #?

No necesita ser demasiado elegante, solo seleccionar una hoja de trabajo y leer los datos como cadenas. Hasta ahora, he estado utilizando la función Exportar a texto Unicode de Excel y analizando el archivo resultante (delimitado por tabulaciones), pero me gustaría eliminar el paso manual.

dbkk
fuente

Respuestas:

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

Esto es lo que suelo usar. Es un poco diferente porque generalmente pego un AsEnumerable () en la edición de las tablas:

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

ya que esto me permite usar LINQ para buscar y construir estructuras a partir de los campos.

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"),
                    });
Robin Robinson
fuente
Si parece que Seleccionar en este enfoque intenta adivinar el tipo de datos de la columna y aplicar ese tipo de datos adivinado. Por ejemplo, si tiene una columna con valores dobles en su mayoría, no le gustará que pase x.Field <string>, pero espera x.Field <double>. ¿Es esto cierto?
Kevin Le - Khnle
1
Solo lo busqué en MSDN. Parece que <T> solo se usa para intentar convertir el contenido de la columna a un tipo. En este ejemplo y solo enviando los datos en las columnas a cadenas. Si desea un doble, debe llamar a double.Parse (x.Field <string> ("Cost") o algo así. Field es un método de extensión para DataRow y parece que no hay versiones no genéricas.
Robin Robinson
¿Agregar un double.Parse a la consulta Linq lo ralentiza mucho?
Tipo anónimo el
23
Tenga en cuenta que si está leyendo xlsx, debe utilizar esta cadena de conexión en su lugar:string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName)
Andreas Grech
77
Lamentablemente, el controlador Jet.OLEDB no es compatible con 64 bits; deberá cambiar al objetivo x86 en lugar de a cualquier CPU (si aún desea seguir adelante con este método). Alternativamente, instale el controlador ACE de 64 bits y cambie la cadena de conexión para usar este controlador (como lo indica Andreas) - microsoft.com/en-us/download/…
Duncan
83

Si solo se trata de datos simples contenidos en el archivo Excel, puede leer los datos a través de ADO.NET. Consulte las cadenas de conexión enumeradas aquí:

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

-Ryan

Actualización: entonces puedes leer la hoja de trabajo a través de algo como select * from [Sheet1$]

Ryan Farley
fuente
1
De esta manera es, con mucho, el más rápido.
StingyJack
17
Por supuesto que no es cierto, tacaño. Tiene que examinar todos los datos y escribir un código de base de datos horrible (cree manualmente sus modelos, asigne columnas a propiedades, yadda yadda). La forma más rápida es dejar que algún otro SOB pobre haga esto por usted . Es por eso que las personas usan marcos en lugar de escribir todo de abajo hacia arriba.
12
Método sin valor! Trunca las columnas de texto a 255 caracteres cuando se lee. ¡Tener cuidado! Consulte: stackoverflow.com/questions/1519288/… ¡El motor ACE hace lo mismo!
Triynko
55
Tenga en cuenta que usar ADO.NET para leer datos de exel requiere Microsoft Access o Microsoft Access Database Engine Redistributable instalado.
zihotki
3
El controlador también adivinará los tipos de columnas según las primeras filas. Si tiene una columna con lo que parecen enteros en las primeras filas, encontrará un error cuando golpee un no entero (por ejemplo, un flotador, una cadena)
Brian Low
27

El enfoque ADO.NET es rápido y fácil, pero tiene algunas peculiaridades que debe tener en cuenta, especialmente con respecto a cómo se manejan los DataTypes.

Este excelente artículo lo ayudará a evitar algunas dificultades comunes: http://blog.lab49.com/archives/196

Ian Nelson
fuente
Respondiste mi pregunta (en forma de un comentario arriba).
Kevin Le - Khnle
22

Esto es lo que usé para 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);
    }
}
Dmitry Shechtman
fuente
2
la hoja de trabajo no está definida ... me parece un poco extraño después de definir claramente todo lo demás.
Jeremy Holovacs
21

¿Qué hay de Excel Data Reader?

http://exceldatareader.codeplex.com/

He utilizado su ira, en un entorno de producción, para extraer grandes cantidades de datos de una variedad de archivos de Excel en SQL Server Compact. Funciona muy bien y es bastante robusto.

Michał Pawłowski
fuente
2
Voy a segundo Excel Data Reader; también ha llevado a la increíblemente útil biblioteca de Pruebas controladas por datos de Excel, que utiliza el atributo TestCaseSource de NUnit 2.5 para hacer que las pruebas basadas en datos usando hojas de cálculo Excel sean ridículamente fáciles. Solo tenga en cuenta que Resharper aún no es compatible con TestCaseSource, por lo que debe usar el corredor NUnit.
David Keaveny
Desafortunadamente, hay algunos problemas con esta biblioteca que acabamos de encontrar. En primer lugar, hemos tenido algunos campos de moneda que salen como fechas. En segundo lugar, se bloquea si el libro de trabajo tiene hojas vacías. Entonces, aunque fue muy fácil de integrar, ahora estamos reevaluando si seguir usando esta biblioteca. No parece estar siendo desarrollado activamente.
Ian1971
También supone la presencia de algunos elementos opcionales en el archivo xlsx que hacen que no pueda leer los datos si están ausentes.
RichieHindle
Tenemos problemas con los archivos de Excel que provienen de SQL Server Reporting Services. Simplemente no funcionan, a menos que los abras y los guardes (incluso sin editar). @RichieHindle: ¿de qué elementos opcionales estás hablando (esperando que esto pueda ayudarme con mis archivos SSRS Excel)?
Peter
@ Peter: Creo que era un <dimension>elemento que faltaba en el <worksheet>que me estaba causando problemas.
RichieHindle
16

Aquí hay un código que escribí en C # usando .NET 1.1 hace unos años. No estoy seguro si esto sería exactamente lo que necesita (y puede que no sea mi mejor código :)).

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;
        }
    }
}
hitec
fuente
No podría estar más de acuerdo con Cherian. Este código tiene muchos años ... antes de que yo era hábil con ReSharper :)
Hitec
2
El código es feo, pero muestra cómo obtener los nombres de las hojas, ¡genial!
Sam
15

Koogra es un componente de código abierto escrito en C # que lee y escribe archivos de Excel.

Runa Grimstad
fuente
Ya no parece particularmente activo, en comparación con, digamos, NPOI
David Burton
8

Leí mucho de los archivos de Excel en C # hace un tiempo, y usamos dos enfoques:

  • La API COM, donde accede a los objetos de Excel directamente y los manipula a través de métodos y propiedades
  • El controlador ODBC que permite usar Excel como una base de datos.

El último enfoque fue mucho más rápido: leer una tabla grande con 20 columnas y 200 líneas tomaría 30 segundos a través de COM y medio segundo a través de ODBC. Por lo tanto, recomendaría el enfoque de la base de datos si todo lo que necesita son los datos.

Salud,

Carl

Carl Seleborg
fuente
6

ExcelMapper es una herramienta de código abierto ( http://code.google.com/p/excelmapper/ ) que se puede usar para leer hojas de cálculo de Excel como objetos fuertemente tipados. Es compatible con los formatos xls y xlsx.

anónimas
fuente
6

Quiero mostrar un método simple para leer el archivo xls / xlsx con .NET. Espero que lo siguiente le sea útil.

 DataTable privado ReadExcelToTable (ruta de cadena)    
 {

     //Cadena de conexión

     string connstring = "Proveedor = Microsoft.ACE.OLEDB.12.0; Fuente de datos =" + ruta + "; Propiedades extendidas = 'Excel 8.0; HDR = NO; IMEX = 1';";  
     //el mismo nombre 
     // string connstring = Provider = Microsoft.JET.OLEDB.4.0; Data Source = "+ path + //"; Extended Properties = 'Excel 8.0; HDR = NO; IMEX = 1'; "; 

     utilizando (OleDbConnection conn = new OleDbConnection (connstring))
     {
        conn.Open ();
        // Obtener el nombre de todas las hojas
        DataTable sheetName = conn.GetOleDbSchemaTable (OleDbSchemaGuid.Tables, nuevo objeto [] {null, null, null, "Table"});  

        // Obtenga el nombre de la primera hoja
        string firstSheetName = sheetName.Rows [0] [2] .ToString (); 

        // Cadena de consulta 
        string sql = string.Format ("SELECT * FROM [{0}]", firstSheetName); 
        OleDbDataAdapter ada = new OleDbDataAdapter (sql, connstring);
        Conjunto de conjunto de datos = nuevo conjunto de datos ();
        ada.Fill (conjunto);
        conjunto de retorno. Tablas [0];   
   }
 }

El código es del artículo: http://www.c-sharpcorner.com/uploadfile/d2dcfc/read-excel-file-with-net/ . Puede obtener más detalles al respecto.

Lizzy
fuente
2
Que era muy útil, especialmente la parte sobre la lectura de los sheetnames.
martinstoeckli
4

No es gratis, pero con la última versión de Office hay una muy buena automatización .Net API. (ha habido una API durante mucho tiempo pero fue una COM desagradable) Puede hacer todo lo que quiera / necesite en el código todo mientras la aplicación de Office siga siendo un proceso oculto en segundo plano.

xanadont
fuente
3
@ Tipo anónimo Leí la pregunta y estaba ofreciendo una alternativa útil a la implementación deseada de OSS ... porque, bueno, estaba bastante seguro de que no había nada disponible. Y, a juzgar por la respuesta aceptada, el requisito de tener instalado Office no es un problema.
xanadont
3

Perdóname si estoy fuera de la base aquí, pero ¿no es esto para lo que son los PIA de Office ?

Rob Cooper
fuente
55
Sí, pero eso implicaría crear una instancia de Excel.Aplicación, cargar el archivo xls, etc. Si el requisito es simplemente leer algunos datos del archivo, entonces es mucho más fácil y mucho más liviano usar uno de los métodos ADO.NET descritos en las otras respuestas
Adam Ralph el
Demasiado lento, al usar Office PIA como línea de base, todo lo demás es más rápido, incluso solo usando una matriz de objetos pasada de la propiedad .Value2. Que todavía está usando el PIA.
Tipo anónimo el
3

Últimamente, en parte para mejorar en LINQ ... He estado usando la API de automatización de Excel para guardar el archivo como hoja de cálculo XML y luego procesar ese archivo usando LINQ to XML.

kenny
fuente
Sospecharía que puede protegerlo de Excel, pero no del hombre con compilador ... como nada ... son solo bytes.
kenny
@gsvirdi, publique una pregunta separada sobre la seguridad de los archivos de Excel, esta pregunta es sobre el rendimiento.
Tipo anónimo el
3

SpreadsheetGear for .NET es un componente de hoja de cálculo compatible con Excel para .NET. Puede ver lo que dicen nuestros clientes sobre el rendimiento en el lado derecho de nuestra página de productos . Puede probarlo usted mismo con la evaluación gratuita y totalmente funcional .

Joe Erickson
fuente
3

SmartXLS es otro componente de hoja de cálculo de Excel que admite la mayoría de las características de Gráficos de Excel, motores de fórmulas y puede leer / escribir el formato opencel de Excel2007.

liya
fuente
2

Recomiendo FileHelpers Library, que es una biblioteca .NET gratuita y fácil de usar para importar / exportar datos desde EXCEL, longitud fija o registros delimitados en archivos, cadenas o secuencias + Más.

La sección de documentación del enlace de datos de Excel http://filehelpers.sourceforge.net/example_exceldatalink.html

Jason Von Ruden
fuente
1
No te decepcionaré, pero recientemente comencé a usar FileHelpers y me sorprendió lo ... horrible que es. Por ejemplo, la única forma de asignar columnas en un csv a propiedades ... disculpe, CAMPOS, de un modelo es crear los campos en el orden de las columnas . No sé sobre ti, pero no confiaría en una peculiaridad del compilador para una de las consideraciones de diseño más centrales de mi marco f8king.
2

SpreadsheetGear es asombroso. Sí, es un gasto, pero en comparación con jugar con estas otras soluciones, vale la pena el costo. Es rápido, confiable, muy completo, y debo decir que después de usar este producto en mi trabajo de software a tiempo completo durante más de un año y medio, ¡su atención al cliente es fantástica!

John R
fuente
Es difícil de justificar cuando hay tantas formas simples y efectivas (gratis) de leer y escribir en Excel.
Tipo anónimo el
2

La solución que utilizamos necesitaba:

  • Permitir lectura / escritura de archivos producidos en Excel
  • Sea rápido en rendimiento (no como usar COM)
  • Sea independiente de MS Office (debe ser utilizable sin clientes que tengan instalado MS Office)
  • Ser libre o de código abierto (pero desarrollado activamente)

Hay varias opciones, pero encontramos que NPoi (puerto .NET del proyecto de código abierto Poi existente de Java ) es el mejor: http://npoi.codeplex.com/

También permite trabajar con formatos de archivo .doc y .ppt

Marcel Toth
fuente
2

Si solo se trata de datos tabulares. Recomendaría los ayudantes de datos de archivos de Marcos Melli que se pueden descargar aquí .

cless
fuente
1

podría escribir una hoja de cálculo de Excel que cargue una hoja de cálculo de Excel dada y la guarde como csv (en lugar de hacerlo manualmente).

entonces podrías automatizar eso desde c #.

y una vez que está en csv, el programa c # puede asimilar eso.

(también, si alguien le pide que programe en Excel, es mejor fingir que no sabe cómo)

(Editar: ah sí, Rob y Ryan tienen razón)

Leon Bambrick
fuente
1

Sé que la gente ha estado haciendo una "extensión" de Excel para este propósito.
Más o menos crea un botón en Excel que dice "Exportar al programa X", y luego exporta y envía los datos en un formato que el programa pueda leer.

http://msdn.microsoft.com/en-us/library/ms186213.aspx debería ser un buen lugar para comenzar.

Buena suerte

Lars Mæhlum
fuente
1

Acabo de hacer un proyecto de demostración rápida que requería administrar algunos archivos de Excel. El componente .NET del software GemBox fue adecuado para mis necesidades. Tiene una versión gratuita con algunas limitaciones.

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

Christian Hagelid
fuente
FYI: Lo intenté y no satisfizo mi necesidad de poder leer un archivo encriptado.
Chad
1

Excel Package es un componente de código abierto (GPL) para leer / escribir archivos de Excel 2007. Lo utilicé en un proyecto pequeño y la API es sencilla. Funciona solo con XLSX (Excel 200 y), no con XLS.

El código fuente también parece estar bien organizado y es fácil de manejar (si necesita ampliar la funcionalidad o solucionar problemas menores como lo hice yo).

Al principio, probé el enfoque ADO.Net (cadena de conexión de Excel), pero estaba lleno de trucos desagradables; por ejemplo, si la segunda fila contiene un número, devolverá entradas para todos los campos de la columna a continuación y soltará silenciosamente cualquier dato Eso no encaja.

dbkk
fuente
1

Usamos ClosedXML en sistemas bastante grandes.

  • Gratis
  • Fácil de instalar
  • Codificación directa
  • Soporte muy receptivo
  • El equipo de desarrolladores está extremadamente abierto a nuevas sugerencias. A menudo, las nuevas funciones y correcciones de errores se implementan en la misma semana.
Doctor Rudolf
fuente
1

Take.ioLa hoja de cálculo hará este trabajo por usted, y sin cargo. Solo mira esto .

verde
fuente
Esta es una pequeña biblioteca realmente genial. Simplemente convierte todo en Listas de Listas de cadenas, lo cual está bien para el tipo de trabajo para el que lo necesitaba.
Drewmate
0

Acabo de usar ExcelLibrary para cargar una hoja de cálculo .xls en un DataSet. Funcionó muy bien para mí.

Hafthor
fuente