【问题标题】:How can I generate GUIDs in Excel?如何在 Excel 中生成 GUID?
【发布时间】:2011-08-11 19:00:37
【问题描述】:

我有一个 excel 文件,每一行都有一个订单,我希望每个订单都有一个唯一的标识符,所以会有一个唯一 ID 列。每次我填写一行时,我都希望 Excel 自动为我填充唯一 ID 列。我做了一些研究,并指出了 GUID 的方向。我找到了以下代码:

Function GenGuid() As String
Dim TypeLib As Object
Dim Guid As String
Set TypeLib = CreateObject("Scriptlet.TypeLib")
Guid = TypeLib.Guid
' format is {24DD18D4-C902-497F-A64B-28B2FA741661}
Guid = Replace(Guid, "{", "")
Guid = Replace(Guid, "}", "")
Guid = Replace(Guid, "-", "")
GenGuid = Guid
End Function

但我不确定如何实现它。任何帮助将不胜感激。提前谢谢你。

【问题讨论】:

  • 我不认为您的问题是生成 GUID。你有工作代码。您甚至可以通过为它分配公式=GenGuid() 将 GUID 放入任何单元格,尽管它会在每次计算公式时发生变化。您的问题应该是:如何让 Excel 使用 VBA 函数的结果自动填充单元格?
  • 警告:以上代码会在字符串末尾添加随机垃圾:stackoverflow.com/questions/19556268/…
  • 不要将此函数作为公式=GenGuid() 放入单元格中 - 这将在每次工作表重新计算时为每一行生成所有新的 GUID!相反,使用 Worksheet 事件来查找对工作表的更改,在其中您需要设计一种方法来确定是否正在编辑新/空白行(“此行上的 GUID 列是否为空白?”),以及是否然后您需要将单元格值设置为生成的 GUID(使其保持静态)。这是确保在为行分配 GUID 后它永远保持相同值的最佳方式。

标签: vba excel guid


【解决方案1】:

以下 Excel 表达式的计算结果为 V4 GUID:

=CONCATENATE(DEC2HEX(RANDBETWEEN(0,4294967295),8),"-",DEC2HEX(RANDBETWEEN(0,65535),4),"-",DEC2HEX(RANDBETWEEN(16384,20479),4),"-",DEC2HEX(RANDBETWEEN(32768,49151),4),"-",DEC2HEX(RANDBETWEEN(0,65535),4),DEC2HEX(RANDBETWEEN(0,4294967295),8))

-或(取决于区域设置/十进制和列表分隔符)-

=CONCATENATE(DEC2HEX(RANDBETWEEN(0;4294967295);8);"-";DEC2HEX(RANDBETWEEN(0;65535);4);"-";DEC2HEX(RANDBETWEEN(16384;20479);4);"-";DEC2HEX(RANDBETWEEN(32768;49151);4);"-";DEC2HEX(RANDBETWEEN(0;65535);4);DEC2HEX(RANDBETWEEN(0;4294967295);8))

请注意,根据 RFC 4122 第 4.4 节,第三组的第一个字符始终为 4,表示 V4(生成的伪随机数)GUID/UUID。

另请注意,根据同一 RFC,第四组的第一个字符始终介于 8 和 B 之间。

标准免责声明:生成的 GUID/UUID 的密码强度不高。

编辑:删除不可见字符

【讨论】:

  • 这在 Excel 2007 中对我不起作用。我收到了一个泛型,此公式错误有问题。
  • 在 Excel for Mac 上完美运行,只需将 ; 更改为 ,
  • 这是具有更改的函数,这在 Windows 中也可以使用 ',' 更改 =CONCATENATE(DEC2HEX(RANDBETWEEN(0,4294967295),8),"-",DEC2HEX(RANDBETWEEN(0 ,65535),4),"-",DEC2HEX(RANDBETWEEN(16384,20479),4),"-",DEC2HEX(RANDBETWEEN(32768,49151),4),"-",DEC2HEX(RANDBETWEEN(0,65535) ),4),DEC2HEX(RANDBETWEEN(0,4294967295),8))
  • @MirkoAkkov 这不是 Mac,而是 Thread.CurrentCulture 的 System.Globalization.CultureInfo 实例,它包含一个 TextInfo 对象,该对象定义了一个 ListSeparator 属性,该属性确定 Excel 将在函数参数之间正确解析Excel 一个公式。在 Windows 中,这(以及许多其他设置)可以在控制面板的 regional settings 中查看/更改。
  • 用这种方法我们可以预期多少熵损失?
