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.
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 Function
Un 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
1 respuesta más de otro experto
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