FUNCIONES PERSONALIZADAS PARA EXCEL (UDF)

32
Más sobre las funciones de bases de datos personalizadas miércoles 25 de junio de 2008 Silvia, mi amiga auditora, me ha planteado otro reto. Me pregunta: "Oye, si en excel tengo una relación de personas, y una serie de datos asociados a cada uno de ellos, ¿cómo puedo obtener las columnas en las que se obtienen determinados datos?". Como así, a bote pronto, y sin un ejemplo claro, parece un problema un poco abstracto, procedimos a montar un supuesto para dejar claras las cosas. El ejemplo era el siguiente: La pregunta era bien clara: "¿cómo puedo obtener las columnas en las que se obtienen determinados datos?". Bien, supongamos que queremos saber las veces que se obtiene el valor 1, para todos esos usuarios. En el caso de MANOLITO, el dato 1, se obtiene en la columna D y F, como se puede ver en la tabla anterior. Pero en el caso de FULANITO, el valor 1 no está presente en ninguna de las columnas. La cuestión era crear un macro o una fórmula que nos permitiera determinar las columnas en las que obtenemos el dato que busquemos. Al final decidí montar una función, a la que he llamado localizar, y que tiene el siguiente código: Function Localizar(rango As Range, valor As Variant) 'fichamos la celda donde están los datos 'inicial y final (el rango, vamos) mi_rango = rango.Address 'separamos los datos inicial y final coordenadas = Split(mi_rango, ":") inicio = coordenadas(0) fin = coordenadas(1) 'pasamos a una variable la dirección de la celda inicial celda = Range(inicio).Address 'para todo el rango de datos... For i = 0 To Range(fin).Column - Range(inicio).Column 'Comprobamos el valor introducido If Range(celda) = valor Then columna = columna & " " & Range(celda).Address 'eliminamos el signo de $ de referencia absoluta columna = Replace(columna, "$", "") End If 'pasamos a la siguiente columna celda = Range(celda).Offset(0, 1).Address 'seguimos con el bucle Next 'Si no existe el dato en ninguna columna If columna = 0 Then columna = " No existe" 'eliminamos los números de la fila

description

Algunas funciones personalizadas para Excel (UDF) que sirven para minimizar el uso de una fórmula

Transcript of FUNCIONES PERSONALIZADAS PARA EXCEL (UDF)

Ms sobre las funciones de bases de datos personalizadas mircoles 25 de junio de 2008

Ms sobre las funciones de bases de datos personalizadas mircoles 25 de junio de 2008

Silvia, mi amiga auditora, me ha planteado otro reto. Me pregunta: "Oye, si en excel tengo una relacin de personas, y una serie de datos asociados a cada uno de ellos, cmo puedo obtener las columnas en las que se obtienen determinados datos?". Como as, a bote pronto, y sin un ejemplo claro, parece un problema un poco abstracto, procedimos a montar un supuesto para dejar claras las cosas. El ejemplo era el siguiente:

La pregunta era bien clara: "cmo puedo obtener las columnas en las que se obtienen determinados datos?".

Bien, supongamos que queremos saber las veces que se obtiene el valor 1, para todos esos usuarios. En el caso de MANOLITO, el dato 1, se obtiene en la columna D y F, como se puede ver en la tabla anterior. Pero en el caso de FULANITO, el valor 1 no est presente en ninguna de las columnas.

La cuestin era crear un macro o una frmula que nos permitiera determinar las columnas en las que obtenemos el dato que busquemos. Al final decid montar una funcin, a la que he llamado localizar, y que tiene el siguiente cdigo:

Function Localizar(rango As Range, valor As Variant)'fichamos la celda donde estn los datos'inicial y final (el rango, vamos)mi_rango = rango.Address'separamos los datos inicial y finalcoordenadas = Split(mi_rango, ":")inicio = coordenadas(0)fin = coordenadas(1)'pasamos a una variable la direccin de la celda inicialcelda = Range(inicio).Address'para todo el rango de datos...For i = 0 To Range(fin).Column - Range(inicio).Column'Comprobamos el valor introducidoIf Range(celda) = valor Thencolumna = columna & " " & Range(celda).Address'eliminamos el signo de $ de referencia absolutacolumna = Replace(columna, "$", "")End If'pasamos a la siguiente columnacelda = Range(celda).Offset(0, 1).Address'seguimos con el bucleNext'Si no existe el dato en ninguna columnaIf columna = 0 Then columna = " No existe"'eliminamos los nmeros de la filanumeros = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)For j = 0 To UBound(numeros)columna = Replace(columna, numeros(j), "")Next'asignamos a la funcin, el dato del contador'eliminando previamente el primer espacio vacoLocalizar = Mid(columna, 2)End Function

Como veis en la primera lnea de la funcin, aparecen dos argumentos: el rango, y el valor. El rango es precisamente, el rea donde tenemos los datos, mientras que el valor es el dato que buscamos. La frmula nos devolver las letras correspondientes a las columnas donde aparezca ese valor.

Por ejemplo, si buscamos las columnas donde aparece el valor 1, para MANOLITO, deberemos seleccionar como rango, el rea comprendida entre C4 y G4, por lo que la funcin la llamaremos as:Como veis en la primera lnea de la funcin, aparecen dos argumentos: el rango, y el valor. El rango es precisamente, el rea donde tenemos los datos, mientras que el valor es el dato que buscamos. La frmula nos devolver las letras correspondientes a las columnas donde aparezca ese valor.

Por ejemplo, si buscamos las columnas donde aparece el valor 1, para MANOLITO, deberemos seleccionar como rango, el rea comprendida entre C4 y G4, por lo que la funcin la llamaremos as:Como veis en la primera lnea de la funcin, aparecen dos argumentos: el rango, y el valor. El rango es precisamente, el rea donde tenemos los datos, mientras que el valor es el dato que buscamos. La frmula nos devolver las letras correspondientes a las columnas donde aparezca ese valor.

Por ejemplo, si buscamos las columnas donde aparece el valor 1, para MANOLITO, deberemos seleccionar como rango, el rea comprendida entre C4 y G4, por lo que la funcin la llamaremos as:

=localizar(C4:G4;1)

Si lo preferimos, tambin podemos utilizar como valor, las coordenadas de la celda donde tenemos el dato a buscar. Por ejemplo, si en la celda A1 tuviramos un 1, podramos haber escrito la funcin, tal y como la hemos escrito antes, o bien de esta otra forma:

=localizar(C4:G4;A1)

Como podis ver en la imagen siguiente, aparece a la derecha la frmula localizar, donde nos devuelve como resultado, las columnas donde aparece el valor buscado. Si no se encuentra el valor, simplemente nos imprimir en pantalla el texto No existe, tal y como tambin podis ver en la imagen:

Desde aqu podis descargar el fichero de excel, con el ejemplo que os presento, y por supuesto, con la funcin y el cdigo de este artculo.

Publicado porJavier Marco Validacin de listas dependientes mircoles 10 de septiembre de 2008

Bajo el nombre de validacin de listas dependientes, os explicar como podemos validar datos de forma automtica en una lista desplegable, que a su vez requiera de la interaccin con otra lista desplegable. Supongamos que tenemos dos listas de datos, una lista corresponder a los datos padre y la otra a los datos hijos. Dependiendo de los datos padre que seleccionemos en el desplegable, nos aparecern unos u otros datos hijos de forma automtica.

Como esto parece algo farragoso, ser mejor explicarlo con un sencillo ejemplo. Supongamos que tenemos varias marcas de automviles, y en cada una de ellas, tenemos un grupo de modelos de cada marca. Algo as como esto:

Lo que pretendemos hacer a partir de esos datos, es montar dos listas desplegables, una con las marcas de automviles, y otra con los modelos de cada una de las marcas, de tal forma que si elegimos una marca en concreto, en la otra lista solo nos aparezcan los modelos de esa marca.

Lo primero que haremos ser crear la lista de validacin de las marcas de automviles, para que nadie pueda introducir marcas que no tengamos en nuestro listado (recordemos que estamos validando datos). Para ello, nos situaremos por ejemplo en la celda E12, y lo que haremos ser definir la lista desde el men Datos, eligiendo a continuacin Validacin, y en la pestaa Configuracin, que es la que nos saldr por defecto en primer plano, elegiremos en Permitir la opcin Lista, y en Origen seleccionaremos el rango comprendido entre B3 y D3 que corresponde a los nombres de las marcas que tenemos, tal y como se puede observar en la imagen anterior. Si queris una ayuda grfica, lo que tenis que poner es esto que se ve en la siguiente imagen:

Es decir, habremos creado este desplegable en E12:

Una vez hecho esto, ahora solo nos quedar crear el desplegable correspondiente a los modelos de cada marca. Para ello, crearemos unos nombres, para cada grupo de modelos de cada marca. Esto es imprescindible, porque usaremos posteriormente la funcin indirecto (luego explicar para que nos va a servir). Para definir cada rango de datos con un nombre, la forma ms sencilla es hacer lo siguiente:

Seleccionaremos cada grupo homogneo de modelos, partiendo por ejemplo con los modelos de coche de Ferrari, y seleccionando desde la celda B4 hasta la B6. Una vez tengamos seleccionados los modelos (ver la imagen siguiente), tendremos que ponerles un nombre. Necesariamente ese nombre debe coincidir con el que hemos utilizado en el encabezado de cada grupo, es decir, en este caso debe llamarse Ferrari, no puede llamarse Pepito, ni Audi. Para ponerle un nombre a ese rango, tan solo deberemos escribirlo en la zona enmarcada en rojo, y pulsar intro (ver la siguiente imagen):

Haremos lo mismo con el rango que va desde C4 a C6, y le pondremos como nombre la marca correspondiente, es decir, Lamborghini. Finalmente haremos lo mismo con el rango de datos comprendido entre D4 y D7, al que le pondremos como nombre Porsche.

Una vez hayamos definido todos los nombres, podremos comprobarlos. Para ello nos situaremos en cualquier celda, por ejemplo en E6, y desde el men Insertar, seleccionaremos Nombre, y a continuacin Definir. Si lo hemos hecho todo correctamente, veremos algo como esto:

Ahora ya tenemos todo lo necesario para crear la lista dependiente correspondiente a los modelos de cada marca. Para ello nos situaremos en la celda E14, y desde el men Datos, elegiremos a continuacin Validacin, y en la pestaa Configuracin, que es la que nos saldr por defecto en primer plano, elegiremos en Permitir la opcin Lista, y en Origen escribiremos =INDIRECTO(E12), tal y como muestra la siguiente imagen:

La funcin indirecto, al utilizarla como origen de datos referenciada a la celda E12 que es donde tenemos las marcas de coches, lo que va a hacer es mostrarnos solo las correspondientes a la marca seleccionada (recordemos que en E12 tenemos el primer desplegable donde seleccionaremos una marca en concreto). Es decir, =INDIRECTO(E12) lo que va a hacer es buscar si existe un nombre (recordemos que precisamente hemos definido para esto los nombres anteriores) Ferrari, Lamborghini, o Porsche, y nos va a mostrar los datos correspondientes a ese nombre, que en este caso coinciden y adems de forma necesaria, con cada marca en cuestin, tal y como comentbamos anteriormente.

Si lo hemos hecho todo correctamente, cada vez que seleccionemos una marca, el segundo desplegable, es decir, la lista dependiente (pues la segunda, la de los modelos de coche, depende de la primera, es decir, de las marcas de automviles), nos mostrar los modelos especficos de la marca seleccionada. Algo como lo que muestra la siguiente imagen:

Finalmente, para darle un toque de elegancia a nuestros desplegables, haremos que cada vez que se cambie la marca de coches, se elimine el modelo de vehculo que habamos seleccionado anteriormente, si es que hemos estado jugando con los deplegables. Para ello tan solo tendremos que copiar y pegar este cdigo pero no en un mdulo, sino en la Hoja1, pues es en ella donde tenemos los desplegables:

Private Sub Worksheet_Change(ByVal Target As Range)'Si ha errores, que contineOn Error Resume Next'Si cambiamos el dato de la celda E12,'limpiamos el segundo desplegableIf Target.Cells = Range("E12") Then'eliminamos el contenido de E14Range("E14").ClearContentsEnd IfEnd Sub

Desde aqu podis descargar el fichero de excel, con el ejemplo que os presento en este artculo, para que podis ver en funcionamiento como se crean listas de validacin dependientes.

Publicado porJavier Marco Convertir unidades de tiempo: horas, minutos, y segundos mircoles 13 de agosto de 2008

A veces nos es imprescindible convertir horas en minutos, o minutos en segundos, y no sabemos como podemos conseguirlo de una forma sencilla y sin complicaciones. Bueno, pues hoy os presento un par de funciones que nos ahorrarn estas conversiones.

Imaginemos que tenemos esto en una celda (7 horas, 12 minutos, y 45 segundos):

07:12:45

Si deseamos mostrar en pantalla el formato de esa forma, tendremos que situarnos en esa celda, y seleccionar desde el men Formato, la opcin Celdas, y en la pestaa Nmero, que es la que nos saldr en primer plano, por defecto, aadiremos dentro de la categora Personalizada, este formato: hh:mm:ss, tal y como se muestra en esta imagen:

Ahora imaginemos que deseamos convertir esas horas, minutos, y segundos, en una nica unidad de tiempo, por ejemplo, en horas. Para ello, tan solo deberemos introducir esta frmula en cualquier celda, excepto en aquella donde tenemos el dato a convertir. Suponiendo que tengamos el dato a convertir en la celda D4, escribiramos la frmula de la siguiente forma:

=HORA(D4)+(MINUTO(D4)/60)+(SEGUNDO(D4)/(60*60))

Si lo que deseamos es convertir esa unidad de tiempo, en minutos, deberemos introducir esta otra frmula:

=(HORA(D4)*60)+MINUTO(D4)+(SEGUNDO(D4)/60)

Y si por el contrario, lo que deseamos es convertir esa unidad de tiempo, en segundos, deberemos introducir esta otra frmula:

=(HORA(D4)*(60*60))+(MINUTO(D4)*60)+SEGUNDO(D4)

Si somos un poco ms atrevidos y preferimos crearnos nuestras propias funciones en excel, podemos hacer algo como esto, para pasar todo a horas (debemos copiar y pegar estas funciones en un mdulo):

Function pasarahoras(celda As Range)dato = CDate(celda)datos = Split(dato, ":")horas = datos(0)horas = horas + (datos(1) / 60)horas = horas + (datos(2) / (60 * 60))pasarahoras = horasEnd Function

Esta otra funcin, nos servir para pasar el dato a minutos:

Function pasaraminutos(celda As Range)dato = CDate(celda)datos = Split(dato, ":")minutos = datos(0) * 60minutos = minutos + datos(1)minutos = minutos + (datos(2) / 60)pasaraminutos = minutosEnd Function

Y esta otra funcin, nos servir para pasar el dato a segundos:

Function pasarasegundos(celda As Range)dato = CDate(celda)datos = Split(dato, ":")segundos = datos(0) * 60 * 60segundos = segundos + (datos(1) * 60)segundos = segundos + datos(2)pasarasegundos = segundosEnd Function

Para llamar a esas funciones personalizadas, por ejemplo a la que nos convierte el dato en horas, nos bastar con escribir algo como esto, en cualquier celda:

=pasarahoras(D4)

Para pasar el dato a minutos, escribiremos esto otro:

=pasaraminutos(D4)

Y para pasar el dato a segundos, escribiremos esto otro:

=pasarasegundos(D4)

Tanto si utlizamos las funciones de tiempo propias de excel, como las funciones personalizadas que os propongo, el resultado que obtendremos ser exactamente el mismo.

Desde aqu podis descargar el fichero de excel, con el ejemplo que os presento en este artculo, para que podis ver en funcionamiento como se convierten unidades de tiempo, de dos formas distintas, con las funciones propias de excel, o con funciones personalizadas.

Publicado porJavier Marco Etiquetas: formatos, funciones personalizadas 6 comentarios:

Annimo dijo... 18 de agosto de 2008 13:28 Hola, la verdad es que me has solucionado un quebradero de cabeza importante pero tengo un problemilla.Yo tengo un programa de fichajes que me indica el balance con el siguiente formato:4:30 (4 horas 30 minutos) como yo necesito pasarlo a minutos y multiplicarlo por un valor para hallar el nmero de euros he aplicado la frmula que indicas:=(HORA(D62)*60)+MINUTO(D62)

El caso es que tengo un trabajador que ha hecho 27 horas extras en este mes. Al pasarlo a minutos, con esa frmula, no me salen los 1620 minutos correspondientes sino 180 que en realidad son 3 horas, las 3 horas ms por encima de 24. Cmo puedo solucionarlo?

Muchas graciasIsabel

Annimo dijo... 20 de agosto de 2008 18:14 qu bueno este blog, por lo til (hay mucho usuario de excel) y lo bien publiado que est

Javier Marco dijo... 21 de agosto de 2008 18:02 Hola Isabel, te comento que lo que quieres hacer, puede solucionarse de una forma un poco ms compleja.

Si e fijas, cuando pones como hora 27:30:00, en la barra de frmulas te aparece 01/01/1900 3:30:00, con lo que efectivamente, los clculos que se realizan, solo tiene en consideracin el tiempo transcurrido por encima de las 24 h.

Para solucionarlo, se me ha ocurrido esto. La celda donde tienes la hora (en el ejemplo 27:30:00), debe tener formato de texto (ya sabes, Formato --> Celdas --> Categora Texto).

Una vez hecho eso, crate esta frmula personalizada. Para ello, pulsa Alt+F11 para entrar en modo VBA, y creas un mdulo (Insertar --> Mdulo). Dentro del mdulo copias esta frmula:

Function minutillos(celda As Range)datos = Split(celda, ":")minutillos = datos(0) * 60minutillos = minutillos + datos(1)If UBound(datos) = 2 Thenminutillos = minutillos + (datos(2) / 60)End IfEnd Function

Y eso es todo. Ahora tan solo te quedar llamar a la funcin. Suponiendo que tienes la hora en la celda A1, pon por ejemplo en A2 esto:

=minutillos(A1)

Y con eso, resuelves el problema.

Un saludo. Sigo de vacaciones.

Por cierto, gracias por vuestros comentarios a ambos usuarios.

Michelle dijo... 22 de agosto de 2008 23:17 Me parecio, muy util la informacin yo trabajo constantemente con Excel y este es un problema que siempre se me presenta, pero ahora ya esta muy claro.....

Gracias....

Rafa dijo... 29 de agosto de 2008 10:53 Pues la verdad esde agradecer las molestias que te tomas en solucionar estos problemas.

Muchisssiiiimmas gracias, compaero.

saludos

Rafa

carol dijo... 29 de agosto de 2008 16:59 Hola!

Tienes un blog muy til!

Pero no encuentro exctamente lo que necesito. Te comento:

Tengo un libro Excel con varias hojas de clculo en la primera estn unos presupuestos de todos los meses del ao, y en las siguientes una copia de cada mes con ms formulas aadidas. Por lo que me gustara saber que hay que hacer para que cuando escriba algo en la 1 hoja (de la que he copiado cosas en la 2 xej) me aparezca en la hoja donde he copiado esa celda.

Muchas Gracias de antemano!!Saludos!

Convertir unidades de tiempo: horas, minutos, y segundos mircoles 13 de agosto de 2008

A veces nos es imprescindible convertir horas en minutos, o minutos en segundos, y no sabemos como podemos conseguirlo de una forma sencilla y sin complicaciones. Bueno, pues hoy os presento un par de funciones que nos ahorrarn estas conversiones.

Imaginemos que tenemos esto en una celda (7 horas, 12 minutos, y 45 segundos):

07:12:45

Si deseamos mostrar en pantalla el formato de esa forma, tendremos que situarnos en esa celda, y seleccionar desde el men Formato, la opcin Celdas, y en la pestaa Nmero, que es la que nos saldr en primer plano, por defecto, aadiremos dentro de la categora Personalizada, este formato: hh:mm:ss, tal y como se muestra en esta imagen:

Ahora imaginemos que deseamos convertir esas horas, minutos, y segundos, en una nica unidad de tiempo, por ejemplo, en horas. Para ello, tan solo deberemos introducir esta frmula en cualquier celda, excepto en aquella donde tenemos el dato a convertir. Suponiendo que tengamos el dato a convertir en la celda D4, escribiramos la frmula de la siguiente forma:

=HORA(D4)+(MINUTO(D4)/60)+(SEGUNDO(D4)/(60*60))

Si lo que deseamos es convertir esa unidad de tiempo, en minutos, deberemos introducir esta otra frmula:

=(HORA(D4)*60)+MINUTO(D4)+(SEGUNDO(D4)/60)

Y si por el contrario, lo que deseamos es convertir esa unidad de tiempo, en segundos, deberemos introducir esta otra frmula:

=(HORA(D4)*(60*60))+(MINUTO(D4)*60)+SEGUNDO(D4)

Si somos un poco ms atrevidos y preferimos crearnos nuestras propias funciones en excel, podemos hacer algo como esto, para pasar todo a horas (debemos copiar y pegar estas funciones en un mdulo):

Function pasarahoras(celda As Range)dato = CDate(celda)datos = Split(dato, ":")horas = datos(0)horas = horas + (datos(1) / 60)horas = horas + (datos(2) / (60 * 60))pasarahoras = horasEnd Function

Esta otra funcin, nos servir para pasar el dato a minutos:

Function pasaraminutos(celda As Range)dato = CDate(celda)datos = Split(dato, ":")minutos = datos(0) * 60minutos = minutos + datos(1)minutos = minutos + (datos(2) / 60)pasaraminutos = minutosEnd Function

Y esta otra funcin, nos servir para pasar el dato a segundos:

Function pasarasegundos(celda As Range)dato = CDate(celda)datos = Split(dato, ":")segundos = datos(0) * 60 * 60segundos = segundos + (datos(1) * 60)segundos = segundos + datos(2)pasarasegundos = segundosEnd Function

Para llamar a esas funciones personalizadas, por ejemplo a la que nos convierte el dato en horas, nos bastar con escribir algo como esto, en cualquier celda:

=pasarahoras(D4)

Para pasar el dato a minutos, escribiremos esto otro:

=pasaraminutos(D4)

Y para pasar el dato a segundos, escribiremos esto otro:

=pasarasegundos(D4)

Tanto si utlizamos las funciones de tiempo propias de excel, como las funciones personalizadas que os propongo, el resultado que obtendremos ser exactamente el mismo.

Desde aqu podis descargar el fichero de excel, con el ejemplo que os presento en este artculo, para que podis ver en funcionamiento como se convierten unidades de tiempo, de dos formas distintas, con las funciones propias de excel, o con funciones personalizadas.

Publicado porJavier Marco 6 comentarios Etiquetas: formatos, funciones personalizadas Ms sobre las funciones de bases de datos personalizadas mircoles 25 de junio de 2008

Silvia, mi amiga auditora, me ha planteado otro reto. Me pregunta: "Oye, si en excel tengo una relacin de personas, y una serie de datos asociados a cada uno de ellos, cmo puedo obtener las columnas en las que se obtienen determinados datos?". Como as, a bote pronto, y sin un ejemplo claro, parece un problema un poco abstracto, procedimos a montar un supuesto para dejar claras las cosas. El ejemplo era el siguiente:

La pregunta era bien clara: "cmo puedo obtener las columnas en las que se obtienen determinados datos?".

Bien, supongamos que queremos saber las veces que se obtiene el valor 1, para todos esos usuarios. En el caso de MANOLITO, el dato 1, se obtiene en la columna D y F, como se puede ver en la tabla anterior. Pero en el caso de FULANITO, el valor 1 no est presente en ninguna de las columnas.

La cuestin era crear un macro o una frmula que nos permitiera determinar las columnas en las que obtenemos el dato que busquemos. Al final decid montar una funcin, a la que he llamado localizar, y que tiene el siguiente cdigo:

Function Localizar(rango As Range, valor As Variant)'fichamos la celda donde estn los datos'inicial y final (el rango, vamos)mi_rango = rango.Address'separamos los datos inicial y finalcoordenadas = Split(mi_rango, ":")inicio = coordenadas(0)fin = coordenadas(1)'pasamos a una variable la direccin de la celda inicialcelda = Range(inicio).Address'para todo el rango de datos...For i = 0 To Range(fin).Column - Range(inicio).Column'Comprobamos el valor introducidoIf Range(celda) = valor Thencolumna = columna & " " & Range(celda).Address'eliminamos el signo de $ de referencia absolutacolumna = Replace(columna, "$", "")End If'pasamos a la siguiente columnacelda = Range(celda).Offset(0, 1).Address'seguimos con el bucleNext'Si no existe el dato en ninguna columnaIf columna = 0 Then columna = " No existe"'eliminamos los nmeros de la filanumeros = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)For j = 0 To UBound(numeros)columna = Replace(columna, numeros(j), "")Next'asignamos a la funcin, el dato del contador'eliminando previamente el primer espacio vacoLocalizar = Mid(columna, 2)End Function

Como veis en la primera lnea de la funcin, aparecen dos argumentos: el rango, y el valor. El rango es precisamente, el rea donde tenemos los datos, mientras que el valor es el dato que buscamos. La frmula nos devolver las letras correspondientes a las columnas donde aparezca ese valor.

Por ejemplo, si buscamos las columnas donde aparece el valor 1, para MANOLITO, deberemos seleccionar como rango, el rea comprendida entre C4 y G4, por lo que la funcin la llamaremos as:Como veis en la primera lnea de la funcin, aparecen dos argumentos: el rango, y el valor. El rango es precisamente, el rea donde tenemos los datos, mientras que el valor es el dato que buscamos. La frmula nos devolver las letras correspondientes a las columnas donde aparezca ese valor.

Por ejemplo, si buscamos las columnas donde aparece el valor 1, para MANOLITO, deberemos seleccionar como rango, el rea comprendida entre C4 y G4, por lo que la funcin la llamaremos as:Como veis en la primera lnea de la funcin, aparecen dos argumentos: el rango, y el valor. El rango es precisamente, el rea donde tenemos los datos, mientras que el valor es el dato que buscamos. La frmula nos devolver las letras correspondientes a las columnas donde aparezca ese valor.

Por ejemplo, si buscamos las columnas donde aparece el valor 1, para MANOLITO, deberemos seleccionar como rango, el rea comprendida entre C4 y G4, por lo que la funcin la llamaremos as:

=localizar(C4:G4;1)

Si lo preferimos, tambin podemos utilizar como valor, las coordenadas de la celda donde tenemos el dato a buscar. Por ejemplo, si en la celda A1 tuviramos un 1, podramos haber escrito la funcin, tal y como la hemos escrito antes, o bien de esta otra forma:

=localizar(C4:G4;A1)

Como podis ver en la imagen siguiente, aparece a la derecha la frmula localizar, donde nos devuelve como resultado, las columnas donde aparece el valor buscado. Si no se encuentra el valor, simplemente nos imprimir en pantalla el texto No existe, tal y como tambin podis ver en la imagen:

Desde aqu podis descargar el fichero de excel, con el ejemplo que os presento, y por supuesto, con la funcin y el cdigo de este artculo.

Publicado porJavier Marco 0 comentarios Etiquetas: funciones personalizadas Funciones de bases de datos personalizadas mircoles 18 de junio de 2008

No saba si llamar a este artculo "a mi manera" en memoria de la clebre cancin de Frank Sinatra, o bien llamarlo como lo he hecho. Posiblemente un ttulo como el que finalmente he desestimado, atrajese ms curiosos, frikis, y gente que se pierde por la red, pero menos pblico interesado realmente por las posibilidades de excel, y ms concretamente por la funciones de bases de datos, como la que hoy nos ocupa nuevamente, la funcin BDcontar, origen de lo que hoy os presento.

Todo ha nacido gracias a mi buena amiga Silvia, una chica de culo inquieto, que de vez en cuando delega en m el trabajo sucio. Como buena auditora de cuentas, dedica su tiempo al anlisis, y no a las tareas de control repetitivas. Eso implica que cuando tiene que controlar y analizar un conjunto extenso de datos, recurra a su buen amigo Javier, el mismo que escribe estas lneas, para que le solucione, si sabe -cosa que rara vez ocurre-, alguna de sus dudas para tratar tan compleja y abultada informacin.

Silvia me dijo: oye, mira a ver si puedes solucionarme este problema que tengo, que quiero acostarme pronto: tengo una base de datos en excel, con una serie de usuarios que se repiten unas cuantas veces. A su derecha tenemos una columna, con el permiso que se le otorga a cada usuario, pero que puede ser variado, entre Administrador y Usuario, pudindose repetir cualquiera de esos permisos, en las diferentes filas de la base de datos donde aparece ese usuario. Por qu no me creas una funcin que determine las veces se le otorga uno y otro permiso a ese usuario?.

Bueno, creo que me toc leer as como tres o cuatro veces la pregunta, para hacerme una idea de lo que quera mi buena amiga Silvia. Finalmente, y tras recibir su ejemplo, todo me qued mucho ms claro. Concretamente quera saber cuntas veces obtenamos el permiso Administrador y Usuario, para cada uno de los usuarios.

La tabla originaria era de unas 2.000 filas, pero para nuestro ejemplo nos dar igual 1 que 50, porque nos bastar utilizar una frmula y arrastrarla en tantas celdas como nos interese.

A lo que iba, la tabla originaria era esta:

Una de las posibilidades era crear un encabezado de datos, donde incluiramos el nombre del usuario y el permiso a evaluar. Algo as como esto:

Si os fijis, en la celda C22 estamos evaluando las veces que se obtiene el permiso de Administrador, para el usuario Andrea, pues esos son los datos del encabezado, de B2 a C3, es decir, los criterios o las condiciones de bsqueda. Esta funcin incorpora la novedad de que no se trata exactamente de la funcin BDcontar, sino de la funcin BDcontara, que se diferencia de aquella, en que esta permite el uso de datos de texto, mientras que la funcin BDcontar, solo evala datos numricos.

Esto tiene sus limitaciones, puesto que si tenemos 2.000 filas y deseamos evaluar tanto las veces que tenemos permisos de Administrador, como de Usuario, deberemos cambiar las celdas B3 y C3 muchsimas veces, tantas que se nos acabar la paciencia, y encontraremos la funcin BDcontara realmente intil.

Qu podemos hacer para simplificar esta tarea?. Pues crearnos una funcin personalizada (o como la llama excel, una funcin definida por el usuario). Despus de dedicar un rato a analizar la tarea, y tener bien claro que es lo que debamos incluir en la funcin, acab obteniendo una funcin en la que intervenan cuatro variables:

1.- El rango de datos: en nuestro ejemplo, de B7 a C20, pues son en esas celdas donde tenemos los datos.

