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.

Respuesta
2

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.

Excelente, gracias, Eduardo cada vez me aproximo más a utilizar PostgreSQL con Access es una buena pareja. Voy a poner en práctica su función y le comento.

1 respuesta más de otro experto

Respuesta
1

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

¡Gracias! Jacinto muy interesante su validador, pero en esta oportunidad he tomado la respuesta de Eduardo.

Martha: Eduardo es un gran maestro, por lo que no me extraña que hayas elegido su Función de validación. Yo la he incorporado en mi Base de datos.

Un saludo >> JTJ

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas