Hvordan Rund i MS Access, VBA

stemmer
12

Hva er den beste måten å runde i VBA Access?

Min nåværende metoden utnytter Excel-metoden

Excel.WorksheetFunction.Round(...

Men jeg leter etter et middel som ikke er avhengig av Excel.

Publisert på 25/09/2008 klokken 22:30
kilden bruker
På andre språk...                            


12 svar

stemmer
2

Int Fix og er begge nyttige avrundings funksjoner, som gir deg heltallsdelen av et tall.

Int runder alltid ned - int (3,5) = 3, Int (-3,5) = -4

Fiks alltid runder mot null - Fix (3,5) = 3, Fix (-3,5) = -3

Det er også de tvangs funksjoner, særlig Cint og CLng, som prøver å tvinge et tall til et heltall typen eller en lang type (heltall er mellom -32 768 og 32 767, Longs er mellom-2147483648 og 2147483647). Disse vil både runde mot nærmeste hele tall, avrunding bort fra null fra 0,5 - Cint (3,5) = 4, Cint (3,49) = 3, Cint (-3,5) = -4, etc.

Svarte 25/09/2008 kl. 22:37
kilden bruker

stemmer
0
VBA.Round(1.23342, 2) // will return 1.23
Svarte 25/09/2008 kl. 22:47
kilden bruker

stemmer
25

Vær forsiktig, bruker VBA Round funksjon Bankerens avrunding, hvor den runder 0,5 til en selv, som så:

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)   

Mens Excel regneark Function Round, runder alltid 0,5 opp.

Jeg har gjort noen tester, og det ser ut som 0,5 opp avrunding (symmetrisk avrunding) er også brukt av celleformatering, og også for kolonnebredde avrunding (når du bruker Generelt Antall format). The 'Precision som vises' flagg synes ikke å gjøre noe avrunding seg selv, den bruker bare den avrundede resultatet av celleformat.

Jeg prøvde å implementere SymArith funksjonen fra Microsoft i VBA for min avrunding, men fant ut at Fix har en feil når du prøver å gi det et nummer som 58,55; funksjonen gir et resultat på 58,5 i stedet for 58,6. Jeg så til slutt oppdaget at du kan bruke Excel-regneark Round-funksjon, som så:

Application.Round (58.55, 1)

Dette vil tillate deg å gjøre normal avrunding i VBA, selv om det ikke kan være så rask som noen egendefinerte funksjonen. Jeg innser at dette har kommet full sirkel fra spørsmålet, men ønsket å ta det for fullstendighet.

Svarte 25/09/2008 kl. 22:53
kilden bruker

stemmer
1

Hvis du snakker om avrunding til et heltall (og ikke avrunding til n desimaler), det er alltid den gamle skolen måte:

return int(var + 0.5)

(Du kan gjøre dette arbeidet for n desimaler også, men det begynner å bli litt rotete)

Svarte 25/09/2008 kl. 23:09
kilden bruker

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

og så on.You'll ofte at tilsynelatende kludgy løsninger som dette er mye raskere enn å bruke Excel-funksjoner, fordi VBA synes å operere i en annen plass i minnet.

for eksempel If A > B Then MaxAB = A Else MaxAB = Ber omtrent 40 ganger raskere enn ved bruk av ExcelWorksheetFunction.Max

Svarte 30/09/2008 kl. 22:28
kilden bruker

stemmer
4

I Sveits og i particulat i forsikringsbransjen, må vi bruke flere avrundingsregler, avhengig av om det chash ut, en fordel etc.

Jeg bruker funksjonen

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

som synes å fungere fint

Svarte 03/10/2008 kl. 08:46
kilden bruker

stemmer
9

For å utvide litt på den aksepterte svaret:

"The Round funksjonen utfører rundt til selv, som er forskjellig fra runde til større."
--Microsoft

Format runder alltid opp.

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

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

ACC2000: avrundingsfeil når du bruker flyttall: http://support.microsoft.com/kb/210423

ACC2000: Hvordan avrunde et tall opp eller ned ved en ønsket Increment: http://support.microsoft.com/kb/209996

Round Funksjon: http://msdn2.microsoft.com/en-us/library/se6f2zfx.aspx

Hvordan implementere Custom avrunding Prosedyrer: http://support.microsoft.com/kb/196652

Svarte 05/11/2008 kl. 19:21
kilden bruker

stemmer
1

Lance allerede nevnt arve avrunding bugi VBA implementering. Så jeg trenger en skikkelig avrunding funksjon i en VB6 app. Her er en som jeg bruker. Den er basert på en jeg fant på nettet som er angitt i kommentarfeltet.

' -----------------------------------------------------------------------------
' 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
' ----------------------------------------------------------------------------- 
Svarte 25/02/2009 kl. 14:46
kilden bruker

stemmer
0

Her er enkel måte å alltid runde opp til nærmeste hele tall i Access 2003:

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

For eksempel:

  • [Weight] = 5,33; Int ([vekt]) = 5; så 5,33 til 5 = 0,33 (<> 0), så svaret er BillWt = 5 + 1 = 6.
  • [Weight] = 6,000, Int ([vekt]) = 6, slik at 6,000 til 6 = 0, så svaret er BillWt = 6.
Svarte 30/12/2009 kl. 14:35
kilden bruker

stemmer
0

For å løse problemet med penny deler ikke legge opp til det beløpet de opprinnelig ble splittet fra, jeg opprettet en brukerdefinert funksjon.

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
Svarte 27/03/2014 kl. 12:35
kilden bruker

stemmer
0

Jeg brukte følgende enkle funksjonen for å runde mine valutaer som i vårt selskap vi alltid runde opp.

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

men dette vil alltid runde opp til 2 desimaler og kan også feil.

selv om det er negativt vil den runde opp (-1,011 vil være -1,01 og 1,011 vil være 1,02)

så å gi flere alternativer for avrunding opp (eller ned for negativ) du kan bruke denne funksjonen:

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

(Brukt i en modul, hvis det ikke er åpenbare)

Svarte 07/05/2014 kl. 13:26
kilden bruker

stemmer
2

Dessverre er de innfødte funksjoner av VBA som kan utføre avrunding enten mangler, er begrenset, unøyaktig eller buggy, og hver adresser bare en enkelt avrunding metode. På oppsiden er at de er raske, og at kan i noen situasjoner være viktig.

Men ofte presisjon er obligatorisk, og med hastigheten på datamaskiner i dag, vil en litt tregere behandling neppe bli lagt merke til, faktisk ikke for behandling av enkeltverdier. Alle funksjonene på linkene nedenfor løp på ca 1 ms.

Det komplette sett av funksjoner - for alle vanlige avrundings metoder, alle datatyper VBA, for noen verdi, og ikke returnerer uventede verdier - finner du her:

Avrunding verdier opp, ned, etter 4/5, eller til signifikante siffer (EE)

eller her:

Avrunding verdier opp, ned, etter 4/5, eller til signifikante siffer (CodePlex)

Kode bare på GitHub:

VBA.Round

De dekker de vanlige avrundings metoder:

  • Runde ned, med mulighet for å runde negative verdier mot null

  • Rund opp, med mulighet for å runde negative verdier fra null

  • Rund av 4/5, enten bort fra null eller til og med (Bankerens avrunding)

  • Runde til en telling av viktige tall

De tre første funksjonene godta alle de numeriske datatyper, mens den siste finnes i tre varianter - for Valuta, Desimal, og Double hhv.

De aksepterer en spesifisert teller desimaler - inkludert en negativ teller som vil runde til ti, hundre, etc. De med Variant som returtypen vil returnere Null for uforståelig innspill

En testmodulen for test og validering blir også inkludert.

Et eksempel er her - for den vanlige 4/5 avrunding. Vennligst studere in-line kommentarer til de subtile detaljer og måten CDec brukes for å unngå litt feil.

' 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
Svarte 01/05/2016 kl. 10:30
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more