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?
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
=BASE64SHA1(A1)
dans Excel après avoir copié la macro dans un module VBA 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
Const cutoff As Integer = 5
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
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)
Où 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.
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.
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.
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
À 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 ...