ドキュメント名をキーとする多くのデータリストを使用しています。ドキュメント名は非常に説明的ですが、表示する必要がある場合は非常に面倒です(最大256バイトは多くの不動産です)。行うにはVLOOKUP
、別のworkseetやワークブックから。
私は、ユニークかつ再現性のあることだタイトルからハッシュを考えているため、各タイトルが最も適切であろう。利用可能な機能はありますか、それとも独自のアルゴリズムの開発を検討していますか?
これまたは別の戦略に関する考えやアイデアはありますか?
ドキュメント名をキーとする多くのデータリストを使用しています。ドキュメント名は非常に説明的ですが、表示する必要がある場合は非常に面倒です(最大256バイトは多くの不動産です)。行うにはVLOOKUP
、別のworkseetやワークブックから。
私は、ユニークかつ再現性のあることだタイトルからハッシュを考えているため、各タイトルが最も適切であろう。利用可能な機能はありますか、それとも独自のアルゴリズムの開発を検討していますか?
これまたは別の戦略に関する考えやアイデアはありますか?
回答:
独自の関数を作成する必要はありません。他の人がすでにそれを行っています。
たとえば、このstackoverflow回答で 5つのVBAハッシュ関数を収集して比較しました
個人的に私はこのVBA機能を使用します
=BASE64SHA1(A1)
マクロをVBA モジュールにコピーした後、Excelで呼び出されます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
ハッシュ長のカスタマイズ
Const cutoff As Integer = 5
.NETを必要とせず、外部ライブラリを使用しないハッシュ関数(3つすべてのCRC16関数)もあります。ただし、ハッシュはより長く、より多くの衝突が発生します。
このサンプルワークブックをダウンロードして、5つのハッシュ実装すべてを試すこともできます。ご覧のとおり、最初のシートに良い比較があります
cutoff
関数パラメーターリストに移動して、関数Public Function BASE64SHA1(ByVal sTextToHash As String, Optional ByVal cutoff As Integer = 8)
内の宣言を削除することにより、異なるデフォルトでパラメーター化されたオプションを作成できます。
衝突についてはあまり気にしませんが、可変長文字列フィールドに基づく行の弱い擬似ランダム化が必要でした。うまくいった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)は任意です。何でも使用します。
適度に小さいリストの場合、組み込みの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))
長さが意味のあるスクランブラーになるように。
私はこれを使用して、毎回スクリプトを実行する必要なしに衝突を防ぐことでかなり良い結果をもたらします。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関数を実行します。
これを試すことができます。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
私の知る限り、ハッシュ関数はExcelに組み込まれていません。VBAでユーザー定義関数として構築する必要があります。
ただし、あなたの目的のために、ハッシュを使用する必要があるとは思わないことに注意してください!VLOOKUP
256バイトでも、より小さなハッシュで動作するのと同じように機能します。確かに、それはほんの少し遅いかもしれません-それは計り知れないほど確かに非常に小さいビットです。そして、ハッシュ値を追加することは、あなたにとって-そしてExcelにとっては...
title
...私のフローズン左ペインにある
#NAME?
。コードを表示>コードを新しいウィンドウにカットアンドペースト-ナビゲーターの正しいワークシート内>マクロ対応ワークシートとして保存>閉じてExcelに戻る... 何とかコンパイルする必要がありますか?