Saltar al contenido

¿Existe una función de Excel para crear un valor hash?

La guía paso a paso o código que encontrarás en este artículo es la resolución más rápida y efectiva que hallamos a tu duda o problema.

Solución:

No necesita escribir su propia función; otros ya lo hicieron por usted.
Por ejemplo, recopilé y comparé cinco funciones hash de VBA en esta respuesta de stackoverflow

Personalmente uso esta función de VBA

  • se llama con =BASE64SHA1(A1) en Excel después de copiar el macro a un VBA módulo
  • requiere .NET ya que usa la biblioteca “Microsoft MSXML” (con enlace tardío)

Public Function BASE64SHA1(ByVal sTextToHash As String)

    Dim asc As Object
    Dim enc As Object
    Dim TextToHash() As Byte
    Dim SharedSecretKey() As Byte
    Dim bytes() As Byte
    Const cutoff As Integer = 5

    Set asc = CreateObject("System.Text.UTF8Encoding")
    Set enc = CreateObject("System.Security.Cryptography.HMACSHA1")

    TextToHash = asc.GetBytes_4(sTextToHash)
    SharedSecretKey = asc.GetBytes_4(sTextToHash)
    enc.Key = SharedSecretKey

    bytes = enc.ComputeHash_2((TextToHash))
    BASE64SHA1 = EncodeBase64(bytes)
    BASE64SHA1 = Left(BASE64SHA1, cutoff)

    Set asc = Nothing
    Set enc = Nothing

End Function

Private Function EncodeBase64(ByRef arrData() As Byte) As String

    Dim objXML As Object
    Dim objNode As Object

    Set objXML = CreateObject("MSXML2.DOMDocument")
    Set objNode = objXML.createElement("b64")

    objNode.DataType = "bin.base64"
    objNode.nodeTypedValue = arrData
    EncodeBase64 = objNode.text

    Set objNode = Nothing
    Set objXML = Nothing

End Function

Personalización de la longitud del hash

  • el hash inicialmente es un Unicode de 28 caracteres de largo string (sensible a mayúsculas y minúsculas + caracteres especiales)
  • Personalizas la longitud del hash con esta línea: Const cutoff As Integer = 5
  • Hash de 4 dígitos = 36 colisiones en 6895 líneas = 0,5 % de tasa de colisión
  • Hash de 5 dígitos = 0 colisiones en 6895 líneas = 0 % tasa de colisión

También hay funciones hash (las tres funciones CRC16) que no requieren .NET y no usan bibliotecas externas. Pero el hash es más largo y produce más colisiones.

También puede simplemente descargar este libro de trabajo de ejemplo y jugar con las 5 implementaciones de hash. Como veis hay una buena comparativa en la primera hoja

No me importan mucho las colisiones, pero necesitaba un pseudoaleatorizador débil de filas basado en una longitud variable string campo. Aquí hay una solución loca que funcionó bien:

=MOD(MOD(MOD(MOD(MOD(IF(LEN(Z2)>=1,CODE(MID(Z2,1,1))+10,31),1009)*IF(LEN(Z2)>=3,CODE(MID(Z2,3,1))+10,41),1009)*IF(LEN(Z2)>=5,CODE(MID(Z2,5,1))+10,59),1009)*IF(LEN(Z2)>=7,CODE(MID(Z2,7,1))+10,26),1009)*IF(LEN(Z2)>=9,CODE(MID(Z2,9,1))+10,53),1009)

Dónde Z2 es la celda que contiene el string quieres hacer hash.

Los “MOD” están ahí para evitar el desbordamiento a la notación científica. 1009 es primo, podría usar cualquier cosa X para que X*255 max_int_size. 10 es arbitrario; usa cualquier cosa Los valores “Else” son arbitrarios (¡dígitos de pi aquí!); usa cualquier cosa La ubicación de los caracteres (1,3,5,7,9) es arbitraria; usa cualquier cosa

Para una lista razonablemente pequeña, puede crear un codificador (función hash del hombre pobre) utilizando las funciones integradas de Excel.

P.ej

 =CODE(A2)*LEN(A2) + CODE(MID(A2,$A$1,$B$1))*LEN(MID(A2,$A$1,$B$1))

Aquí A1 y B1 tienen una letra inicial aleatoria y string longitud.

Un poco de manipulación y verificación y, en la mayoría de los casos, puede obtener una identificación única viable con bastante rapidez.

Cómo funciona: La fórmula utiliza la primera letra de la string y una letra fija sacada de mediados destring y usa LEN() como una ‘función de abanico’ para reducir la posibilidad de colisiones.

ADVERTENCIA: esto es no un hash, pero cuando necesita hacer algo rápidamente y puede inspeccionar los resultados para ver que no haya colisiones, funciona bastante bien.

Editar:
Si sus cadenas deben tener longitudes variables (por ejemplo, nombres completos) pero se extraen de un registro de base de datos con campos de ancho fijo, querrá hacerlo así:

 =CODE(TRIM(C8))*LEN(TRIM(C8))
       +CODE(MID(TRIM(C8),$A$1,1))*LEN(MID(TRIM(C8),$A$1,$B$1))

para que las longitudes sean un codificador significativo.

valoraciones y comentarios

Agradecemos que quieras añadir valor a nuestro contenido informacional colaborando tu veteranía en las reseñas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *