truncar redondear quitar menos mas hacia funcion decimales cómo como arriba abajo excel ms-access access-vba rounding worksheet-function

excel - quitar - redondear.mas en access



Cómo redondear en MS Access, VBA (12)

Para expandir un poco sobre la respuesta aceptada:

"La función Round funciona de forma redonda a par, que es diferente de redonda a más grande".
--Microsoft

El formato siempre se redondea.

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

ACC2000: Errores de redondeo cuando utiliza números de coma flotante: http://support.microsoft.com/kb/210423

ACC2000: Cómo redondear un número hacia arriba o hacia abajo por un incremento deseado: http://support.microsoft.com/kb/209996

Función de ronda: http://msdn2.microsoft.com/en-us/library/se6f2zfx.aspx

Cómo implementar procedimientos de redondeo personalizados: http://support.microsoft.com/kb/196652

¿Cuál es la mejor forma de redondear el acceso a VBA?

Mi método actual utiliza el método de Excel

Excel.WorksheetFunction.Round(...

Pero estoy buscando un medio que no dependa de Excel.


Int y Fix son funciones de redondeo útiles, que le dan la parte entera de un número.

Int siempre redondea hacia abajo - Int (3.5) = 3, Int (-3.5) = -4

Arreglar siempre redondea hacia cero - Fix (3.5) = 3, Fix (-3.5) = -3

También están las funciones de coerción, en particular CInt y CLng, que intentan forzar un número a un tipo entero o largo (los enteros están entre -32,768 y 32,767, los largos están entre-2,147,483,648 y 2,147,483,647). Estos redondearán hacia el número entero más cercano, redondeando desde cero desde .5 - CInt (3.5) = 4, Cint (3.49) = 3, CInt (-3.5) = -4, etc.


Si está hablando de redondear a un valor entero (y no redondear a números decimales), siempre existe la forma de la vieja escuela:

return int(var + 0.5)

(También puedes hacer que esto funcione con n decimales, pero empieza a ser un poco desordenado)


VBA.Round(1.23342, 2) // will return 1.23


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

y así sucesivamente. A menudo encontrará que las soluciones aparentemente kludgy como esta son mucho más rápidas que el uso de funciones de Excel, porque VBA parece operar en un espacio de memoria diferente.

por ejemplo, If A > B Then MaxAB = A Else MaxAB = B es aproximadamente 40 veces más rápido que con ExcelWorksheetFunction.Max


En Suiza y, en particular, en la industria de seguros, tenemos que usar varias reglas de redondeo, dependiendo de si se cancela, un beneficio, etc.

Actualmente uso la función

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

que parece funcionar bien


Lance ya mencionó el bug redondeo heredado en la implementación de VBA. Necesito una función real de redondeo en una aplicación VB6. Aquí hay uno que estoy usando. Se basa en uno que encontré en la web como se indica en los comentarios.

'' ----------------------------------------------------------------------------- '' 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 '' -----------------------------------------------------------------------------


Tenga cuidado, la función VBA Round usa el redondeo Banker, donde redondea .5 a un número par, así:

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)

Mientras que la ronda de funciones de la hoja de cálculo de Excel, siempre redondea .5 hacia arriba.

He hecho algunas pruebas y parece que el redondeo de .5 (redondeo simétrico) también se usa para el formato de celdas y también para el redondeo de ancho de columna (cuando se usa el formato de Número General). La bandera ''Precisión como se muestra'' no parece hacer ningún redondeo, solo usa el resultado redondeado del formato de celda.

Traté de implementar la función SymArith de Microsoft en VBA para mi redondeo, pero encontré que Fix tiene un error cuando intentas darle un número como 58.55; la función da un resultado de 58.5 en lugar de 58.6. Finalmente descubrí que puede usar la función de hoja de cálculo de Excel, de la siguiente manera:

Application.Round (58.55, 1)

Esto le permitirá redondear normalmente en VBA, aunque puede no ser tan rápido como una función personalizada. Me doy cuenta de que esto ha cerrado el círculo de la pregunta, pero quería incluirlo para completarlo.


Para resolver el problema de las divisiones de centavo que no suman la cantidad originalmente dividida, creé una función definida por el usuario.

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://.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


Utilicé la siguiente función simple para redondear mis monedas ya que en nuestra empresa siempre lo redondeamos.

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

pero esto SIEMPRE redondeará hasta 2 decimales y también puede error.

incluso si es negativo redondeará (-1.011 será -1.01 y 1.011 será 1.02)

para proporcionar más opciones para redondear hacia arriba (o hacia abajo para negativo) puede usar esta función:

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

(utilizado en un módulo, si no es obvio)


Desafortunadamente, las funciones nativas de VBA que pueden realizar el redondeo faltan, son limitadas, inexactas o tienen errores, y cada una solo aborda un único método de redondeo. Lo bueno es que son rápidos, y que en algunas situaciones pueden ser importantes.

Sin embargo, a menudo la precisión es obligatoria, y con la velocidad actual de las computadoras, apenas se notará un procesamiento un poco más lento, de hecho, no para el procesamiento de valores individuales. Todas las funciones en los enlaces a continuación se ejecutan a aproximadamente 1 μs.

El conjunto completo de funciones, para todos los métodos de redondeo comunes, todos los tipos de datos de VBA, para cualquier valor y para no devolver valores inesperados, se puede encontrar aquí:

Redondear valores hacia arriba, abajo, en 4/5, o a cifras significativas (EE)

o aquí:

Redondeando los valores hacia arriba, abajo, en 4/5, o hacia cifras significativas (CodePlex)

Código solo en GitHub:

VBA.Round

Cubren los métodos de redondeo normales:

  • Redondear hacia abajo, con la opción de redondear los valores negativos hacia cero

  • Round up, con la opción de redondear valores negativos lejos de cero

  • Redondee 4/5, ya sea desde cero o hasta par (Redondeo de banca)

  • Redondea a un conteo de figuras significativas

Las primeras tres funciones aceptan todos los tipos de datos numéricos, mientras que la última existe en tres variedades: para Moneda, Decimal y Doble, respectivamente.

Todos aceptan un recuento de decimales especificado, incluido un recuento negativo que redondeará a decenas, cientos, etc. Aquellos con variante como tipo de retorno devolverán nulo para una entrada incomprensible

También se incluye un módulo de prueba para prueba y validación.

Aquí hay un ejemplo: para el redondeo común de 4/5. Estudie los comentarios en línea para los detalles sutiles y la forma en que CDec se usa para evitar errores de bits.

'' 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


Esta es una forma fácil de redondear siempre al próximo número entero en Access 2003:

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

Por ejemplo:

  • [Peso] = 5,33; Int ([Peso]) = 5; entonces 5.33-5 = 0.33 (<> 0), entonces la respuesta es BillWt = 5 + 1 = 6.
  • [Peso] = 6.000, Int ([Peso]) = 6, entonces 6.000-6 = 0, entonces la respuesta es BillWt = 6.