martes, 23 de diciembre de 2008

Cargar hoja de Excel (.xls) en GridView de Asp.Net

Algo que a menudo sucede, es que nuestros usuarios pueden tener "bases de datos" enteras en sus computadores en formato Excel y por alguna cuestión que desconozco repentinamente quieren comenzar a utilizarlas dentro de un determinado sistema como una fuente de datos para no tener que cargar todo de nuevo.

Una posible aproximación a solucionar este problema es la que trato de mostrar acá, que básicamente seria importar una hoja de MS Excel a un GridView de Asp.Net, una vez cargada en nuestra grilla, poder darles la posibilidad a nuestros usuarios de corregir algún dato. Finalmente quedaría recorrer la grilla y guardar estos datos en nuestra DB o procesarlos de alguna otra manera (si alguien tiene problema con esta ultima cuestión por favor no dude en escribir). También es válido aclarar que en el ejemplo asumo de antemano que conocemos la estructura del Excel que pretende bindearse al nuestro GridView.


Yendo directamente el punto, la idea en es poder utilizar al motor de consultas JET 4.0, de la misma manera en la que lo utilizaríamos para consultar cualquier otra fuente de datos (una base de datos de MS Acces por ejemplo).

Les copio el código, que me parece que habla por sí solo y más abajo un link con una solución de prueba en la que dejo también incluido un archivo de Excel con el que se podrá probar la solución, solo deberán seleccionar el archivo y luego darle un click al botón importar.

 protected void btnImportarNomina_Click(object sender, EventArgs e)
    {
        if (nominaExcel.PostedFile != null)
        {
            List<Lista> listaCollection = new List<Lista>();
         
             StringBuilder sbConnection = new StringBuilder();
                sbConnection.Append("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=");
                if (nominaExcel.PostedFile.FileName.Contains(".xls"))
                {
                    sbConnection.Append(nominaExcel.PostedFile.FileName);
                    sbConnection.Append(";Extended Properties=Excel 8.0;Persist Security Info=False");
                    System.Data.OleDb.OleDbConnection SQLCon = new System.Data.OleDb.OleDbConnection(sbConnection.ToString());
                    System.Data.OleDb.OleDbCommand SQLCom = new System.Data.OleDb.OleDbCommand("select * from [Hoja1$]", SQLCon);
                    System.Data.OleDb.OleDbDataAdapter SQLDa = new System.Data.OleDb.OleDbDataAdapter(SQLCom);
                 
                    SQLCon.Open();
                    IDataReader Odbreader = SQLCom.ExecuteReader();
                    listaCollection.Clear();
                    while (Odbreader.Read())
                    {
                        Lista lista = new Lista();
                        if (!String.IsNullOrEmpty(Odbreader[0].ToString()))
                        {
                            lista.NumeroDocumento = Convert.ToInt32(Odbreader[0]);
                            lista.Nombre = Odbreader[1].ToString();
                            lista.FechaNac = Convert.ToDateTime(Odbreader[2]);
                            listaCollection.Add(lista);
                        }
                    }
                    SQLCon.Close();
                    GridView1.DataSource = listaCollection;
                    GridView1.DataBind();
                }
        }
    }


Ariel Serlin

Para bajar el codigo hace click aqui

13 comentarios:

Anónimo dijo...

hola sabes estuve probando tu codigo para cargar datos de excel.. a visual.net 2005(c#, pero me sale un error .. que es sgte:

List "Lista" listaCollection = new
error en la palabra "lista"
...me dice que...
Le falta una directiva using o una referencia de ensamblado...
Porfa si me puedes ayudar .

Ah otra consulta es posible no dejarle una ruta predefinida.//ej. using System.Text. (o sea que posible cargar el archivo de cualquier parte del pc)

Ariel Serlin dijo...

Hola Guns, he bajado el codigo desde el link de la entrada de mi blog y me compilo correctamente, tambien lo he corrido con VS2005 y la ejecucion fue normal.

Respecto de la segunda pregunta, si, es posible que el archivo este en cualquier parte del disco, yo estoy usando un control asp:FileUpload para darle la posiblidad al usuario que elija la ubicacion del archivo.
Por favor no dudes en escribirme si tu problema al compilar sigue y vemos de como pasarte mi mail personal asi puedo ayudar a solucionar el problema.

Anónimo dijo...

nose porque me sale un error en la palabra "lista"
List Lista listaCollection new List Lista();

me sale algo que no se encuentra el espacio de nombres...
a que te refieres con esa sentencia.. quizas eso me puede servir.. para aclarar mi dudas

nominaExcel.PostedFile = al fileupload..verdad!!

Ariel Serlin dijo...

Hola guns, lo que estoy haciendo con la sentencia List{Lista} listaCollection = new List{Lista}(); (uso {} porque blogger no acpta mayores y menores) , es basicamente crear una colleccion generica de objetos, estos objetos dentro de esa la coleccion se corresponden con la clases llamada "Lista" que se encuantra dentro de la carpeta App_Code que encuentras dentro de la solucion que puede bajarte como ejemplo.
Me queda la duda ahora, de como estas abriendo la solucion que te bajas desde el link... la abres como sitio web y seleccionas la carpeta XLSToGrid, verdad??
Te repito, cualquier cosas si para ti esto es urgente, mandame tu email y vemos de conectarnos por msn y te ayudo con tu problema.

Anónimo dijo...

antes que nada muchisimas gracias por buena disposicion a responder mis inquietudes..
soluc.:me faltaba agregar la carpeta.. app_code. ahora si puedo cargar tu proyecto..(ahora lo que quiero es insertar ese gridwiev con datos excel a una tabla sql server)
por eso te envio mi correo para consultar cualquier duda

jvillagra21@hotmail.com

Ariel Serlin dijo...

Deberiamos ir por parte, ya que lo primero que debes hacer es recorrer tu grilla (dentro de un foreach por ejemplo).
Ahora la pregunta tambien es como haces tu acceso a datos, ya que las opciones son muchas(ADO.Net con DataSets, LINQ, EntLib o simplemente ejecutas un insert desde tu capa de acceso a datos)
Para no hacer tan larga la ida y vuelta me voy a poner en contacto contigo y eventualmente posteo la solucion asi queda tambien en el blog por si a alguien mas le pudiera servir.

Evelyn dijo...

Hola a todos por favor necesito que me ayuden estoy tratando de adapatar su ejemplo, pero me da un error estoy trabajando con VS 2008

System.Data.OleDb.OleDbException was unhandled by user code
Message="Error no especificado"
Source="Microsoft JET Database Engine"
ErrorCode=-2147467259
StackTrace:
en System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)
en System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
en System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup)
en System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
en System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
en System.Data.OleDb.OleDbConnection.Open()
en Test._Default.btnVerDatos_Click1(Object sender, EventArgs e) en C:\Proyectos\Test\Test\Default.aspx.cs:línea 139
en System.Web.UI.WebControls.Button.OnClick(EventArgs e)
en System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
en System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
en System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
en System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
en System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:

Ariel Serlin dijo...

Hola, gracias por escribirme. He probado la aplicacion con visual studio 2008, corriendo sobre windows 2008 RS(version de evaluacion) y me funciono correctamente. Necesitaria que por favor me especifiques en que momento da el error (si es que pudiste hacer debug en la aplicacion) y sobre que plataforma lo estas probando (que version de windows y cuantos bits es x86 o x64)

Ariel Serlin dijo...

Persona la version de windows que utilizo es windows 2008 R2 version de prueba o windows 7 server que seria lo mismo y no RS :-)

Victor Baduel dijo...

Muchas gracias por tu publicación, la estoy probando y me salio el siguiente error:

El motor de base de datos Microsoft Jet no pudo encontrar el objeto 'Hoja1$'. Asegúrese de que el objeto existe, y que ha escrito el nombre y la ruta de acceso al objeto correctamente.

Que es lo que sucede?

Victor Baduel dijo...

Gracias por tu aporte, te queria consultar.

Me sale este error:
El motor de base de datos Microsoft Jet no pudo encontrar el objeto 'Hoja1$'. Asegúrese de que el objeto existe, y que ha escrito el nombre y la ruta de acceso al objeto correctamente.

alguna opinión?

gracias

Ariel Serlin dijo...

Hola Víctor, acabo de bajar el ejemplo que esta posteado y me funciona, se me ocurre que puede ser lo siguiente.
Como sabrás el motor Jet esta en el cliente (lo cual es bueno porque no tenemos que instalar Excel ni nada en nuestro server). Al estar en el cliente se me ocurre que puede ser que estés probando con alguna versión distinta de MS-Office que la mía (yo al momento y aunque no me guste estoy usando una versión en español), cuando abres el Excel que está incluido en la aplicación de prueba, tú ves que el nombre de tu Hoja es Hoja1 o Sheet1. Si lo ves en ingles en deberías cambiar en el select Hoja1 por Sheet1 o como se llame tu primera hoja del archivo de Excel.
Si sigues teniendo problemas por favor avísame y coméntame que versión tienes instalada y veo de cómo puedo ayudarte.
Gracias por escribir y espero me comentes como te fue!!

Victor Baduel dijo...

Gracias por tu rapida respuesta.

Revice lo que mencionas, tengo la version MSO 2007 en español, entonces no creo que por ahi sea el problema.

Tambien estoy tratando de encontrar otra posible causa, has encontrado algo?