此代码会重复值吗?我需要一个永远不会重复的数字,并且不需要存储的变量



希望生成一个唯一的值来保存报价订单,以便于调用。这个数字是否会重复,除非在 1 秒内点击。

idNumber = Application.Worksheetfunction.Roundup(DateValue(Now) * TimeValue(Now),0)

根据您的实际需要,唯一值可能不需要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

如果两个值发生碰撞,你最好有一张彩票!

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

但是,执行基于时间的 ID 的一种简单方法是科学的反向日期方法。精度级别取决于您的需求。对于以下示例,今天是 2018 年 9 月 1 日,时间为 1655(24 小时制(和 35 秒。

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

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

是的,由于四舍五入,该数字可能会重复。TimeValue始终是一个浮点数,小数点右侧为 0(小数日(。所以你基本上在做的是按时间划分一天。在接近午夜的值处,您开始接近除数 1。例如,23:55:55.9971643519。今天的DateValue43343.如果将两个值相乘并四舍五入,则得到43220,这是 2018 年 4 月 30 日在23:59:59

如果需要从"时间戳"中获取唯一的整数值,最好只获取基础日期\时间值并按适当的精度对其进行缩放。VBADate只是一个Double,其中"日期值"部分作为整数部分,"时间值"位于小数点右侧。 如果您需要对唯一值进行高精度处理,则可能需要偏移到新的纪元日期,这样就不会有溢出过快的风险。例如,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

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

是的,它有可能重复。日期是长整数;1899 年 12 月 31 日之后的每一天 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 秒内的任何两个事件都存在产生重复项的高风险。

感谢您的所有输入。以下是我打算用于我的唯一号码的内容。这将达到我想要的目的。这个数字将每 100 年或 1 秒内重复一次,但这应该不是我如何使用它的问题。工作表名称在用户窗体的顶部。

If sheetName <> "" Then
Workbooks.Open "C:UsersjschuDesktopprice testQuote_Database.xlsx"
Workbooks("Quote_Database.xlsx").Sheets(sheetName).Select
Else
Workbooks.Open "C:UsersjschuDesktopprice testQuote_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,他的回答非常有力,但对于我正在寻找的东西来说有点矫枉过正。我敢肯定,我稍后会使用它。谢谢!

相关内容

最新更新