SINCRONIZAR LA INFORMACIÓN DE VARIOS LISTBOX

Hola a todos!

Qué tal os va?, espero que muy bien!. El post de hoy tratará sobre los listbox y la posibilidad de sincronizar la información entre varios.

Como es habitual, el post surge fruto de una duda, en la que el lector planteaba la siguiente problemática: Tenía varios listbox en los que se mostraban varios campos de un tabla de Excel y lo que necesitaba es que si en el primero seleccionada un determinado ítem, en el segundo se debía mostrar la información relacionada con ese ítem, y así hasta varios.

Como sabéis, cuando cargamos información en varios listbox, aunque provengan de la misma tabla, la selección y el uso del scroll es totalmente independiente el uno del otro. Para hacer lo que el lector solicita, debemos sincronizarlos. Ahora os mostraré el ejemplo.

Vamos a cargar una base de datos en 3 listbox:

SINCRONIZAR LA INFORMACION DE VARIOS LISTBOX

En este ejemplo voy a utilizar ADO para cargar los listbox (no es el tema del post) y ya lo vimos en otras entradas, por ejemplo: CARGAR DATOS EN LISTBOX Y REALIZAR BÚSQUEDAS CON ADO Y CONSULTAS SQL por eso, no voy a publicar aquí el código, os lo dejo en el archivo de prueba.

Pues bien, la información cargada quedaría así:

SINCRONIZAR LA INFORMACION DE VARIOS LISTBOX_1

Como podéis observar he dejado un textbox para realizar búsquedas dado que he reutilizado parte del código de la entrada que os he mencionado al principio.

Y ahora, para sincronizar los listbox, debemos utilizar el evento click en cada uno de ellos y pegar este código en el formulario:

Private Sub ListBox1_Click()
ListBox2.ListIndex = ListBox1.ListIndex
ListBox2.TopIndex = ListBox1.TopIndex
ListBox3.ListIndex = ListBox1.ListIndex
ListBox3.TopIndex = ListBox1.TopIndex
End Sub

Private Sub ListBox2_Click()
ListBox1.ListIndex = ListBox2.ListIndex
ListBox1.TopIndex = ListBox2.TopIndex
ListBox3.ListIndex = ListBox2.ListIndex
ListBox3.TopIndex = ListBox2.TopIndex
End Sub

Private Sub ListBox3_Click()
ListBox1.ListIndex = ListBox3.ListIndex
ListBox1.TopIndex = ListBox3.TopIndex
ListBox2.ListIndex = ListBox3.ListIndex
ListBox2.TopIndex = ListBox3.TopIndex
End Sub

Lo que estamos haciendo es igualar la propiedad .ListIndex para identificar el elemento que tiene el foco y el .TopIndex para detectar el elemento en la parte superior del listbox.

El resultado será que siempre marcaremos la línea de información del ítem seleccionado en todos los listbox:

SINCRONIZAR LA INFORMACION DE VARIOS LISTBOX_2

y eso es todo. Ya está solucionada la consulta : )

Descarga el archivo de ejemplo pulsando en: SINCRONIZAR LA INFORMACIÓN DE VARIOS LISTBOX

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

Mediante la suscripción al blog, la realización comentarios o el uso del formulario de contacto estás dando tu consentimiento expreso al tratamiento de los datos personales proporcionados según lo dispuesto en la ley vigente (LOPD). Tienes más información al respecto en esta página del blog: Política de Privacidad y Cookies

Anuncios

LIMPIAR CONTENIDO DE CONTROLES DE FORMULARIO EN HOJA EXCEL O EN USERFORM

Hola a todos!.

Hoy me gustaría dejaros un par de códigos para borrar el contenido de los controles de formulario, tanto aquellos que se insertan en la hoja excel como aquellos que insertamos en nuestros userform o formularios en el editor de VBA.

Voy a comenzar con los controles insertados en una hoja (controles ActiveX), por ejemplo una en la que tengamos varios: Textbox, ComboBox, ListBox y CheckBox. Para que podamos automatizar el proceso de forma óptima debemos utilizar la instrucción Select Case:

Sub LIMPIAR_CONTROLES()
With ActiveSheet
'Por cada objeto que indiquemos en el select case, borramos contenido
For Each Control In .OLEObjects
Select Case TypeName(Control.Object)
Case "TextBox"
Control.Object.Text = vbNullString
Case "ComboBox"
Control.Object.Clear
Case "ListBox"
Control.Object.Clear
Case "CheckBox"
Control.Object.Value = False
End Select
Next Control
End With
End Sub

