Hoy voy a incluir una macro que sirve para validar con SAS un número de DNI peruano verificando si el dígito verificador es correcto o no.
Hay que empezar diciendo que inicialmente, y hasta 2007, los DNIs sin fecha de caducidad tenían un dígito verificador que correspondía con una de estas letras: A, B, C, D, E, F, G, H, I, J o K. En el resto de casos se asigna un número de 0 a 9 que sirve para verificar el resto de dígitos del DNI a través de una serie de operaciones matemáticas.
Para trabajar con algunos ejemplos alimentaremos la macro con la siguiente tabla con DNIs a evaluar:
/* Ejemplos*/;
data DNIS;
format DNI $10.;
input DNI;
datalines;
67415321-0
1657351-A
31874-1
671354134
run;
La macro %validarDNI
añade dos campos a la tabla que se le pase por parámetro: dni_normal y ind_valido. dni_normal es el valor del campo que contenía el DNI originalmente, pero normalizado. ind_valido toma dos valores posibles: 1 que indica que el DNI es correcto y 0 que indica que es erróneo.
%validarDNI
acepta además dos parámetros obligatorios: el nombre de la tabla y el nombre del campo DNI a validar dentro de ella.
/*Macro*/;
%macro validarDNI(tabla=, campo=);
data DNI1 (drop=a valor resto codigo:);
set &tabla;
rename &campo=dni_original;
dni_normal = upcase(compress(&campo,'-_. '));
a = 9 - length(dni_normal);
if a > 0 then dni_normal = compress(repeat('0',a-1) || dni_normal);
ind_valido = 1;
if length(dni_normal) > 9 then ind_valido = 0;
%do i = 1 %to 8;
if 0 > put(substr(dni_normal,&i,1),8.) or put(substr(dni_normal,&i,1),8.) > 9 then ind_valido = 0;
%end;
if substr(dni_normal,9,1) not in ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K') then ind_valido = 0;
if ind_valido > 0 then do;
valor = 3*put(substr(dni_normal,1,1),8.) +
2*put(substr(dni_normal,2,1),8.) +
7*put(substr(dni_normal,3,1),8.) +
6*put(substr(dni_normal,4,1),8.) +
5*put(substr(dni_normal,5,1),8.) +
4*put(substr(dni_normal,6,1),8.) +
3*put(substr(dni_normal,7,1),8.) +
2*put(substr(dni_normal,8,1),8.);
resto = mod(valor,11);
if resto = 0 then resto = 11;
resto = resto + 1;
codigo1 = substr('67890112345',resto,1);
codigo2 = substr('KABCDEFGHIJ',resto,1);
if substr(dni_normal,9) ne codigo1 and substr(dni_normal,9) ne codigo2 then ind_valido = 0;
end;
run;
data &tabla;
set DNI1;
rename dni_original = &campo;
run;
%mend;
%validarDNI(tabla=DNIS, campo=DNI);
El algoritmo para calcular el dígito verificador del DNI es el siguiente: se multiplica cada número del DNI normalizado (sus 8 primeros dígitos) por el dígito que ocupe la misma posición en la cadena: 1, 7, 8, 0, 1, 1, 4, 6 y luego se suman todos los factores para dar una cifra de la que calcularemos el resto con resto a dividirla entre 11 (aquí, si el resto es 0 tomaremos 11).
Restamos 11 menos la resultante de la operación anterior. Le sumaremos 1 y entonces tomaremos ese valor para buscar el dígito correspondiente a esa posición en la cadena: 6, 7, 8, 9, 0, 1, 1, 2, 3, 4, 5. Este último es el dígito de verificación.