Este ejemplo implementa una función FPScript definida por el usuario que se puede utilizar como una función incorporada en fórmulas FPScript después del registro en FlexPro. Se admite en la ventana del asistente del Editor FPScript y está disponible automáticamente en todas las bases de datos cargadas.
Notas
El ejemplo muestra la implementación de dicha función en VBA. El código fuente VBA completo del ejemplo se encuentra en la base de datos del proyecto CustomFunction.fpd. No obstante, también puede utilizar cualquier otro lenguaje de programación compatible con Automatización, por ejemplo C# o C++. Una variante del ejemplo, realizada como complemento en C++, también se incluye con FlexPro. El nombre de la ruta de acceso de la base de datos del proyecto es normalmente C:\Users\Public\Documents\Weisang\FlexPro\2025\Examples\VBA\Custom Function\CustomFunction.fpd bzw. C:>Usuario>Público>Documentos públicos>Weisang>FlexPro>2025>Examples>VBA>Custom Function>CustomFunction.fpd.
También puedes implementar una función FPScript definida por el usuario en FPScript. Consulte el tutorial Funciones FPScript personalizadas.
Fondo
El ejemplo define una función con tres argumentos que calcula los dos primeros en función del tercer argumento. Su estructura es, por tanto, similar a la de muchas funciones incorporadas. El ejemplo cubre los elementos esenciales a la hora de implementar una función FPScript definida por el usuario:
•Definición de los argumentos
•Restricción del tipo y la estructura de los argumentos
•Uso de argumentos por defecto
•Alta y baja de la función
•Acceso a los argumentos tras la llamada a la función
•Definición de constantes FPScript personalizadas
Registro de una función definida por el usuario
Antes de registrar la función, hay que definir sus argumentos y otras propiedades. El propio registro representa entonces la conclusión de la definición de la función.
En primer lugar, la función se añade a la lista CustomFPScriptFunctions. A continuación, debe asignarse una descripción. Esto se muestra automáticamente cuando se utiliza la ventana del asistente, por ejemplo.
Con CustomFPScriptFunctions.Add("MyFunction")
.Description = "Adds or subtracts two values"
.Indeterministic = False
…
End With
La propiedad Indeterministic determina si la función devuelve siempre el mismo resultado para la misma entrada. Si Indeterministic se establece en True, las fórmulas que utilizan esta función deben calcularse en cada ciclo de actualización. Por este motivo, este valor solo debe establecerse en True si es absolutamente necesario, posiblemente en caso de que cambien las dependencias externas.
Una vez añadida la función a la lista CustomFPScriptFunctions, se pueden añadir los argumentos necesarios. Solo se requiere el nombre del argumento, todos los demás parámetros son opcionales. Sin embargo, es aconsejable introducir una descripción para que pueda aparecer una nota sobre el argumento en la ventana del asistente. Además, por regla general, los tipos y estructuras de datos del argumento deben limitarse exactamente a lo necesario. Este procedimiento tiene la ventaja de que la comprobación del cumplimiento de las restricciones de tipo y estructura de datos ya se realiza en FlexPro antes de llamar a la rutina de cálculo de la función FPScript definida por el usuario. De esta manera, el código requerido para implementar la función puede ser reducido y la salida de mensajes de error para esto es manejada por FlexPro.
With .Parameters.Add("Arg1")
.Description = "First argument"
.AllowedTypes = fpParameterTypeNumeric
.AllowedStructures = fpParameterStructureScalar Or _
fpParameterStructureDataSeries Or fpParameterStructureSignal
End With
En este caso, el primer argumento está restringido a tipos de datos numéricos y se permiten valores escalares, series de datos y señales como estructuras de datos. Los tipos de datos y las estructuras de datos pueden vincularse mediante OR durante la asignación, como se muestra. Si el argumento se desvía de las restricciones dadas al utilizar la función, se muestra un mensaje de error.
Se utiliza un valor por defecto para el último argumento de la función. Esto significa que el argumento puede omitirse. En este caso, se utiliza internamente el valor por defecto de este argumento.
With .Parameters.Add("Operation")
.Description = "Type of operation"
.AllowedTypes = fpParameterTypeNumeric
.AllowedStructures = fpParameterStructureScalar
.DefaultValue = "MYFUNC_OPERATION_ADD"
End With
El presente caso es especial. El tipo del parámetro de operaciónes numérico, pero se especifica un texto como valor por defecto. El texto contiene el nombre de una constante FPScript definida por el usuario introducida previamente, cuyo valor se determina automáticamente como valor por defecto en este caso. La ventaja de este tipo de definición es que el nombre más comprensible de la constante se muestra en la ventana del asistente.
Las constantes FPScript definidas por el usuario pueden introducirse de la siguiente manera:
With CustomFPScriptConstants
.Add "MYFUNC_OPERATION_ADD", "Selects the add operation", 1
.Add "MYFUNC_OPERATION_MIN", "Selects the subtract operation", 2
End With
Simplemente se añade un nuevo elemento a la lista CustomFPScriptConstantsespecificando un nombre, una descripción y un valor escalar. Las colisiones de nombres con constantes existentes incorporadas o definidas por el usuario provocan el correspondiente mensaje de error.
Una vez declarados los parámetros de la función, ésta puede registrarse para su uso. Para ello se llama al método de Registro. Como argumento, recibe una referencia a un objeto que implementa la interfaz ICustomFunctionCalculate.
.Register oMyFunction
La interfaz ICustomFunctionCalculate contiene el método Calculateque es llamado por FlexPro cuando calcula una fórmula que utiliza MyFunction, siempre y cuando se cumplan las restricciones de los parámetros.
Notas
Solo se comprueba la coherencia de los parámetros definidos cuando se registra una función. Si se produce un error, debe comprobarse el código que define los parámetros.
Normalmente, las funciones FPScript definidas por el usuario se utilizan en una función de ejecución automática como AutoOpen o AutoExec para que estén disponibles en un momento definido y temprano.
Registrar una función se opone a anular su registro, lo que suele hacerse en AutoAbrir o AutoCerrar:
Sub AutoClose()
' unregister function
CustomFPScriptFunctions.Item("MyFunction").Delete
' unregister constants
With CustomFPScriptConstants
.Item("MYFUNC_OPERATION_ADD").Delete
.Item("MYFUNC_OPERATION_SUB").Delete
End With
End Sub
Cuando la función se elimina de la lista CustomFPScriptFunctions, se da de baja automáticamente. Las constantes se anulan del mismo modo.
Nota No es absolutamente necesario dar de baja los elementos FPScript definidos por el usuario, ya que éstos se eliminan automáticamente cuando finaliza el programa. Sin embargo, como se proporciona una referencia de objeto cuando se registra una función, se puede utilizar la baja explícita para controlar el abandono del objeto que ejecuta el cálculo de la función. De este modo, pueden evitarse los desagradables efectos secundarios (cuelgues FlexPro).
Utilizar una función definida por el usuario
Cuando se llama a la función FPScript registrada MyFunction, se llama al método Calculatede la interfaz ICustomFunctionCalculate. Los argumentos se transfieren en forma de campo Variante. El ejemplo de implementación muestra un ejemplo de cómo se accede a los argumentos. Debido a la posible variedad de estructuras y tipos de datos, el ejemplo se ha simplificado en algunos puntos.
El campo con los argumentos SafeArrayOfArguments está basado en uno, como es habitual en VBA. Por lo tanto, se accede a la operación deseada utilizando el índice tres:
' MYFUNC_OPERATION_ADD = 1
' MYFUNC_OPERATION_SUB = 2
nOperation = SafeArrayOfArguments(3)
El tercer argumento estaba restringido a valores escalares de tipo numérico. Sin embargo, todavía se puede especificar un valor no válido para la operación que se va a realizar. Por lo tanto, se lleva a cabo una auditoría:
' check operation
If nOperation <> 1 And nOperation <> 2 Then
' will be propagated as error 0x800a0002 to FlexPro
Err.Raise 2, "ICustomFunctionCalculate_Calculate"_
, "Invalid operation value"
End If
En caso de error, se activa una excepción. Aparecerá el mensaje "Invalid operation value", junto con el código de error mencionado, en la pantalla de eventos de FlexPro o en un cuadro de diálogo de mensajes.
La parte restante del cálculo de la función muestra cómo utilizar las funciones de VB IsObject, TypeOf e IsArray para hacer distinciones de caso basadas en el primer argumento y luego ejecutar la operación deseada.
Notas sobre el desarrollo en VBA
•Si el método de cálculode una función se modifica después de haberla registrado, la función debe darse de baja y volver a registrarse. Esto es necesario porque, de lo contrario, el punto de entrada de la función deja de ser válido y se muestra un mensaje de error.
•Al menos cuando se prueba un método Calcular, la opción Actualizar objetos en segundo plano debería estar desactivada en Archivo > Opciones en la pestaña Configuración del sistema. De lo contrario, FlexPro puede bloquearse si se utilizan puntos de interrupción en el método Calcular. La razón es que se producen problemas en el entorno VBA cuando se llama al método Calcularen un hilo de programa en segundo plano.
•Para las funciones FPScript definidas por el usuario en VBA, el sistema de tiempo de ejecución garantiza que solo se produzca una ejecución del método Calcularen un momento dado. Esta restricción se aplica por motivos de seguridad. Por un lado, el entorno de ejecución de VBA no admite realmente la ejecución en paralelo, por otro, la posible restricción necesaria a una instancia de ejecución en el propio VBA no es posible con los medios del lenguaje por sí solo.