407 lines
14 KiB
VB.net
407 lines
14 KiB
VB.net
|
|
Imports System.Linq.Expressions
|
|
Imports System.Text.RegularExpressions
|
|
|
|
|
|
''' <summary>
|
|
''' Representa un número. En la clase se desglosan las distintas opciones que se puedan
|
|
''' encontrar
|
|
''' </summary>
|
|
Public Class ValidarDocumentoIdentidad
|
|
''' <summary>
|
|
''' Tipos de Códigos.
|
|
''' </summary>
|
|
''' <remarks>Aunque actualmente no se utilice el término CIF, se usa en la enumeración
|
|
''' por comodidad</remarks>
|
|
Public Enum TiposDocumentosEnum
|
|
NIF
|
|
NIE
|
|
CIF
|
|
End Enum
|
|
|
|
' Número tal cual lo introduce el usuario
|
|
Private m_numero As String
|
|
|
|
Private tipo As TiposDocumentosEnum
|
|
Public ReadOnly Property TipoDocumento As TiposDocumentosEnum
|
|
Get
|
|
Return tipo
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Parte de Nif: En caso de ser un Nif intracomunitario, permite obtener el cógido del país
|
|
''' </summary>
|
|
Public Property CodigoIntracomunitario() As String
|
|
Get
|
|
Return m_CodigoIntracomunitario
|
|
End Get
|
|
Friend Set(value As String)
|
|
m_CodigoIntracomunitario = value
|
|
End Set
|
|
End Property
|
|
Private m_CodigoIntracomunitario As String
|
|
Friend Property EsIntraComunitario() As Boolean
|
|
Get
|
|
Return m_EsIntraComunitario
|
|
End Get
|
|
Set(value As Boolean)
|
|
m_EsIntraComunitario = value
|
|
End Set
|
|
End Property
|
|
Private m_EsIntraComunitario As Boolean
|
|
|
|
''' <summary>
|
|
''' Parte de Nif: Letra inicial del Nif, en caso de tenerla
|
|
''' </summary>
|
|
Public Property LetraInicial() As String
|
|
Get
|
|
Return m_LetraInicial
|
|
End Get
|
|
Friend Set(value As String)
|
|
m_LetraInicial = value
|
|
End Set
|
|
End Property
|
|
Private m_LetraInicial As String
|
|
|
|
''' <summary>
|
|
''' Parte de Nif: Bloque numérico del NIF. En el caso de un NIF de persona física,
|
|
''' corresponderá al DNI
|
|
''' </summary>
|
|
Public Property Identificador() As Integer
|
|
Get
|
|
Return m_numero
|
|
End Get
|
|
Friend Set(value As Integer)
|
|
m_numero = value
|
|
End Set
|
|
End Property
|
|
Private m_Identificador As Integer
|
|
|
|
''' <summary>
|
|
''' Parte de Nif: Dígito de control. Puede ser número o letra
|
|
''' </summary>
|
|
Public Property DigitoControl() As String
|
|
Get
|
|
Return m_DigitoControl
|
|
End Get
|
|
Friend Set(value As String)
|
|
m_DigitoControl = value
|
|
End Set
|
|
End Property
|
|
Private m_DigitoControl As String
|
|
|
|
''' <summary>
|
|
''' Valor que representa si el Nif introducido es correcto
|
|
''' </summary>
|
|
Public Property EsCorrecto() As Boolean
|
|
Get
|
|
Return m_EsCorrecto
|
|
End Get
|
|
Friend Set(value As Boolean)
|
|
m_EsCorrecto = value
|
|
End Set
|
|
End Property
|
|
Private m_EsCorrecto As Boolean
|
|
|
|
''' <summary>
|
|
''' Cadena que representa el tipo de Nif comprobado:
|
|
''' - NIF : Número de identificación fiscal de persona física
|
|
''' - NIE : Número de identificación fiscal extranjería
|
|
''' - CIF : Código de identificación fiscal (Entidad jurídica)
|
|
''' </summary>
|
|
Public ReadOnly Property TipoNif() As String
|
|
Get
|
|
Return tipo.ToString()
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Constructor. Al instanciar la clase se realizan todos los cálculos
|
|
''' </summary>
|
|
''' <param name="numero">Cadena de 9 u 11 caracteres que contiene el DNI/NIF
|
|
''' tal cual lo ha introducido el usuario para su verificación</param>
|
|
Public Sub New(numero As String)
|
|
' Se eliminan los carácteres sobrantes
|
|
Try
|
|
' numero = EliminaCaracteres(numero)
|
|
|
|
|
|
' numero = numero.ToUpper()
|
|
|
|
' Comprobación básica de la cadena introducida por el usuario
|
|
If numero.Length <> 9 AndAlso numero.Length <> 11 Then
|
|
Me.EsCorrecto = False ' Throw New ArgumentException("El NIF no tiene un número de caracteres válidos")
|
|
Else
|
|
|
|
Me.m_numero = numero
|
|
Desglosa()
|
|
|
|
Select Case tipo
|
|
Case TiposDocumentosEnum.NIF, TiposDocumentosEnum.NIE
|
|
Me.EsCorrecto = CompruebaNif()
|
|
Exit Select
|
|
Case TiposDocumentosEnum.CIF
|
|
Me.EsCorrecto = validateCif(numero)
|
|
' Me.EsCorrecto = CompruebaCif()
|
|
Exit Select
|
|
End Select
|
|
End If
|
|
Catch ex As Exception
|
|
Me.EsCorrecto = False
|
|
End Try
|
|
End Sub
|
|
|
|
#Region "Preparación del número (desglose)"
|
|
|
|
''' <summary>
|
|
''' Realiza un desglose del número introducido por el usuario en las propiedades
|
|
''' de la clase
|
|
''' </summary>
|
|
Private Sub Desglosa()
|
|
Dim n As Int32
|
|
If m_numero.Length = 11 Then
|
|
' Nif Intracomunitario
|
|
EsIntraComunitario = True
|
|
CodigoIntracomunitario = m_numero.Substring(0, 2)
|
|
LetraInicial = m_numero.Substring(2, 1)
|
|
Int32.TryParse(m_numero.Substring(3, 7), n)
|
|
DigitoControl = m_numero.Substring(10, 1)
|
|
tipo = GetTipoDocumento(LetraInicial(0))
|
|
Else
|
|
' Nif español
|
|
tipo = GetTipoDocumento(m_numero(0))
|
|
EsIntraComunitario = False
|
|
If tipo = TiposDocumentosEnum.NIF Then
|
|
LetraInicial = String.Empty
|
|
Int32.TryParse(m_numero.Substring(0, 8), n)
|
|
Else
|
|
LetraInicial = m_numero.Substring(0, 1)
|
|
Dim listaLetrasNIE As Char() = {"X", "Y", "Z"}
|
|
If listaLetrasNIE.Contains(LetraInicial) Then
|
|
'// Las letras por las que comienza el NIE deben ser reemplazadas por números antes de realizar
|
|
'// la operación Int32.TryParse, que además deberá incluir ese número reemplazado.
|
|
'// X = 0
|
|
'// Y = 1
|
|
'// Z = 2
|
|
Select Case LetraInicial
|
|
Case "X"
|
|
m_numero = 0 & m_numero.Substring(1, m_numero.Length - 1)
|
|
Case "Y"
|
|
m_numero = 1 & m_numero.Substring(1, m_numero.Length - 1)
|
|
Case "Z"
|
|
m_numero = 2 & m_numero.Substring(1, m_numero.Length - 1)
|
|
End Select
|
|
Int32.TryParse(m_numero.Substring(0, 8), n)
|
|
Else
|
|
'// El curso normal, cuando la letra inicial no es X, Y o Z.
|
|
Int32.TryParse(m_numero.Substring(1, 7), n)
|
|
End If
|
|
|
|
End If
|
|
DigitoControl = m_numero.Substring(8, 1)
|
|
End If
|
|
Identificador = n
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' En base al primer carácter del código, se obtiene el tipo de documento que se intenta
|
|
''' comprobar
|
|
''' </summary>
|
|
''' <param name="letra">Primer carácter del número pasado</param>
|
|
''' <returns>Tipo de documento</returns>
|
|
Private Function GetTipoDocumento(letra As Char) As TiposDocumentosEnum
|
|
Dim regexIdentificadors As New Regex("[0-9]")
|
|
If regexIdentificadors.IsMatch(letra.ToString()) Then
|
|
Return TiposDocumentosEnum.NIF
|
|
End If
|
|
|
|
Dim regexLetrasNIE As New Regex("[LKMXYZ]")
|
|
If regexLetrasNIE.IsMatch(letra.ToString()) Then
|
|
Return TiposDocumentosEnum.NIE
|
|
End If
|
|
|
|
Dim regexLetrasCIF As New Regex("[ABCDEFGHJPQRSUVNW]")
|
|
If regexLetrasCIF.IsMatch(letra.ToString()) Then
|
|
Return TiposDocumentosEnum.CIF
|
|
End If
|
|
|
|
Throw New ApplicationException("El código no es reconocible")
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Eliminación de todos los carácteres no numéricos o de texto de la cadena
|
|
''' </summary>
|
|
''' <param name="numero">Número tal cual lo escribe el usuario</param>
|
|
''' <returns>Cadena de 9 u 11 carácteres sin signos</returns>
|
|
Private Function EliminaCaracteres(numero As String) As String
|
|
' Todos los carácteres que no sean números o letras
|
|
Dim caracteres As String = "[^\w]"
|
|
Dim regex As New Regex(caracteres)
|
|
Return regex.Replace(numero, "")
|
|
End Function
|
|
|
|
#End Region
|
|
|
|
#Region "Cálculos"
|
|
|
|
Private Function CompruebaNif() As Boolean
|
|
Return DigitoControl = GetLetraNif()
|
|
End Function
|
|
|
|
|
|
|
|
Public Shared Function validateCif(ByVal cif As String) As Boolean
|
|
If String.IsNullOrEmpty(cif) Then Return False
|
|
cif = cif.Trim().ToUpper()
|
|
If cif.Length <> 9 Then Return False
|
|
Dim firstChar As String = cif.Substring(0, 1)
|
|
Dim cadena As String = "ABCDEFGHJNPQRSUVW"
|
|
If cadena.IndexOf(firstChar) = -1 Then Return False
|
|
|
|
Try
|
|
Dim sumaPar As Int32 = Nothing
|
|
Dim sumaImpar As Int32 = Nothing
|
|
Dim cif_sinControl As String = cif.Substring(0, 8)
|
|
Dim digits As String = cif_sinControl.Substring(1, 7)
|
|
|
|
For n As Int32 = 0 To digits.Length - 1 Step 2
|
|
|
|
If n < 6 Then
|
|
sumaPar += Convert.ToInt32(digits(n + 1).ToString())
|
|
End If
|
|
|
|
Dim dobleImpar As Int32 = 2 * Convert.ToInt32(digits(n).ToString())
|
|
sumaImpar += (dobleImpar Mod 10) + (dobleImpar \ 10)
|
|
Next
|
|
|
|
Dim sumaTotal As Int32 = sumaPar + sumaImpar
|
|
sumaTotal = (10 - (sumaTotal Mod 10)) Mod 10
|
|
Dim digitoControl As String = ""
|
|
|
|
Select Case firstChar
|
|
Case "N", "P", "Q", "R", "S", "W"
|
|
Dim characters As Char() = {"J"c, "A"c, "B"c, "C"c, "D"c, "E"c, "F"c, "G"c, "H"c, "I"c}
|
|
digitoControl = characters(sumaTotal).ToString()
|
|
Case Else
|
|
digitoControl = sumaTotal.ToString()
|
|
End Select
|
|
|
|
Return digitoControl.Equals(cif.Substring(8, 1))
|
|
Catch __unusedException1__ As Exception
|
|
Return False
|
|
End Try
|
|
End Function
|
|
|
|
|
|
|
|
''' <summary>
|
|
''' Cálculos para la comprobación del Cif (Entidad jurídica)
|
|
''' </summary>
|
|
'Private Function CompruebaCif() As Boolean
|
|
' Dim letrasCodigo As String() = {"J", "A", "B", "C", "D", "E", _
|
|
' "F", "G", "H", "I"}
|
|
|
|
' Dim n As String = Identificador.ToString()
|
|
' Dim sumaPares As Int32 = 0
|
|
' Dim sumaImpares As Int32 = 0
|
|
' Dim sumaTotal As Int32 = 0
|
|
' Dim i As Int32 = 0
|
|
' Dim digitoCalculado As String
|
|
' Dim retVal As Boolean = False
|
|
|
|
' ' Recorrido por todos los dígitos del número
|
|
' For i = 0 To n.Length - 1
|
|
' Dim aux As Int32
|
|
' Int32.TryParse(n(i).ToString(), aux)
|
|
|
|
' If (i + 1) Mod 2 = 0 Then
|
|
' ' Si es una posición par, se suman los dígitos
|
|
' sumaPares += aux
|
|
' Else
|
|
' ' Si es una posición impar, se multiplican los dígitos por 2
|
|
' aux = aux * 2
|
|
|
|
' ' se suman los dígitos de la suma
|
|
' sumaImpares += SumaDigitos(aux)
|
|
' End If
|
|
' Next
|
|
' ' Se suman los resultados de los números pares e impares
|
|
' sumaTotal += sumaPares + sumaImpares
|
|
|
|
' ' Se obtiene el dígito de las unidades
|
|
' Dim unidades As Int32 = sumaTotal Mod 10
|
|
|
|
' ' Si las unidades son distintas de 0, se restan de 10
|
|
' If unidades <> 0 Then
|
|
' unidades = 10 - unidades
|
|
' End If
|
|
|
|
' Select Case LetraInicial
|
|
' ' Sólo números
|
|
' Case "A", "B", "E", "H"
|
|
' retVal = DigitoControl = unidades.ToString()
|
|
' Exit Select
|
|
|
|
' ' Sólo letras
|
|
' Case "K", "P", "Q", "S"
|
|
' retVal = DigitoControl = letrasCodigo(unidades)
|
|
' Exit Select
|
|
' Case Else
|
|
|
|
' retVal = (DigitoControl = unidades.ToString()) OrElse (DigitoControl = letrasCodigo(unidades))
|
|
' Exit Select
|
|
' End Select
|
|
|
|
' Return retVal
|
|
|
|
'End Function
|
|
|
|
''' <summary>
|
|
''' Obtiene la suma de todos los dígitos
|
|
''' </summary>
|
|
''' <returns>de 23, devuelve la suma de 2 + 3</returns>
|
|
Private Function SumaDigitos(digitos As Int32) As Int32
|
|
Dim sIdentificador As String = digitos.ToString()
|
|
Dim suma As Int32 = 0
|
|
|
|
For i As Int32 = 0 To sIdentificador.Length - 1
|
|
Dim aux As Int32
|
|
Int32.TryParse(sIdentificador(i).ToString(), aux)
|
|
suma += aux
|
|
Next
|
|
Return suma
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Obtiene la letra correspondiente al Dni
|
|
''' </summary>
|
|
Private Function GetLetraNif() As String
|
|
Dim indice As Integer = Identificador Mod 23
|
|
Return "TRWAGMYFPDXBNJZSQVHLCKET"(indice).ToString()
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Obtiene una cadena con el número de identificación completo
|
|
''' </summary>
|
|
Public Overrides Function ToString() As String
|
|
Dim nif As String
|
|
nif = If(EsIntraComunitario, CodigoIntracomunitario, Convert.ToString(String.Empty + LetraInicial & Identificador) & DigitoControl)
|
|
Return nif
|
|
End Function
|
|
|
|
#End Region
|
|
|
|
''' <summary>
|
|
''' Comprobación de un número de identificación fiscal español
|
|
''' </summary>
|
|
''' <param name="numero">Identificador a analizar</param>
|
|
''' <returns>Instancia de <see cref="IdentificadorNif"/> con los datos del número.
|
|
''' Destacable la propiedad <seealso cref="IdentificadorNif.EsCorrecto"/>, que contiene la verificación
|
|
''' </returns>
|
|
Public Shared Function CompruebaNif(numero As String) As ValidarDocumentoIdentidad
|
|
|
|
Return New ValidarDocumentoIdentidad(numero)
|
|
End Function
|
|
|
|
End Class |