문제

VBA 액세스를 반올림하는 가장 좋은 방법은 무엇입니까?

현재 방법은 Excel 방법을 사용합니다.

Excel.WorksheetFunction.Round(...

하지만 엑셀에 의존하지 않는 수단을 찾고 있어요.

도움이 되었습니까?

해결책

VBA 라운드 기능은 은행원의 반올림을 사용하여 .5를 짝수로 짝수로 사용합니다.

Round (12.55, 1) would return 12.6 (rounds up) 
Round (12.65, 1) would return 12.6 (rounds down) 
Round (12.75, 1) would return 12.8 (rounds up)   

Excel 워크 시트 기능은 항상 .5를 둥글게합니다.

나는 일부 테스트를 수행했으며 .5 UP 반올림 (대칭 반올림)도 셀 포맷에 의해 사용되며 열 폭 형식 (일반 번호 형식을 사용할 때)에도 사용됩니다. '표시된 정밀도'플래그는 반올림 자체를 수행하는 것처럼 보이지 않으며 셀 형식의 둥근 결과 만 사용합니다.

반올림을 위해 VBA의 Microsoft에서 Symarith 함수를 구현하려고했지만 Fix는 58.55와 같은 숫자를 줄 때 오류가 있음을 발견했습니다. 58.6 대신 58.5의 결과를 제공하는 함수. 그런 다음 마침내 Excel 워크 시트 라운드 기능을 사용할 수 있음을 발견했습니다.

application.round (58.55, 1)

이렇게하면 VBA에서 정상적인 반올림을 수행 할 수 있지만 일부 사용자 정의 기능만큼 빠르지는 않습니다. 나는 이것이 질문에서 완전한 원을 받았다는 것을 알고 있지만 완전성을 위해 그것을 포함시키고 싶었다.

다른 팁

수용된 답변에 대해 조금 확장하려면 :

"라운드 함수는 라운드에서 균일하게 수행되며, 이는 라운드마다 다릅니다."
-마이크로 소프트

형식은 항상 반올림합니다.

  Debug.Print Round(19.955, 2)
  'Answer: 19.95

  Debug.Print Format(19.955, "#.00")
  'Answer: 19.96

ACC2000 : 부동 소수점 번호를 사용할 때 반올림 오류 : http://support.microsoft.com/kb/210423

ACC2000 : 원하는 증분으로 숫자를 위 또는 아래로 반올림하는 방법 : http://support.microsoft.com/kb/209996

라운드 기능 : http://msdn2.microsoft.com/en-us/library/se6f2zfx.aspx

맞춤형 반올림 절차를 구현하는 방법 : http://support.microsoft.com/kb/196652

스위스와 보험 업계의 입수에서는 샤시 아웃, 혜택 등에 따라 여러 반올림 규칙을 사용해야합니다.

나는 현재이 기능을 사용하고 있습니다

Function roundit(value As Double, precision As Double) As Double
    roundit = Int(value / precision + 0.5) * precision
End Function

잘 작동하는 것 같습니다

Int와 Fix는 둘 다 유용한 반올림 함수이며, 이는 숫자의 정수 부분을 제공합니다.

int는 항상 반올림 -int (3.5) = 3, int (-3.5) = -4

항상 Zero를 향한 수정 -수정 (3.5) = 3, Fix (-3.5) = -3

강요 함수, 특히 고화물과 CLNG가 있는데, 이는 정수 유형 또는 긴 유형으로 숫자를 강요하려고합니다 (정수는 -32,768에서 32,767 사이이며, 길이는 2,147,483,648에서 2,147,483,647))). 이들은 모두 가장 가까운 전체 숫자로 반올림되어 .5 -Cint (3.5) = 4, 고린 (3.49) = 3, 고린 (-3.5) = -4 등에서 0에서 둥글게됩니다.

1 place = INT(number x 10 + .5)/10
3 places = INT(number x 1000 + .5)/1000

VBA는 다른 메모리 공간에서 작동하는 것처럼 보이기 때문에 이와 같은 kludgy 솔루션이 Excel 함수를 사용하는 것보다 훨씬 빠르다는 것을 알게 될 것입니다.

예를 들어 If A > B Then MaxAB = A Else MaxAB = B ExcelWorkSheetFunction.Max를 사용하는 것보다 약 40 x 빠릅니다

불행하게도 반올림을 수행할 수 있는 VBA의 기본 기능은 누락, 제한, 부정확 또는 버그가 있으며 각 기능은 단일 반올림 방법만 다룹니다.장점은 빠르며 어떤 상황에서는 중요할 수 있다는 것입니다.

그러나 정밀도가 필수인 경우가 많으며 오늘날 컴퓨터의 속도로 인해 처리 속도가 약간 느려지는 것은 거의 눈에 띄지 않으며 실제로 단일 값을 처리하는 경우에도 마찬가지입니다.아래 링크의 모든 기능은 약 1μs에서 실행됩니다.

모든 일반적인 반올림 방법, VBA의 모든 데이터 유형, 모든 값에 대해, 예상치 못한 값을 반환하지 않는 전체 함수 세트는 여기에서 찾을 수 있습니다.

값을 4/5로 반올림하거나 유효 숫자(EE)로 반올림

아니면 여기:

값을 4/5로 반올림하거나 유효 숫자로 반올림(CodePlex)

GitHub에서만 코드를 작성하세요.

VBA.라운드

일반적인 반올림 방법은 다음과 같습니다.

  • 반내림(음수 값을 0으로 반올림하는 옵션 포함)

  • 반올림(0에서 먼 쪽 음수 값을 반올림하는 옵션 포함)

  • 0에서 멀어지거나 짝수로 4/5로 반올림(은행가 반올림)

  • 유효숫자 수로 반올림

처음 세 함수는 모든 숫자 데이터 유형을 허용하는 반면, 마지막 함수는 각각 통화, 소수 및 이중의 세 가지 유형으로 존재합니다.

그들은 모두 지정된 소수 자릿수를 허용합니다(십, 백 등으로 반올림되는 음수 포함).반환 유형으로 Variant를 사용하는 경우 이해할 수 없는 입력에 대해 Null을 반환합니다.

테스트 및 검증을 위한 테스트 모듈도 포함되어 있습니다.

일반적인 4/5 반올림에 대한 예가 여기에 있습니다.세세한 부분과 방법은 인라인 댓글을 참고해주세요 CDec 비트 오류를 ​​방지하는 데 사용됩니다.

' Common constants.
'
Public Const Base10     As Double = 10

' Rounds Value by 4/5 with count of decimals as specified with parameter NumDigitsAfterDecimals.
'
' Rounds to integer if NumDigitsAfterDecimals is zero.
'
' Rounds correctly Value until max/min value limited by a Scaling of 10
' raised to the power of (the number of decimals).
'
' Uses CDec() for correcting bit errors of reals.
'
' Execution time is about 1µs.
'
Public Function RoundMid( _
    ByVal Value As Variant, _
    Optional ByVal NumDigitsAfterDecimals As Long, _
    Optional ByVal MidwayRoundingToEven As Boolean) _
    As Variant

    Dim Scaling     As Variant
    Dim Half        As Variant
    Dim ScaledValue As Variant
    Dim ReturnValue As Variant

    ' Only round if Value is numeric and ReturnValue can be different from zero.
    If Not IsNumeric(Value) Then
        ' Nothing to do.
        ReturnValue = Null
    ElseIf Value = 0 Then
        ' Nothing to round.
        ' Return Value as is.
        ReturnValue = Value
    Else
        Scaling = CDec(Base10 ^ NumDigitsAfterDecimals)

        If Scaling = 0 Then
            ' A very large value for Digits has minimized scaling.
            ' Return Value as is.
            ReturnValue = Value
        ElseIf MidwayRoundingToEven Then
            ' Banker's rounding.
            If Scaling = 1 Then
                ReturnValue = Round(Value)
            Else
                ' First try with conversion to Decimal to avoid bit errors for some reals like 32.675.
                ' Very large values for NumDigitsAfterDecimals can cause an out-of-range error 
                ' when dividing.
                On Error Resume Next
                ScaledValue = Round(CDec(Value) * Scaling)
                ReturnValue = ScaledValue / Scaling
                If Err.Number <> 0 Then
                    ' Decimal overflow.
                    ' Round Value without conversion to Decimal.
                    ReturnValue = Round(Value * Scaling) / Scaling
                End If
            End If
        Else
            ' Standard 4/5 rounding.
            ' Very large values for NumDigitsAfterDecimals can cause an out-of-range error 
            ' when dividing.
            On Error Resume Next
            Half = CDec(0.5)
            If Value > 0 Then
                ScaledValue = Int(CDec(Value) * Scaling + Half)
            Else
                ScaledValue = -Int(-CDec(Value) * Scaling + Half)
            End If
            ReturnValue = ScaledValue / Scaling
            If Err.Number <> 0 Then
                ' Decimal overflow.
                ' Round Value without conversion to Decimal.
                Half = CDbl(0.5)
                If Value > 0 Then
                    ScaledValue = Int(Value * Scaling + Half)
                Else
                    ScaledValue = -Int(-Value * Scaling + Half)
                End If
                ReturnValue = ScaledValue / Scaling
            End If
        End If
        If Err.Number <> 0 Then
            ' Rounding failed because values are near one of the boundaries of type Double.
            ' Return value as is.
            ReturnValue = Value
        End If
    End If

    RoundMid = ReturnValue

End Function

정수 값으로 반올림하는 것에 대해 이야기하고 있다면 (반올림하지 않음 N 소수점 이하), 항상 구식 길이 있습니다.

return int(var + 0.5)

(이 일을 할 수 있습니다 N 소수점이지만 조금 지저분 해지 기 시작합니다)

랜스는 이미 상속 반올림을 언급했습니다 bug VBA의 구현에서. 따라서 VB6 앱에 실제 반올림 기능이 필요합니다. 여기에 내가 사용하는 것이 있습니다. 주석에 표시된대로 웹에서 찾은 것을 기반으로합니다.

' -----------------------------------------------------------------------------
' RoundPenny
'
' Description:
'    rounds currency amount to nearest penny
'
' Arguments:
'    strCurrency        - string representation of currency value
'
' Dependencies:
'
' Notes:
' based on RoundNear found here:
' http://advisor.com/doc/08884
'
' History:
' 04/14/2005 - WSR : created
'
Function RoundPenny(ByVal strCurrency As String) As Currency

         Dim mnyDollars    As Variant
         Dim decCents      As Variant
         Dim decRight      As Variant
         Dim lngDecPos     As Long

1        On Error GoTo RoundPenny_Error

         ' find decimal point
2        lngDecPos = InStr(1, strCurrency, ".")

         ' if there is a decimal point
3        If lngDecPos > 0 Then

            ' take everything before decimal as dollars
4           mnyDollars = CCur(Mid(strCurrency, 1, lngDecPos - 1))

            ' get amount after decimal point and multiply by 100 so cents is before decimal point
5           decRight = CDec(CDec(Mid(strCurrency, lngDecPos)) / 0.01)

            ' get cents by getting integer portion
6           decCents = Int(decRight)

            ' get leftover
7           decRight = CDec(decRight - decCents)

            ' if leftover is equal to or above round threshold
8           If decRight >= 0.5 Then

9              RoundPenny = mnyDollars + ((decCents + 1) * 0.01)

            ' if leftover is less than round threshold
10          Else

11             RoundPenny = mnyDollars + (decCents * 0.01)

12          End If

         ' if there is no decimal point
13       Else

            ' return it
14          RoundPenny = CCur(strCurrency)

15       End If

16       Exit Function

RoundPenny_Error:

17       Select Case Err.Number

            Case 6

