ハッシュ値を作成するExcel関数はありますか?


26

ドキュメント名をキーとする多くのデータリストを使用しています。ドキュメント名は非常に説明的ですが、表示する必要がある場合は非常に面倒です(最大256バイトは多くの不動産です)。行うにはVLOOKUP、別のworkseetやワークブックから。

私は、ユニークかつ再現性のあることだタイトルからハッシュを考えているため、各タイトルが最も適切であろう。利用可能な機能はありますか、それとも独自のアルゴリズムの開発を検討していますか?

これまたは別の戦略に関する考えやアイデアはありますか?

回答:


34

独自の関数を作成する必要はありません。他の人がすでにそれを行っています。
たとえば、このstackoverflow回答で 5つのVBAハッシュ関数を収集して比較しました

個人的に私はこのVBA機能を使用します

  • =BASE64SHA1(A1)マクロをVBA モジュールにコピーした後、Excelで呼び出されます
  • ライブラリ "Microsoft MSXML"(遅延バインディング)を使用するため、.NETが必要

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

ハッシュ長のカスタマイズ

  • ハッシュは最初は28文字の長さのUnicode文字列です(大文字と小文字を区別+特殊文字)
  • 次の行でハッシュの長さをカスタマイズします。 Const cutoff As Integer = 5
  • 4桁のハッシュ= 6895行で36の衝突= 0.5%の衝突率
  • 5桁のハッシュ= 6895行で0衝突= 0%衝突率

.NETを必要とせず、外部ライブラリを使用しないハッシュ関数(3つすべてのCRC16関数)もあります。ただし、ハッシュはより長く、より多くの衝突が発生します。

このサンプルワークブックをダウンロードして、5つのハッシュ実装すべてを試すこともできます。ご覧のとおり、最初のシートに良い比較があります


1
素晴らしく見える。ただし、Excelが戻るのを防ぐのに十分なVBAの経験がありません#NAME?。コードを表示>コードを新しいウィンドウにカットアンドペースト-ナビゲーターの正しいワークシート内>マクロ対応ワークシートとして保存>閉じてExcelに戻る... 何とかコンパイルする必要がありますか?
dwwilson66

はい...明確にするために...ワークシートタブに移動したときにポップアップした新しいコードウィンドウに貼り付けました>コードを表示しています...今サンプルをダウンロードしていますが、Excelがコードを認識しない理由を理解したい
dwwilson66

WooHoo ...サンプルシートが役に立ちました。私はコードをMODULEウィンドウではなくOBJECTウィンドウに貼り付けて、それを上回っていたことに気付きました。ワークブックでハッシュを取得しています!
dwwilson66

1
これは優れたツールです。
ジェイキリーン

1
cutoff関数パラメーターリストに移動して、関数Public Function BASE64SHA1(ByVal sTextToHash As String, Optional ByVal cutoff As Integer = 8) 内の宣言を削除することにより、異なるデフォルトでパラメーター化されたオプションを作成できます。
コア

9

衝突についてはあまり気にしませんが、可変長文字列フィールドに基づく行の弱い擬似ランダム化が必要でした。うまくいった1つの非常識なソリューションを次に示します。

=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ハッシュする文字列を含むセルはどこにありますか。

「MOD」は、科学表記法へのオーバーフローを防ぐためにあります。1009は素数で、X * 255 <になるように任意のXを使用できますmax_int_size。10は任意です。何でも使用します。「その他」の値は任意です(ここではpiの桁!); 何でも使用します。文字の位置(1,3,5,7,9)は任意です。何でも使用します。


2
正直なところ、これが最も簡単な答えです。衝突はほとんどのExcelユースケースの問題だと思います。
ロールを

3

適度に小さいリストの場合、組み込みのExcel関数を使用してスクランブラー(貧乏人のハッシュ関数)を作成できます。

例えば

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

ここで、A1とB1はランダムな開始文字と文字列の長さを保持します。

少し手間をかけて確認すると、ほとんどの場合、実行可能な一意のIDを非常にすばやく取得できます。

仕組み:数式では、文字列の最初の文字と文字列の中間から取得した固定文字を使用し、LEN()を「ファンニング関数」として使用して、衝突の可能性を減らします。

警告:これはハッシュではありませんが、何かをすばやく完了させる必要があり、結果を調べて衝突がないことを確認できる場合、非常にうまく機能します。

編集: 文字列が可変長(フルネームなど)である必要があるが、固定幅フィールドを持つデータベースレコードから取得される場合は、次のようにします。

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

長さが意味のあるスクランブラーになるように。


1
素晴らしい答えです!(:「貧乏人のハッシュ関数」、「警告」、「それがどのように機能するか」:)
ナッツについてのナッツ

1
「衝突がないことを確認するために結果を検査する」ために、 DATA> REMOVE DUPLICATESを実行してこれを試してテストし、存在するかどうかを確認できます。[明らかに/恐らく、重複を発見した場合、重複がなくなるまでこれらの関数に対して上記の関数を繰り返し実行することができます]
ナッツについて

2

私はこれを使用して、毎回スクリプトを実行する必要なしに衝突を防ぐことでかなり良い結果をもたらします。0〜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)))

文字列全体から文字を選択し、それらの各文字の値を取得し、値を追加して(異なる場所で同じ文字が同じ結果になるのを防ぐため)、それぞれを乗算/除算し、合計に対してCOS関数を実行します。


1

これを試すことができます。2つの列でPseudo#を実行します。

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

A1とB1が手動で入力されたランダムシードを保存する場所:0


0

私の知る限り、ハッシュ関数はExcelに組み込まれていません。VBAでユーザー定義関数として構築する必要があります。

ただし、あなたの目的のために、ハッシュを使用する必要があるとは思わないことに注意してください!VLOOKUP256バイトでも、より小さなハッシュで動作するのと同じように機能します。確かに、それはほんの少し遅いかもしれません-それは計り知れないほど確かに非常に小さいビットです。そして、ハッシュ値を追加することは、あなたにとって-そしてExcelにとっては...


ええ...私はそれを知っているが、単にプレゼンテーションの観点から、私はむしろ、ディスプレイ、たとえば、ハッシュの15バイトの256バイトのことと思いますtitle...私のフローズン左ペインにある
dwwilson66
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.