Dado que estamos trabajando con controles ActiveX debemos tratar en nuestro código con los objetos OLEObject, que son los que nos van a permitir interactuar con nuestra hoja. A continuación solo tendremos que especificar el tipo de objeto y la forma en la que debemos limpiarlo o vaciarlo en el Select – Case.

Con los Formularios o Userforms resulta más sencillo, dado que haremos referencia a la colección Controls. El resultado del código es similar al anterior:

Private Sub CommandButton1_Click()
'Por cada objeto que indiquemos en el select case, borramos contenido
For Each Control In Me.Controls
Select Case TypeName(Control)
Case "TextBox"
Control.Text = vbNullString
Case "ComboBox"
Control.Clear
Case "ListBox"
Control.Clear
Case "CheckBox"
Control.Value = False
End Select
Next Control
End Sub

Como podéis ver, ambas estructuras son idénticas (salvo por la forma de hacer referencia a los controles de formulario).

Dado que se trata de fragmentos de código bastante específicos y sencillos, considero que no requieren un archivo de ejemplo. Os invito a que los probéis en vuestros proyectos : )

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

Mediante la suscripción al blog, la realización comentarios o el uso del formulario de contacto estás dando tu consentimiento expreso al tratamiento de los datos personales proporcionados según lo dispuesto en la ley vigente (LOPD). Tienes más información al respecto en esta página del blog: Política de Privacidad y Cookies

INTRODUCIR MÚLTIPLES VALORES EN UN INPUTBOX

Hola a todos!.

Qué tal estáis? espero que bien! y supongo que muchos de vosotros ya estáis disfrutando de las vacaciones o esperando a que lleguen.

Hoy voy a comentar una solución que le ofrecí a un lector que me consultaba cómo podría introducir en un inputbox dos o más datos. Normalmente esta tarea se realiza con un formulario o userform, habilitando tantos cuadros de texto como sean necesarios.

Pero en el caso del inputbox solo tenemos un cuadro de texto, sin posibilidad de poder crear más cuadros de texto. Lo que nos obligaría a crear tantos inputbox como datos necesitemos introducir.

Pero existe una solución para poder introducir valores múltiples en un inputbox. Veamos un ejemplo, imaginad que queréis pasar dos fechas (Inicio y Fin) a través del mismo inputbox y mostrar los datos en las siguientes celdas:

INTRODUCIR MÚLTIPLES VALORES EN UN INPUTBOX

Para poder hacerlo, vamos a utilizar el siguiente código que he programado:

Sub INPUT_VARIOS()
'Declaramos las variables
Dim formulario, miarray
'Invocamos inputbox e indicamos las fechas separadas por una coma
formulario = InputBox("INDICA FECHA INICIO Y FECHA FIN SEPARADO POR UNA COMA:" & Chr(13) & Chr(13) & "EJEM: 01/01/2018,01/03/2018", "FECHAS")
'Si no ponemos nada, salimos del proceso
If formulario = Empty Then Exit Sub
'verificamos que los datos introducidos son correctos, si hay errores, los detectamos al final
On Error GoTo etiqueta
'Pasamos las dos fechas a una matriz utilizando la función split
miarray = Split(formulario, ",")
'Pasamos los datos a cada celda igualando los array
With Sheets("Hoja1")
.Cells(2, 1) = CDate(miarray(0))
.Cells(2, 2) = CDate(miarray(1))
End With
Exit Sub
etiqueta:
MsgBox ("Verifica los datos que has introducido e inténtalo de nuevo"), vbExclamation
End Sub

Al ejecutarlo veremos el siguiente inputbox en nuestra hoja:

INTRODUCIR MÚLTIPLES VALORES EN UN INPUTBOX_1

Como podéis observar en la macro, estamos utilizando la función split para pasar la información que hemos indicado en cuadro de texto del inputbox a una matriz. Como necesitamos indicar un elemento o carácter que separe las dos fechas (o cualquier otro dato), he decido utilizar la coma “,”aunque podríamos usar el punto y coma, “;” una arroba “@” etc, sustituyéndolo en la macro:

miarray = Split(formulario, ",")

Una vez que tenemos ambos datos, tan solo tendremos que pasar la información a las celdas de la hoja que necesitamos rellenar y lo hacemos pulsando en el botón aceptar de nuestro inputbox. Como cortesía hacia el lector, he programados varias líneas de código para controlar los datos erróneos o que surjan errores a la hora de ejecutar la macro.