18             Err.Raise vbObjectError + 334, c_strComponent & ".RoundPenny", "Number '" & strCurrency & "' is too big to represent as a currency value."

19          Case Else

20             DisplayError c_strComponent, "RoundPenny"

21       End Select

End Function
' ----------------------------------------------------------------------------- 
VBA.Round(1.23342, 2) // will return 1.23

Penny Splits의 문제를 해결하기 위해 원래 분할 된 금액을 추가하지 않기 위해 사용자 정의 기능을 만들었습니다.

Function PennySplitR(amount As Double, Optional splitRange As Variant, Optional index As Integer = 0, Optional n As Integer = 0, Optional flip As Boolean = False) As Double
' This Excel function takes either a range or an index to calculate how to "evenly" split up dollar amounts
' when each split amount must be in pennies.  The amounts might vary by a penny but the total of all the
' splits will add up to the input amount.

' Splits a dollar amount up either over a range or by index
' Example for passing a range: set range $I$18:$K$21 to =PennySplitR($E$15,$I$18:$K$21) where $E$15 is the amount and $I$18:$K$21 is the range
'                              it is intended that the element calling this function will be in the range
' or to use an index and total items instead of a range: =PennySplitR($E$15,,index,N)
' The flip argument is to swap rows and columns in calculating the index for the element in the range.

' Thanks to: http://stackoverflow.com/questions/5559279/excel-cell-from-which-a-function-is-called for the application.caller.row hint.
Dim evenSplit As Double, spCols As Integer, spRows As Integer
If (index = 0 Or n = 0) Then
    spRows = splitRange.Rows.count
    spCols = splitRange.Columns.count
    n = spCols * spRows
    If (flip = False) Then
       index = (Application.Caller.Row - splitRange.Cells.Row) * spCols + Application.Caller.Column - splitRange.Cells.Column + 1
     Else
       index = (Application.Caller.Column - splitRange.Cells.Column) * spRows + Application.Caller.Row - splitRange.Cells.Row + 1
    End If
 End If
 If (n < 1) Then
    PennySplitR = 0
    Return
 Else
    evenSplit = amount / n
    If (index = 1) Then
            PennySplitR = Round(evenSplit, 2)
        Else
            PennySplitR = Round(evenSplit * index, 2) - Round(evenSplit * (index - 1), 2)
    End If
End If
End Function

나는 다음을 사용했다 단순한 내 반올림하는 기능 통화 우리 회사와 마찬가지로 언제나 모으다.

Function RoundUp(Number As Variant)
   RoundUp = Int(-100 * Number) / -100
   If Round(Number, 2) = Number Then RoundUp = Number
End Function

그러나 이것은 항상 최대 2 개의 소수성을 반올림하며 오류가 발생할 수도 있습니다.

음수이더라도 반올림됩니다 (-1.011은 -1.01이고 1.011은 1.02입니다)

따라서 더 많은 옵션을 제공합니다 반올림 (또는 부정적인 경우) ~할 수 있었다 이 기능 사용 :

Function RoundUp(Number As Variant, Optional RoundDownIfNegative As Boolean = False)
On Error GoTo err
If Number = 0 Then
err:
    RoundUp = 0
ElseIf RoundDownIfNegative And Number < 0 Then
    RoundUp = -1 * Int(-100 * (-1 * Number)) / -100
Else
    RoundUp = Int(-100 * Number) / -100
End If
If Round(Number, 2) = Number Then RoundUp = Number
End Function

(명백하지 않은 경우 모듈에서 사용)

다음은 Access 2003의 다음 전체 번호로 항상 반올림하는 쉬운 방법입니다.

BillWt = IIf([Weight]-Int([Weight])=0,[Weight],Int([Weight])+1)

예를 들어:

  • 무게] = 5.33; int ([weight]) = 5; 따라서 5.33-5 = 0.33 (<> 0)이므로 대답은 Billwt = 5+1 = 6입니다.
  • weight] = 6.000, int ([weight]) = 6, 6.000-6 = 0이므로 대답은 Billwt = 6입니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top