Funciones personalizadas

From Apache OpenOffice Wiki
< ES‎ | Manuales‎ | GuiaAOO‎ | TemasAvanzados‎ | Macros‎ | StarBasic‎ | TrabajandoConCalc
Revision as of 18:01, 28 March 2013 by Salva (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


Editing.png Esta página está en estado borrador.

La posibilidad de implementar nuestras propias funciones es una de las características más ricas de una hoja de calculo.

Para todo este capitulo asumimos que no tienes problemas con la implementación de formulas y funciones en Calc, es muy útil, que tengas muy claro, que las funciones siempre devuelven un valor, aún y cuando éste sea un error, que estas pueden o no necesitar argumentos, que los argumentos son de un tipo y el valor devuelto puede ser de otro.

Por ejemplo, supongamos las triviales formulas para obtener el diámetro, el perímetro y el área de un circulo


ES StarBasic FuncionesPersonalizadas.04.png





Donde:

  • r = radio
  • D = Diámetro
  • A = Área
  • P = Perímetro


En Calc, suponiendo que el radio este en la celda A2 las formulas serían.


 Diámetro = A2 * 2
 Perímetro = PI() * A2 * 2
 Área= PI() * POTENCIA(A2;2)


En OOo Basic, estas funciones podrían quedar así:


 Option Explicit
 
 'Función para obtener el diámetro de un circulo
 Function DiametroCirculo( Radio As Single ) As Double 
 
     DiametroCirculo = Radio * 2
 
 End Function
 
 'Función para obtener el perímetro de un circulo
 Function PerimetroCirculo( Radio As Single ) As Double 
 Const PI As Single = 3.1416
 
     PerimetroCirculo = Radio * 2 * PI
 
 End Function
 
 'Función para obtener el área de un circulo
 Function AreaCirculo( Radio As Single ) As Double 
 Const PI As Single = 3.1416
 
     AreaCirculo = PI * Radio ^ 2
 
 End Function


Estas funciones, se usan exactamente igual que cualquier otra función de Calc, es decir, escribiendo su nombre correctamente y pasándole los argumentos correctos. Observa la siguiente imagen, donde estamos calculando estos valores, por los dos métodos, con formulas y funciones incorporadas de Calc, y con nuestras funciones personalizadas.


La forma como establecemos los argumentos y el valor devuelto de la función, no te son desconocidos, los hemos venido usando a lo largo de los temas vistos, la diferencia, es que, ahora, solo “llamábamos” a las funciones desde otras macros, ahora, las estamos usando desde la hoja de calculo.


Pero las funciones personalizadas son mucho más versátiles, nota como en las tres formulas, usamos el mismo argumento, solo el radio, podemos crear nuestra función para que nos devuelva el valor deseado de los tres, simplemente pasándole un segundo argumento para indicarlo.


 'Función para devolver un dato de un círculo
 'QueDato puede tener los valores
 ' 1 = Diámetro
 ' 2 = Perímetro
 ' 3 = Área
 Function Circulo( Radio As Single, QueDato As Byte ) As Double
 Const PI As Single = 3.141592
 Dim dTmp As Double
 
     Select Case QueDato
         Case 1
             dTmp = Radio * 2
         Case 2
             dTmp = Radio * 2 * PI
         Case 3
             dTmp = PI * Radio ^ 2
     End Select
 
     Circulo = dTmp
 
 End Function


Cuando le pasas un argumento a una función desde una hoja de calculo (generalmente una referencia a una o varias celdas), lo que realmente toma la función es el valor de estas celdas. Las funciones personalizadas, tienen las mismas consideraciones presentes en las funciones incorporadas de Calc, principalmente, las relacionadas con el correcto paso de argumentos y el tipo de valor devuelto.

Nuestro siguiente ejemplo también es muy simple, vamos a obtener el área de un triángulo, cuya formula es.


ES StarBasic FuncionesPersonalizadas.02.png



Donde:


  • b = Base
  • h = Altura
  • A = Área


Nuestra función para calcular el área, quedaría así.


 'Función para calcular el área de un triángulo
 Function AreaTriangulo( B As Single, H As Single ) As Double
 
     AreaTriangulo = (B * H) / 2
 
 End Function


El asunto cambia bastante cuando lo que conocemos son la longitud de los lados del triángulo, para estos casos, usamos la famosa formula de Herón.



Donde:


  • a, b y c = son los lados del triángulo
  • S= Semiperímetro, es decir, el perímetro entre dos
  • A= Área


Como función.


 'Función para calcular el área de un triángulo
 'con la formula de Herón
 Function AreaTrianguloHeron( a As Single, b As Single, c As Single ) As Double
 Dim S As Double
 
     S = ( a + b + c ) / 2
     AreaTrianguloHeron = Sqr( S*(S-a)*(S-b)*(S-c) )
 
 End Function


Por supuesto, no solo puedes manejar números como argumentos, en el siguiente ejemplo, usamos una fecha como argumento, el planteamiento es el siguiente; se contrato un servicio anual, queremos mostrar en otra celda, el número de días que faltan para renovar el servicio, no importa el número de años que lleva contratado, solo queremos saber cuantos días faltan para la próxima renovación, una primera aproximación sería.


  • Celda A2 = Fecha de contratación
  • Celda B2 = Días que faltan para renovar


La formula de la columna B es:


=FECHA(SI(FECHA(AÑO(HOY());MES(A2);DÍA(A2))>HOY();AÑO(HOY());AÑO(HOY())+1);MES(A2);DÍA(A2))-HOY()


Esta formula ya es un poco más compleja, nos pide un poco más de esfuerzo para comprenderla, pero es un buen ejemplo de lo que hay que hacer cuando queremos hacer una función personalizada, es decir, tenemos que tener muy claro que es lo que queremos obtener y que datos de origen tenemos, en este caso, solo tenemos una fecha, la fecha de contratación del servicio, ¿que es lo que haces para saber cuantos días faltan para la renovación?, cuidado, no es una pregunta ligera, recuerda que el trabajo de programador, es resolver problemas, y los problemas, entre más sencillos, son más fáciles de resolver, así que, tomate con calma la respuesta de la pregunta. En la solución de la función comentamos paso a paso la respuesta.


 'Función para saber cuantos días faltan para renovar
 Function DiasParaRenovar( FechaInicial As Date ) As Integer
 Dim FechaActual As Date
 Dim iDiferencia As Integer
 
     'Lo primero que necesitamos es tener la misma fecha inicial
     'mismo día y mes, pero con el año actual, observa como obtenemos
     'el año actual, la función Now, devuelve la fecha actual, con Year obtenemos el año
     FechaActual = DateSerial( Year(Now()), Month(FechaInicial), Day(FechaInicial) )
 
     'El siguiente paso, es saber si esta fecha actual, es mayor o menor al día de hoy
     If FechaActual < Now() Then
         'Si es menor, significa que la renovación ya paso, por lo que se tiene
         'que aumentar un año a la fecha actual para obtener la correcta de renovación
         FechaActual = DateSerial( Year(Now())+1, Month(FechaInicial), Day(FechaInicial) )
     End If
 
     'Restamos la fecha futura con el día de hoy, para saber cuantos días faltan
     'Usamos Fix para eliminar las horas y evitar el redondeo
     iDiferencia = FechaActual - Fix(Now())
     'Asignamos el resultado
     DiasParaRenovar = iDiferencia
 
 End Function


Comparando, aquí es bastante notable la comodidad de una función personalizada:


=FECHA(SI(FECHA(AÑO(HOY());MES(A2);DÍA(A2))>HOY();AÑO(HOY());AÑO(HOY())+1);MES(A2);DÍA(A2))-HOY()


=DIASPARARENOVAR(A2)


En nuestro siguiente ejemplo, tenemos como argumentos números y regresamos un texto, la tarea es mostrar el valor de un ángulo, configurado correctamente, por ejemplo: 125º 45' 35, lo que logramos con la siguiente función.


 'Función para dar formato a valores sexagesimales
 Function AnguloFormateado( Gra As Integer, Min As Byte, Seg As Byte ) As String
 Dim sTmp As String
 
     sTmp = Str(Gra) & "º " & Str(Min) & "' " & Str(Seg) & "''"
     AnguloFormateado = sTmp
 
 End Function


Observa como estamos regresando una cadena (String). Tu tarea es hacer la operación inversa, a partir de la cadena, regresar cualquiera de los tres valores, grados, minutos o segundos, según el argumento pasado, te pongo el esqueleto de la función y tú la desarrollas.


 'Función para devolver un valor de una ángulo 
 'El argumento QueValor, puede tomar los valores
 ' 1 = Devuelve los grados
 ' 2 = Devuelve los minutos
 ' 3 = Devuelve los segundos
 Function DatoAngulo( Angulo As String, QueValor As Byte ) As Integer
 
     'Esta es tú tarea
 
 End Function


Otro ejemplo donde tenemos como argumento un número (Byte) y regresamos una cadena (String), es el siguiente.


 'Función para convertir un número en texto
 Function NumeroTexto( Num As Byte ) As String
 Dim sTmp As String
 
     Select Case Num
         Case 0 : sTmp = "Cero" 
         Case 1 : sTmp = "Uno" 
         Case 2 : sTmp = "Dos" 
         Case 3 : sTmp = "Tres" 
         Case 4 : sTmp = "Cuatro" 
         Case 5 : sTmp = "Cinco" 
         Case 6 : sTmp = "Seis" 
         Case 7 : sTmp = "Siete" 
         Case 8 : sTmp = "Ocho" 
         Case 9 : sTmp = "Nueve" 
     End Select
     NumeroTexto = sTmp
 
 End Function


¿Y para que crees que sirve eso?..., exactamente, para hacer la famosa función que convierte números a letras, sumamente útil y muy usada en áreas administrativas, te invito a que intentes desarrollarla, dada la extensión de la misma, no la incluimos aquí, pero si en los archivos de ejemplo que acompañan a este libro.


Hasta ahora, todos los argumentos que le hemos pasado a nuestras funciones, han sido celdas individuales, pero también puedes pasarle rangos de celdas, donde, lo único que tienes que tener en cuenta, es que los valores de este rango, los tomará como una matriz de dos dimensiones, nuestra versión de la función SUMA, es la siguiente.


 'Función para sumar los valores de un rango
 Function SumarRango( Rango ) As Double 
 Dim dTmp As Double
 Dim co1 As Long, co2 As Long
 
     'Iteramos en la primer dimensión de la matriz
     For co1 = LBound( Rango,1 ) To UBound( Rango,1 )
         'Iteramos en la segunda dimensión de la matriz
         For co2 = LBound( Rango,2 ) To UBound( Rango,2 )
             'Vamos sumando los valores
             dTmp = dTmp + Rango( co1, co2 )
         Next co2
     Next co1
     'Asignamos el resultado
     SumarRango = dTmp
 
 End Function


Observa como no establecemos el tipo del argumento Rango, esto es por que, al ser una matriz, esta, forzosamente tiene que ser tipo variante (Variant). Veamos un ejemplo practico donde pasamos como argumento un rango de celdas. En topografía, se puede calcular el área de un terreno o de cualquier poligonal cerrada cualquiera, donde se cuenta con sus coordenadas, por varios métodos, uno de ellos se llama por “Productos Cruzados”, cuyo algoritmo, espero sea bastante claro en la siguiente imagen.


ES StarBasic FuncionesPersonalizadas.01.png


En la celda D214, tenemos el calculo del área, pero usando todo el desarrollo del método, en la celda D216 (en rojo), tenemos el mismo resultado, pero usando la función mostrada en la celda D218, cuyo código es el siguiente.


 'Función para obtener el área de un polígono irregular
 'por medio de coordenadas y el método de productos cruzados
 Function AreaPoligono( Rango ) As Double 
 Dim Suma1 As Double
 Dim Suma2 As Double
 Dim co1 As Long
 
     'Calculamos las suma de los productos cruzados
     For co1 = LBound( Rango,1 ) To UBound( Rango,1 ) - 1
         Suma1 = Suma1 + Rango(co1,1) * Rango(co1+1,2)
         Suma2 = Suma2 + Rango(co1+1,1) * Rango(co1,2)
     Next co1
     'Asignamos el resultado
     AreaPoligono = Abs(Suma1 - Suma2) / 2
 
 End Function


Muy importante, observa que para acceder a la segunda dimensión de la matriz, estamos empezando en 1, no se cual sea la razón de que al acceder a los valores de un rango de celdas por medio de una función, el limite inferior sea siempre 1 (por ahora), es la única excepción que me he encontrado con el uso de matrices, recuérdalo.


ES.Plantillas.Logo foro es.png
Si tienes dudas acerca de lo aquí explicado, tienes algún problema con AOO,
o quieres ampliar la información, no dudes en dirigirte al

Foro Oficial en español de Apache OpenOffice para Macros y API UNO

Personal tools