在 UDF 中使用 Excel 的 Rounddown 从 1 舍入到 0
Using Excel's Rounddown in a UDF rounds 1 to 0
长话短说,我工作的地方用时钟的象限来测量时间。例如,1.1 是 1 小时 0-15 分钟,1.2 是 1 小时 15-30 分钟,1.3 是 1 小时 30-45 分钟。没有1.4因为1.4当然等于2.
我想做一个excel sheet,它会在这个系统下自动添加我的时间,所以我写了这个UDF来转换时间,通过分隔十进制值并乘以2.5得到一个正常的十进制值(.1 = .25,.2 = .5,.3 = .75),然后在最后除以 2.5 以转换回我雇主的格式。我知道可以使用 excel 的现有公式来完成,但是有点乱,老实说,我太固执了,现在不能放手。
如果您查看下面的屏幕截图,您会发现该函数适用于所有列,但出于某种原因显示 39.4 而不是 40 的最终每周总计列除外(同样,这两个值在技术上是等效的,但是由于某种原因,该程序没有将 .4 转换为 1)。
http://i.imgur.com/yxOvlkP.png
这是完整的代码。当余数正好等于 1(为简单起见,假设输入了两个以 .2 结尾的值)然后在末尾以某种方式四舍五入为零时,问题似乎就出现了。
Function newMath(week As Range) As Double
Dim time As Variant
Dim remainder As Double
Dim wholeTime As Double
remainder = 0
wholeTime = 0
For Each time In week
remainder = remainder + ((time - WorksheetFunction.RoundDown(time, 0)) * 2.5) 'Separate and sum up decimal values
wholeTime = wholeTime + WorksheetFunction.RoundDown(time, 0) 'Separate and sum up whole hours
Next time
'Problem occurs at this point when remainder = 1
'WorksheetFunction.RoundDown(remainder, 0) will equal 0 below even when 1 should round down to 1
wholeTime = wholeTime + WorksheetFunction.RoundDown(remainder, 0) 'Add the whole remainder hours to whole time
remainder = (remainder - WorksheetFunction.RoundDown(remainder, 0)) / 2.5 'Get decimal value of remainder and convert back to quadrant
newMath = wholeTime + remainder
End Function
当余数恰好等于 1 时 excel 的舍入函数似乎将其四舍五入为 0。
这意味着下面的行没有按应有的方式将 1 添加到整数中:
wholeTime = wholeTime + WorksheetFunction.RoundDown(remainder, 0)
并且这一行将 return 一个 1,它在不应该除以 2.5 的时候被除以 2.5(这是 .4 的来源):
remainder = (remainder - WorksheetFunction.RoundDown(remainder, 0)) / 2.5
我不确定发生了什么,也不确定为什么 excel 将 1 的余数四舍五入为 0(如果这确实是问题所在)。我非常感谢任何帮助,如果您需要更多信息,请告诉我。谢谢!
这里有一个稍微不同的做事方式,以免以 0.3999999 代替 4。请注意,我使用了 VBA Int
函数,它的执行速度应该比worksheetfunction.roundown(n,0).
通过乘以 time
* 10,然后使用 Mod
函数对最后一位求和,我们可以进行整数运算,直到需要转换回最终结果。
另请注意,以下例程仅适用于正数。如果你的时间可能是负数 sheet,你应该使用 Fix
代替 Int
Option Explicit
Function newMath(week As Range) As Double
Dim time As Range
Dim remainder As Variant
Dim wholeTime As Long
remainder = 0
wholeTime = 0
For Each time In week
wholeTime = wholeTime + Int(time)
remainder = remainder + (time * 10) Mod 10
Next time
'Problem occurs at this point when remainder = 1
'WorksheetFunction.RoundDown(remainder, 0) will equal 0 below even when 1 should round down to 1
wholeTime = wholeTime + Int(remainder / 4) 'Add the whole remainder hours to whole time
remainder = ((remainder / 4) - Int(remainder / 4)) / 2.5 'Get decimal value of remainder and convert back to quadrant
newMath = wholeTime + remainder
End Function
试试这个代码:
Function newMath(Rng As Range) As Double
Dim CL As Range
Dim hs As Long, hs1 As Long
Dim ms As Double, ms1 As Double, ms2 As Double
For Each CL In Rng
hs = hs + Fix(CL.Value)
ms = ms + CL.Value
Next
ms1 = Round((ms - hs), 1)
hs1 = Fix(ms1 / 0.4)
ms2 = ms1 - (hs1 * 0.4)
newMath = hs + hs1 + ms2
End Function
长话短说,我工作的地方用时钟的象限来测量时间。例如,1.1 是 1 小时 0-15 分钟,1.2 是 1 小时 15-30 分钟,1.3 是 1 小时 30-45 分钟。没有1.4因为1.4当然等于2.
我想做一个excel sheet,它会在这个系统下自动添加我的时间,所以我写了这个UDF来转换时间,通过分隔十进制值并乘以2.5得到一个正常的十进制值(.1 = .25,.2 = .5,.3 = .75),然后在最后除以 2.5 以转换回我雇主的格式。我知道可以使用 excel 的现有公式来完成,但是有点乱,老实说,我太固执了,现在不能放手。
如果您查看下面的屏幕截图,您会发现该函数适用于所有列,但出于某种原因显示 39.4 而不是 40 的最终每周总计列除外(同样,这两个值在技术上是等效的,但是由于某种原因,该程序没有将 .4 转换为 1)。
http://i.imgur.com/yxOvlkP.png
这是完整的代码。当余数正好等于 1(为简单起见,假设输入了两个以 .2 结尾的值)然后在末尾以某种方式四舍五入为零时,问题似乎就出现了。
Function newMath(week As Range) As Double
Dim time As Variant
Dim remainder As Double
Dim wholeTime As Double
remainder = 0
wholeTime = 0
For Each time In week
remainder = remainder + ((time - WorksheetFunction.RoundDown(time, 0)) * 2.5) 'Separate and sum up decimal values
wholeTime = wholeTime + WorksheetFunction.RoundDown(time, 0) 'Separate and sum up whole hours
Next time
'Problem occurs at this point when remainder = 1
'WorksheetFunction.RoundDown(remainder, 0) will equal 0 below even when 1 should round down to 1
wholeTime = wholeTime + WorksheetFunction.RoundDown(remainder, 0) 'Add the whole remainder hours to whole time
remainder = (remainder - WorksheetFunction.RoundDown(remainder, 0)) / 2.5 'Get decimal value of remainder and convert back to quadrant
newMath = wholeTime + remainder
End Function
当余数恰好等于 1 时 excel 的舍入函数似乎将其四舍五入为 0。
这意味着下面的行没有按应有的方式将 1 添加到整数中:
wholeTime = wholeTime + WorksheetFunction.RoundDown(remainder, 0)
并且这一行将 return 一个 1,它在不应该除以 2.5 的时候被除以 2.5(这是 .4 的来源):
remainder = (remainder - WorksheetFunction.RoundDown(remainder, 0)) / 2.5
我不确定发生了什么,也不确定为什么 excel 将 1 的余数四舍五入为 0(如果这确实是问题所在)。我非常感谢任何帮助,如果您需要更多信息,请告诉我。谢谢!
这里有一个稍微不同的做事方式,以免以 0.3999999 代替 4。请注意,我使用了 VBA Int
函数,它的执行速度应该比worksheetfunction.roundown(n,0).
通过乘以 time
* 10,然后使用 Mod
函数对最后一位求和,我们可以进行整数运算,直到需要转换回最终结果。
另请注意,以下例程仅适用于正数。如果你的时间可能是负数 sheet,你应该使用 Fix
代替 Int
Option Explicit
Function newMath(week As Range) As Double
Dim time As Range
Dim remainder As Variant
Dim wholeTime As Long
remainder = 0
wholeTime = 0
For Each time In week
wholeTime = wholeTime + Int(time)
remainder = remainder + (time * 10) Mod 10
Next time
'Problem occurs at this point when remainder = 1
'WorksheetFunction.RoundDown(remainder, 0) will equal 0 below even when 1 should round down to 1
wholeTime = wholeTime + Int(remainder / 4) 'Add the whole remainder hours to whole time
remainder = ((remainder / 4) - Int(remainder / 4)) / 2.5 'Get decimal value of remainder and convert back to quadrant
newMath = wholeTime + remainder
End Function
试试这个代码:
Function newMath(Rng As Range) As Double
Dim CL As Range
Dim hs As Long, hs1 As Long
Dim ms As Double, ms1 As Double, ms2 As Double
For Each CL In Rng
hs = hs + Fix(CL.Value)
ms = ms + CL.Value
Next
ms1 = Round((ms - hs), 1)
hs1 = Fix(ms1 / 0.4)
ms2 = ms1 - (hs1 * 0.4)
newMath = hs + hs1 + ms2
End Function