microsoft excel 2010
Gibt es eine Excel-Funktion zur Erstellung eines Hash-Wertes
Ich arbeite mit einer Reihe von Datenlisten, die nach Dokumentnamen verschlüsselt sind. Die Dokumentnamen sind zwar sehr aussagekräftig, aber ziemlich umständlich, wenn ich sie anzeigen muss (bis zu 256 Bytes sind viel Platz), und ich würde gerne ein kleineres Schlüsselfeld erstellen können, das bei Bedarf leicht reproduzierbar ist um einen VLOOKUP
von einem anderen Workset oder einer anderen Arbeitsmappe durchzuführen.
Ich denke, ein Hash aus dem Titel, der für jeden Titel einzigartig und reproduzierbar wäre, wäre am besten geeignet. Gibt es eine Funktion oder möchte ich einen eigenen Algorithmus entwickeln?
Haben Sie eine Idee für diese oder eine andere Strategie?
Sie brauchen keine eigene Funktion zu schreiben-das haben schon andere für Sie getan.
Zum Beispiel habe ich fünf VBA-Hash-Funktionen für diese Antwort gesammelt und verglichen
Ich persönlich verwende diese VBA-Funktion
- Es wird mit
=BASE64SHA1(A1)
in Excel aufgerufen, nachdem Sie das Makro in ein VBA -Modul kopiert haben - erfordert .NET,da es die Bibliothek "Microsoft MSXML" (mit später Bindung)verwendet
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
Anpassen der Hash-Länge
- der Hash ist zunächst eine 28 Zeichen lange Unicode-Zeichenfolge (Groß-und Kleinschreibung sowie Sonderzeichen werden berücksichtigt)
- Sie passen die Hash-Länge mit dieser Zeile an:
Const cutoff As Integer = 5
- 4-stelliger Hash=36 Kollisionen in 6895 Zeilen=0,5 % Kollisionsrate
- 5-stelliger Hash=0 Kollisionen in 6895 Zeilen=0 % Kollisionsrate
Es gibt auch Hash-Funktionen ( alle drei CRC16-Funktionen ), die kein .NET erfordern und keine externen Bibliotheken verwenden. Aber der Hash ist länger und erzeugt mehr Kollisionen.
Sie können auch einfach diese Beispielarbeitsmappe herunterladen und mit allen 5 Hash-Implementierungen herumspielen. Wie Sie sehen, gibt es auf dem ersten Blatt einen guten Vergleich
Ich mache mir nicht viel aus Kollisionen,brauchte aber einen schwachen Pseudozufallsgenerator für Zeilen,der auf einem Stringfeld variabler Länge basiert.Hier ist eine verrückte Lösung,die gut funktioniert hat:
=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)
Wobei Z2
die Zelle ist, die die Zeichenfolge enthält, die Sie hashen möchten.
"MOD"s sind da, um ein Überlaufen in die wissenschaftliche Notation zu verhindern. 1009
ist eine Primzahl, könnte alles X verwenden, sodass X*255 < max_int_size
. 10 ist willkürlich; irgendetwas verwenden. "Else"-Werte sind willkürlich (Ziffern von pi hier!); irgendetwas verwenden. Die Position der Zeichen (1,3,5,7,9) ist willkürlich; irgendetwas verwenden.