简体   繁体   English

将Excel VBA中的日期写入工作表会给出错误的值

[英]Writing a date from Excel VBA to a worksheet gives the wrong value

When I write a date from VBA into an Excel worksheet, sometimes the value on the worksheet ends up being one less (one day earlier) than I expect. 当我将VBA中的日期写入Excel工作表时,有时工作表上的值最终比我预期的少一个(比前一天早)。 Here's an example that I've tested on a multiple computers with Excel 2003, 2007, and 2010. From the immediate window: 这是我在使用Excel 2003,2007和2010的多台计算机上测试过的示例。从即时窗口:

?Format(41652.9999999963, "yyyy-mm-dd hh:mm:ss")

> 2014-01-14 00:00:00

[A1].value = CDate(41652.9999999963)
?Format([A1].value, "yyyy-mm-dd hh:mm:ss")

> 2014-01-13 00:00:00

[A1].value = CDbl(CDate(41652.9999999963))
?Format([A1].value, "yyyy-mm-dd hh:mm:ss")

> 2014-01-14 00:00:00

What exactly triggers this? 究竟是什么引发了这个

EDIT: 编辑:

Okay, let me be more clear that this isn't a rounding issue. 好的,让我更清楚一点, 这不是一个四舍五入的问题。 If I go up or down one fraction of a second I get the correct time. 如果我上升或下降一小时,我得到正确的时间。 It's just that if I hit near this exact number the date goes off by an entire day: 只是如果我接近这个确切的数字,那么日期就会消失一整天:

[A1].value = CDate(41652.99999)
?Format([A1].value, "yyyy-mm-dd hh:mm:ss")

> 2014-01-13 23:59:59

[A1].value = CDate(41652.999999999996)
?Format([A1].value, "yyyy-mm-dd hh:mm:ss")

> 2014-01-13 00:00:00

[A1].value = CDate(41652.999999999997)
?Format([A1].value, "yyyy-mm-dd hh:mm:ss")

> 2014-01-14 00:00:00

[A1].value = CDate(41653.00001)
?Format([A1].value, "yyyy-mm-dd hh:mm:ss")

> 2014-01-14 00:00:01

As stated in Help for CDate, "CDate recognizes date literals and time literals as well as some numbers that fall within the range of acceptable dates. When converting a number to a date, the whole number portion is converted to a date . Any fractional part of the number is converted to a time of day , starting at midnight." 正如CDate的帮助中所述,“CDate识别日期文字和时间文字以及属于可接受日期范围内的一些数字。将数字转换为日期时, 整数部分将转换为日期任何小数部分该数字从午夜开始转换为一天的时间 。“ It never says that time rounded to next day adds to dates!! 它永远不会说到第二天的时间增加了日期! I believe that this solves the mystery. 我相信这解决了这个谜。

In fact you can use round yourself to get the desired result. 事实上,您可以自己使用圆形来获得所需的结果。 Tests demonstrated that 9 digits are the top number for rounding, with 10 providing the undesired effect... 测试表明,9位是舍入的最高数字,10位提供了不良影响......

ex [a1]=cdate(round(41652.9999999999,8)) --> 14/01/14 00:00 ex [a1]=cdate(round(41652.9999999999,8)) - > 14/01/14 00:00

[a1]=cdate(round(41652.9999999999,10)) --> 13/01/14 00:00 [a1]=cdate(round(41652.9999999999,10)) - > 13/01/14 00:00

added code after comment: 评论后添加代码:

Sub dower() 

Dim v1 As Double, vdt As Date, vv As Variant, vdbl As Double
Range("a1:a6").ClearContents

v1 = 41652.9999999996
vdt = CDate(v1)
vv = CDate(v1)
vdbl = CDate(v1)

[a1] = v1
[a2] = vdt
[a3] = vv
[a4] = vdbl

vdt = CDbl(v1)
[a5] = vdt

End Sub

Both cell value and cdate have enough precision to story this value: 41652.9999999963. 单元格值和cdate都具有足够的精度来记录此值:41652.9999999963。

?CDate(41652.9999999963) = 41652.9999999963
True
[A1].Value=cdbl(CDate(41652.9999999963))
?[A1].Value= 41652.9999999963
True

So I think this should be one Excel defect when user assign the cdate to cell value. 所以我认为当用户将cdate分配给单元格值时,这应该是一个Excel缺陷。

Though we don't know the detail implementaion of it, I can guess it might be look like: 虽然我们不知道它的详细实现,但我猜它可能看起来像:

[A1].Value=StringToDate(DateToString(CDate(41652.9999999963)))

When we do 当我们这样做

[A1].Value=CDate(41652.9999999963))

And the "DateToString" function do not do the right thing: it cut the 41652.9999999963 into two part, 41652 and .9999999963 and it use 41652 to calculate the date part("2014-1-13"), and use .9999999963 to calculate the rest part ("1 day and 0:0:0"), then finally, they are merged into one value "2014-1-13 0:0:0" but "1 day" was lost. 并且“DateToString”函数不做正确的事情:它将41652.9999999963分为41652和.9999999963两部分,并使用41652计算日期部分(“2014-1-13”),并使用.9999999963计算其余部分(“1天0:0:0”),最后,它们合并为一个值“2014-1-13 0:0:0”,但“1天”丢失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM