这段代码会不会重复一个值?我需要一个永远不会重复且不需要存储变量的数字

问题描述 投票:4回答:5

希望生成一个独特的值来保存报价订单,方便召回。除了在1秒内点击之外,这个数字是否会重复。

idNumber = Application.Worksheetfunction.Roundup(DateValue(Now) * TimeValue(Now),0)
excel vba excel-vba
5个回答
3
投票

我使用字符串作为ID不是数字 - 因为你不对ID进行算术运算。

但是,基于时间的ID的简单方法是科学的反向日期方法。精度水平取决于您的需求。对于下面的示例,今天是2018年9月1日,时间是1655(24小时制)和35秒。

  • (1)每天只有一个:年,月和日(例如180901,今天是9月的第一天)。如果您希望这些ID持续时间超过一个世纪,则使用4位数年份(2018年而不是18年)。
  • (2)每小时最多一次:(1)和小时(例如18090116)
  • (3)每分钟最多一次:(2)和分钟(例如1809011655)
  • (4)每秒最多一次:(3)&秒(例如180901165535)
  • (5+)是的,你可以到几分之一秒。

上述方案的优点是ID可以按字母顺序和数字顺序排序(只要您保持与数据中ID的长度一致)。对于粒度低至一秒,您只需使用Format(Now(),"yymmddhhnnss")命令生成String。如果你真的需要一个数字,你可以将其转换为Long,相信你只使用了数字。


5
投票

根据您的实际需要,唯一值可能不需要是Long整数;如果是这样那么很高兴知道Windows有一个生成它们的内置方式(在OLE32.DLL中),你可以利用它来生成全局唯一标识符:

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

source

如果两个值发生碰撞,you better have a lottery ticket


3
投票

是的,由于四舍五入,这个数字可能会重复。 TimeValue总是一个浮点数,小数点右边的0(一个小数天)。所以你基本上做的是将时间除以时间。在接近午夜的值时,您开始接近1的除数。例如,23:55:55.9971643519。今天的DateValue43343。如果你将这两个值加倍并且是圆的,那么你将获得43220,这是2018年4月30日在23:59:59

如果需要从“timestamp”获取唯一的整数值,最好简单地获取基础date \ time值并按适当的精度进行缩放。 VBA Date只是一个Double,其中“DateValue”部分为整数部分,“TimeValue”位于小数点右侧。如果您需要高精度的独特值,您可能希望偏移到新的纪元日期,这样您就不会有快速溢出的风险。例如,2018年1月1日是43101,所以你可以通过减去43101来设置你的“内部时代”:

Public Function GetNumberFromTimestamp() As Long
    Dim current As Double
    current = CDbl(Now())
    'Set to a custom epoch
    current = current - 43101
    'Scale by whatever precision you need.
    GetNumberFromTimestamp = current * 1000000
End Function

3
投票

你的公式是多余的。你只需要: idNumber = Application.Worksheetfunction.Roundup(Date * Time,0)

是的,它有可能会重复。日期是长整数; 1899年12月31日至1899年每天1次。时间是日期的小数部分;例如中午是0.5。今天(2018年8月31日)下午04:00是43343.667。

因此,如果您将整数乘以小数并向上舍入到最接近的整数,那么明天将有一个时间(即十进制)可以乘以匹配的天。

'today at noon (rounded up)
43343 * 0.5 = 21671.5 = 21672
'tomorrow at noon (rounded up)
43344 * 0.5 = 21672 = 21672

即使没有四舍五入,日期*时间也可能重复;单边四舍五入的机会更大。

除了基本十进制乘以整数重复之外,似乎需要大约2秒来更改公式返回的值。 2秒内的任何两个事件都会产生重复的高风险。


0
投票

感谢所有的投入。以下是我打算用于我的唯一号码的内容。这符合我的意图。这个数字每100年重复一次,或者在1秒内重复,但这不应该是我如何使用它的问题。 sheetName在userform的顶部进行了delcared。

    If sheetName <> "" Then
Workbooks.Open "C:\Users\jschu\Desktop\price test\Quote_Database.xlsx"
Workbooks("Quote_Database.xlsx").Sheets(sheetName).Select

Else
Workbooks.Open "C:\Users\jschu\Desktop\price test\Quote_Database.xlsx" ' Open Quote Database file

idNumber = Format(Now, "YYMMDDHHSS") ' Generate unique #
sheetName = idNumber & " " & UserForm3.nameText
    With Workbooks("Quote_Database.xlsx") ' Finds the last sheet then adds a new sheet with the idnumber and customer name
        .Sheets.Add(After:=.Sheets(.Sheets.count)).Name = sheetName
    End With
End If

附注:特别感谢Mathieu Guindon,他的答案非常强大,但对于我正在寻找的东西有点矫枉过正。稍后我肯定会对此有所帮助。谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.