【解决方案2】:

我在 v.2013 excel vba 中使用了以下函数来创建 GUID,并且运行良好..

Public Function GetGUID() As String 
    GetGUID = Mid$(CreateObject("Scriptlet.TypeLib").GUID, 2, 36) 
End Function 

【讨论】:

  • 一段不错的代码。要消除连字符,您可以将其设为 GetGUID = Replace(Mid$(CreateObject("Scriptlet.TypeLib").GUID, 2, 36),"-",vbNullString)
  • 它不适用于最新的 Windows 更新。以下是在这种情况下如何使用此宏的信息:stackoverflow.com/questions/45332357/…
  • 由于windows更新取出了“Scriptlet.TypeLib”,尝试以下操作:Declare Function CoCreateGuid Lib "ole32" (ByRef GUID As Byte) 只要公共函数 GenerateGUID() As String Dim ID(0 To 15) As Byte Dim N As Long Dim GUID As String Dim Res As Long Res = CoCreateGuid(ID(0)) For N = 0 To 15 GUID = GUID & IIf(ID(N)
【解决方案3】:

我知道这个问题已经得到解答,但我认为有问题的代码应该类似于此页面上的内容:http://snipplr.com/view/37940/

尚未测试,但此代码似乎利用 Windows API 来获取其 GUID - 我会尝试将其放入公共模块并在 Excel 单元格中键入 =GetGUId() 以查看我会得到什么。如果它在 VB6 中工作,那么你很有可能在 VBA 中也能工作:

Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(7) As Byte
End Type

Private Declare Function CoCreateGuid Lib "OLE32.DLL" (pGuid As GUID) As Long

Public Function GetGUID() As String
'(c) 2000 Gus Molina

    Dim udtGUID As GUID

    If (CoCreateGuid(udtGUID) = 0) Then

        GetGUID = _
            String(8 - Len(Hex$(udtGUID.Data1)), "0") & Hex$(udtGUID.Data1) & _
            String(4 - Len(Hex$(udtGUID.Data2)), "0") & Hex$(udtGUID.Data2) & _
            String(4 - Len(Hex$(udtGUID.Data3)), "0") & Hex$(udtGUID.Data3) & _
            IIf((udtGUID.Data4(0) < &H10), "0", "") & Hex$(udtGUID.Data4(0)) & _
            IIf((udtGUID.Data4(1) < &H10), "0", "") & Hex$(udtGUID.Data4(1)) & _
            IIf((udtGUID.Data4(2) < &H10), "0", "") & Hex$(udtGUID.Data4(2)) & _
            IIf((udtGUID.Data4(3) < &H10), "0", "") & Hex$(udtGUID.Data4(3)) & _
            IIf((udtGUID.Data4(4) < &H10), "0", "") & Hex$(udtGUID.Data4(4)) & _
            IIf((udtGUID.Data4(5) < &H10), "0", "") & Hex$(udtGUID.Data4(5)) & _
            IIf((udtGUID.Data4(6) < &H10), "0", "") & Hex$(udtGUID.Data4(6)) & _
            IIf((udtGUID.Data4(7) < &H10), "0", "") & Hex$(udtGUID.Data4(7))
    End If

End Function

感谢格斯·莫利纳!

如果此代码有效(我不怀疑),我认为您会在评估函数时获得一组新的 GUID,这意味着每次计算工作表时 - 当您保存工作簿时,例子。如果您需要 GUID 以供以后使用,请确保复制粘贴特殊值……这有点可能。

【讨论】:

  • 谁能在该代码中添加 cmets 来解释它在做什么?
  • @EmilyBeth 它从 OLE32.DLL 调用 CoCreateGuid,将结果存储在用户定义的类型中,然后用 0 填充每个部分并将它们转换为十六进制字符串。 Data1 As Long 保存前 4 个字节,Data2Data3 As Integer 保存接下来的 4 个字节,然后Data4 保存剩余的 8 个字节。 GUID 实际上只是一个非常非常大的数字,存储在 16 个字节中,具有特定的部分。
【解决方案4】:

一种基于使用 Rnd() 函数而不是外部 API 调用或 Scriptlet.TypeLib 生成随机数的 VBA 方法:

Public Function CreateGUID() As String
    Do While Len(CreateGUID) < 32
        If Len(CreateGUID) = 16 Then
            '17th character holds version information
            CreateGUID = CreateGUID & Hex$(8 + CInt(Rnd * 3))
        End If
        CreateGUID = CreateGUID & Hex$(CInt(Rnd * 15))
    Loop
    CreateGUID = "{" & Mid(CreateGUID, 1, 8) & "-" & Mid(CreateGUID, 9, 4) & "-" & Mid(CreateGUID, 13, 4) & "-" & Mid(CreateGUID, 17, 4) & "-" & Mid(CreateGUID, 21, 12) & "}"
End Function

这本质上是 NekojiruSou 的答案的 VBA 实现(它还生成 v4 GUID),并具有相同的限制,但可以在 VBA 中工作并且可能更容易实现。

请注意,您可以省略最后一行,以免在结果中返回破折号和花括号。

【讨论】:

    【解决方案5】:

    我在这里找到了很好的解决方案:
    http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=751237&msg=8634441

    Option Explicit
    
    Private Type GUID
      Data1 As Long
      Data2 As Integer
      Data3 As Integer
      Data4(0 To 7) As Byte
    End Type
    Private Declare Function CoCreateGuid Lib "ole32" (pguid As GUID) As Long
    Private Declare Function StringFromGUID2 Lib "ole32" ( _
      rguid As GUID, ByVal lpsz As Long, ByVal cchMax As Long) As Long
    
    Public Function CreateGUID() As String
      Dim NewGUID As GUID
      CoCreateGuid NewGUID
      CreateGUID = Space$(38)
      StringFromGUID2 NewGUID, StrPtr(CreateGUID), 39
    End Function
    

    【讨论】:

      【解决方案6】:

      德语 Excel 版本也一样:

      =VERKETTEN(DEZINHEX(ZUFALLSBEREICH(0;4294967295);8);"-";DEZINHEX(ZUFALLSBEREICH(0;65535);4);"-";DEZINHEX(ZUFALLSBEREICH(16384;20479);4);"-";DEZINHEX(ZUFALLSBEREICH(32768;49151);4);"-";DEZINHEX(ZUFALLSBEREICH(0;65535);4);DEZINHEX(ZUFALLSBEREICH(0;4294967295);8))
      

      【讨论】:

      • 版本其实是一样的。本地设置决定了函数别名是什么以及函数参数用什么字符分隔。
      【解决方案7】:

      由于windows更新取出了“Scriptlet.TypeLib”,请尝试以下操作:

      Declare Function CoCreateGuid Lib "ole32" (ByRef GUID As Byte) As Long
      Public Function GenerateGUID() As String
          Dim ID(0 To 15) As Byte
          Dim N As Long
          Dim GUID As String
          Dim Res As Long
          Res = CoCreateGuid(ID(0))
      
          For N = 0 To 15
              GUID = GUID & IIf(ID(N) < 16, "0", "") & Hex$(ID(N))
              If Len(GUID) = 8 Or Len(GUID) = 13 Or Len(GUID) = 18 Or Len(GUID) = 23 Then
                  GUID = GUID & "-"
              End If
          Next N
          GenerateGUID = GUID
      End Function
      

      或者,

      如果您要连接到 SQL Server 2008 或更高版本,请尝试改用 SQL NEWID() 函数。

      【讨论】:

      • 请注意,如果您使用的是 Access,而不是 Excel,则可以使用 Application.StringFromGUID(ID) 将 GUID 转换为字符串。避免您自己对其进行迭代,并以您可以使用 Application.GuidFromString 轻松转换回字节的格式创建 GUID。
      【解决方案8】:

      我最近在一些 vba 代码中使用 CreateObject("Scriptlet.TypeLib") 时遇到了问题。

      因此,基于 NekojiruSou excel 函数编写了以下内容,它应该可以在没有任何特定 excel 函数的情况下工作。这可用于在 excel 中开发用户定义的函数。

      Public Function Get_NewGUID() As String
          'Returns GUID as string 36 characters long
      
          Randomize
      
          Dim r1a As Long
          Dim r1b As Long
          Dim r2 As Long
          Dim r3 As Long
          Dim r4 As Long
          Dim r5a As Long
          Dim r5b As Long
          Dim r5c As Long
      
          'randomValue = CInt(Math.Floor((upperbound - lowerbound + 1) * Rnd())) + lowerbound
          r1a = RandomBetween(0, 65535)
          r1b = RandomBetween(0, 65535)
          r2 = RandomBetween(0, 65535)
          r3 = RandomBetween(16384, 20479)
          r4 = RandomBetween(32768, 49151)
          r5a = RandomBetween(0, 65535)
          r5b = RandomBetween(0, 65535)
          r5c = RandomBetween(0, 65535)
      
          Get_NewGUID = (PadHex(r1a, 4) & PadHex(r1b, 4) & "-" & PadHex(r2, 4) & "-" & PadHex(r3, 4) & "-" & PadHex(r4, 4) & "-" & PadHex(r5a, 4) & PadHex(r5b, 4) & PadHex(r5c, 4))
      
      End Function
      
      Public Function Floor(ByVal X As Double, Optional ByVal Factor As Double = 1) As Double
          'From: http://www.tek-tips.com/faqs.cfm?fid=5031
          ' X is the value you want to round
          ' Factor is the multiple to which you want to round
              Floor = Int(X / Factor) * Factor
      End Function
      
      Public Function RandomBetween(ByVal StartRange As Long, ByVal EndRange As Long) As Long
          'Based on https://msdn.microsoft.com/en-us/library/f7s023d2(v=vs.90).aspx
          '         randomValue = CInt(Math.Floor((upperbound - lowerbound + 1) * Rnd())) + lowerbound
              RandomBetween = CLng(Floor((EndRange - StartRange + 1) * Rnd())) + StartRange
      End Function
      
      Public Function PadLeft(text As Variant, totalLength As Integer, padCharacter As String) As String
          'Based on https://stackoverflow.com/questions/12060347/any-method-equivalent-to-padleft-padright
          ' with a little more checking of inputs
      
          Dim s As String
          Dim inputLength As Integer
          s = CStr(text)
          inputLength = Len(s)
      
          If padCharacter = "" Then
              padCharacter = " "
          ElseIf Len(padCharacter) > 1 Then
              padCharacter = Left(padCharacter, 1)
          End If
      
          If inputLength < totalLength Then
              PadLeft = String(totalLength - inputLength, padCharacter) & s
          Else
              PadLeft = s
          End If
      
      End Function
      
      Public Function PadHex(number As Long, length As Integer) As String
          PadHex = PadLeft(Hex(number), 4, "0")
      End Function
      

      【讨论】:

      • 最近在使用 CreateObject("Scriptlet.TypeLib") 方法时也遇到了问题。权限被拒绝?
      【解决方案9】:

      我创建了一个适用于 mac 和 windows 的 VBA 函数:

      https://github.com/Martin-Carlsson/Business-Intelligence-Goodies/blob/master/Excel/GenerateGiud/GenerateGiud.bas

      'Generates a guid, works on both mac and windows 
      Function Guid() As String
          Guid = RandomHex(3) + "-" + _
              RandomHex(2) + "-" + _
              RandomHex(2) + "-" + _
              RandomHex(2) + "-" + _
              RandomHex(6)
      End Function
      
      'From: https://www.mrexcel.com/forum/excel-questions/301472-need-help-generate-hexadecimal-codes-randomly.html#post1479527
      Private Function RandomHex(lngCharLength As Long)
          Dim i As Long
          Randomize
          For i = 1 To lngCharLength
              RandomHex = RandomHex & Right$("0" & Hex(Rnd() * 256), 2)
          Next
      End Function
      

      【讨论】:

        【解决方案10】:

        这是基于javascript implementation

        Private Function getGUID() As String
          getGUID = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
          getGUID = Replace(getGUID, "y", Hex(Rnd() And &H3 Or &H8))
          Dim i As Long: For i = 1 To 30
            getGUID = Replace(getGUID, "x", Hex$(CLng(Rnd() * 15.9999)), 1, 1)
          Next
        End Function
        

        【讨论】:

          【解决方案11】:

          如果您要将记录插入数据库,您可以使用这种方式来创建 GUID。

          这可能是最简单和最容易实现的方法,因为您不需要复杂的VBA 函数,因为您使用内置 SQL 函数。

          语句使用NewID()

          语法如下,

          INSERT INTO table_name (ID,Column1,Column2,Column3)
          VALUES (NewID(),value1,value2,value3) 
          

          VBA语法如下,

          strSql = "INSERT INTO table_name " _
                 & "(ID,Column1,Column2,Column3) " _
                 & "VALUES (NewID(),value1,value2,value3)"
          

          如果您需要连接值,只需将其视为字符串并像通常用于 SQL 语句一样连接,

          strSql = "INSERT INTO table_name " _
                 & "(ID,Column1,Column2,Column3) " _
                 & "VALUES (" & "NewID()" & "," & "value1" & "," & "value2" & "," & "value3" & ")"
          

          【讨论】:

          • 这是一个很好的方法,但如果您需要先在 VBA 中使用 guid,然后再上传(即在多个表中插入相同的 GUID)
          • @BrendanGooden,我现在明白了。 OP 没有插入数据库。我将更新我的答案以表明这一点。谢谢。
          【解决方案12】:

          仅使用 Rnd() 函数生成随机 guid,不使用任何库或 API,我能想到的最简单的是:

          ' UUID Version 4 (random)
          Function GetUUID4()
          
              Dim guid As String
              Dim i As Integer
              Dim r As Integer
              
              guid = ""
              Randomize
              
              For i = 0 To 31
                  ' random digit 0..15
                  r = Rnd() * 15
          
                  ' add dash separators
                  If (i = 8) Or (i = 12) Or (i = 16) Or (i = 20) Then guid = guid & "-"
          
                  ' uuid4 version info in 12th and 16th digits
                  If (i = 12) Then r = 4
                  If (i = 16) Then r = (r And 3 Or 8)
          
                  ' add as hex digit
                  guid = guid & Hex(r)
              Next i
          
              GetUUID4 = guid
          End Function
          

          【讨论】:

            【解决方案13】:
            Function funGetGuid() As String
            
                Const URL As String = "http://www.guidgen.com/"
                Const strMask As String = "value="
            
                Dim l As Long
                Dim txt As String
            
                With CreateObject("MSXML2.XMLHTTP")
                    .Open "GET", URL, False
                    .send
                    txt = .responseText
                End With
            
                Do
                    l = InStr(l + 1, txt, strMask)
                    If l = 0 Then Exit Do
                    funGetGuid = Mid$(txt, l + Len(strMask) + 1, 36)
                Loop
            
            End Function
            

            【讨论】:

            • 在我看来,仅仅为了生成 GUID 而发出远程请求是不合适的。
            猜你喜欢
            • 2012-05-16
            • 2011-03-03
            • 1970-01-01
            • 1970-01-01
            • 2010-12-25
            • 1970-01-01
            • 2011-07-26
            • 2010-12-04
            相关资源
            最近更新 更多