มีฟังก์ชัน Excel เพื่อสร้างค่าแฮชหรือไม่


26

ฉันกำลังทำงานกับรายการข้อมูลจำนวนมากที่คีย์โดยชื่อเอกสาร ชื่อเอกสารในขณะที่อธิบายได้ค่อนข้างยุ่งยากถ้าฉันต้องการดูพวกเขาใน (มากถึง 256 ไบต์เป็นอสังหาริมทรัพย์จำนวนมาก) และฉันชอบที่จะสร้าง keyfield ขนาดเล็กที่สามารถทำซ้ำได้ในกรณีที่ฉันต้องการ เพื่อทำVLOOKUPจากเวิร์กเซ็ตหรือเวิร์กบุ๊กอื่น

ฉันคิดว่าแฮชจากชื่อที่จะไม่ซ้ำกันและทำซ้ำได้สำหรับแต่ละชื่อจะเหมาะสมที่สุด มีฟังก์ชั่นให้ใช้หรือฉันกำลังดูการพัฒนาอัลกอริทึมของตัวเองหรือไม่?

ความคิดหรือความคิดเกี่ยวกับกลยุทธ์นี้หรือกลยุทธ์อื่น?

คำตอบ:


34

คุณไม่จำเป็นต้องเขียนฟังก์ชั่นของคุณเอง - คนอื่นทำเพื่อคุณแล้ว
ตัวอย่างเช่นฉันรวบรวมและเปรียบเทียบห้าฟังก์ชันแฮช VBA กับคำตอบของ stackoverflowนี้

ส่วนตัวฉันใช้ฟังก์ชั่น 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

การปรับแต่งความยาวแฮช

  • hash เริ่มแรกคือสตริง Unicode ที่มีความยาว 28 ตัวอักษร (case sensitive + chars พิเศษ)
  • คุณปรับแต่งความยาวแฮชด้วยบรรทัดนี้: Const cutoff As Integer = 5
  • แฮช 4 หลัก = 36 การชนใน 6895 บรรทัด = 0.5% อัตราการชน
  • แฮช 5 หลัก = 0 การชนใน 6895 บรรทัด = 0% อัตราการชน

นอกจากนี้ยังมีฟังก์ชันแฮช (ฟังก์ชั่นCRC16 ทั้งสาม ) ซึ่งไม่ต้องการ. NET และไม่ใช้ไลบรารีภายนอก แต่แฮชนั้นยาวกว่าและสร้างการชนได้มากขึ้น

คุณสามารถดาวน์โหลดเวิร์กบุ๊กตัวอย่างนี้และเล่นกับการแฮชทั้ง 5 แบบ อย่างที่คุณเห็นมีการเปรียบเทียบที่ดีในแผ่นงานแรก


1
ดูดี. แต่ผมไม่ได้มีประสบการณ์ VBA พอที่จะป้องกัน Excel #NAME?จากการกลับมา ดูรหัส> ตัดและวางรหัสลงในหน้าต่างใหม่ - ภายในเวิร์กชีตที่ถูกต้องในเนวิเกเตอร์> บันทึกเป็นเวิร์กชีตที่เปิดใช้งานมาโคร> ปิดและกลับไปที่ excel ... มีอะไรอีกบ้างที่ขาดหายไป ฉันจำเป็นต้องรวบรวมมันด้วยวิธีใด?
dwwilson66

ใช่ ... เพื่อชี้แจง ... ฉันวางมันลงในหน้าต่างรหัสใหม่ที่โผล่ขึ้นมาเมื่อฉันไปที่แท็บแผ่นงาน> ดูรหัส ... กำลังดาวน์โหลดตัวอย่างตอนนี้ แต่ฉันต้องการที่จะเข้าใจว่าทำไม excel ไม่รู้จักรหัสของฉัน
dwwilson66

