Accediendo a datos de Excel desde C# con OleDb

Microartículo al canto sobre extracción de datos de Excel utilizando ADO.NET. Excitante, ¿verdad?


¿Que no?… Bueno, quizá no tanto, pero como me ha resultado útil, sobre todo para evitar picar datos a mano, y pasarlos a SQL Server… Pues aprovecho y calzo un microartículo.


Lo primero que debemos hacer es hacer nuestros datos accesibles a OleDb. Para ellos, desde Excel, abrimos nuestro fichero excel, y en la hoja en la que tengamos los datos, los seleccionamos, incluyendo las cabeceras de las columnas. Incluir las cabeceras es importante, porque nos darán los nombres de las columnas cuando accedamos al DataTable.


Teniendo los datos seleccionados, vamos al menú Insertar->Nombre->Definir…, (Insert->Name->Define…), y elegimos un nombre para la selección. Este nombre será el que usemos a la hora de hacer nuestra consulta como nombre de tabla.


Una vez hecho esto, guardamos el fichero y cerramos Excel.


En nuestra aplicación C#, lo que debemos hacer es crear una OleDbConnection con la siguiente cadena de conexión:


String sConnectionString = “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Book1.xls;Extended Properties=Excel 8.0;”;

Y ya tenemos lista la conexión. Para recuperar los datos, crearemos un OleDbCommand, con una consulta similar a la siguiente:


OleDbCommand objCmdSelect =
      new OleDbCommand(“SELECT * FROM NombreAsignadoEnExcel”, objConn);

Y con esto, habremos terminado.


Saludos!