2.- La columna donde figura el criterio que queremos contar: en nuestro ejemplo queremos contar tanto las veces que aparece la palabra Administrador como Usuario que aparecen en la segunda columna, por lo que deberemos informar que la columna a evaluar es la 2.

3.- El primer criterio de bsqueda: en nuestro caso, el nombre del usuario.

4.- El segundo criterio de bsqueda: en nuestro caso, Administrador y/o Usuario.

Y la funcin que obtuve, la llam Coincidencias, y fue esta:

Function Coincidencias(rango As Range, columna As Integer, _usuario As String, permiso As String)'fichamos la celda donde estn los datos'inicial y final (el rango, vamos)mi_rango = rango.Address'separamos los datos inicial y finalcoordenadas = Split(mi_rango, ":")inicio = coordenadas(0)fin = coordenadas(1)'pasamos a una variable la direccin de la celda inicialcelda = Range(inicio).Address'para todo el rango de datos...For i = 0 To Range(fin).Row - Range(inicio).Row'si el usuario coincide con el que'hemos introducido en la frmulaIf LCase(Range(celda)) = LCase(usuario) Then'comprobamos si el permiso es el que'hemos introducido en la frmulaIf LCase(Range(celda).Offset(0, columna - 1)) = LCase(permiso) Then'y en ese caso, sumamos 1contador = contador + 1End IfEnd If'pasamos a la siguiente filacelda = Range(celda).Offset(1, 0).Address'seguimos con el bucleNext'asignamos a la funcin, el dato del contadorCoincidencias = contadorEnd Function

Si os fijis, en C27 tenemos esta funcin:

=Coincidencias($B$7:$C$20;2;$B27;C$25)

Fijaos en la siguiente imagen:

Como veis, B7:C20 es el rango (est puesto en trminos absolutos, de ah el smbolo del $ que incorpora), la columna 2, el primer criterio que es B27 (Andrea), y el segundo criterio que es C25 (Administrador). Como podis comprobar, obtenemos el mismo dato que utilizando la funcin BDcontara, pero de una forma ms sencilla ahora que ya tenemos definida la funcin. Por eso nos bastar crear una tabla como la que he incluido yo desde B25 a D29, o en el caso de tener muchos datos (como as era en el ejemplo, pues tenamos 2.000 filas), tambin podemos poner la funcin en una columna anexa a la tabla de datos inicial, por ejemplo en la columna D. Si lo hacemos de esta ltima forma, podemos poner la funcin con los criterios referidos al valor de una celda, o bien podemos ponerlos directamente en la frmula, de tal forma que esto que vamos a presentar a continuacin ser exactamente lo mismo que lo que hemos visto anteriormente:

=Coincidencias($B$7:$C$20;2; "Andrea";"Administrador")

Y no hay ms cera que la que arde. Espero que esta funcin os haya sido tan til como le ha sido a mi amiga Silvia.

Desde aqu podis descargar el fichero de excel, con todo el cdigo que os presento en este artculo.

Publicado porJavier Marco 4 comentarios Etiquetas: funciones personalizadas Calcular la letra del NIF (o del DNI) mircoles 23 de abril de 2008

Hoy os presento una utilidad bastante sencilla, y que muchos ya conocis, especialmente los espaoles, pues esta utilidad es de aplicacin por estas tierras de Dios. Vamos a tratar de obtener la letra del NIF (Nmero de Identificacin Fiscal) o la letra del DNI (Documento Nacional de Identidad), pues desde hace ya unos aos, el DNI tambin incorpora la famosa letra de marras.

Antes de comenzar, veremos como se determina la letra que le corresponde a un NIF (o DNI), y luego pondremos eso en prctica de diferentes formas: utilizando una funcin personalizada, y utilizando un macro.

Para calcular la letra, tomaremos el nmero del NIF (o del DNI), y lo dividiremos entre 23, y al resto que obtengamos de esa divisin, le sumaremos 1. Esa cifra nos servir para asignarle una letra al NIF/DNI. El nmero mximo que obtendremos despus de hacer esa operacin, ser el 24. Veamos todo esto con un ejemplo prctico:

Si tenemos el NIF/DNI nmero 30.655.784, con esta frmula que podemos poner en cualquier celda, obtendremos ese nmero:

=RESIDUO(30655784;23)+1

En lugar de poner directamente en la frmula, el nmero del NIF/DNI, podemos poner la referencia a una celda (A1, A23, B12, M55, etc...), siempre y cuando, en esa celda tengamos el nmero del NIF/DNI.

Esa frmula de nuestro ejemplo, nos devuelve como cifra, el nmero 5. Ahora solo nos bastar obtener la letra a partir de ese nmero, a travs de la siguiente tabla:

1 = T2 = R3 = W4 = A5 = G6 = M7 = Y8 = F9 = P10 = D11 = X12 = B13 = N14 = J15 = Z16 = S17 = Q18 = V19 = H20 = L21 = C22 = K23 = E24 = T

Siguiendo con el ejemplo anterior, podemos observar que al 5, le corresponde la letra G, con lo cual, al NIF/DNI 30.655.784, le corresponde la letra G.

Vamos a ver como se puede resolver esto con una funcin personalizada:

Function LetraNIF(NIF As Long)'Controlamos que no sea un nmero'mayor de 8 cifrasIf NIF = 0 Or NIF > 99999999 ThenLetraNIF = "NIF incorrecto"Else'Dividimos el NIF entre 23, y nos'quedamos con el restoresto = (NIF Mod 23) + 1'la lnea anterior la podamos haber complicado'poniendo esto otro:'resto = NIF - ((Int(NIF / 23)) * 23) + 1'Ahora seleccionaremos la letra que'le corresponda al NIF introducido,'dependiendo del resto obtenidoSelect Case restoCase 1, 24LetraNIF = "T"Case 2LetraNIF = "R"Case 3LetraNIF = "W"Case 4LetraNIF = "A"Case 5LetraNIF = "G"Case 6LetraNIF = "M"Case 7LetraNIF = "Y"Case 8LetraNIF = "F"Case 9LetraNIF = "P"Case 10LetraNIF = "D"Case 11LetraNIF = "X"Case 12LetraNIF = "B"Case 13LetraNIF = "N"Case 14LetraNIF = "J"Case 15LetraNIF = "Z"Case 16LetraNIF = "S"Case 17LetraNIF = "Q"Case 18LetraNIF = "V"Case 19LetraNIF = "H"Case 20LetraNIF = "L"Case 21LetraNIF = "C"Case 22LetraNIF = "K"Case 23LetraNIF = "E"End SelectEnd IfEnd Function

Y llamaremos a la funcin, desde excel, de la siguiente forma:

=letraNIF(celda)

celda: corresponde a la celda donde tenemos el NIF/DNI (A12, B33, M58, o la celda de que se trate), aunque podemos poner directamente el NIF/DNI en la frmula, sin necesidad de referenciarlo a una celda.

Quizs te preguntes: "Se puede resumir esa funcin, para que no sea tan larga?". La respuesta es s. Vamos a aplicar esta otra funcin que hace exactamente lo mismo, pero con menos lneas de cdigo (ojo, a esta nueva funcin la llamaremos "LetradelNIF", mientras que la que acabamos de ver se llama "LetraNIF"):

Function LetradelNIF(NIF As Long)'Controlamos que no sea un nmero'mayor de 8 cifrasIf NIF = 0 Or NIF > 99999999 ThenletradelNif = "NIF incorrecto"Else'Tenemos una constante que contiene las'posibles letras que puede tener un NIFLista_de_letras = "TRWAGMYFPDXBNJZSQVHLCKE"'Cogemos el NIF, lo dividimos entre 23'y nos quedamos con el resto. Luego'al resto le sumamos 1, y obtenemos de'la lista de letras, la que corresponda'con ese nmero de NIFletradelNif = Mid(Lista_de_letras, (NIF Mod 23) + 1, 1)End IfEnd Function

Y llamaremos a la funcin, desde excel, de la siguiente forma:

=letradelNIF(celda)

celda: corresponde a la celda donde tenemos el NIF/DNI (A12, B33, M58, o la celda de que se trate), aunque podemos poner directamente el NIF/DNI en la frmula, sin necesidad de referenciarlo a una celda.

Si no queremos usarla con una funcin, y preferimos utilizar un inputbox para que el usuario introduzca el NIF/DNI, y nosotros devolvamos la letra en una celda cualquiera, podemos utilizar este procedimiento (en el ejemplo pondremos la letra que le corresponda al NIF/DNI introducido, en la celda B18):

Sub calcular_letra_del_NIF()NIF = InputBox("Introduce el NIF cuya letra quieres calcular:", "NIF")'Controlamos que no sea un nmero'mayor de 8 cifrasIf NIF = 0 Or NIF > 99999999 ThenRange("B18") = "NIF incorrecto"Else'Tenemos una constante que contiene las'posibles letras que puede tener un NIFLista_de_letras = "TRWAGMYFPDXBNJZSQVHLCKE"'Cogemos el NIF, lo dividimos entre 23'y nos quedamos con el resto. Luego'al resto le sumamos 1, y obtenemos de'la lista de letras, la que corresponda'con ese nmero de NIFRange("B18") = Mid(Lista_de_letras, (NIF Mod 23) + 1, 1)End IfEnd Sub

Y si lo queremos a travs de un bonito UserForm?. ...Joder, s que peds cosas!!!. Bueno, vale, aqu os dejo la otra opcin, la de utilizar un UserForm. Para los que no lo sepan, aqu explico como crear un USerForm. Para ello, crearemos un UserForm como este (doble clic en la imagen, para verla ms grande), al que llamaremos Letra_NIF:

Haremos clic en el botn del UserForm llamado "Calcular la letra", y pegaremos este cdigo:

Private Sub CalcularLetra_Click()On Error GoTo Fin'Si el nmero del NIF est vacoIf NumeroNIF = Empty ThenNumeroNIF.SetFocusMsgBox (Chr(13) + " Por favor, introduce el nmero del N.I.F. " _+ Chr(13) + Chr(13)), vbOKOnly, " Datos incompletos"End If'Si el nmero del NIF no es numricoIf Not IsNumeric(NumeroNIF) Then'que elimine la entradaNumeroNIF = EmptyNumeroNIF.SetFocusEnd If'Si el nmero del NIF tiene separador de miles,'lo enva a la Linea1If NumeroNIF = Format(NumeroNIF, "#,##0") ThenGoTo Linea1End If'Si el formato es distinto del numricoIf NumeroNIF Format(NumeroNIF, "##0") Then'que elimine las entradaNumeroNIF = EmptyTexto2.Caption = EmptyTexto3.Caption = EmptyNumeroNIF.SetFocusEnd IfLinea1:'si el nmero del NIF es numricoIf IsNumeric(NumeroNIF) And NumeroNIF > 0 Then'le da formato con punto de millarNumeroNIF = Format(NumeroNIF, "##,##0")'Tenemos una constante que contiene las'posibles letras que puede tener un NIFLista_de_letras = "TRWAGMYFPDXBNJZSQVHLCKE"'Cogemos el NIF, lo dividimos entre 23'y nos quedamos con el resto. Luego'al resto le sumamos 1, y obtenemos de'la lista de letras, la que corresponda'con ese nmero de NIFTexto2.Caption = Mid(Lista_de_letras, (NumeroNIF Mod 23) + 1, 1)'ponemos la etiqueta correspondienteTexto3.Caption = NumeroNIF & "-" & Texto2.CaptionEnd IfFin:End Sub

Justo debajo de ese cdigo, pondremos este otro:

Private Sub NumeroNIF_Enter()On Error GoTo Fin'eliminamos las entradasNumeroNIF = EmptyTexto2.Caption = EmptyTexto3.Caption = EmptyFin:End Sub

Y este otro:

Private Sub NumeroNIF_MouseDown(ByVal Button As Integer, _ ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)On Error GoTo Fin'eliminamos las entradasNumeroNIF = EmptyTexto2.Caption = EmptyTexto3.Caption = EmptyFin:End Sub

Y este otro tambin:

Private Sub cerrar_Click()On Error GoTo Fin'Descarga el formulario de la memoriaUnload MeFin:End Sub

Y ya para finalizar, solo nos bastar incluir este cdigo en un mdulo:

Sub calcular_letra_NIF()On Error GoTo FinLetra_NIF.ShowFin:End Sub

Desde aqu podis descargar el fichero de excel, con todo el cdigo que os presento en este artculo.

Publicado porJavier Marco 3 comentarios Etiquetas: funciones personalizadas, macros en excel Extraer la incial de cada palabra jueves 6 de marzo de 2008

Esta funcin personalizada que hoy os presento, no es que tenga excesiva utilidad, pero bueno, nos sirve para aprender ms sobre el uso de vectores, o arrays. Es lo que tiene Excel, que nos permite construirnos nuestras propias funciones, de la misma forma que tenemos otras ya predefinidas, como SUMA, CONTAR, SI, o FECHA, por poner solo unos ejemplos.

Imaginemos que tenemos en una columna, un listado con nombres de personas (nombre y dos apellidos), y que deseamos poner en la columna contigua, las iniciales de cada uno de los nombres. Podemos hacerlo a mano, de tal forma que si tenemos por ejemplo en la lista, una persona llamada Irene Hermosilla Martn, en la columna continua deberemos poner IHM, a mano.

Para hacerlo de una forma ms profesional, vamos a construir una funcin que nos permita hacer eso de forma mucho ms rpida, para lo cual copiaremos y pegaremos esto en un mdulo:

Function iniciales(celda As Range)'Descomponemos el texto, en partes,'para lo cual indicamos el delimitador " ", aunque'por defecto, podramos haberlo omitido, pues es ese mismo'(espacio), con lo cual tendremos tantas palabras,'como estn separadas por espaciostexto = Split(Trim(celda), " ", -1, 1)'miramos las palabras que componen el texto,'para lo cual le decimos que recorra desde el primer'valor de la matriz (empieza en cero), hasta el mximo'valor (n de la ltima palabra) que lo obtenemos con el UBoundFor i = 0 To UBound(texto)'ponemos la inicial en maysculas, y el resto'de las letras, simplemente no nos interesantexto(i) = UCase(Left(texto(i), 1))Next'Unimos los textos, con la funcin Jointexto = Join(texto)'quitamos el espacio que separa las inicialestexto = Replace(texto, " ", "")'pasamos los datos a la funcininiciales = textoEnd Function

Y como llamamos a esa funcin?. Pues simplemente as:

=iniciales(celda)

celda: corresponde a la celda, cuyas iniciales deseamos extraer (A12, B33, M58, o la celda de que se trate).

He aqu un ejemplo donde ponemos en la fila de abajo, las iniciales del nombre que aparece justo encima. Fijaos en la barra de frmulas donde aparece lo de =iniciales(B3):

Publicado porJavier Marco 2 comentarios Etiquetas: funciones personalizadas, macros en excel Contar palabras martes 19 de febrero de 2008

En una entrega anterior, vimos como se podan contar caracteres, a travs de una funcin personalizada que habamos creado. Esta vez haremos algo parecido, pero en lugar de contar caracteres, contaremos palabras enteras, despreciando los signos de puntuacin, por si los colocamos incorrectamente.

Function contarpalabras(celda As Range)'si ponemos un espacio antes de los signos de'puntuacin, mejor los eliminamos del cmputodatos = Replace(celda, ".", "")datos = Replace(datos, ",", "")datos = Replace(datos, ";", "")datos = Replace(datos, ":", "")'reemplazamos los posibles dobles espaciosdatos = Replace(datos, " ", " ")'eliminamos los espacios inicial y finaldatos = Trim(datos)'Descomponemos la cadena, en subcadenas,'para lo cual indicamos el delimitador " ", aunque'por defecto, podramos haberlo omitido,'pues es ese mismo (espacio)palabras = Split(datos, " ")'Buscamos el mximo de palabras que se han'formado, y le sumamos 1, porque el array'comienza a contar desde ceronumero_de_palabras = UBound(palabras) + 1'asignamos ese mximo a la funcincontarpalabras = numero_de_palabrasEnd Function

Tan solo nos quedar llamar a la funcin desde nuestra hoja de clculo de excel, para lo cual, nos bastar con introducirla de la siguiente forma:

=contarpalabras(celda)

celda: corresponde a la celda, cuyos caracteres queremos contar (A1, A5, B35, AB167, o la que sea).

Y nos quedar algo como esto que vemos en pantalla:

Publicado porJavier Marco 4 comentarios Etiquetas: funciones personalizadas, macros en excel Contar el nmero de caracteres mircoles 23 de enero de 2008

Hoy os presento una funcin que nos puede servir para contar el nmero de caracteres que tiene una cadena de texto, sin contar los espacios en blanco (si queremos contar tambin los espacios en blanco, tan solo tendremos que cambiar ligeramente el cdigo que os propongo, tal y como aparece en la segunda funcin). Para ello, construiremos una funcin que nos ahorrar tiempo y trabajo. Comenzaremos entrando en modo VBA, ...ya sabis, Alt + F11, y creando un mdulo donde introduciremos el siguiente cdigo:

Function contarsinespacios(celda As range)'Reemplazamos los espacios vacos por nada,'es decir, los eliminamos, pero solo a efectos'del clculo del n de caracteres.mi_texto = Replace(celda, " ", "")'Contamos los caracteres que hay, ahora que tenemos el'texto en la variable mi_texto, el texto sin espacios vacoscantidad_de_texto = Len(mi_texto)'ponemos el nmero de caracteres en la celda'donde tenemos esta funcin (la fmula)contarsinespacios = cantidad_de_textoEnd Function

Ahora solo tendremos que llamar a la funcin, de la misma forma que llamamos por ejemplo a la funcin SUMA:

=contarsinespacios(celda)

celda: corresponde a la celda, cuyos caracteres queremos contar (A1, A5, B35, AB167, o la que sea).

He aqu un ejemplo grfico que lo aclarar todo:

Si deseamos que la funcin nos cuente tambin el nmero de espacios en blanco, tan solo tendremos que adaptar la funcin anterior, a esta nueva forma (ojo, que tambin le hemos cambiado el nombre a la funcin):

Function contarconespacios(celda As range)'Contamos los caracteres que haycantidad_de_texto = Len(celda)'ponemos el nmero de caracteres en la celda'donde tenemos esta funcin (la fmula)contarconespacios = cantidad_de_textoEnd Function

Para llamar a la funcin, lo haremos igual que en el ejemplo anterior:

=contarconespacios(celda)

celda: corresponde a la celda, cuyos caracteres queremos contar (A1, A5, B35, AB167, o la que sea).

Publicado porJavier Marco 4 comentarios