Validar contenido de un campo compuesto por grupos de números
Continuando con mi programa de rifas me encuentro con la situación que debo validar en el campo numeros de un formulario, conformado por grupos de números de 4 dígitos separados por guion (-), de acuerdo con el parámetro tipo que va desde 1 hasta 5. Validar con una función lo siguiente:
Por ejemplo, contenido del campo numeros:
"0036" tipo=1 (un solo grupo)
"2158-0254" tipo= 2 (dos grupos
"0245-3654-6547" tipo= 3 (tres grupos) y así sucesivamente para tipos 4 y 5
VALIDAR:
1. De acuerdo con el campo numeros y el tipo se valide la cantidad de grupos
2. Se valide que cada grupo tenga 4 digítos
3. Que no se repite el número de 4 digítos en el campo numeros, por ejemplo, "0250-1255-0250" NO es permitido
La función debe retornar un valor booleano.
2 Respuestas
Gracias Jacinto voy a estudiar su ejemplo y le comento
¡Gracias! Pero me faltó comentarle que además ningún número se puede repetir en otra fila, es la parte más difícil.
Jacinto y Martha les dejo esta función, le adicioné 1 parámetro para condicionar el tamaño de los grupos.
Public Function ValidarFormatoConTipo(campo As String, tipo As Integer) As Boolean
' Función para validar grupos de números
' Condiciones:
' 1. No se pueden repetir en campo
' 2. Deben tener la misma longitud dependiento del tipo
'Parámetros:
' campo = Cadena de caracteres a validar, por ejemplo, "0125-5257-2356-4524"
' tipo = 1 Un grupo de 4 dígitos, por ejemplo, "0215"
' 2 Dos grupos de 4 dígitos, por ejemplo, "1215-1265"
' 3 Tres grupos de 4 dígitos, por ejemplo,"1215-1265-0145"
' 4 Cuatros grupos de 4 dígitos, por ejemplo,"1215-1265-0145-9657"
' Retorna: True o False
'
'Ejemplos de llamada:
' ValidarFormatoConTipo("0123-1215-1310-1206",4) -- retorna True
' ValidarFormatoConTipo("0123-1215-1310-0123",4) -- retorna False 0123 está repetido
' ValidarFormatoConTipo("0123-1215-1310-012",4) -- retorna False 012 está incompleto
' ValidarFormatoConTipo("0123-1215-1310",4) -- retorna False falta un grupo
'Elaborada por:
' EDUARDO PÉREZ FERNÁNDEZ
' 19/12/2024
Dim grupos() As String
Dim i As Integer, j As Integer
' Eliminar espacios al inicio y al final del campo
campo = Trim(campo)
' Verificar si el campo está vacío
If Len(campo) = 0 Then
ValidarFormatoConTipo = False
Exit Function
End If
' Dividir el campo en grupos usando "-" como separador
grupos = Split(campo, "-")
' Validar el número de grupos según el tipo
Select Case tipo
Case 1
' Tipo 1: Un único grupo de 4 dígitos
If UBound(grupos) + 1 = 1 Then
If Len(grupos(0)) = 4 And IsNumeric(grupos(0)) Then
ValidarFormatoConTipo = True
Else
ValidarFormatoConTipo = False
End If
Else
ValidarFormatoConTipo = False
End If
Case 2
' Tipo 2: Dos grupos de 4 dígitos separados por "-"
If UBound(grupos) + 1 = 2 Then
For i = LBound(grupos) To UBound(grupos)
If Len(grupos(i)) <> 4 Or Not IsNumeric(grupos(i)) Then
ValidarFormatoConTipo = False
Exit Function
End If
Next i
' Validar que no se repitan los grupos
If grupos(0) = grupos(1) Then
ValidarFormatoConTipo = False
Exit Function
End If
ValidarFormatoConTipo = True
Else
ValidarFormatoConTipo = False
End If
Case 3
' Tipo 3: Tres grupos de 4 dígitos separados por "-"
If UBound(grupos) + 1 = 3 Then
For i = LBound(grupos) To UBound(grupos)
If Len(grupos(i)) <> 4 Or Not IsNumeric(grupos(i)) Then
ValidarFormatoConTipo = False
Exit Function
End If
Next i
' Validar que no se repitan los grupos
If grupos(0) = grupos(1) Or grupos(0) = grupos(2) Or grupos(1) = grupos(2) Then
ValidarFormatoConTipo = False
Exit Function
End If
ValidarFormatoConTipo = True
Else
ValidarFormatoConTipo = False
End If
Case 4
' Tipo 4: Cuatro grupos de 4 dígitos separados por "-"
If UBound(grupos) + 1 = 4 Then
For i = LBound(grupos) To UBound(grupos)
If Len(grupos(i)) <> 4 Or Not IsNumeric(grupos(i)) Then
ValidarFormatoConTipo = False
Exit Function
End If
Next i
' Validar que no se repitan los grupos
If grupos(0) = grupos(1) Or grupos(0) = grupos(2) Or grupos(0) = grupos(3) _
Or grupos(1) = grupos(2) Or grupos(1) = grupos(3) Or grupos(2) = grupos(3) Then
ValidarFormatoConTipo = False
Exit Function
End If
ValidarFormatoConTipo = True
Else
ValidarFormatoConTipo = False
End If
Case 5
' Tipo 5: Cinco grupos de 4 dígitos separados por "-"
If UBound(grupos) + 1 = 5 Then
For i = LBound(grupos) To UBound(grupos)
If Len(grupos(i)) <> 4 Or Not IsNumeric(grupos(i)) Then
ValidarFormatoConTipo = False
Exit Function
End If
Next i
' Validar que no se repitan los grupos
If grupos(0) = grupos(1) Or grupos(0) = grupos(2) Or grupos(0) = grupos(3) Or grupos(0) = grupos(4) _
Or grupos(1) = grupos(2) Or grupos(1) = grupos(3) Or grupos(1) = grupos(4) _
Or grupos(2) = grupos(3) Or grupos(2) = grupos(4) Or grupos(3) = grupos(4) Then
ValidarFormatoConTipo = False
Exit Function
End If
ValidarFormatoConTipo = True
Else
ValidarFormatoConTipo = False
End If
Case Else
' Caso para un tipo no válido
ValidarFormatoConTipo = False
End Select
End FunctionUn saludo a Jacinto y por supuesto a Martha.
Excelente Eduardo, como siempre dando respuestas objetivas. Eduardo, hay forma hacer lo mismo con PostgreSQL?
Mil y mil gracias
Claro que se puede hacer con PostgreSQL, le dejo el script y ejemplos de llamada.
CREATE OR REPLACE FUNCTION validar_formato_con_tipo(campo TEXT, tipo INTEGER)
RETURNS BOOLEAN AS $$
DECLARE
grupos TEXT[];
i INT;
n_grupos INT;
BEGIN
-- Eliminar espacios al inicio y al final
campo := TRIM(campo);
-- Verificar si el campo está vacío
IF campo = '' THEN
RETURN FALSE;
END IF;
-- Dividir el campo en grupos usando '-' como separador
grupos := STRING_TO_ARRAY(campo, '-');
n_grupos := array_length(grupos, 1);
-- Validar el número de grupos según el tipo
CASE tipo
WHEN 1 THEN
IF n_grupos = 1 AND LENGTH(grupos[1]) = 4 AND grupos[1] ~ '^\d+$' THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
WHEN 2 THEN
IF n_grupos = 2 THEN
FOR i IN 1..n_grupos LOOP
IF LENGTH(grupos[i]) <> 4 OR grupos[i] !~ '^\d+$' THEN
RETURN FALSE;
END IF;
END LOOP;
-- Validar que no se repitan los grupos
IF grupos[1] = grupos[2] THEN
RETURN FALSE;
END IF;
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
WHEN 3 THEN
IF n_grupos = 3 THEN
FOR i IN 1..n_grupos LOOP
IF LENGTH(grupos[i]) <> 4 OR grupos[i] !~ '^\d+$' THEN
RETURN FALSE;
END IF;
END LOOP;
-- Validar que no se repitan los grupos
IF grupos[1] = grupos[2] OR grupos[1] = grupos[3] OR grupos[2] = grupos[3] THEN
RETURN FALSE;
END IF;
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
WHEN 4 THEN
IF n_grupos = 4 THEN
FOR i IN 1..n_grupos LOOP
IF LENGTH(grupos[i]) <> 4 OR grupos[i] !~ '^\d+$' THEN
RETURN FALSE;
END IF;
END LOOP;
-- Validar que no se repitan los grupos
IF grupos[1] = grupos[2] OR grupos[1] = grupos[3] OR grupos[1] = grupos[4] OR
grupos[2] = grupos[3] OR grupos[2] = grupos[4] OR grupos[3] = grupos[4] THEN
RETURN FALSE;
END IF;
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
ELSE
-- Tipo no válido
RETURN FALSE;
END CASE;
END;
$$ LANGUAGE plpgsql;
-- Ejemplos de llamada
SELECT validar_formato_con_tipo('0123-1215-1310-1206', 4); -- Retorna TRUE
SELECT validar_formato_con_tipo('0123-1215-1310-0123', 4); -- Retorna FALSE
SELECT validar_formato_con_tipo('0123-1215-1310', 4); -- Retorna FALSE
SELECT validar_formato_con_tipo('0123-1215', 2); -- Retorna TRUE
No es nada del otro mundo, pero practico, como puede apreciar las bondades del PostgreSQL son inmensas.
Un saludo Martha y me alegro de que siga utilizando PostgreSQL como backend.
Martha lo único que merece aclaración del script es esta parte ~ '^\d+$'.
1. El operador ~:
Es el operador de coincidencia con expresión regular en PostgreSQL.
Se utiliza para comprobar si un texto cumple con el patrón proporcionado.
Si la cadena cumple con el patrón, devuelve TRUE; de lo contrario, FALSE.
2. El patrón '^\d+$':
Es una expresión regular que define el formato esperado. Analicemos cada parte:
^:
Indica el inicio de la cadena. Esto significa que la cadena debe empezar coincidiendo con lo que sigue.
\d:
Representa cualquier dígito numérico (del 0 al 9).
Es equivalente a [0-9].
+:
Significa que debe haber uno o más dígitos consecutivos.
Si la cadena no contiene al menos un dígito, no coincidirá.
$:
Indica el final de la cadena. Esto asegura que toda la cadena esté formada exclusivamente por los dígitos definidos y no haya caracteres adicionales antes o después.
3. Significado completo de ~ '^\d+$':
La cadena debe estar formada únicamente por dígitos (del 0 al 9).
Debe haber al menos un dígito.
No se permiten caracteres antes o después de los dígitos.
Observe estos ejemplos:
Casos válidos:
SELECT '1234' ~ '^\d+$'; -- TRUE, es solo números
SELECT '0123456789' ~ '^\d+$'; -- TRUE, contiene solo dígitos
Casos no válidos:
SELECT '1234abc' ~ '^\d+$'; -- FALSE, tiene letras
SELECT '123 456' ~ '^\d+$'; -- FALSE, tiene un espacio
SELECT '' ~ '^\d+$'; -- FALSE, está vacío
SELECT '-1234' ~ '^\d+$'; -- FALSE, tiene un signo menos
Si tiene alguna otra duda con gusto trato de colaborarle.
- Compartir respuesta
Martha:
No estoy seguro de haber entendido tu pregunta.
Si la he entendido, seguro que hay varias soluciones para conseguir lo que pides.
Dado que es un poco extenso de explicación, la que yo usaría, te adjunto un enlace para que descargues el ejemplo que he preparado.
https://www.mediafire.com/file/epwgo2i9fsscffl/ValidaDatosNumerosRifa.rar/file
Dentro del Formulario que se abre inicialmente está tu pregunta y unas notas mías.
Así queda documentado, por si es de utilidad a algún otro(a) usuario(a).
Un cordial saludo >> JTJ
Martha: En el Módulo >> MdlJTJ sobran las líneas de:
DoCmd.Echo False
DoCmd.Hourglass True
......
DoCmd.Echo True
DoCmd.Hourglass False
Deben ir mejor en la llamada al Procedimiento en el Formulario:
Private Sub BtnComprueba_Click() DoCmd.Echo False DoCmd.Hourglass True Call ProcesaDatos DoCmd.Echo True DoCmd.Hourglass False Me.Requery End Sub
Saludos >>JTJ
Martha:
Repasando mi ejemplo, observo que tiene algunas lagunas.
He intentado solucionarlas con una opción complementaria, que está añadido a la BD anterior.
Este es el enlace de descarga del nuevo fichero
https://www.mediafire.com/file/g0c5eiymqutk60h/ValidaDatosNumerosRifaB.rar/file
En el Formulario de apertura, he añadido una nota breve.
Tal como cito y en mi opinión sería bueno robustecer el proceso anterior de modo que la comprobación fuera más "sabe"
Quizá si la generación de los "bloques" de 4 números es seguro y el de los guiones también, por si acaso quedaría mirar si se había colado algún duplicado.
Un saludo >> JTJ
He ampliado la respuesta y no lo veo. La ampliación era >>
Martha:
Repasando mi ejemplo, observo que tiene algunas lagunas.
He intentado solucionarlas con una opción complementaria, que está añadido a la BD anterior.
Este es el enlace de descarga del nuevo fichero
https://www.mediafire.com/file/g0c5eiymqutk60h/ValidaDatosNumerosRifaB.rar/file
En el Formulario de apertura, he añadido una nota breve.
Tal como cito y en mi opinión sería bueno robustecer el proceso anterior de modo que la comprobación fuera más "suave"
Quizá si la generación de los "bloques" de 4 números es seguro y el de los guiones también, por si acaso quedaría mirar si se había colado algún duplicado.
Un saludo >> JTJ
- Compartir respuesta
Eduardo: Tal como le digo a Martha, incorporo tu Función a mi Base de Datos. Saludos. - Jacinto Trillo Jareño
Jacinto, gracias por su comentario, lo invito a probar la función en PostgreSQL la utilizo en un programa de rifas cuando no se asignan números aleatoriamente sino manualmente. Un saludo - Eduardo Pérez Fernández