30 comentarios en “Accediendo a datos de Excel desde C# con OleDb”

  1. Si existe el archivo y tiene el nombre definido, puedes exportarlo a excel haciendo inserts sobre la tabla… Pero si quieres crear uno desde cero, tendrás que utilizar los PIAs de Office (Primary Interop Assemblies). O bien, usando una pequeña argucia, generar un fichero de valores separados por comas y guardarlo como fichero .xls. Excel lo abrirá sin chistar, pero ¡ojo! todas las columnas con valores numéricos te las traducirá a columnas numéricas (perdiendo los ceros que tengas por delante).

  2. Igual podrian cargar el archivo excel en un objeto de la clase ExcelFileManager y luego tratarlo con alguna clase para obtener los datos deseados de ese archivo. Esta Clase ExcelFileManager permite leer archivos que tienen varias hojas incrustadas.

    Saludos.

    ExcelFileManager efmgr = new ExcelFileManager();
    string filename = “d:\FormatoExcell.xls”;
    ExcelBag formato = efmgr.readExcelData(filename);

  3. Para acceder a una tabla de sql server 2000 tienes muchas opciones… Utilizarías el acceso a datos normal. Y luego lo enlazarías con un textbox, o con el control que desees 😉

    Tienes un tutorial disponible aquí:

    http://www.asp.net/learn/data-access/

    Es de ASP.NET, pero el acceso a datos es similar para una aplicación WinForms o SmartClient.

  4. No se porque estan tan contentos con este poster.
    La verdad solo de ha declarado la query a usar, la linea que falta despues de:
    new OleDbCommand(“SELECT * FROM NombreAsignadoEnExcel”, objConn);
    seria:
    OleDbDataReader reader = cmd.ExecuteReader();
    y esa linea da ERROR.
    Asi que el ejemplo al final no sirve.

  5. Hola exceptico, (por aquí decimos escéptico…)

    ¿Qué error te da?

    El ejemplo está siendo usado en un proyecto real, así que _sé_ que funciona… Podría ser que el nombre que has declarado en la consulta no coincide con el nombre que has declarado en el Excel?

    Saludos!

  6. Buen artículo, en pocos sitios se trata este tema…creo que hay otra forma de hacerlo, y no es definiendo la tabla desde excel, sino en la consulta SQL, en vez de poner

    SELECT * FROM NombreAsignadoEnExcel

    , se pone:

    SELECT * FROM [NombreAsignadoALaHojaEnExcel$]

    ; esta fórmula hasta ahora no me genera ningun error, sé que accede a los datos que quiero; sin embargo, mi inconveniente está en la visualización de estos datos en un objeto DataGridViewer (primera vez que lo utilizo). Si puede ayudarme en esta visualización, se lo agradezco mucho.

  7. Es muy bueno el ejemplo, te felicito, ademas es muy practico y sencillo
    ya lo probe y funciona y lo enlace con el gridview , lo que hice es sacar todos esos datos y colocarlos en un objeto ( Ej. PersonaVO) con cada registro y lo metia a una coleccion (ArrayList o List) y posteriormente se utiliza un ObjectDataSouurce que le tienes que especificar el cs que donde esta tu metodo asi como el metodo que utlizara y solo bastaria asociar el ObjectDataSource al Grid , si desean solo var algunas columnas tendra que asociar cada columna el vo con su propiedad
    bye

  8. — Ademas conesto
    select * from
    — carga todas las columnas en la hoja pero si solo quiero algunas
    — en especifico.
    — Supongamos q mi hoja tiene 10 columnas y solo quiero 5
    — entonces le pongo
    select columna1, columna2, columna3, etc from

    pero da error .. alguien sabe como hacerlo ??.

  9. Como al parecer no hay respuesta de nadie ya lo resolvi…. miren para quien lo valla hacer se hace de la siguiente forma.

    SELECT [Columna1], [Columna2], [Etc] FROM [” hoja$]”

    y para victor que pidio lo del where seria asi:

    SELECT [Columna1], [Columna2], [Etc] FROM [” hoja$]” Where Columna1=” & valor

  10. Hola,

    @Pepe: Siento no haber sido lo suficientemente rápido para contestarte… 🙁

    @Victor: Basta con que la consulta la definas incluyendo la cláusula WHERE que necesites… Eso sí, deberás usar los nombres de las columnas tal y como indica Pepe.

  11. woow
    muy buena pagina
    pues yo le se un poco
    y nadie a puesto un insert
    creo yo
    pues aqui les dejo uno de un insert para quien lo desee

    string conexion = @”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:UsersTOYOS!!!Documentsexcelwithsql.xls;Extended Properties=Excel 8.0″;
    OleDbConnection cnn1 = new OleDbConnection(conexion);

    OleDbDataAdapter da = new OleDbDataAdapter();
    da.InsertCommand = new OleDbCommand(“INSERT INTO [Sheet1$] (id, Nombre,Apellido) VALUES(‘”+reader[0].ToString()+”‘,'”+reader[1].ToString()+”‘,'”+reader[2].ToString()+”‘)”, cnn1);
    da.InsertCommand.Connection = cnn1;
    cnn1.Open();
    da.InsertCommand.ExecuteNonQuery();
    cnn1.Close();

    probando hasta que salio
    y pues ahi esta

  12. Gracias por su gran aporte me sirvio mucho. Como soy nuevo en esto les pediria el favor de guiarme para que la hubicacion y nombre del archivo sea seleccionado por el usuario y pueda elegirlo desde cualquier.
    Gracias

  13. Hola a tod@s!!

    Tengo un conjunto de excel, cada uno de ellos tengo que importarlo a una tabla diferente en sql server. Cada uno de los excel únicamente cuenta con una sola hoja. Mi pregunta es, cómo puedo yo extraer el nombre de la hoja para poder realizar la sentencia select?

    Este es mi código, ahora mismo funciona correctamente, pero tengo que asignarle un nombre “estático” a la variable sHoja. Y lo que quiero es que coja directamente el nombre que viene en el excel.

    // Cadena de conexión al libro de excel
    string sCadenaConexionExcel = @”Provider=Microsoft.Jet.OLEDB.4.0;” +
    @”Data Source=” + sFichero + “;” +
    @”Extended Properties=” + ‘”‘ + “Excel 8.0;HDR=YES;” + ‘”‘;

    // Crear y abrir la conexión al libro de excel
    OleDbConnection conexionExcel = new OleDbConnection(sCadenaConexionExcel);

    string sConsulta;
    sConsulta = ” SELECT * FROM [” + sHoja + “$]”;
    conexionExcel.Open();

  14. Hola!
    Lo primero, gracias por el ejemplo. Me está resultando muy muy útil.
    Tengo una pregunta, si no conozco el nombre de la hoja, como puedo hacer el select para que lo haga sobre la primera hoja.

    Muchas gracias!!

  15. C# 2005 : ( http://support.microsoft.com/kb/306572 )

    using System.Data.OleDb;

    string conexion = @”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:RUTAARCHIVO.xls;Extended Properties=Excel 8.0″;

    OleDbConnection objConn = new OleDbConnection(conexion);

    // Abrir la conexión con la base de datos.
    objConn.Open();

    // El código utiliza un comando SQL SELECT para mostrar los datos de la hoja de cálculo.

    OleDbCommand objCmdSelect = new OleDbCommand(“SELECT * FROM MyTabla”, objConn);

    // Crear un nuevo OleDbDataAdapter que se usa para generar un DataSet
    // basado en la instrucción SQL SELECT anterior.
    OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();

    // Pasar el comando Select al adaptador.
    objAdapter1.SelectCommand = objCmdSelect;

    // Crear el nuevo DataSet para que aloje la información de la hoja de cálculo.
    DataSet objDataset1 = new DataSet();

    // Llenar el DataSet con la información de la hoja de cálculo.
    objAdapter1.Fill (objDataset1, “XLData”);

    // Enlazar los datos al control DataGrid.
    dataGridView1.DataSource = objDataset1.Tables[0].DefaultView;

    // Limpiar los objetos.
    objConn.Close();

    Pro: Fácil y efectivo.
    Contra: Hay que definir como MyTable el rango en el archivo de excel… Han usado MSQuery como intermediario?… Es Limitado… pero practico!

  16. Estaba en un error!

    Si es posible aceder a los datos sin definir un rango (Insertar, Nombre.. Definir…) desde excel.

    Solo hay que cambiar (en mi comment anterior) el MyTabla por [Sheet1$] o [Hoja1$] o el nombre de la hoja.

    Esto me es útil cuando exporto bases completas de fox pro u otros BD a Excel!

  17. Hola a todos!!
    Necesito de su ayuda, mi caso es el siguiente:
    Se que en mi aplicación web, al leer los datos de un archivo excel, este lee los datos de una estructura ya definida, es decir, los archivos que lee se encuentran desde la primera fila y primera columna.
    Entienden???
    Ese es el formato que he visto en todos los ejemplos….
    Mi pregunta es que cómo hago para que lea los datos de un archivo excel, pero que estos datos se encuentren en otras celdas. Por ejemplo que comience en la celda A7 y no necesariamente en la primera fila.
    Estoy utilizando ASP.NET y C#
    Espero puedan ayudarme!!!

  18. Para los que quieren saber el nombre de la tabla es facil con

    DataTable esquemaTabla = cn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new object[] {null, null,null, “TABLE”});
    // donde cn el el objeto OleDbConnection
    // y el DataTable esquemaTabla obtiene las propiedades
    // de las tablas en cada renglon , ntonces pueden hacer
    string nombreTabla =””;
    for(int i =0; i< esquemaTabla.Rows.Count; i++){ nombreTabla = esquemaTabla.Rows[i]["TABLE_NAME"].ToString(); // y aqui el codigo de lo que quieran hacer con el nombre de la // tabla, solo que al nombre le deben de agregar los [] // ya que solo viene como Sheet1$ }

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *