Você não precisa escrever sua própria função - outros já fizeram isso por você.
Por exemplo, eu coletei e comparei cinco funções de hash do VBA nesta resposta de stackoverflow
Pessoalmente, eu uso essa função VBA
- é chamado
=BASE64SHA1(A1)
no Excel depois que você copiou a macro para um módulo VBA
- requer .NET, pois usa a biblioteca "Microsoft MSXML" (com ligação tardia)
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
Personalizando o comprimento do hash
- o hash inicialmente é uma string unicode de 28 caracteres (diferencia maiúsculas de minúsculas + caracteres especiais)
- Você personaliza o comprimento do hash com esta linha:
Const cutoff As Integer = 5
- Hash de 4 dígitos = 36 colisões em 6895 linhas = taxa de colisão de 0,5%
- Hash de 5 dígitos = 0 colisões em 6895 linhas = 0% de taxa de colisão
Também existem funções de hash ( todas as três funções CRC16 ) que não requerem .NET e não usam bibliotecas externas. Mas o hash é mais longo e produz mais colisões.
Você também pode fazer o download desta pasta de trabalho de exemplo e brincar com todas as 5 implementações de hash. Como você vê, há uma boa comparação na primeira folha
#NAME?
. Exibir código> recortar e colar código em uma nova janela - dentro da planilha correta no navegador> salvar como planilha habilitada para macro> fechar e retornar ao excel ... mais alguma coisa que esteja faltando? Preciso compilá-lo de alguma forma?cutoff
parâmetro e o opcional com um padrão diferente movendo-o para a lista de parâmetros FunctionPublic Function BASE64SHA1(ByVal sTextToHash As String, Optional ByVal cutoff As Integer = 8)
e removendo a declaração dentro da função.Não me importo muito com colisões, mas precisava de um pseudo-randomizador fraco de linhas com base em um campo de string de comprimento variável. Aqui está uma solução insana que funcionou bem:
Onde
Z2
está a célula que contém a sequência que você deseja hash.Os "MOD" estão lá para evitar transbordar para notação científica.
1009
é primo, poderia usar qualquer coisa X para que X * 255 <max_int_size
. 10 é arbitrário; use qualquer coisa. Os valores "restantes" são arbitrários (dígitos de pi aqui!); use qualquer coisa. A localização dos caracteres (1,3,5,7,9) é arbitrária; use qualquer coisa.fonte
Para uma lista razoavelmente pequena, você pode criar um embaralhador (função de hash do pobre homem) usando funções internas do Excel.
Por exemplo
Aqui A1 e B1 mantêm uma letra inicial aleatória e o comprimento da string.
Um pouco de mexer e checar e, na maioria dos casos, é possível obter um ID exclusivo viável rapidamente.
Como funciona : a fórmula usa a primeira letra da string e uma letra fixa tirada do meio da string e usa LEN () como uma 'função de ventilação' para reduzir a chance de colisões.
CAVEAT : isso não é um hash, mas quando você precisa fazer algo rapidamente e pode inspecionar os resultados para ver se não há colisões, funciona muito bem.
Edit: Se suas strings tiverem comprimentos variáveis (por exemplo, nomes completos), mas forem extraídas de um registro de banco de dados com campos de largura fixa, convém fazer o seguinte:
para que os comprimentos sejam um embaralhador significativo.
fonte
Estou usando isso, que fornece bons resultados com a prevenção de conflitos sem a necessidade de executar um script a cada vez. Eu precisava de um valor entre 0 - 1.
Ele seleciona letras do outro lado da string, pega o valor de cada uma dessas letras, adiciona um valor (para evitar que as mesmas letras em lugares diferentes gerem os mesmos resultados), multiplica / divide cada uma e executa uma função COS sobre o total.
fonte
Você pode tentar isso. Execute um pseudo # em duas colunas:
Onde A1 e B1 armazenam sementes aleatórias inseridas manualmente: 0
fonte
Que eu saiba, não há nenhuma função de hash embutida no Excel - você precisaria criar uma como uma Função Definida pelo Usuário no VBA.
No entanto, observe que, para o seu propósito, não acho que é necessário usar um hash ou realmente vantajoso!
VLOOKUP
funcionará tão bem em 256 bytes quanto em um hash menor. Claro, pode ser um pouco mais lento - com certeza é tão pequeno que é incomensurável. E, em seguida, adicionar os valores de hash é mais trabalhoso para você - e para o Excel ...fonte
title
no meu painel esquerdo congelado ...