SGCG

…esto no es un subtítulo…

Ir a: contenido categorías calendario archivo suscripción

Volver arriba

Emacs Lisp en casos prácticos (2): cálculo de la letra del NIF (1)

2015-07-08

GNU Emacs es un editor de textos potentísimo. Por debajo, es un intérprete de Emacs Lisp, un lenguaje de programación de la familia de Lisp. En esta serie de artículos vamos a mostrar algunas formas de adaptar Emacs a nuestras necesidades con algunos casos prácticos.

En el artículo de hoy y el siguiente artículo veremos la forma de completar cómo calcular el dígito de control de un NIF (como la letra del DNI) y completar un texto.

El problema

El Número de Identificación Fiscal (NIF) es un código que identifica a efectos fiscales en España a las personas físicas y a las personas jurídicas. Este código es una combinación de 9 caracteres alfanuméricos (con las letras en mayúsculas) en la que el último carácter es un dígito de control que se calcula a partir de los 8 primeros caracteres. Hay diferentes tiposd de NIF, cada uno con su tipo de cálculo de dígito de control correspodiente:

DNI
Los 8 primeros caracteres de un NIF del tipo DNI son números y el dígito de control es una letra que sale del resto de la división del número formado por las 8 primeras cifras entre 23. Este resto puede ser un número entre 0 y 22; a cada número le corresponde una letra diferente que es el dígito de control.
NIE
Se parece al DNI, pero el primer carácter es una letra («X», «Y» o «Z») y el dígito de control se calcula a partir del número formado al excluir la letra inicial.
CIF
El CIF empieza por una letra (diferente a las del NIE) y sigue un algoritmo más complicado que no veremos hoy.

El dígito de control del NIF y el CIF sale de la siguiente relación entre el resto y la letra correspondiente:

0
T
1
R
2
W
3
A
4
G
5
M
6
Y
7
F
8
P
9
D
10
X
11
B
12
N
13
J
14
Z
15
S
16
Q
17
V
18
H
19
L
20
C
21
K
22
E

Hoy buscamos calcular el dígito de control de un DNI o un NIE e incluso completar un código al que le falta su dígito.

Cálculo del dígito de control

La letra del DNI es fácil de calcular con la siguiente función. Esta función acepta un texto que consiste en los 8 primeros dígitos del DNI (es decir, el código a falta del dígito de control), convierte dicho texto a un número para calcular el resto, y finalmente devuelve la letra que corresponde al resto.

(defun nif-letra-dni (dni) "Devuelve la letra correspondiente a un número de DNI." (let ((table "TRWAGMYFPDXBNJZSQVHLCKE") (remainder (mod (if (stringp dni) (string-to-number dni) dni) 23))) (substring table remainder (1+ remainder))))

Para calcular la letra de un NIE, reutilizamos la función que hace el trabajo con el NIF, a la que le pasamos el NIE tras retirar la letra inicial:

(defun nif-letra-nie (nie) "Devuelve la letra correspondiente a un NIE." (nif-letra-dni (substring nie 1)))

Además de esto, vamos a definir una función que devuelve un dígito de control nulo (una cadena de texto vacía) para los casos en los que no podemos calcular un dígito de control real:

(defun nif-digito-nulo (nif) "")

Calculador genérico del dígito de control

Es conveniente tener una función capaz de discernir el tipo de NIF que se le pasa y calcular el dígito de control de acuerdo al algoritmo correspondiente. Para ello, imaginamos que disponemos de una función llamada nif--calculador-del-digito-de-control que acepta un NIF y devuelve la función que se encarga de calcular el dígito de control (con lo que tenemos definido ahora, la que corresponda entre nif-letra-dni, nif-letra-nie o nif-digito-nulo). Si disponemos de esta función, el trabajo de calcular el dígito de control es así de fácil:

(defun nif-digito-de-control (nif) "Obtiene el dígito de control de un NIF." (funcall (nif--calculador-del-digito-de-control nif) nif))

La función que nos devuelve el calculador del dígito de control puede basarse tanto en el tamaño del código que le pasamos (si no es de 8 caracteres, no vale) como en el propio contenido (cazado con expresiones regulares mediante string-match):

(defun nif--calculador-del-digito-de-control (nif) (cond ((not (= 8 (length nif))) 'nif-digito-nulo) ((string-match "[0-9]\\{8\\}" nif) 'nif-letra-dni) ((string-match "[XYZ][0-9]\\{7\\}" nif) 'nif-letra-nie) (t 'nif-digito-nulo)))

Completar un NIF

Lo último que nos falta es poder completar un NIF. Esto lo hacemos añadiendo el dígito de control (calculado con la función nif-digito-de-control definida arriba) al final del código:

(defun nif-completar (nif) "Completa un NIF añadiéndole el dígito de control que le corresponde." (concat nif (nif-digito-de-control nif)))

Digamos que usamos esta función con el DNI 12345678:

(nif-completar "12345678")

Obtenemos el siguiente resultado:

"12345678Z"

Finalmente, creamos una función interactiva para completar un NIF que hayamos seleccionado mientras editamos un texto. Esta función obtiene como argumentos las posiciones inicial y final de la región seleccionada (que obtenemos en la invocación interactiva mediante el código "r"), extrae el texto en esta región mediante buffer-substring-no-properties (que sirve para obtener el texto simple sin información que ahora no nos interesa como los tipos de letra y los colores) e inserta al final el dígito de control calculado con nuestra función nif-digito-de-control:

(defun nif-completar-region (start end) "Añade la letra al nif en la región marcada entre START y END." (interactive "r") (let ((nif (buffer-substring-no-properties start end))) (save-excursion (goto-char end) (insert (nif-digito-de-control nif)))))


Categorías: Informática

Permalink: http://sgcg.es/articulos/2015/07/08/emacs-lisp-en-casos-practicos-2-calculo-de-la-letra-del-nif-1/