web-dev-qa-db-fra.com

Existe-t-il une fonction Excel pour créer une valeur de hachage?

Je travaille avec un certain nombre de listes de données classées par nom de document. Les noms de document, bien que très descriptifs, sont assez encombrants si je dois les visualiser (jusqu'à 256 octets est une grande quantité de biens immobiliers) et j'aimerais pouvoir créer un champ de clé plus petit, facilement reproductible au cas où j'en aurais besoin. faire une VLOOKUP à partir d'un autre classeur ou classeur.

Je pense qu'un hachage du titre qui serait unique et reproductible pour chaque titre serait le plus approprié. Existe-t-il une fonction disponible ou envisage-t-on de développer mon propre algorithme?

Des idées ou des idées sur ceci ou sur une autre stratégie?

24
dwwilson66

Vous n'avez pas besoin d'écrire votre propre fonction - d'autres l'ont déjà fait pour vous.
Par exemple, j'ai collecté et comparé cinq fonctions de hachage VBA sur cette réponse stackoverflow

Personnellement j'utilise cette fonction VBA

  • il est appelé avec =BASE64SHA1(A1) dans Excel après avoir copié la macro dans un module VBA
  • nécessite .NET puisqu'il utilise la bibliothèque "Microsoft MSXML" (avec liaison tardive)

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

Personnaliser la longueur de hachage

  • le hachage est initialement une chaîne unicode de 28 caractères (sensible à la casse + caractères spéciaux)
  • Vous personnalisez la longueur de hachage avec cette ligne: Const cutoff As Integer = 5
  • Dièse à 4 chiffres = 36 collisions sur 6895 lignes = taux de collision de 0,5%
  • Dièse à 5 chiffres = 0 collisions sur 6895 lignes = taux de collision de 0%

Il existe également des fonctions de hachage ( ), les trois fonctions CRC16 ) qui ne nécessitent pas .NET et n'utilisent pas de bibliothèques externes. Mais le hash est plus long et produit plus de collisions.

Vous pouvez également simplement télécharger cet exemple classeur et vous amuser avec les 5 implémentations de hachage. Comme vous le voyez, il y a une bonne comparaison sur la première feuille

32
nixda

Je me moque bien des collisions, mais il me fallait un pseudo-randomiseur faible de lignes basé sur un champ de chaîne de longueur variable. Voici une solution insensée qui a bien fonctionné:

=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)

Z2 est la cellule contenant la chaîne que vous voulez hacher.

Les "MOD" sont là pour empêcher le débordement de la notation scientifique. 1009 est un nombre premier, peut utiliser n'importe quoi X pour que X * 255 <max_int_size. 10 est arbitraire; utiliser n'importe quoi. Les "autres" valeurs sont arbitraires (chiffres de pi ici!); utiliser n'importe quoi. L'emplacement des caractères (1,3,5,7,9) est arbitraire; utiliser n'importe quoi.

7
Anonymous Coward

Pour une liste assez petite, vous pouvez créer un brouilleur (fonction de hachage du pauvre) à l'aide des fonctions Excel intégrées.

Par exemple.

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

Ici, A1 et B1 tiennent une lettre de début et une longueur de chaîne aléatoires.

Un peu de bidouillage, de vérification et, dans la plupart des cas, vous pouvez obtenir rapidement un identifiant unique utilisable.

Comment ça marche : La formule utilise la première lettre de la chaîne et une lettre fixe tirée de la chaîne moyenne et utilise LEN () en tant que fonction de "fanning". 'pour réduire les risques de collision.

MISE EN GARDE: c'est pas un hachage, mais quand vous en avez besoin faire quelque chose rapidement et pouvoir examiner les résultats pour s'assurer qu'il n'y a pas de collision, cela fonctionne assez bien.

Edit: Si vos chaînes doivent avoir des longueurs variables (par exemple des noms complets) mais sont extraites d'un enregistrement de base de données avec des champs de largeur fixe, vous voudrez le faire. comme ça:

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

de sorte que les longueurs sont un brouilleur significatif.

3
Assad Ebrahim

J'utilise ceci qui donne de très bons résultats pour éviter les conflits sans avoir à exécuter un script à chaque fois. J'avais besoin d'une valeur comprise entre 0 et 1.

=ABS(COS((CODE(MID(A2,ROUNDUP(LEN(A2)/9,0),1))*(CODE(MID(A2,ROUNDUP(LEN(A2)/5,0),1))+100)/CODE(MID(A2,ROUNDUP(LEN(A2)/3,0),1))*(CODE(MID(A2,ROUNDUP(LEN(A2)*8/9,0),1))+25)/CODE(MID(A2,ROUNDUP(LEN(A2)*6/9,0),1))*(CODE(MID(A2,ROUNDUP(LEN(A2)*4/9,0),1))-25))/LEN(A2)+CODE(A2)))

Il sélectionne les lettres dans la chaîne, prend la valeur de chacune de ces lettres, ajoute une valeur (pour éviter que les mêmes lettres donnent des résultats identiques à différents endroits), multiplie/divise chacune et exécute une fonction COS sur le total.

1
Ant Cole

Vous pouvez essayer ça. Exécutez un pseudo # sur deux colonnes:

= + IF (AND (ISBLANK (D3), ISBLANK (E3)), "", CODE (TRIM (D3 & E3)) * LEN (TRIM (D3 et E3)) + CODE (MID (TRIM (D3 & E3)), $ A $ 1 * LEN (D3 & E3), 1)) INT (LEN (TRIM (D3 & E3)) $ B $ 1))

Où A1 et B1 stockent des graines aléatoires entrées manuellement: 0

1

À ma connaissance, il n’existe pas de fonction de hachage dans Excel. Vous devez en créer une en tant que fonction définie par l’utilisateur dans VBA.

Cependant, veuillez noter que pour votre propos, je ne pense pas que l’utilisation d’un hash soit nécessaire ou vraiment avantageuse! VLOOKUP fonctionnera aussi bien sur 256 octets que sur un hachage plus petit. Bien sûr, il est possible qu’il soit un peu plus lent, ce qui est certainement si petit qu’il est incommensurable. Et puis ajouter les valeurs de hachage demande plus d'effort pour vous - et pour Excel ...

0
Peter Albert