El resultado es que tenemos en las celdas la información indicada en el cuadro de texto:

INTRODUCIR MÚLTIPLES VALORES EN UN INPUTBOX_2

Y eso es todo, como podéis observar sí es posible introducir valores múltiples en un inputbox.

Descarga el archivo de ejemplo pulsando en: INTRODUCIR MÚLTIPLES VALORES EN UN INPUTBOX

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

Mediante la suscripción al blog, la realización comentarios o el uso del formulario de contacto estás dando tu consentimiento expreso al tratamiento de los datos personales proporcionados según lo dispuesto en la ley vigente (LOPD). Tienes más información al respecto en esta página del blog: Política de Privacidad y Cookies

ELIMINAR DUPLICADOS DIRECTAMENTE SOBRE EL CONTENIDO DE UN LISTBOX

Hola a todos:

Ya sabéis que en esta web hay varias entradas que tratan el tema de los duplicados o cómo obtener registros únicos en nuestras informaciones, tanto en formularios como en bases de datos y usando métodos diferentes.

Sin embargo, esta semana un lector me solicitaba lo siguiente:

¿Es posible quitar los duplicados de un listbox mediante un boton
tomando los datos directamente del listbox sin tener que guardar la informacion a una hoja o tabla de calculo y que mantengan el mismo orden en el que fueron encontrados los registros por primera vez?

Es decir, interactuar directamente con el contenido del listbox sin posibilidad de acudir a la fuente de los datos y eliminar los duplicados antes de cargar la información en el listbox.

Aunque soy partidario de tratar la información antes de enviarla a un listbox (o combobox, etc…), lo cierto es que sí es posible hacer lo que el lector solicita. Y ese es el objetivo de este post.

Vamos a tomar un ejemplo en el que tenemos una base de datos con duplicados:

ELIMINAR DUPLICADOS DIRECTAMENTE SOBRE EL CONTENIDO DE UN LISTBOX

Estos datos los pasamos a un listbox en nuestro formulario y el código que utilizaremos para cargar el listbox es el siguiente:

Private Sub UserForm_Initialize()
Dim fin As Long
'Indicamos el número de columnas que tendrá el listbox
Me.ListBox1.ColumnCount = 7
'Definimos tamaño de los espacios
Me.ListBox1.ColumnWidths = "30pt;150pt;150pt;50pt;50pt;60pt"
'Cargamos listbox
With Sheets("BBDD")
fin = Application.CountA(.Range("A:A"))
Me.ListBox1.List = .Range("A2:G" & fin).Value
End With
End Sub

Es importante usar la propiedad listbox.list para cargar la información, dado que nos posibilitará el poder eliminar duplicados directamente en el listbox con el método RemoveItem.

ELIMINAR DUPLICADOS DIRECTAMENTE SOBRE EL CONTENIDO DE UN LISTBOX1

Podéis ver que nuestro listbox muestra todos los duplicados, pues bien, para eliminar los duplicados usaremos esta otra macro, vinculada al botón de comando “ELIMINAR DUPLICADOS”:

Private Sub CommandButton1_Click()
'Declaramos variables
Dim i As Long, j As Long
With ListBox1
'Eliminamos duplicados
For i = 0 To .ListCount - 1
For j = .ListCount - 1 To (i + 1) Step -1
If .List(j) = .List(i) Then .RemoveItem j
Next j
Next i
End With
End Sub

Una vez que hemos pulsado el botón, automáticamente se eliminan los duplicados en nuestro listbox, así:

ELIMINAR DUPLICADOS DIRECTAMENTE SOBRE EL CONTENIDO DE UN LISTBOX2

Pues bien, el utilizar la propiedad .list nos ha permitido solucionar este problema. Ahora ya tenemos nuestro listbox sin duplicados y listo para ser usado en otras tareas.

Espero que os haya resultado interesante y que os pueda ayudar en vuestros trabajos y proyectos.

Como siempre, os dejo el archivo de ejemplo : )

Descarga el archivo de ejemplo pulsando en: ELIMINAR DUPLICADOS DIRECTAMENTE SOBRE EL CONTENIDO DE UN LISTBOX

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

REALIZAR BÚSQUEDAS DEPENDIENTES EN UN LISTBOX

Hola a todos : )

