Funciones creadas por el usurio con Rango

30/08/2004 - 12:59 por Adolfo Aparicio | Informe spam
Como bien me aconsejó Hector Miguel en el post titulado:
Re: Ayuda en las funciones definidas por el usuario
de fecha: 8/26/2004 10:31:31 PM
para hacer una función definida por el usuario que use
rangos, lo único que se ha de hacer es usar como
argumentos alguna variable tipo Range.

He probado ha construir una función que sume, de igual
forma que lo hace la función =SUMA(). La función es la
siguiente:

Function sumado(R As Range) As Double
Dim s As Double
For Each c In R
s = s + c
Next
sumado = s
End Function

Pongamos los siguientes valores:
en A1 --> 1
en A2 --> 2
en A3 --> 3
en A10 --> 4

Si aplicamos la función suma, obtenemos la suma correcta
que es 10
=SUMA(A1:A3;A10)
Por el contrario si aplicamos la fórmula que hemos creado:
=sumado(A1:A3;A10)
obtenemos un error del tipo #¡VALOR!

Pero la función 'sumado' no está mal ya que si la
llamamos desde un procedimiento funciona

Sub prueba()
MsgBox sumado(Range("A1:A3,A10"))
End Sub

Y también funciona si el rango es un sólo bloque de
celdas. Por ejemplo: =sumado(A1:A3) da como resultado 6.

Después de dar vueltas al problema he visto que si en la
fórmula que escribes añades unos paréntesis se soluciona:

=sumado((A1:A3;A10)) y el resultado es 10.

¿Sabéis como conseguir que la fórmula funcione sin
necesidad de estos paréntesis, al igual que la función
=SUMA()?

Gracias.

Adolfo

Preguntas similare

Leer las respuestas

#1 Fernando Arroyo
30/08/2004 - 14:18 | Informe spam
Para poder pasarle más de un rango a la función desde una celda sin necesidad de los dobles paréntesis tienes que definir el rango como una matriz de parámetros, usando ParamArray, algo como:

Function sumado(ParamArray Rango()) As Double
Dim vCelda As Variant, lngElem As Long
For lngElem = LBound(Rango) To UBound(Rango)
For Each vCelda In Rango(lngElem)
sumado = sumado + vCelda
Next vCelda
Next lngElem
End Function


Respecto a las causas de este comportamiento, no estoy completamente seguro, pero pienso que es porque al poner los dobles paréntesis los más interiores se evalúan antes de llamar a la función, lo que produce un rango (si bien es verdad que se trata de un rango con dos áreas) que es lo que se le pasa a la función (y lo que ésta espera que le sea pasado), mientras que si no se ponen los dobles parénteris la función recibe dos rangos cuando sólo espera uno, y esto hace que la función ni siquiera se ejecute.

Esto explicaría también por qué la función trabaja si es invocada desde VBA (con msgbox, por ejemplo): poque al hacerlo, el argumento se evalúa antes de ejecutarla.

Un saludo.


Fernando Arroyo
MS MVP - Excel


"Adolfo Aparicio" escribió en el mensaje news:295001c48e80$62c56c00$
Como bien me aconsejó Hector Miguel en el post titulado:
Re: Ayuda en las funciones definidas por el usuario
de fecha: 8/26/2004 10:31:31 PM
para hacer una función definida por el usuario que use
rangos, lo único que se ha de hacer es usar como
argumentos alguna variable tipo Range.

He probado ha construir una función que sume, de igual
forma que lo hace la función =SUMA(). La función es la
siguiente:

Function sumado(R As Range) As Double
Dim s As Double
For Each c In R
s = s + c
Next
sumado = s
End Function

Pongamos los siguientes valores:
en A1 --> 1
en A2 --> 2
en A3 --> 3
en A10 --> 4

Si aplicamos la función suma, obtenemos la suma correcta
que es 10
=SUMA(A1:A3;A10)
Por el contrario si aplicamos la fórmula que hemos creado:
=sumado(A1:A3;A10)
obtenemos un error del tipo #¡VALOR!

Pero la función 'sumado' no está mal ya que si la
llamamos desde un procedimiento funciona

Sub prueba()
MsgBox sumado(Range("A1:A3,A10"))
End Sub

Y también funciona si el rango es un sólo bloque de
celdas. Por ejemplo: =sumado(A1:A3) da como resultado 6.

Después de dar vueltas al problema he visto que si en la
fórmula que escribes añades unos paréntesis se soluciona:

=sumado((A1:A3;A10)) y el resultado es 10.

¿Sabéis como conseguir que la fórmula funcione sin
necesidad de estos paréntesis, al igual que la función
=SUMA()?

Gracias.

Adolfo
Respuesta Responder a este mensaje
#2 Héctor Miguel
31/08/2004 - 09:19 | Informe spam
hola, chicos !

solo por [tratar de] 'aportar' algo de informacion 'adicional' :D
para 'igualar' el 'comportamiento' de la funcion 'personalizada'
[en este caso... 'similar' a la funcion integrada de excel =Suma(...)]...

1.- para evitar que 'se atore' si alguna celda es texto...
'forzar' en la funcion a que 'tome/convierta' la celda a un dato de 'valor numerico'
2.- para igualar el que 'suma' se detiene Y DEVUELVE el primer valor de error que encuentra...
'condicionar' cada celda a 'si contiene error'... 'devolverlo' y... 'terminar' la funcion
3.- para que la funcion 'pueda devolver' los valores de error [si los encuentra]...
cambiar el tipo de la funcion de 'As Double' a... 'As Variant' [o dejarla 'sin tipo']

saludos,
hector.
-> las modificaciones propuestas dejarian a la funcion +/- como sigue...
en un modulo de codigo 'normal' ==Function Sumando(ParamArray Rango()) As Variant
Dim Lote As Integer, Celda As Range, Total As Double
For Lote = LBound(Rango) To UBound(Rango)
For Each Celda In Rango(Lote)
If IsError(Celda) Then
Sumando = Celda
Exit Function
End If
Total = Total + Val(Celda)
Next
Next
Sumando = Total
End Function
Respuesta Responder a este mensaje
#3 Daniel.M
01/09/2004 - 00:21 | Informe spam
Hola Héctor, Fernando, Adolfo,

Sabemos que =SUMA(3;4) da 7

Entonces, para añadir ;-) la posibilidad de tratar constantes (solas _O_
matriciales), aqui tiene una otra solucion :

=MiSumando(($A$1;$A$5);$A$2:$A$4;1000;{3,4;5,6})

Function MiSumando(ParamArray MultiRng()) As Variant
Dim SubElem As Variant, Elem As Long, ElemType As String
For Elem = LBound(MultiRng) To UBound(MultiRng)
ElemType = TypeName(MultiRng(Elem))
If ElemType Like "*()" Or ElemType = "Range" Then
For Each SubElem In MultiRng(Elem)
If IsError(SubElem) Then
MiSumando = SubElem
Exit Function
End If
MiSumando = MiSumando + Val(SubElem)
Next SubElem
Else
If IsError(MultiRng(Elem)) Then
MiSumando = MultiRng(Elem)
Exit Function
End If
MiSumando = MiSumando + Val(MultiRng(Elem))
End If
Next Elem
End Function

Saludos,

Daniel M.

"Héctor Miguel" wrote in message
news:u$
hola, chicos !

solo por [tratar de] 'aportar' algo de informacion 'adicional' :D
para 'igualar' el 'comportamiento' de la funcion 'personalizada'
[en este caso... 'similar' a la funcion integrada de excel =Suma(...)]...

1.- para evitar que 'se atore' si alguna celda es texto...
'forzar' en la funcion a que 'tome/convierta' la celda a un dato de


'valor numerico'
2.- para igualar el que 'suma' se detiene Y DEVUELVE el primer valor de error


que encuentra...
'condicionar' cada celda a 'si contiene error'... 'devolverlo' y...


'terminar' la funcion
3.- para que la funcion 'pueda devolver' los valores de error [si los


encuentra]...
cambiar el tipo de la funcion de 'As Double' a... 'As Variant' [o


dejarla 'sin tipo']

saludos,
hector.
-> las modificaciones propuestas dejarian a la funcion +/- como sigue...
en un modulo de codigo 'normal' ==> Function Sumando(ParamArray Rango()) As Variant
Dim Lote As Integer, Celda As Range, Total As Double
For Lote = LBound(Rango) To UBound(Rango)
For Each Celda In Rango(Lote)
If IsError(Celda) Then
Sumando = Celda
Exit Function
End If
Total = Total + Val(Celda)
Next
Next
Sumando = Total
End Function
Respuesta Responder a este mensaje
#4 Héctor Miguel
01/09/2004 - 02:52 | Informe spam
hola, Daniel !

... para añadir ;-) la posibilidad de tratar constantes (solas _O_matriciales) ... otra solucion [...]



¡ una excel_ente añadidura !!! [ya la he pasado a mi 'aservo' particular] ;)

saludos,
hector.
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida