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.

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

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$]


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


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

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.


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

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.


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



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.


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.


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 ?


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.


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

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.



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


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!


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


2

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



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)



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


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.


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.

1

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


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.