Hace unos días me enviaron una consulta en la que me solicitaban la necesidad de poder realizar consultas dependientes en un listbox.

Sobre el tema de las consultas dependientes, ya había tratado algo en esta entrada: COMBOBOX DEPENDIENTES EN USERFORM CON SQL , solo que esa ocasión estaba utilizando combobox.

En concreto, en esa consulta el filtro debería hacerse sobre un único listbox y utilizando varios textbox para indicar los items por los que realizar el filtrado.

Utilizará la base de datos de empleados de unos grandes almacenes (ya es un clásico en esta web) y pasaré los datos a un listbox:

Esta es la base de datos:

REALIZAR BUSQUEDAS DEPENDIENTES EN UN LISTBOX

Y mediante este código pasamos la información al listbox:

Private Sub UserForm_Initialize()
'Indicamos el número de columnas que tendrá el listbox
Me.ListBox1.ColumnCount = 7
'Definimos tamaño de los espacios
Me.ListBox1.ColumnWidths = "30pt;150pt;150pt;50pt;50pt;60pt"
'Cargamos listbox
Me.ListBox1.RowSource = ("A2:G") & Worksheets("BBDD").Range("A" & Rows.Count).End(xlUp).Row
End Sub

Aquí ya tenemos la información cargada:

REALIZAR BUSQUEDAS DEPENDIENTES EN UN LISTBOX2

Pero ahora debemos filtrar según nuestras necesidades. Para este ejemplo realizaré un secuencia de tres consultas dependientes: Primero filtramos por Sección, una vez tengamos esos datos, filtramos por Estudios y finalmente, filtraremos por Idioma.

Para ello es necesario crear tres textbox, y en cada uno de ellos realizar la programación correspondiente. Os dejo el código de cada textbox:

TextBox1 – Filtrar por Sección:

Private Sub TextBox1_Change()
'Declaramos variables
Dim fin As Long, i As Long, n As Long
Dim sCadena_seccion As String
'Filtramos por sección
With Sheets("BBDD")
fin = Application.CountA(.Range("A:A"))
If TextBox1 = "" Then
Me.ListBox1.RowSource = ("A2:G") & Worksheets("BBDD").Range("A" & Rows.Count).End(xlUp).Row
Exit Sub
End If
Me.TextBox2 = Clear
Me.TextBox3 = Clear
Me.ListBox1.RowSource = Clear
For i = 2 To fin
sCadena_seccion = .Cells(i, 3).Value
If UCase(sCadena_seccion) Like "*" & UCase(TextBox1.Value) & "*" Then
Me.ListBox1.AddItem
Me.ListBox1.List(n, 0) = .Cells(i, 1).Value
Me.ListBox1.List(n, 1) = .Cells(i, 2).Value
Me.ListBox1.List(n, 2) = .Cells(i, 3).Value
Me.ListBox1.List(n, 3) = .Cells(i, 4).Value
Me.ListBox1.List(n, 4) = .Cells(i, 5).Value
Me.ListBox1.List(n, 5) = .Cells(i, 6).Value
Me.ListBox1.List(n, 6) = .Cells(i, 7).Value
n = n + 1
End If
Next
Me.ListBox1.ColumnWidths = "30pt;150pt;150pt;50pt;50pt;60pt"
End With
End Sub

TextBox2 – Filtrar por Estudios:

Private Sub TextBox2_Change()
Dim fin As Long, i As Long, n As Long
Dim sCadena_seccion As String, sCadena_estudios As String
'Una vez filtrados los datos por sección, filtramos por estudios
With Sheets("BBDD")
fin = Application.CountA(.Range("A:A"))
If TextBox2 = "" Then
Me.ListBox1.RowSource = ("A2:G") & Worksheets("BBDD").Range("A" & Rows.Count).End(xlUp).Row
Exit Sub
End If
Me.ListBox1 = Clear
Me.ListBox1.RowSource = Clear
For i = 2 To fin
sCadena_seccion = .Cells(i, 3).Value
sCadena_estudios = .Cells(i, 7).Value
If UCase(sCadena_seccion) Like "*" & UCase(TextBox1.Value) & "*" And _
UCase(sCadena_estudios) Like "*" & UCase(TextBox2.Value) & "*" Then
Me.ListBox1.AddItem
Me.ListBox1.List(n, 0) = .Cells(i, 1).Value
Me.ListBox1.List(n, 1) = .Cells(i, 2).Value
Me.ListBox1.List(n, 2) = .Cells(i, 3).Value
Me.ListBox1.List(n, 3) = .Cells(i, 4).Value
Me.ListBox1.List(n, 4) = .Cells(i, 5).Value
Me.ListBox1.List(n, 5) = .Cells(i, 6).Value
Me.ListBox1.List(n, 6) = .Cells(i, 7).Value
n = n + 1
End If
Next
Me.ListBox1.ColumnWidths = "30pt;150pt;150pt;50pt;50pt;60pt"
End With
End Sub

TextBox3 – Filtrar por Idiomas:

Private Sub TextBox3_Change()
Dim fin As Long, i As Long, n As Long
Dim sCadena_seccion As String, sCadena_estudios As String, sCadena_idioma As String
'una vez filtrada la información por sección y estudios, filtramos por idioma

With Sheets("BBDD")

fin = Application.CountA(.Range("A:A"))
If TextBox2 = "" Then
Me.ListBox1.RowSource = ("A2:G") & Worksheets("BBDD").Range("A" & Rows.Count).End(xlUp).Row
Exit Sub
End If
Me.ListBox1 = Clear
Me.ListBox1.RowSource = Clear
For i = 2 To fin
sCadena_seccion = .Cells(i, 3).Value
sCadena_estudios = .Cells(i, 7).Value
sCadena_idioma = .Cells(i, 6).Value
If UCase(sCadena_seccion) Like "*" & UCase(TextBox1.Value) & "*" And _
UCase(sCadena_estudios) Like "*" & UCase(TextBox2.Value) & "*" And _
UCase(sCadena_idioma) Like "*" & UCase(TextBox3.Value) & "*" Then
Me.ListBox1.AddItem
Me.ListBox1.List(n, 0) = .Cells(i, 1).Value
Me.ListBox1.List(n, 1) = .Cells(i, 2).Value
Me.ListBox1.List(n, 2) = .Cells(i, 3).Value
Me.ListBox1.List(n, 3) = .Cells(i, 4).Value
Me.ListBox1.List(n, 4) = .Cells(i, 5).Value
Me.ListBox1.List(n, 5) = .Cells(i, 6).Value
Me.ListBox1.List(n, 6) = .Cells(i, 7).Value
n = n + 1
End If
Next
Me.ListBox1.ColumnWidths = "30pt;150pt;150pt;50pt;50pt;60pt"
End With
End Sub

Una vez te tenemos el código incluido en todos los controles, ya podemos proceder a probar la herramienta. Probaremos con la siguiente consulta: todos los empleados que pertenezcan a la sección de “Bricolaje“, que en sus estudios sean “Diplomados” y que sepan “Chino“.

El resultado es el siguiente:

REALIZAR BUSQUEDAS DEPENDIENTES EN UN LISTBOX3

Como podéis observar, el filtro funciona perfectamente y no es necesario escribir la palabra completa en los textbox, basta con ir escribiendo y la información se irá mostrando. En este caso tenemos a dos personas, perfecto!.

Y eso es todo, creo que es un método muy sencillo, donde trabajamos con un loop, un buscador y cargamos información si los parámetros de la consulta coinciden.

Espero que os resulte de interés : )

Descarga el archivo de ejemplo pulsando en: REALIZAR BÚSQUEDAS DEPENDIENTES EN UN LISTBOX

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

ELIMINAR REGISTROS DUPLICADOS Y ORDENAR ALFABÉTICAMENTE LA INFORMACIÓN

Hola a todos:

En el post anterior hemos visto una nueva técnica para obtener registros únicos usando el objeto “Diccionario”: ELIMINAR REGISTROS DUPLICADOS Y CARGAR DATOS ÚNICOS EN COMBOBOX Y LISTBOX

Entre las consultas que me enviaron los lectores, una de ellas era sobre si se podían ordenar esos datos una vez eliminados los duplicados y pasar esa información al combobox y al listbox. Como me pareció útil e interesante, he decidido crear un nuevo post como continuación al anterior (de esta forma se verá más claro).

Partiendo de una información diferente, no meses, sino por nombre de personas:

ELIMINAR REGISTROS DUPLICADOS Y ORDENAR ALFABETICAMENTE LA INFORMACION

Vamos a hacer el mismo ejercicio que en post anterior, es decir, eliminar duplicados, ordenar la información y pasar los datos a un combobox y a un listbox:

