Macro SAS: Validar teléfonos (España)

Esta macro que incluyo a continuación permite validar número de teléfonos de España, aunque no se encuentre normalizados, esto es, contengan el prefijo internacional o no, o estén separados por algún tipo de separador o de espacio. Al final se ofrecen los números de teléfonos normalizados y sin prefijo.

Esta macro solo hace una verificación del formato del número del teléfono, pero no sabe distinguir entre números reales o no. Para hacer este tipo de verificaciones tenemos servicios que dan información vía API (protocolo de comunicación entre sistemas) devolviendo un fichero JSON sobre el tipo de teléfono, operador, país, etc. Espero poder poner un ejemplo sobre cómo integrar un servicio de terceros como este en un futuro (Hazme un comentario si estás interesado en ello).

%macro telefono(tabla=,campo=);
data &tabla;
set &tabla;
&campo = compress(&campo,' ','P');
if substr(&campo,1,4) = '0034' then &campo = substr(&campo,5);
if substr(&campo,1,2) = '34' then &campo = substr(&campo,3);
if substr(&campo,1,1) not in ('6','7','8','9') or
substr(&campo,1,2) in ('80','90') or
length(&campo) ne 9 then ind_valido = 0;
else ind_valido = 1;
run;
%mend;

Puedes probar con estos ejemplos la macro:

data clientes;
    format telefono $20.;
    input telefono;
    datalines;
    9851246323
    981122044
    +34666777888
    902123123
    0034-616875794
    +0034 615 789 456
    658.452.187
    001 32157979
    34715845978
    888123456
    (95)6543232
    ;
run;*/

%telefono(tabla=clientes,campo=telefono);

Macro SAS: Validar y normalizar el DNI

Comparto con vosotros esta macro que realiza una validación del campo DNI de una tabla. Admite como parámetros el nombre de la tabla (DNIS) y el nombre del campo con el DNI (DNI). Como salida genera otra tabla que se llama DNIS_ (añade un subrallado al final) y le añade el campo dni_norm. La macro normaliza DNIs y NIEs españoles.

En el primer paso se verifica el formato del DNI y se rechazan los que tengan un formato que no sea compatible. Estos se marcan con el indicador ind_valido. Para aquellos que cumplen con el formato básico de los DNIs, trocea ese DNI en prefix, number y sufix, De forma que se validan por separado.

En el segundo paso se normaliza la parte numérica del DNI dándole tantos dígitos como vaya a necesitar añadiendo ceros por la izquierda. En el tercer paso se calcula la letra del DNI/NIE y se juntan todos los trozos para tener el DNI normalizado. En un último paso se realiza el cruce que la tabla inicial de DNIs.

%macro normalizar_dni(tabla=,campo=);
    /* obtenemos las partes del DNI y localizamos formatos incorrectos */
    data norm1;
        set &tabla;
        &campo = upcase(&campo);
        if anypunct(&campo) > 0 then ind_valido = 0;
        else if length(&campo) > 9 then ind_valido = 0;
        else if 0 < anyalpha(substr(&campo,2)) < length(substr(&campo,2)) then ind_valido = 0;
        else if compress(substr(&campo,1,1),'XYZ','D') ne '' then ind_valido = 0;
        else if length(&campo)=9 and anyalpha(&campo)=0 and substr(&campo,1,1)='0' then do;
            &campo=substr(&campo,2);
            ind_valido = 1;
            prefix = compress(substr(&campo,1,1),'','D');
            number = input(compress(&campo,'','A'),8.);
            sufix = compress(substr(&campo,length(&campo)),'','D');
        end;
        else if length(&campo)=9 and anyalpha(&campo)=0 then ind_valido = 0;
        else do;
            ind_valido = 1;
            prefix = compress(substr(&campo,1,1),'','D');
            number = input(compress(&campo,'','A'),8.);
            sufix = compress(substr(&campo,length(&campo)),'','D');
        end;
    run;

    /* normalizamos el número */
    data norm2;
        set norm1;
        format numero $8.;
        length numero $ 8;
        n = number;
        if anyalpha(prefix)=1 then numero = put(number,z7.);
            else numero = put(number,z8.);
    run;

    /* calculamos la letra del DNI y verificamos si es correcta cuando venga informada */
    data norm3 (drop=prefix number sufix numero n letras resto letra_norm ind_valido);
        set norm2;
        letras = 'TRWAGMYFPDXBNJZSQVHLCKE';
        if prefix='Y' then n=n+10000000;
        if prefix='Z' then n=n+20000000;
        resto = mod(n,23);
        letra_norm = substr(letras,resto+1,1);
        dni_norm = compress(prefix||numero||letra_norm);
    run;

    /* salida */
    proc sql;
        create table &tabla._ as
        select a.*, dni_norm
        from &tabla a
        left join norm3 b
        on a.&campo = b.&campo;
    quit;
%mend normalizar_dni;

Podéis probarla con este set de datos de prueba que os dejo aquí:

data DNIS;
    format dni $20.;
    length dni $ 20;
    input dni $;
    datalines;
    16634732A
    1b
    16634732
    32631459w
    X00123
    Y1234612
    123&134
    Z1224536
    X00z12
    064563314
    6843131058
    1635740.65
    000000315
    G12
run;

%normalizar_dni(tabla=DNIS,campo=dni);