microsoft excel 2010

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

Estoy trabajando con una serie de listas de datos que están codificadas por nombre de documento. Los nombres de los documentos, aunque son muy descriptivos, son bastante engorrosos si necesito verlos (hasta 256 bytes es mucho espacio) y me encantaría poder crear un campo clave más pequeño que sea fácilmente reproducible en caso de que necesite para hacer una VLOOKUP desde otra hoja de trabajo o libro de trabajo.

Estoy pensando que un hash del título que sería único y reproducible para cada título sería lo más apropiado. ¿Hay una función disponible o estoy pensando en desarrollar mi propio algoritmo?

¿Alguna idea sobre esto u otra estrategia?

No es necesario que escriba su propia función:otros ya lo han hecho por usted.
Por ejemplo, recopilé y comparé cinco funciones hash de VBA en esta respuesta

Personalmente uso esta función VBA

  • se llama con =BASE64SHA1(A1) en Excel después de copiar la macro en unmódulo de VBA
  • requiere .NET ya que utiliza la librería "Microsoft MSXML" (con late binding)

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 una cadena unicode de 28 caracteres (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 % de 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 pseudorandomizador débil de filas basado en un campo de cadenas de longitud variable.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)

Donde Z2 es la celda que contiene la cadena que desea codificar.

Los "MOD" están ahí para evitar el desbordamiento a la notación científica. 1009 es un número primo, podría usar cualquier 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