Sub CARGAR_UNICOS_ORDENADOS()
'Declaramos las variables
Dim rango As Range, celda As Object, oDic As Object, npalabra As String
Dim sCadena As String, sCadena1 As String, ipalabra As String, OrdenarAlfa As Variant
Dim matriz As Variant, matriz1 As Variant, palabra As Variant, alfadato As Variant
Dim i As Long, j As Long, fin As Integer
'Trabajamos con la hoja
With Sheets("UNICOS")
'Limpiamos combo y listbox
.ComboBox1.Clear
.ListBox1.Clear
'Definimos el rango de los datos
fin = .Range("A" & Rows.Count).End(xlUp).Row
'Trabajamos con rango establecido
Set rango = .Range("A2:A" & fin)
'Por cada celda del rango componemos un string
For Each celda In rango
If celda <> vbNullString Then
ipalabra = ipalabra & "," & celda
End If
Next celda
'Eliminamos posibles espacios en blanco
sCadena = Trim(Mid(ipalabra, 2, Len(ipalabra)))
'Comprobamos que cada palabra que incluimos en la matriz no existe en cadena
matriz = Split(sCadena, ",")
Set oDic = CreateObject("scripting.dictionary")
For i = 0 To UBound(matriz)
If Not oDic.Exists(matriz(i)) Then oDic.Add matriz(i), matriz(i)
Next i
'Creamos una nueva cadena ya sin duplicados
sCadena1 = Join(oDic.Keys, ",")
'Pasamos los datos a una matriz
Set matriz1 = CreateObject("System.Collections.ArrayList")
'Y ordenamos las palabras
For Each palabra In Split(sCadena1, ",")
matriz1.Add palabra
Next palabra
matriz1.Sort
'Pasamos de nuevo las palabras ordenadas a un string
For Each alfadato In matriz1
npalabra = npalabra & "," & alfadato
Next alfadato
OrdenarAlfa = Split(Trim(Mid(npalabra, 2, Len(npalabra))), ",")
'Pasamos los datos al Combo y al listbox
For j = 0 To UBound(OrdenarAlfa)
.ComboBox1.AddItem (OrdenarAlfa(j))
.ListBox1.AddItem (OrdenarAlfa(j))
Next
'Limpiamos variable de objeto
Set rango = Nothing
Set oDic = Nothing
End With
End Sub

Si vais observando la construcción de la macro, podéis ver que hemos incluido un pequeño subproceso en el código a través del cual volvemos a pasar los datos del rango a una matriz y los ordenamos con la propiedad “.sort”.

El resto del código es igual que el ejemplo anterior, y para que veáis cómo funciona, os dejo el resultado:

ELIMINAR REGISTROS DUPLICADOS Y ORDENAR ALFABETICAMENTE LA INFORMACION1

Como podéis observar, hemos conseguir el objetivo propuesto, los datos se han cargado sin duplicados y se han ordenado alfabéticamente.

Descarga el archivo de ejemplo pulsando en: ELIMINAR REGISTROS DUPLICADOS Y ORDENAR ALFABÉTICAMENTE LA INFORMACIÓN

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

CALCULAR LA EDAD CON DATEDIF EN UN FORMULARIO DE EXCEL

Hola a todos, espero que estéis bien y supongo que ya disfrutando de vacaciones (a mí aún me quedan unas semanas para comenzarlas).

En el post de hoy vamos a tratar de resolver una consulta que me enviaron la semana pasada sobre un tema que ya hace tiempo que tenía ganas de abordar. La pregunta era cómo se podía calcular la edad en un formulario de Excel.

Bien, existen varios post sobre el cálculo de la edad en esta web, y en todas ellas usamos la función SIFECHA() de excel, que normalmente la usamos en la hoja y en menor medida en VBA. En VBA esta función se denomina DATEDIF (y NO es lo mismo que otra función denominada DATEDIFF, que trabaja con valores absolutos).

Esta función, si utilizamos la grabadora de datos para obtener su traducción en VBA sería algo así:

AÑO = "=DATEDIF(RC[-12],TODAY(),""Y"")"

Es decir, nos ofrece la posibilidad de generar la fórmula en la hoja desde VBA. Pero lo cierto es que queremos trabajar con esta función sin acudir a la hoja en ningún momento, simplemente utilizar el formulario y los parámetros que hayamos incluido para calcular la edad de una persona.

