microsoft excel 2010
Существует ли функция Excel для создания хэш-значения
Я работаю с рядом списков данных, которые вводятся по имени документа. Имена документов, хотя и очень описательные, довольно громоздки, если мне нужно их просмотреть (до 256 байтов — это много недвижимости), и я хотел бы иметь возможность создать ключевое поле меньшего размера, которое легко воспроизвести в случае необходимости. для выполнения VLOOKUP
из другого рабочего стола или книги.
Я думаю, что хэш из названия, который был бы уникальным и воспроизводимым для каждого названия, был бы наиболее подходящим. Доступна ли функция, или я рассматриваю возможность разработки собственного алгоритма?
Есть мысли или идеи по этой или другой стратегии?
Вам не нужно писать свою собственную функцию-другие уже сделали это за вас.
Например, в этом ответе я собрал и сравнил пять хеш-функций VBA.
Лично я использую эту функцию VBA
- он вызывается с помощью
=BASE64SHA1(A1)
в Excel после того, как вы скопировали макрос в модуль VBA - требует .NET,так как использует библиотеку "Microsoft MSXML" (с поздним связыванием)
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 символов (с учетом регистра+специальные символы)
- Вы настраиваете длину хеша с помощью этой строки:
Const cutoff As Integer = 5
- хэш из 4 цифр=36 коллизий в 6895 строках=0,5 % коллизий
- 5 разрядов хэша=0 коллизий в 6895 строках=0 % коллизий
Существуют также хэш-функции ( все три функции CRC16 ), которые не требуют .NET и не используют внешние библиотеки. Но хэш длиннее и производит больше столкновений.
Вы также можете просто загрузить этот пример рабочей книги и поиграть со всеми 5 реализациями хеширования. Как видите, на первом листе есть хорошее сравнение
Я не очень забочусь о коллизиях,но мне нужен был слабый псевдорандомизатор строк на основе строкового поля переменной длины.Вот одно безумное решение,которое хорошо сработало:
=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, чтобы X*255 < max_int_size
. 10 произвольно; использовать что угодно. Значения «иначе» произвольны (здесь цифры числа пи!); использовать что угодно. Расположение символов (1,3,5,7,9) произвольное; использовать что угодно.