mejorar mi codigo

02/07/2009 - 19:34 por j_lete | Informe spam
Hola grupo, tengo la siguente funcion que utilizo para actualizar cantidades
a disttintos tipos de interes de forma acumulada.
Las cantidades son datos que tengo e una hoja de calculo y se las paso a la
funcion.
Me gustaria saber como poder hacer esta funcion utilizando arrays, es decir,
un aray para los importes y otro para los porcentajes.

Gracias anticipadas por la ayuda que me puedan prestar.

Function ActualizaImp (imp1, imp2, imp3, imp4, imp5, imp6, imp7, imp8 As
Double) As Double

Dim A As Double, B As Double, C As Double, D As Double, E As Double, F As
Double, G As Double
Dim H As Double

PORC1 = 0.016
PORC2 = 0.027
PORC3 = 0.022
PORC4 = 0.017
PORC5 = 0.012
PORC6 = 0.012
PORC7 = 0.014
PORC8 = 0.021

A = ((((((((imp8 * (1 + PORC8)) * (1 + PORC7)) * (1 + PORC6)) * (1 + PORC5))
* (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
B = (((((((imp7 * (1 + PORC7)) * (1 + PORC6)) * (1 + PORC5)) * (1 + PORC4))
* (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
C = ((((((imp6 * (1 + PORC6)) * (1 + PORC5)) * (1 + PORC4)) * (1 + PORC3)) *
(1 + PORC2)) * (1 + PORC1))
D = (((((imp5 * (1 + PORC5)) * (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2)) *
(1 + PORC1))
E = ((((imp4 * (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
F = (((imp3 * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
G = (imp2) * 1
H = (imp1) * 1

ActualizaImp = A + B + C + D + E + F + G + H
End Function

Preguntas similare

Leer las respuestas

#31 j_lete
07/07/2009 - 20:11 | Informe spam
Hola Alexander:

He estado viendo tu función y el resultado obtenido coincide con lo que
hacía la mía.
Con la ayuda del excel al final entiendo como funciona. Tengo dudas con usar
Redim con Preserve (parece que no es obligatorio) y solo Redim.
Muchas gracias por tu ayuda.
Saludos

"Alexander Chacin" escribió:

Creo que una manera pudiera ser esta

Public Function ActualizaImp2(Cantidades As Variant, Optional Porcentajes As
Variant) As Double

Dim Cant() As Double
Dim Porc() As Double
Dim Factores() As Double
Dim I As Integer
Dim J As Integer
Dim Numero As Integer
Dim Valor As Variant
Dim Temp As Double
Dim Suma As Double

Numero = Cantidades.Count - 1

I = 0
For Each Valor In Cantidades

ReDim Preserve Cant(I)
Cant(I) = CDbl(Valor)
I = I + 1
Next Valor

If Not IsMissing(Porcentajes) Then
I = 0
For Each Valor In Porcentajes
ReDim Preserve Porc(I)
Porc(I) = CDbl(Valor)
I = I + 1
Next Valor

Else
ReDim Porc(I - 1)

If Numero <> 7 Then Suma = 1 / 0

Porc(0) = 0.016
Porc(1) = 0.027
Porc(2) = 0.022
Porc(3) = 0.017
Porc(4) = 0.012
Porc(5) = 0.012
Porc(6) = 0.014
Porc(7) = 0.021

End If
ReDim Factores(2 To Numero)

Temp = 0
Suma = 0
For I = 2 To Numero
Temp = Cant(I)
For J = 0 To I

Temp = Temp * (1 + Porc(J))

Next J
Suma = Suma + Temp
Next I

ActualizaImp2 = Suma + Cant(1) + Cant(0)

End Function


Esta forma te permite manejar cantidades diferentes de ocho, por si lo
necesitas

Si no introduces porcentajes, los valores que indicas son tomados por
defecto

Espero que esto te ayude

Saludos
Alexander Chacin


"j_lete" escribió en el mensaje de
noticias news:
> Hola grupo, tengo la siguente funcion que utilizo para actualizar
> cantidades
> a disttintos tipos de interes de forma acumulada.
> Las cantidades son datos que tengo e una hoja de calculo y se las paso a
> la
> funcion.
> Me gustaria saber como poder hacer esta funcion utilizando arrays, es
> decir,
> un aray para los importes y otro para los porcentajes.
>
> Gracias anticipadas por la ayuda que me puedan prestar.
>
> Function ActualizaImp (imp1, imp2, imp3, imp4, imp5, imp6, imp7, imp8 As
> Double) As Double
>
> Dim A As Double, B As Double, C As Double, D As Double, E As Double, F As
> Double, G As Double
> Dim H As Double
>
> PORC1 = 0.016
> PORC2 = 0.027
> PORC3 = 0.022
> PORC4 = 0.017
> PORC5 = 0.012
> PORC6 = 0.012
> PORC7 = 0.014
> PORC8 = 0.021
>
> A = ((((((((imp8 * (1 + PORC8)) * (1 + PORC7)) * (1 + PORC6)) * (1 +
> PORC5))
> * (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
> B = (((((((imp7 * (1 + PORC7)) * (1 + PORC6)) * (1 + PORC5)) * (1 +
> PORC4))
> * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
> C = ((((((imp6 * (1 + PORC6)) * (1 + PORC5)) * (1 + PORC4)) * (1 + PORC3))
> *
> (1 + PORC2)) * (1 + PORC1))
> D = (((((imp5 * (1 + PORC5)) * (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2))
> *
> (1 + PORC1))
> E = ((((imp4 * (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
> F = (((imp3 * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
> G = (imp2) * 1
> H = (imp1) * 1
>
> ActualizaImp = A + B + C + D + E + F + G + H
> End Function
>


Respuesta Responder a este mensaje
#32 Héctor Miguel
07/07/2009 - 23:59 | Informe spam
hola, !

... como funcionan estas 2 instrucciones, en particular resize (2) y count to
Fijo = Application.Sum(Importes.Resize(2))
For n = Importes.Rows.Count To 4 Step -1



1) el resize es para "ajustar" la dimension del rango pasado en el argumento (Importes), ejemplo:
si le pasas a la funcion el rango [A1:A10] la instruccion considera el rango [A1:A2]
si la pasas a la funcion el rango [A5:A20] la instruccion considera el rango [A5:A6]
y corresponde a los dos valores iniciales que pasan SIN calculo de acumulacion de intereses

2) este es un bucle que hace iteraciones "en reversa" (por el incremento en negativo)
segun la sintaxis (de la ayuda en linea): For contador = principio To fin [Step incremento]
- Importes.Rows.Count hace que el punto de partida sea el ultimo dato en el argumento/rango pasado a la funcion
- To 4 hace que el ciclo se detenga al llegar al dato en la posicion 4 del rango pasado como argumento a la funcion
- Step -1 (esto hace que el bucle se realice "en reversa")

el resto corresponde a los valores sin intereses (Fijo) mas al dato en la posicion 3 (que lleva la acumulacion de 2 tasas mas)

saludos,
hector.

__ previos __
1) el importe mas actual es el 1 y el mas antiguo el 8.
2) los datos estan en... (rango b7:b15 para el primer registro, siendo b7 el mas actual y b15 el mas antiguo.
El siguinte registro los valores son c7:c15 y asi sucesivamente).
... al orden del algoritmo, lo hice asi del mas complicado al mas sencillo.
... al final sumo los valores que son los que aparecen en la celda resultado b16 para el 1 registro c16 segundo y asi...
3) los dos valores iniciales no se actualizan, pero su valor si se suma al total.
4) conocer... el importe... al... % actualizado de precios de productos de los ultimos 8 a#o... sin actualizar los 2 primeros.
5) entre 8 y 16, pero en principio 8
La 6) no la entiendo muy bien.



partiendo de que el procedimiento del objetivo determina las alternativas de la programacion, habra mas de una forma de algoritmo
(sin olvidar la interaccion con diferentes usuarios que podria ser causa de interpretaciones diferentes del "como" usar una funcion)

incluso, sin recurrir a funciones personalizadas, una (probable) alternativa es el uso de celdas auxiliares y funciones de excel (p.e.)

- si tu rango de valores/importes es b7:b15 (b7 el "imp1") y el rango de tasas es c7:c15 (c7 el "porc1")
[D7] ·
[D8] ¸
[D9] =vf.plan(b9,c$7:c9) (si tu excel es en ingles, cambias la formula a: =fvschedule(... )
esta ultima formula la copias/arrastras hasta [D_n]
y al final del rango (columna D) simplemente "sumas": =suma(d7:d_n)

si prefieres el uso de una funcion personalizada, (creo que) la siguiente "forma" te resultaria mas facil de entender/modificar
OJO: no contempla prevencion/correccion de errores y asume que siempre pasaras los argumentos en las mismas dimensiones (filas)
ademas, tambien se asume que siempre habra (cuando menos) CUATRO importes/tasas (solo por facilidad de programacion)

Function VFTV(Importes As Range, Tasas As Range) As Double
Dim n As Integer, Fijo As Double, Parcial As Double
Fijo = Application.Sum(Importes.Resize(2))
For n = Importes.Rows.Count To 4 Step -1
Parcial = (Parcial + Importes(n)) * (1 + Tasas(n))
Next
Parcial = (Parcial + Importes(3)) * (1 + Tasas(3)) * (1 + Tasas(2)) * (1 + Tasas(1))
VFTV = Fijo + Parcial
End Function

el nombre (VFTV = ValorFuturoTasaVariable) es "alusivo/acronimo" de su similar en el complemento "herramientas para analialis": VF.PLAN
Respuesta Responder a este mensaje
#33 Alexander Chacin
08/07/2009 - 00:25 | Informe spam
Buenas tardes

Utilizo el "Preserve" para consevar la data que ha sido leida en la
iteración anterior, si lo eliminas solo vas a tener la última lectura

Saludos
Alexander Chacin


"j_lete" escribió en el mensaje de
noticias news:
Hola Alexander:

He estado viendo tu función y el resultado obtenido coincide con lo que
hacía la mía.
Con la ayuda del excel al final entiendo como funciona. Tengo dudas con
usar
Redim con Preserve (parece que no es obligatorio) y solo Redim.
Muchas gracias por tu ayuda.
Saludos

"Alexander Chacin" escribió:

Creo que una manera pudiera ser esta

Public Function ActualizaImp2(Cantidades As Variant, Optional Porcentajes
As
Variant) As Double

Dim Cant() As Double
Dim Porc() As Double
Dim Factores() As Double
Dim I As Integer
Dim J As Integer
Dim Numero As Integer
Dim Valor As Variant
Dim Temp As Double
Dim Suma As Double

Numero = Cantidades.Count - 1

I = 0
For Each Valor In Cantidades

ReDim Preserve Cant(I)
Cant(I) = CDbl(Valor)
I = I + 1
Next Valor

If Not IsMissing(Porcentajes) Then
I = 0
For Each Valor In Porcentajes
ReDim Preserve Porc(I)
Porc(I) = CDbl(Valor)
I = I + 1
Next Valor

Else
ReDim Porc(I - 1)

If Numero <> 7 Then Suma = 1 / 0

Porc(0) = 0.016
Porc(1) = 0.027
Porc(2) = 0.022
Porc(3) = 0.017
Porc(4) = 0.012
Porc(5) = 0.012
Porc(6) = 0.014
Porc(7) = 0.021

End If
ReDim Factores(2 To Numero)

Temp = 0
Suma = 0
For I = 2 To Numero
Temp = Cant(I)
For J = 0 To I

Temp = Temp * (1 + Porc(J))

Next J
Suma = Suma + Temp
Next I

ActualizaImp2 = Suma + Cant(1) + Cant(0)

End Function


Esta forma te permite manejar cantidades diferentes de ocho, por si lo
necesitas

Si no introduces porcentajes, los valores que indicas son tomados por
defecto

Espero que esto te ayude

Saludos
Alexander Chacin


"j_lete" escribió en el mensaje de
noticias news:
> Hola grupo, tengo la siguente funcion que utilizo para actualizar
> cantidades
> a disttintos tipos de interes de forma acumulada.
> Las cantidades son datos que tengo e una hoja de calculo y se las paso
> a
> la
> funcion.
> Me gustaria saber como poder hacer esta funcion utilizando arrays, es
> decir,
> un aray para los importes y otro para los porcentajes.
>
> Gracias anticipadas por la ayuda que me puedan prestar.
>
> Function ActualizaImp (imp1, imp2, imp3, imp4, imp5, imp6, imp7, imp8
> As
> Double) As Double
>
> Dim A As Double, B As Double, C As Double, D As Double, E As Double, F
> As
> Double, G As Double
> Dim H As Double
>
> PORC1 = 0.016
> PORC2 = 0.027
> PORC3 = 0.022
> PORC4 = 0.017
> PORC5 = 0.012
> PORC6 = 0.012
> PORC7 = 0.014
> PORC8 = 0.021
>
> A = ((((((((imp8 * (1 + PORC8)) * (1 + PORC7)) * (1 + PORC6)) * (1 +
> PORC5))
> * (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
> B = (((((((imp7 * (1 + PORC7)) * (1 + PORC6)) * (1 + PORC5)) * (1 +
> PORC4))
> * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
> C = ((((((imp6 * (1 + PORC6)) * (1 + PORC5)) * (1 + PORC4)) * (1 +
> PORC3))
> *
> (1 + PORC2)) * (1 + PORC1))
> D = (((((imp5 * (1 + PORC5)) * (1 + PORC4)) * (1 + PORC3)) * (1 +
> PORC2))
> *
> (1 + PORC1))
> E = ((((imp4 * (1 + PORC4)) * (1 + PORC3)) * (1 + PORC2)) * (1 +
> PORC1))
> F = (((imp3 * (1 + PORC3)) * (1 + PORC2)) * (1 + PORC1))
> G = (imp2) * 1
> H = (imp1) * 1
>
> ActualizaImp = A + B + C + D + E + F + G + H
> End Function
>


Respuesta Responder a este mensaje
#34 j_lete
08/07/2009 - 19:30 | Informe spam
Hola de nuevo.
No he leido estas intervienciones KL, Hector y tú hasta ahora. Me puedes
confirmar que mi código está mal?
"Alexander Chacin" escribió:

Buenas tardes KL

Lo que haces mal es pensar, apunta antes de disparar

Como comprenderás la función no adivina, si le introdeces una data, la
considera válida y obtiene un resultado. Como entenderás, si cambias lo
valores, el resultado en general cambiará tambien. Invertir el orden de la
matriz de datos, es una manera de cambiar esos valores

Les recomiendo a los dos, nuevamente que comparen la función original con mi
propuesta, hay un detalle bien curioso que extrañamente se les ha escapado a
ambos y es que si usan lo misma data ( del 1 al 8 y del 8 al 1) tanto en mi
propuesta (ActualizaImp2) como en la funcíón original (ActualizaImp) se
obtienen los mismos resultados en las dos funciones

Imagino Héctor que conociendo esta información, le escribirás a j_lete y le
dirás que su código está mal porque al invertir los valores el resultado
cambia. En todo momento traté de simplificar la función original pero
obviamente sin alterar los resultados que dicha función genera y en ese
sentido "ActualizaImp2" arroja los mismos resultados que "ActualizaImp" para
la misma data de entrada, que creo estaba implícito en la solicitud de
j_lete

Agradezco a KL el proporcionar un ejemplo objetivo que puede ser discutido,
en lugar de vagas sospechas. Espero aclarar el punto, de no ser así, espero
nuevos ejemplos objetivos que muestren los errores, que seguramente, podrá
tener mi propuesta

Saludos
Alexander Chacin



"KL" escribió en el mensaje de noticias
news:
> Hola chicos,
>
> Me vais a perdonar, pero...
>
> Introduzco valores de 1 a 8 en A1:A8 y =ActualizaImp2(A1:A8) me devuelve
> 39.7720491242448
> Introduzco valores de 8 a 1 en B1:B8 y =ActualizaImp2(B1:B8) me devuelve
> 37.9455311958239
>
> Que es lo que hago mal? :-))))
>
> Saludos,
> KL


Respuesta Responder a este mensaje
#35 j_lete
08/07/2009 - 20:10 | Informe spam
Buenas tardes:
Disculpad, pero no he leido vuestras últimas aportaciones hasta hoy.
Respecto a lo que comentais, en efecto, los importes se introducen mediante
un rango como indique a Hector al contestar sus repreguntas. Hasta ahora, si
tengo que introducir otro valor mas actual, lo hago insertando una nueva
columna a la izquierda del valor, hasta ahora mas actual y modificando el
rango que paso a la función. Segín veo no es lo más correcto Respecto a los
tipos de interés, estaban en la propia función y para probar el codigo que
propuso Alexander, le paso a su función los tipos contenidos en otra hoja de
calculo dentro del mismo libro en columnas y en orden descendente, p. ej.
a2:h2 siendo a2 el % aplicado el ultimo año y h2 el aplicado 8 años atrás.
Como comenta Alexander, los resultados coinciden con los de mi función.
Cuando formulé mi pregunta y referirme a "arrays", debí decir matrices, pero
la verdad es que no tengo muchos conocimientos de programación. Tampoco debí
decir "Me gustaria saber como poder hacer esta funcion ", ya que estoy dando
por sentado que es correcta y puede que no lo sea, además de obligaros a
imaginar lo que necesito y a predeterminar vuestras respuestas. Por supuesto,
siempre es de agradecer nuevos enfoques o soluciones a los problemas que los
que no somos programadores o usuarios avanzados planteamos.

"Héctor Miguel" escribió:

hola, Alexander !

> Ya creo entender tu punto, lo interesante de todas tus observaciones es que hasta ahora j_lete no las ha mencionado ...

=> esta parte (creo) le corresponde a OP continuar en la conversacion, aportar nuevos detalles, o darla por "aceptable" (???)

> si lees nuevante la consulta de j_lete, encontrarás lo siguiente
> "Me gustaria saber como poder hacer esta funcion utilizando arrays, es decir, un aray para los importes y otro para los porcentajes"
> dado que los importes son datos de entrada, podria entenderse que se desea introducirlos a partir de un rango
> no es seguro, pero fue mi propuesta y un rango lleva implícito un orden establecido por el usuario...

=> (segun yo ?) le sigue correspondiendo a OP proporcionar cualquier detalle que considere conveniente a sus intereses
por lo que respecta a los "arrays" (y hasta donde se), los hay de varios tipos (rangos, matrices constantes, matrices en vba, etc.)
en principio, los rangos son las "arrays" mas socorridas/esperadas/... cuando hablamos de funciones personalizadas (en excel)
aunque no hay que dejar de considerar la posibilidad de que los rangos se provean en columnas y/o en filas (cosa aparte tambien)

> Tal vez ante mi postura tan radical, tu podrias hacer gala de otra mas flexible y tal vez de esta manera educarme con el ejemplo

=> no es "gala" ni tampoco trato de "educar" (a nadie), simplemente trato de aportar lo que en la experiencia considero apropiado (?)

hice una propuesta (que considere) mas facil de modificar/adaptar/... para quien se inicia en codigos y vba (la transcribo):

== segundo mensaje de respuesta a OP => si prefieres el uso de una funcion personalizada, (creo que) la siguiente "forma" te resultaria mas facil de entender/modificar
OJO: no contempla prevencion/correccion de errores y asume que siempre pasaras los argumentos en las mismas dimensiones (filas)
ademas, tambien se asume que siempre habra (cuando menos) CUATRO importes/tasas (solo por facilidad de programacion)

Function VFTV(Importes As Range, Tasas As Range) As Double
Dim n As Integer, Fijo As Double, Parcial As Double
Fijo = Application.Sum(Importes.Resize(2))
For n = Importes.Rows.Count To 4 Step -1
Parcial = (Parcial + Importes(n)) * (1 + Tasas(n))
Next
Parcial = (Parcial + Importes(3)) * (1 + Tasas(3)) * (1 + Tasas(2)) * (1 + Tasas(1))
VFTV = Fijo + Parcial
End Function

el nombre (VFTV = ValorFuturoTasaVariable) es "alusivo/acronimo" de su similar en el complemento "herramientas para analialis": VF.PLAN
== =>
si el usuario tiene la costumbre de que el dato "mas actual/reciente/..." lo ponga al final del rango (NO en A1 si no en A8 p.e.)
esta propuesta de funcion deberia modificarse +/- a lo siguiente:

Function VFTV(Importes As Range, Tasas As Range) As Double
Dim n As Integer, Fijo As Double, Parcial As Double
Fijo = Application.Sum(Importes.Offset(Importes.Rows.Count - 2).Resize(2))
For n = 1 To Importes.Rows.Count - 3
Parcial = (Parcial + Importes(n)) * (1 + Tasas(n))
Next
With Importes.Rows
Parcial = (Parcial + Importes(.Count - 2)) * (1 + Tasas(.Count - 2)) _
* (1 + Tasas(.Count - 1)) * (1 + Tasas(.Count))
End With
End Function

otra alternativa podria ser "ofrecer" al usuario de opcion de indicar si el ultimo dato es el primero o el ultimo en el rango (?)
solo habria que proveer un argumento adicional (opcional y predeterminado de preferencia) y la funcion "crece" +/- a lo siguiente:

Function VFTV(Importes As Range, Tasas As Range, Optional Inv As Boolean = False) As Double
Dim n As Integer, Fijo As Double, Parcial As Double
If Inv Then GoTo DeAbajoHaciaArriba
Fijo = Application.Sum(Importes.Resize(2))
For n = Importes.Rows.Count To 4 Step -1
Parcial = (Parcial + Importes(n)) * (1 + Tasas(n))
Next
Parcial = (Parcial + Importes(3)) * (1 + Tasas(3)) * (1 + Tasas(2)) * (1 + Tasas(1))
GoTo Fin
DeAbajoHaciaArriba:
Fijo = Application.Sum(Importes.Offset(Importes.Rows.Count - 2).Resize(2))
For n = 1 To Importes.Rows.Count - 3
Parcial = (Parcial + Importes(n)) * (1 + Tasas(n))
Next
With Importes.Rows
Parcial = (Parcial + Importes(.Count - 2)) * (1 + Tasas(.Count - 2)) _
* (1 + Tasas(.Count - 1)) * (1 + Tasas(.Count))
End With
Fin:
VFTV = Fijo + Parcial
End Function

sobra mencionar que "formas/usos/estilos/costumbres/necesidades/..." de programar... hay mas que suficientes (dependiendo de... ???)
razones por las que considero que todo es modificable/acaptable/mejorable/... (segun... ???)

saludos,
hector.



email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida