Vba 使用Excel';在UDF中,s舍入将1轮到0轮

Vba 使用Excel';在UDF中,s舍入将1轮到0轮,vba,excel,spreadsheet,udf,Vba,Excel,Spreadsheet,Udf,长话短说,我工作的地方用时钟的象限来测量时间。例如,1.1是一小时0-15分钟,1.2是一小时15-30分钟,1.3是一小时30-45分钟。没有1.4,因为1.4当然等于2 我想制作一个excel表格,在这个系统下自动添加我的时间,所以我写了这个UDF来转换时间,方法是将十进制值分开,然后乘以2.5得到一个正常的十进制值(.1=.25,.2=.5,.3=.75),最后除以2.5,转换回我雇主的格式。我知道这可以用excel现有的公式来完成,但它有点混乱,老实说,我太固执了,现在不想让它过去 如果

长话短说,我工作的地方用时钟的象限来测量时间。例如,1.1是一小时0-15分钟,1.2是一小时15-30分钟,1.3是一小时30-45分钟。没有1.4,因为1.4当然等于2

我想制作一个excel表格,在这个系统下自动添加我的时间,所以我写了这个UDF来转换时间,方法是将十进制值分开,然后乘以2.5得到一个正常的十进制值(.1=.25,.2=.5,.3=.75),最后除以2.5,转换回我雇主的格式。我知道这可以用excel现有的公式来完成,但它有点混乱,老实说,我太固执了,现在不想让它过去

如果您查看下面的屏幕截图,您将看到该函数适用于所有列,但出于某种原因,最终的每周总计列显示为39.4而不是40(这两个值在技术上是等效的,但由于某种原因,程序没有将.4转换为1)

下面是完整的代码。当余数正好等于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)  
这一行将返回一个1,当它不应该被除以2.5时(这就是.4的来源):


我不太清楚到底发生了什么,也不清楚为什么excel会将剩余的1四舍五入到0,如果这确实是个问题的话。我非常感谢您的帮助,如果您需要更多信息,请告诉我。谢谢

这里有一种稍微不同的方法,这样就不会以0.399999代替4。请注意,我使用了VBA
Int
函数,该函数的执行速度应该比worksheetfunction.roundown(n,0)更快

通过将
时间
*10相乘,然后使用
Mod
函数对最后一位数字求和,我们可以进行整数运算,直到转换回最终结果为止

还请注意,下面的例程仅适用于正数。如果您的时间表上可能有负数,您应该使用
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

这里有一个稍微不同的方法,这样就不会用0.399999代替4。请注意,我使用了VBA
Int
函数,该函数的执行速度应该比worksheetfunction.roundown(n,0)更快

通过将
时间
*10相乘,然后使用
Mod
函数对最后一位数字求和,我们可以进行整数运算,直到转换回最终结果为止

还请注意,下面的例程仅适用于正数。如果您的时间表上可能有负数,您应该使用
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
请尝试以下代码:

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

你的问题是计算机是二进制的,而你在做十进制算术。关于39.4的结果,余数计算为0.399999999999。你需要四舍五入,或者使用十进制算术。你的问题是计算机是二进制的,你在做十进制算术。对于39.4的结果,余数计算为0.399999999999,您需要进行四舍五入,或者使用十进位算术,这很完美。非常感谢你!太好了。非常感谢你!