希望生成一个独特的值来保存报价订单,方便召回。除了在1秒内点击之外,这个数字是否会重复。
idNumber = Application.Worksheetfunction.Roundup(DateValue(Now) * TimeValue(Now),0)
我使用字符串作为ID不是数字 - 因为你不对ID进行算术运算。
但是,基于时间的ID的简单方法是科学的反向日期方法。精度水平取决于您的需求。对于下面的示例,今天是2018年9月1日,时间是1655(24小时制)和35秒。
上述方案的优点是ID可以按字母顺序和数字顺序排序(只要您保持与数据中ID的长度一致)。对于粒度低至一秒,您只需使用Format(Now(),"yymmddhhnnss")
命令生成String
。如果你真的需要一个数字,你可以将其转换为Long
,相信你只使用了数字。
根据您的实际需要,唯一值可能不需要是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
如果两个值发生碰撞,you better have a lottery ticket!
是的,由于四舍五入,这个数字可能会重复。 TimeValue
总是一个浮点数,小数点右边的0(一个小数天)。所以你基本上做的是将时间除以时间。在接近午夜的值时,您开始接近1的除数。例如,23:55:55
是.9971643519
。今天的DateValue
是43343
。如果你将这两个值加倍并且是圆的,那么你将获得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
你的公式是多余的。你只需要: 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秒内的任何两个事件都会产生重复的高风险。
感谢所有的投入。以下是我打算用于我的唯一号码的内容。这符合我的意图。这个数字每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,他的答案非常强大,但对于我正在寻找的东西有点矫枉过正。稍后我肯定会对此有所帮助。谢谢!