【问题标题】:Generate a UNIQUE string made out of numeric / ALPHABET生成由数字/字母组成的唯一字符串
【发布时间】:2017-12-09 14:59:42
【问题描述】:

我的问题

  • 我不知道任何 VBA
  • 需要生成12个字符的字符串(ALPHA + numbers , 0-9 , A-Z)IN VBA...
  • 示例输出:

    "ADF3V3224K1WQ"
    

    (12 个字符长,大写字母和数值)。


故事

我很难弄清楚如何创建一个字符串生成器(没有说它必须是随机的,但它必须 100% 是唯一的,这意味着它必须检查重复项或存储现有值) ,我没有使用VBA的经验。我已经在这里找到了类似的帖子,但它与我的不同,因为它没有明确要求字符串是 100% 唯一的。 (我不需要非常低的机会,我需要 100% 全面)。

语法方面我很困惑,我设法找到事件背后的代码在哪里,即按钮按下,所以我知道我需要在哪里编写它,但我不知道如何检查重复。 (即使依靠时间种子可以确保它 100% 唯一也很棒)。

类似帖子的链接: MS Access Visual Basic - generate random string in text field

【问题讨论】:

  • 101% 唯一。首先问这个问题:已经使用的、先前生成的字符串存储在哪里?如何?我们可能不需要存储所有这些,但至少我们需要在某个地方放置一个柜台。
  • 事情是,我对办公室访问的了解(一般来说办公室几乎没有)一个疯狂的猜测(我的意思是疯狂的)可能在实际表中。
  • 如果我们能找出这些值存储在哪个表中。那么这个问题就容易多了
  • 恐怕是希伯来语,但我知道这张桌子。该字段是主键。它可以被称为 operatorID(相当于希伯来语)和表 tblOperator
  • 请阅读Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers? - 总结是这不是解决志愿者的理想方式,并且可能会适得其反。请不要将此添加到您的问题中。

标签: ms-access vba ms-access-2016


【解决方案1】:

使用日期时间字符串:

  • 公式:=TEXT(NOW(),"yymmddhhmmss") -> 170705161201

  • VBA:Debug.Print Format(Now, "yymmddhhmmss")

【讨论】:

  • Paul,我喜欢你的解决方案,非常有创意,当然没有想过,但里面没有任何 A-Z 字符。
  • 为什么要关心?您可以在一百年内每秒生成一个唯一数字。
  • 你知道我可以用它来自动生成字段吗?这样我就不需要单击按钮或激活事件,而是在打开新记录时会自动激活?
【解决方案2】:

这个问题有多种解决方案,但我喜欢这个:

Public Function newguidx() As String
    With CreateObject("Scriptlet.TypeLib")
        newguidx = Left(.Guid, 38)
    End With  
End Function

它创建一个GUID。这些本身并不是唯一的,但您可以在 Wikipedia 页面上阅读它们也可能是唯一的。如果您愿意,可以使用Replace 删除{}- 标志。

此外,由于格式是标准化的,大多数程序员都会清楚它是什么。

显然,您可以修剪字符以获得所需的长度,这将增加您找到重复的机会。

编辑:

很遗憾,出于安全原因,目前默认阻止访问Scriptlet.TypeLib。请参阅MS Access VBA Error: Run time error '70' Permission Denied 了解相关信息,How can I generate GUIDs in Excel? 了解生成 GUID 的多种方法的概览。

我的个人喜好:

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

【讨论】:

  • 不,但通常使用它来识别独特的案例,就像维基百科所说:“因此,为了有十亿分之一的重复机会,必须有 103 万亿个版本 4 UUID生成”。我不知道您的数据库有多大,但我认为应该这样做。
  • 如果字符串的长度为 12 怎么办(我需要它不超过 12)。如果发现重复错误,有什么方法可以告诉它再次运行?比如说,捕获重复错误或(do while)duplication_error 0(我不知道vba语法)。
  • 嗯,这限制了唯一性,增加了碰撞的机会。如果有机会,我会寻找更合适的答案。请注意,真正的唯一性是不可能的,除非它是基于时间的(限制您每秒最多 1 个 ID 或外部库调用以获得微秒),或者您需要保留先前生成的答案(种子)的日志。
【解决方案3】:

好吧,我想如果它真的需要是字母数字和唯一的,这就是要走的路:

此代码根据当前时间生成一个随机字符串(如@paul-bica 的答案),只是它以字母数字方式对它们进行编码,并使用计时器在几分之一秒内达到 12 个字符)。这样你应该能够每秒生成多个随机字符串。

只需调用UniqueTimeBasedString() 即可获取字符串。 (请注意,如果您在查询中使用此函数,Access 将缓存结果,并且它根本不会是唯一的。

Public Function UniqueTimeBasedString() As String
    Dim alphanumericCharacters As String
    alphanumericCharacters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Dim timeString As String
    timeString = Format(Now, "yymmddhhmmss") & Getmtimestring(6)
    Dim c As Integer
    Dim intTimepart As Integer
    c = 1
    Do While c < Len(timeString)
        intTimepart = CInt(Mid(timeString, c, 3))
        c = c + 3
        UniqueTimeBasedString = UniqueTimeBasedString & Mid(alphanumericCharacters, Int(intTimepart / 61) + 1, 1) & Mid(alphanumericCharacters, intTimepart Mod 61 + 1, 1)
    Loop
End Function

Public Function Getmtimestring(length As Integer) As String
    Dim mtime As Double
    mtime = Timer()
    Dim mtimeLng As Long
    mtimeLng = Int((mtime - Int(mtime)) * (10 ^ length))
    Getmtimestring = CStr(mtimeLng)
    Do While Len(Getmtimestring) < length
        Getmtimestring = "0" & Getmtimestring
    Loop
End Function

注意事项:

  1. Timer() 不是很准确,理论上这会导致 问题
  2. 此代码与 OS X 不兼容,但如果您一直受限于 Access,这将不是问题(Getmtimestring 只会返回零)
  3. 你真的应该和你的老板谈谈。在紧迫的期限内要求你做一些你并不真正有资格做的事情,而没有选择使用稍微其他的解决方案,这不是健康的工作场所行为。
  4. 字符串包含编码时间,可以解码。如果您希望字符串的创建时间保密,请勿报告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    相关资源
    最近更新 更多