Có một hàm Excel để tạo giá trị băm không?


26

Tôi đang làm việc với một số danh sách dữ liệu được khóa bằng tên tài liệu. Tên tài liệu, mặc dù rất mô tả, khá cồng kềnh nếu tôi cần xem chúng (tối đa 256 byte là nhiều bất động sản) và tôi rất thích có thể tạo một trường khóa nhỏ hơn có thể tái tạo trong trường hợp tôi cần để làm một VLOOKUPtừ một workseet hoặc sổ làm việc khác.

Tôi nghĩ rằng một hàm băm từ tiêu đề là duy nhất và có thể tái tạo cho mỗi tiêu đề sẽ phù hợp nhất. Có một chức năng có sẵn, hoặc tôi đang xem xét việc phát triển thuật toán của riêng tôi?

Bất kỳ suy nghĩ hoặc ý tưởng về chiến lược này hay chiến lược khác?

Câu trả lời:


34

Bạn không cần phải viết chức năng của riêng bạn - những người khác đã làm điều đó cho bạn.
Ví dụ tôi đã thu thập và so sánh năm hàm băm VBA trên câu trả lời stackoverflow này

Cá nhân tôi sử dụng chức năng VBA này

  • nó được gọi bằng =BASE64SHA1(A1)Excel sau khi bạn sao chép macro sang mô-đun VBA
  • yêu cầu .NET vì nó sử dụng thư viện "Microsoft MSXML" (có ràng buộc muộn)

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

Tùy chỉnh độ dài băm

  • hàm băm ban đầu là một chuỗi unicode dài 28 ký tự (phân biệt chữ hoa chữ thường + ký tự đặc biệt)
  • Bạn tùy chỉnh độ dài băm với dòng này: Const cutoff As Integer = 5
  • Băm 4 chữ số = 36 va chạm trong 6895 dòng = tỷ lệ va chạm 0,5%
  • Băm 5 chữ số = 0 va chạm trong 6895 dòng = 0% tỷ lệ va chạm

Ngoài ra còn có các hàm băm ( cả ba hàm CRC16 ) không yêu cầu .NET và không sử dụng các thư viện bên ngoài. Nhưng băm dài hơn và tạo ra nhiều va chạm hơn.

Bạn cũng có thể tải xuống sổ làm việc mẫu này và chơi xung quanh với tất cả 5 triển khai băm. Như bạn thấy có một so sánh tốt trên tờ đầu tiên


1
Trông rất tuyệt. Tuy nhiên, tôi không có đủ kinh nghiệm VBA để ngăn Excel quay lại #NAME?. Xem mã> cắt và dán mã vào cửa sổ mới - trong bảng tính chính xác trong bộ điều hướng> lưu dưới dạng bảng tính kích hoạt macro> đóng và trở lại excel ... còn gì nữa không? Tôi có cần phải biên dịch nó bằng cách nào đó không?
dwwilson66

Có ... để làm rõ ... tôi đã dán nó trong cửa sổ mã mới xuất hiện khi tôi đi đến tab bảng tính> xem mã ... Đang tải xuống mẫu ngay bây giờ, nhưng tôi muốn hiểu tại sao excel không nhận ra mã của tôi
dwwilson66

WooHoo ... tờ mẫu đã giúp. Nhận ra tôi đã dán mã vào và excel cửa sổ ĐỐI TƯỢNG, không phải cửa sổ MODULE. Tôi đang nhận được băm trong sổ làm việc của tôi bây giờ!
dwwilson66

1
Đây là một công cụ tuyệt vời.
Jay Killeen

1
Bạn có thể làm cho cutofftham số hóa và tùy chọn với một mặc định khác bằng cách di chuyển nó lên danh sách tham số Hàm Public Function BASE64SHA1(ByVal sTextToHash As String, Optional ByVal cutoff As Integer = 8) và xóa khai báo bên trong hàm.
Lõi

9

Tôi không quan tâm lắm đến các va chạm, nhưng cần một giả ngẫu nhiên yếu của các hàng dựa trên trường chuỗi có độ dài thay đổi. Đây là một giải pháp điên rồ hoạt động tốt:

=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)

Đâu Z2là ô chứa chuỗi bạn muốn băm.

"MOD" đang ở đó để ngăn chặn tràn ra ký hiệu khoa học. 1009là số nguyên tố, có thể sử dụng bất cứ thứ gì X sao cho X * 255 < max_int_size. 10 là tùy ý; sử dụng bất cứ thứ gì Giá trị "Khác" là tùy ý (chữ số của pi ở đây!); sử dụng bất cứ thứ gì Vị trí của các ký tự (1,3,5,7,9) là tùy ý; sử dụng bất cứ thứ gì


2
Thành thật mà nói đây là câu trả lời đơn giản nhất, tôi nghi ngờ va chạm là một vấn đề đối với hầu hết các trường hợp sử dụng excel.
cuộn

3

Đối với một danh sách nhỏ hợp lý, bạn có thể tạo một scrambler (hàm băm của người nghèo) bằng các hàm Excel tích hợp.

Ví dụ

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

Ở đây A1 và B1 giữ một chữ cái bắt đầu ngẫu nhiên và độ dài chuỗi.

Một chút nghịch ngợm và kiểm tra và trong hầu hết các trường hợp, bạn có thể nhận được một ID duy nhất khả thi khá nhanh chóng.

Cách thức hoạt động : Công thức sử dụng chữ cái đầu tiên của chuỗi và một chữ cái cố định được lấy từ giữa chuỗi và sử dụng LEN () làm 'hàm quạt' để giảm nguy cơ va chạm.

CAVEAT : đây không phải là một hàm băm, nhưng khi bạn cần hoàn thành một cái gì đó nhanh chóng và có thể kiểm tra kết quả để thấy rằng không có va chạm, nó hoạt động khá tốt.

Chỉnh sửa: Nếu chuỗi của bạn phải có độ dài thay đổi (ví dụ: tên đầy đủ) nhưng được kéo từ bản ghi cơ sở dữ liệu với các trường có chiều rộng cố định, bạn sẽ muốn làm như thế này:

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

do đó, độ dài là một scrambler có ý nghĩa.


1
Câu trả lời chính xác! (: "Hàm băm của người nghèo", "báo trước", "cách thức hoạt động" :)
hấp dẫn về

1
Để "kiểm tra kết quả để thấy rằng không có va chạm", bạn chỉ cần thử / kiểm tra điều này bằng cách chạy DATA> XÓA B DUNG DUPLICATE và xem liệu có bất kỳ va chạm nào không . [Rõ ràng / có lẽ, nếu bạn làm bản sao encouter bạn có thể chỉ tái chạy các chức năng trên cho những lặp đi lặp lại cho đến khi không có bản sao còn lại]
hấp dẫn về Natty

2

Tôi đang sử dụng điều này mang lại kết quả khá tốt với việc ngăn chặn xung đột mà không cần phải chạy tập lệnh mỗi lần. Tôi cần một giá trị từ 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)))

Nó chọn các chữ cái trên toàn chuỗi, lấy giá trị của từng chữ cái đó, thêm một giá trị (để ngăn các chữ cái giống nhau ở các vị trí khác nhau cho cùng một kết quả), nhân / chia từng chữ cái và chạy một hàm COS trên tổng số.


1

Bạn có thể thử điều này. Chạy một giả # trên hai cột:

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

Trong đó A1 và B1 lưu trữ hạt giống ngẫu nhiên được nhập thủ công: 0


0

Theo hiểu biết của tôi, không có hàm băm nào được tích hợp vào Excel - bạn cần xây dựng một hàm dưới dạng Hàm do người dùng xác định trong VBA.

Tuy nhiên, xin lưu ý rằng vì mục đích của bạn, tôi không nghĩ sử dụng hàm băm là bắt buộc hoặc thực sự có lợi! VLOOKUPsẽ hoạt động tốt trên 256 byte vì nó sẽ ở mức băm nhỏ hơn. Chắc chắn, nó có thể chậm hơn một chút - bit chắc chắn nhỏ đến mức không thể đo lường được. Và sau đó, thêm các giá trị băm là nỗ lực nhiều hơn cho bạn - và cho Excel ...


vâng ... Tôi biết điều đó, nhưng chỉ từ quan điểm trình bày, tôi muốn hiển thị hơn, giả sử, 15 byte băm mà 256 byte titletrong khung bên trái bị đóng băng của tôi ...
dwwilson66
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.