WooHoo ... แผ่นตัวอย่างช่วย ฉันรู้ว่าฉันได้วางโค้ดลงในหน้าต่าง excel OBJECT ไม่ใช่หน้าต่าง MODULE ฉันได้รับแฮชในสมุดงานของฉันตอนนี้!
dwwilson66

1
นี่เป็นเครื่องมือที่ยอดเยี่ยม
Jay Killeen

1
คุณสามารถทำให้cutoffพารามิเตอร์และทางเลือกมีค่าเริ่มต้นที่แตกต่างกันโดยการเลื่อนขึ้นไปที่รายการพารามิเตอร์ฟังก์ชั่นPublic Function BASE64SHA1(ByVal sTextToHash As String, Optional ByVal cutoff As Integer = 8) และลบการประกาศภายในฟังก์ชั่น
คอ

9

ฉันไม่สนใจเกี่ยวกับการชนมากนัก แต่ต้องการเครื่องมือ pseudorandomizer ที่อ่อนแอของแถวตามฟิลด์สตริงที่มีความยาวผันแปรได้ นี่คือหนึ่งในวิธีการแก้ปัญหาบ้าที่ทำงานได้ดี:

=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) โดยพลการ ใช้อะไรก็ได้


2
ความจริงแล้วนี่คือคำตอบที่ง่ายที่สุดฉันสงสัยว่าการชนเป็นปัญหาสำหรับกรณีการใช้งานที่ยอดเยี่ยมที่สุด
ม้วน

3

สำหรับรายการขนาดเล็กที่สมเหตุสมผลคุณสามารถสร้าง scrambler (ฟังก์ชั่นแฮชของคนจน) โดยใช้ฟังก์ชั่น 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
คำตอบที่ดี! (: "ฟังก์ชั่นแฮชของคนจน", "caveat", "มันทำงานอย่างไร" :)
มันบ้าคลั่งเกี่ยวกับ natty

1
หากต้องการ"ตรวจสอบผลลัพธ์เพื่อดูว่าไม่มีการชนกัน"คุณสามารถลอง / ทดสอบสิ่งนี้ได้โดยการเรียกใช้ DATA> ลบ DUPLICATES และดูว่ามีหรือไม่ [ชัด / สันนิษฐานว่าถ้าคุณทำซ้ำการเข้ารหัสคุณสามารถเรียกใช้ฟังก์ชันข้างต้นซ้ำได้จนกว่าจะไม่มีการซ้ำซ้อนเหลืออยู่]
มันบ้าเกี่ยวกับ natty

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

คุณสามารถลองสิ่งนี้ รัน Pseudo # ในสองคอลัมน์:

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

โดยที่ A1 และ B1 เก็บการสุ่มเมล็ดด้วยตนเอง: 0


0

สำหรับความรู้ของฉันไม่มีฟังก์ชั่นแฮชสร้างลงใน Excel - คุณต้องสร้างหนึ่งฟังก์ชันเป็นฟังก์ชันที่กำหนดโดยผู้ใช้ใน VBA

อย่างไรก็ตามโปรดทราบว่าสำหรับวัตถุประสงค์ของคุณฉันไม่คิดว่าการใช้แฮชเป็นสิ่งจำเป็นหรือได้เปรียบจริง ๆ ! VLOOKUPจะทำงานได้ดีบน 256 ไบต์เช่นเดียวกับแฮชขนาดเล็ก แน่นอนว่ามันอาจจะช้ากว่านิดหน่อย - บิตนั้นแน่นอนว่าเล็กมากจนไม่สามารถวัดได้ จากนั้นการเพิ่มค่าแฮชคือความพยายามของคุณ - และสำหรับ Excel ...


ใช่ ... ฉันรู้ว่า แต่เพียงแค่จากมุมมองการนำเสนอฉันควรจะแสดงพูดว่า 15 ไบต์ของแฮชที่ 256 ไบต์titleในบานหน้าต่างด้านซ้ายของฉันแช่แข็ง ...
dwwilson66
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.