Aunque esta función no existe en VBA como tal, podemos invocarla a través del método EVALUATE, aunque eso lo iremos viendo en el caso particular que nos ocupa.

Vamos a imaginar que tenemos un formulario con un cuadro de texto (textbox1) en el que debemos incluir la fecha de nacimiento, un botón de comando para ejecutar la macro y otro cuadro de texto (textbox2) en el que vamos a mostrar la edad completa:

CALCULAR LA EDAD EN UN FORMULARIO

Para calcular la edad vamos a incluir en modulo asociado al botón de comando el siguiente código:

Private Sub CommandButton1_Click()
'Definimos variables
Dim validarfecha As Boolean
Dim hoy As String
Dim f_nac As String
Dim año As Double, mes As Double, dia As Double
'Trabajamos con el formulario1
With UserForm1
'Cada vez que ejecutemos la macro vaciaremos el textbox1
.TextBox2 = Empty
'Si no existe fecha o el dato no es una fecha o está mal escrita, activamos mensaje y salimos el cálculo
validarfecha = IsDate(.TextBox1.Value)
If .TextBox1.Value = Empty Or validarfecha = False Or Len(.TextBox1.Value) > 10 Then
MsgBox ("DEBES INTRODUCIR UNA FECHA Y VERIFICAR QUE EL FORMATO SEA EL ADECUADO"), vbExclamation, "CONTROL"
Exit Sub
End If
'Si la fecha es mayor que la fecha actual, activamos mensaje y salimos el cálculo
If CDate(.TextBox1.Value) > Date Then
MsgBox ("LA FECHA NO PUEDE SER MAYOR QUE EL DÍA ACTUAL"), vbExclamation, "CONTROL"
Exit Sub
Exit Sub
End If
'Indicamos la fecha de hoy con formato mm/dd/aaaa y lo componemos en un string
hoy = (Month(Date) & "/" & Day(Date) & "/" & Year(Date))
'Indicamos la fecha de hoy con formato mm/dd/aaaa y lo componemos en un string
f_nac = (Month(.TextBox1.Value) & "/" & Day(.TextBox1.Value) & "/" & Year(.TextBox1.Value))
'Evaluamos la función Datedif para año, mes y día
año = Evaluate("DATEDIF(""" & f_nac & """,""" & hoy & """,""Y"")")
mes = Evaluate("DATEDIF(""" & f_nac & """,""" & hoy & """,""YM"")")
dia = Evaluate("DATEDIF(""" & f_nac & """,""" & hoy & """,""MD"")")
'Pasamos el string con los años, meses y días de nuestra edad actual al textbox2
.TextBox2 = año & IIf(año = 1, " año", " años") & ", " & mes & IIf(mes = 1, " mes", " meses") & " y " & dia & IIf(dia = 1, " dia", " días")
End With
End Sub

Es importante tener en cuenta que la función reconoce la fecha con formato mm/dd/aaaa por lo que debemos especificar esto tanto para la variable que contiene la fecha actual “hoy” como para la que contiene la fecha de nacimiento “f_nac”. Esto lo podemos solucionar componiendo un string con la fecha en el orden indicado.

En el cuadro de texto de la fecha de nacimiento el formato es el habitual: días, meses y años. Si necesitáis introducir los datos con otro formato, tendréis que modificar la macro en los dos string creados para que la función lea adecuadamente la información.

Luego debemos adaptar la función para trabajar con variables y evaluarla con el método Evaluate. Importante el uso de las comillas.

El resultado es el siguiente (calculado sábado 22 de Julio de 2017 a las 23:22 horas):

CALCULAR LA EDAD EN UN FORMULARIO1

Y el resultado es el correcto (y también lo es que me voy haciendo más viejo). El formulario me muestra información completa de la edad que tengo en el momento de ejecutar el código.

He incluido en la macro varios controles: si no existe fecha, si la fecha está mal escrita o si es mayor que el día actual. Si sucede alguna de estas cosas, mostrará un mensaje y proceso finalizará.

Según configuraciones regionales las fechas tendrán formatos distintos, sin embargo, creo que adaptando la macro a meses, días y años funcionará en todos los lugares (siempre que escribamos la fecha de nacimiento con día, mes y año.

Pues esto ha sido todo, espero que os sea de utilidad a la hora de crear formularios o de poner en práctica la función Datedif en VBA.

Descarga el archivo de ejemplo pulsando en: CALCULAR LA EDAD EN UN FORMULARIO DE EXCEL

 
¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!