curso de x++

Upload: xarbmos5

Post on 06-Jul-2015

1.074 views

Category:

Documents


2 download

TRANSCRIPT

ndice

CURSO DE X++

ndice

ndiceCURSO DE X++ INTRODUCCIN MTODOS CONTENEDORES Y SUS FUNCIONES SENTENCIAS BSICAS DEL LENGUAJE X++ INSTRUCCIONES DE ACCESO A REGISTROS JOBS ESTNDARES PARA LOS MTODOS DE LAS TABLAS MTODOS DISPLAY Y EDIT MTODOS BSICOS EN TABLAS CONTROL DE TRANSACCIONES HERRAMIENTAS DE DESARROLLO PROGRAMACIN DE FORMULARIOS PASO DE PARMETROS ENTRE OBJETOS: LA CLASE ARGS PROGRAMACIN DE INFORMES PLANTILLAS DE INFORMES CLASES DESARROLLO CLIENTE / SERVIDOR 1 4 8 17 19 27 37 38 41 44 51 54 61 79 82 94 95 107

ndice

OTRAS HERRAMIENTAS DE DESARROLLO COMUNICACIN CON EL USUARIO LA CLASE RUNBASE MAPS ACCESO A CLAVES DE FUNCIN DESDE EL CDIGO GESTIN DE EXCEPCIONES ACCESO A MEN ITEMS DESDE EL CDIGO INDICACIN DE OPERACIONES EN EJECUCIN XCLASES PERSONALIZANDO FORMULARIOS LOOKUP DEFINIDO. FUNCIONES GENERALES

109 117 125 131 133 134 137 138 139 ERROR! MARCADOR NO

140

Introduccin

Introduccin1.1.1.

El entorno MorphXDefinicinEl entorno de desarrollo en Navision Axapta se llama MorphX. Podemos considerarlo un entorno integrado de desarrollo (Integrated Development Environment IDE), porque integra muchas funciones diferentes, como diseo, edicin, compilacin y depuracin en un entorno comn. En herramientas de desarrollo ms tradicionales, cada una de estas funciones operara como un programa independiente, cada uno con su propia interfaz. MorphX permite al usuario modificar de un modo sencillo los objetos de la interfaz grfica. Al mismo tiempo que ofrece al usuario avanzado las herramientas necesarias para modificar fcilmente la funcionalidad de la aplicacin o bien crear diseos completamente nuevos. El rbol de objetos de la aplicacin (Application Object Tree AOT) es el elemento central desde el que el programador puede crear nuevos objetos o bien modificar los existentes. El desarrollador puede crear nuevos objetos utilizando la tcnica de arrastre (drag-and-drop) y asignndoles propiedades. Para hacer el trabajo del desarrollador ms fcil y rpido, el sistema tiene valores por defecto para todas las propiedades de los objetos de la aplicacin. Dado que se trata de un sistema de desarrollo orientado a objetos, el concepto de herencia es fundamental. La herencia significa que lo que se ha definido en niveles inferiores del sistema es automticamente heredado en niveles superiores. Un ejemplo claro del concepto de herencia es la posibilidad que tiene el desarrollador de modificar y aumentar la funcionalidad del sistema escribiendo sus propios mtodos. En Navision Axapta, la herencia no se limita nicamente a las clases, sino que se extiende a todo el sistema. De este modo, los objetos heredan no slo variables y mtodos, sino tambin propiedades.

1.2.

Conceptos Importantes en MorphXAlgunos trminos y mecanismos centrales orientados a objetos aparecen repetidamente cuando desarrollamos con MorphX. A continuacin vamos a dar una breve explicacin de los conceptos ms importantes.

1.2.1.

Clase de sistemaUna clase de sistema (system class) es una interfaz de funcionalidad definida en MorphX, por ejemplo para crear o ejecutar un formulario.

1.2.2.

ClaseUna clase (class) define las interfaces de un objeto. Ensea o explica como construir un objeto de un tipo particular.

Pgina 4 de 141

Introduccin

Una caracterstica esencial de una clase es que podemos crear nuevas instancias (objetos) de la clase. Los formularios, informes e incluso las tablas son ejemplos de clases: MorphX tiene una definicin de clase que define qu ocurre exactamente cuando un objeto de cada tipo es creado.

1.2.3.

ControlesUn control es un objeto grfico, como una caja de texto (text box), una casilla de verificacin (check box) o un botn de comando (command button) que podemos situar en un formulario o un informe cuando lo diseamos, para que nos muestre informacin, realice una accin o hacer el formulario o informe ms fcil de leer. Hay aproximadamente 20 controles diferentes y cada uno est definido por alrededor de 50 propiedades.

1.2.4.

Origen de datosUn origen de datos (Data Source) contiene las variables de datos que utilizan un formulario o una consulta. Estas variables de datos pueden ser una o ms tablas, o campos individuales de las tablas.

1.2.5.

DiseosUn nodo de diseos (Designs) proporciona acceso al usuario para definir el aspecto de un formulario o de un informe.

1.2.6.

EncapsulacinLa encapsulacin significa que los datos en el sistema son definidos dentro de los mtodos y solo pueden ser modificados desde los propios mtodos.

1.2.7.

FinalFinal es un modificador de una clase o un objeto que indica que dicha clase o mtodo no puede ser ampliado o sobrecargado.

1.2.8.

HerenciaLa herencia es un concepto fundamental en MorphX. Significa que lo que es definido en niveles inferiores del sistema es automticamente accesible, o lo que es lo mismo, heredado por los niveles superiores.

1.2.9.

ObjetosLos objetos son el concepto central de MorphX. Cualquier formulario y cualquier control es un objeto. La base de datos es tambin un objeto. En definitiva, cualquier cosa presente en el sistema es un objeto. Los objetos son creados a partir de las clases. Decimos por tanto que un objeto es una instancia de una clase.

Pgina 5 de 141

Introduccin

Los objetos proporcionan una forma lgica y conveniente de organizar los datos y los procedimientos. Los objetos estn encapsulados, lo que significa que contienen tanto su cdigo como sus datos. Para utilizar un objeto, debemos mantener una referencia a l mediante una variable del mismo tipo del objeto.

1.2.10. MtodosLos mtodos son tareas que podemos decir a un objeto que realice.

1.2.11. PropiedadLas propiedades son datos que describen un objeto. Cada tipo de objeto tiene diferentes tipos de propiedades. Un mtodo tpicamente tiene unas pocas propiedades, una de las cuales, por ejemplo, define donde queremos que se ejecute. Por otra parte, un control tiene acerca de 50 propiedades que definen el color, el tamao, la posicin, etc.

1.2.12. ConsultaUna consulta es un mecanismo de filtrado para recuperar los datos que nos interesa ver a partir de las tablas de nuestra base de datos. Las consultas son utilizadas normalmente como el origen de datos en los formularios e informes.

2.2.1.

El lenguaje X++IntroduccinEl lenguaje X++ es un lenguaje sencillo y fcil de aprender, para que pueda ser utilizado por la mayora de desarrolladores. Es un lenguaje orientado a objetos, para beneficiarse de las ventajas de las metodologas modernas de desarrollo de software, que se acopla perfectamente en aplicaciones cliente/servidor. Por ltimo, es un lenguaje interpretado, al estilo de Java, para obtener mximas capacidades dinmicas.

2.2.a)

CaractersticasLenguaje simple, orientado a objetos y familiar

Las principales caractersticas de X++ son que se trata de un lenguaje sencillo que puede ser utilizado rpidamente, si se conoce la metodologa de la programacin orientada a objetos. Los conceptos fundamentales de X++ son asimilados rpidamente, por tanto los programadores pueden ser productivos desde el principio. X++ ha sido diseado desde su base para ser orientado a objetos. X++ proporciona una plataforma de desarrollo orientada a objetos limpia y eficiente. El lenguaje X++ utiliza principios de la programacin orientada a objetos como encapsulacin, herencia, clases, objetos, mtodos y propiedades.

Pgina 6 de 141

Introduccin

A pesar de que C++ y Java fueron rechazados como lenguajes para utilizar con MorphX, el aspecto de X++ es muy similar al de estos dos lenguajes, aunque se ha eliminado la complejidad innecesaria de estos lenguajes. Adems, como MorphX es una plataforma para construir complejos sistemas de gestin empresarial y contabilidad, el lenguaje X++ tambin incluye un gran nmero de comandos comunes de SQL como parte integrada del lenguaje. El hecho de que X++ tenga una sintaxis muy similar a lenguajes ya existentes como C++, Java o SQL hace que X++ sea un lenguaje familiar para la mayora de desarrolladores de software. Esto significa que pueden migrar rpidamente a este nuevo lenguaje. b) Lenguaje robusto

El lenguaje X++ ha sido diseado para crear software muy fiable. Proporciona comprobaciones muy amplias en tiempo de compilacin, seguidas de un segundo nivel de comprobaciones en tiempo de ejecucin. Las caractersticas del lenguaje dirigen a los programadores hacia unos hbitos de programacin fiable. El modelo de manejo de la memoria es extremadamente simple: los objetos son creados mediante un operador new. No existe un tipo de datos puntero definido por el programador de forma explcita, lo que implica que no necesitamos aritmtica de punteros ni tenemos la necesidad de realizar limpieza de punteros en memoria, con lo que resulta innecesarias las llamadas al mtodo finalize. Este sencillo modelo de manejo de memoria elimina gran cantidad de errores de programacin muy comunes entre los programadores de C y C++. Podemos desarrollar cdigo en el lenguaje X++ con la seguridad de que el sistema encontrar la mayora de los errores rpidamente y con la tranquilidad de que no tendremos problemas latentes no descubiertos hasta que nuestro cdigo est en circulacin en el mercado. c) Lenguaje de alto rendimiento

El rendimiento es siempre algo a tener en consideracin. El lenguaje X++ consigue un superior rendimiento adoptando un esquema de trabajo en el cual el intrprete puede trabajar a la mxima velocidad sin necesidad de comprobar el entorno en tiempo de ejecucin. El liberador de memoria automtico (automatic garbage collector), se ejecuta automticamente cuando es necesario, asegurando una probabilidad muy alta de que la memoria est disponible cuando se necesite, lo que se traduce en un mejor rendimiento. En general, los usuarios perciben que las aplicaciones interactivas responden ms rpidamente a pesar de que son interpretadas. d) Lenguaje interpretado y dinmico

En una plataforma interpretada como el lenguaje X++, la fase de enlazado de un programa es sencilla, incremental y ligera. De esta forma nos beneficiamos de unos ciclos de desarrollo y prototipado mucho ms rpidos, comparados con los pesados ciclos de compilacin, enlazado y pruebas tradicionales.

Pgina 7 de 141

Mtodos

Mtodos1. IntroduccinTodo objeto puede identificarse por el estado en que se encuentra y por su comportamiento. En programacin, el estado de un objeto se define mediante variables, mientras que su comportamiento est definido por mtodos. Los mtodos actan sobre las variables del objeto haciendo evolucionar su estado. Las variables de un objeto slo son accesibles directamente por mtodos propios del objeto, nunca desde el exterior. En Axapta podemos encontrar mtodos en todos los objetos que componen la aplicacin, es decir, en: Tablas Formularios Informes Consultas Clases

En cada uno de estos objetos, los mtodos se crean del mismo modo que los elementos restantes de la aplicacin, es decir, utilizando el rbol de Objetos de la Aplicacin.

2.

Estructura de los mtodosUn mtodo est formado por una cabecera y un cuerpo. ste, a su vez, est compuesto por la declaracin de variables y otras instrucciones. Seguidamente ilustramos la estructura de los mtodos:

Cabecera

Declaracin de variables Mtodo Cuerpo Declaracin de mtodos

Instrucciones

Pgina 8 de 141

Mtodos

2.1.

CabeceraLa cabecera de un mtodo tiene el siguiente aspecto (entre [] se muestran los valores opcionales):

[Modificador] TipoDatoRetorno NombreMtodo ([ListaParmetros])

Los modificadores y los parmetros se describen en apartados posteriores. El tipo de dato de retorno puede tomar los siguientes valores: Tipo de dato void : este trmino se utiliza cuando el mtodo no devuelve nada. anytype : significa que el mtodo puede devolver todos los tipos de datos (mediante distintas instrucciones de retorno en el cuerpo del mtodo) Siempre que un mtodo devuelva algn valor, se debe especificar el tipo del valor de retorno e incluir una instruccin de retorno (return ...).

2.2.

CuerpoEl cuerpo de un mtodo tendr el siguiente aspecto: { [Declaracin de variables] [Declaracin de mtodos] [;] Instrucciones; }

Aunque no forma parte de la estructura de un mtodo, es recomendable aadir siempre una lnea con un punto y coma (;) antes del grupo de instrucciones. Esto es debido a que en algunas ocasiones, el compilador confunde una instruccin con la declaracin de una variable y devuelve un error de sintaxis en un mtodo cuyas instrucciones son completamente correctas. El nico modo de evitar este error es marcar el inicio del bloque de instrucciones con un punto y coma. Si revisamos algunos de los mtodos de la aplicacin estndar, observaremos que la mayora de ellos utilizan esta tcnica. La declaracin de variables y de mtodos se describe a continuacin. Las instrucciones se irn viendo a lo largo del curso.

Pgina 9 de 141

Mtodos

2.2.1.

Declaracin de variables

Una variable es un puntero a una posicin de memoria donde se almacena informacin de un tipo de datos especfico. Todas las variables deben ser declaradas antes de poder ser usadas. Hay que sealar que X++ no permite que la declaracin de variables se mezcle con otras instrucciones del lenguaje. En otras palabras, el lenguaje X++ requiere que las variables sean declaradas antes de cualquier otra instruccin. La sintaxis de la declaracin es la misma, tanto si es una variable simple o una variable de objeto. Las variables pueden ser declaradas de tres formas en X++: declaracin simple, declaracin con inicializacin y declaracin mltiple. a) Declaracin simple

La declaracin simple de variables es la ms utilizada, ya que es rpida y la mayora de variables son simples. La sintaxis es la siguiente: TipoDato IdentificadorVariable

TipoDato es cualquier tipo de datos del lenguaje X++. IdentificadorVariable es bsicamente un nombre cuyo primer carcter debe ser una letra que puede estar seguida por letras o nmeros. Como letras se consideran los caracteres a..z y el carcter subrayado (_). Para los tipos de datos, si se trata de un objeto de la aplicacin su nombre se escribir mezclando maysculas y minsculas, de manera que el primer carcter sea una mayscula as como la primera letra de cada palabra interna. Si se trata de un tipo de datos primitivo se escribir en minsculas. El nombre de una variable mezclar maysculas y minsculas, siendo la primera letra en minscula y el primer carcter de cada palabra interna en maysculas. A continuacin se muestran algunos ejemplos de declaracin de variables: int i; CustInvoiceJour custInvoiceJour;

La declaracin de variables de la mayora de tipos de datos de X++, exceptuando los objetos, tambin reserva un espacio de memoria para dichas variables. Cuando una variable es declarada adems se inicializa con un valor por defecto. b) Declaracin con inicializacin

En ocasiones nos interesa que una determinada variable tenga un valor distinto al valor por defecto, en el mismo instante en que la variable se crea. El lenguaje X++ permite la inicializacin de variables en la sentencia de declaracin. La inicializacin se lleva a cabo aadiendo una sentencia de asignacin a la declaracin de la variable.

Pgina 10 de 141

Mtodos

Un ejemplo de este tipo de declaracin sera el ejemplo siguiente, donde una variable real de nombre pi, es declarada e inicializada al valor del nmero Pi: real pi = 3.14159265359; Existe otra sintaxis para inicializar objetos, ya que estos son inicializados invocando el mtodo new de la clase. Un ejemplo de inicializacin sera el siguiente: Class classObject = new Class(); Lo que declarara un objeto llamado classObject de la clase Class y lo inicializara. c) Declaracin mltiple

A veces necesitamos varias variables del mismo tipo. En estos casos puede llegar a ser una prdida de tiempo tener que escribir el tipo de dato delante de cada variable que vayamos a declarar. Por este motivo, X++ nos permite declarar ms de una variable en la misma sentencia de declaracin. La sintaxis es la siguiente: TipoDato Variable {, Variable}

Un ejemplo sera de declaracin mltiple sera el siguiente: real a, b = 1.5; En esta sentencia se declaran dos variables de tipo real llamadas a y b, inicializando la variable b a 1.5. Dentro de un mtodo podemos hacer referencia al objeto al que pertenece el mtodo mediante la variable this. sta nos da acceso a todos los mtodos y propiedades de dicho objeto. Es utilizado normalmente como parmetro para los mtodos que necesitan una referencia al objeto.

2.2.2.

Declaracin de mtodos

Los problemas complejos del mundo real son a menudo ms fciles de resolver si los dividimos en problemas ms pequeos que puedan ser resueltos independientemente unos de otros. El lenguaje de programacin X++, nos permite introducir mtodos dentro de otros mtodos. Otros lenguajes como Java o C++ no soportan esta caracterstica. Aunque en la realidad no es una prctica comn. Los mtodos incrustados dentro de otros mtodos solo son visibles dentro del mbito en el cual son creados y definidos. Ejemplo void myMethod() { void myEmbeddedMethod() { Box(1, Este es un mtodo incrustado, 1); }

Box(1, Este es el mtodo principal, 1);

Pgina 11 de 141

Mtodos

myEmbeddedMethod(); } El mtodo llamado myEmbeddedMethod, tan solo estara visible desde el mbito en el que fue creado, es decir dentro del mtodo llamado myMethod.

2.2.3.

mbito de las variables en los mtodos

Las reglas relativas al mbito de las variables en X++ son muy sencillas, todos los mtodos tienen su propio mbito. Para usar datos de un mtodo a otro, o lo que es lo mismo, datos de mbitos diferentes, debemos trasladar los datos utilizando parmetros. Un mtodo puede tener uno o ms argumentos. Dentro del mbito de ese mtodo esos parmetros son tratados como variables locales, inicializadas con el valor que tena el parmetro en la llamada. Es importante sealar que todos los parmetros son pasados por valor. Esto significa que no podemos modificar el valor de la variable original, pero s el de la variable local en el mtodo, la cual es una copia de la original. A continuacin mostramos un ejemplo: void methodA(int i) { i = i + 1; print i; } void methodB() { int i = 3; print i; this.methodA(i); print i; } En este ejemplo el mtodo methodB tiene una variable local llamada i, la cual se utiliza como parmetro para llamar al mtodo methodA. El mtodo methodA utiliza un parmetro llamado i, por lo tanto tiene una variable local llamada i. Esta variable tiene el valor de la variable i del mtodo methodB, ya que ha sido utilizada como parmetro de la llamada. El resultado de invocar el mtodo methodB es la impresin del valor de la variable i del mtodo methodB antes y despus de la invocacin del mtodo methodA que imprime el valor de su variable local i. El resultado de la ejecucin es el siguiente: 3 4 3 Esto ilustra perfectamente que las dos variables i son distintas en cada mtodo y que el mtodo methodA no puede cambiar el valor de los parmetros fuera de su mbito.

Pgina 12 de 141

Mtodos

2.3.

Algunos ejemplosLa forma ms simple que puede tener un mtodo se muestra a continuacin: Ejemplo 1 void methodName() { } Este ejemplo muestra un mtodo que no devuelve nada (void) y que no utiliza parmetros (los parntesis estn vacos). Adems, el cuerpo del mtodo (entre llaves) est vaco. El ejemplo es una declaracin vlida de un mtodo, pero como no hay instrucciones en el cuerpo, el mtodo no har nada. Ejemplo 2 int methodName() { return 1 } Si el mtodo debe devolver algo, por ejemplo un entero, la declaracin debe parecerse al ejemplo 2. La palabra int antes del nombre del mtodo, indica que el mtodo devolver un entero y la instruccin return 1 en el cuerpo devuelve el valor entero 1 al elemento que ha llamado al mtodo. Esto significa que se puede utilizar el resultado de la llamada al mtodo en una expresin, asignacin o incluso como parmetro en una llamada a otro mtodo. Un mtodo un poco ms complejo (sin argumentos ni modificadores) es por ejemplo, el mtodo delete de la tabla de proveedores. Mtodo delete en la tabla VendTable void delete() { Address address; ttsbegin; //Comienza la transaccin super(); //Llamada al mtodo delete de la clase superior

//Selecciona todas las direcciones para ese proveedor while select address where address.AdrTableId == this.TableId && address.AdrRecId == this.RecId { address.delete(); //Llamada al mtodo delete } ttscommit; //Acepta la transaccin

Pgina 13 de 141

Mtodos

} En el ejemplo podemos ver la cabecera del mtodo sin modificadores ni argumentos. A continuacin tenemos la declaracin de una variable llamada address. Al lado de cada instruccin se ha descrito su funcin mediante un comentario. Una lnea de comentario se marca mediante los caracteres //, mientras que un bloque de comentarios debe enmarcarse entre los caracteres /* y */.

3.3.1.

ParmetrosDefinicinEn algunas ocasiones son necesarios datos externos para utilizarlos en un mtodo, y la nica forma de realizar esto es definiendo datos de entrada al mtodo conocidos como parmetros. Si se utilizan parmetros en un mtodo, el mtodo puede escribirse a menudo de una manera ms general, lo que significa que tendr que escribirse menos cdigo para llevar a cabo una tarea. Como se describe en un apartado anterior, los parmetros en los mtodos son declarados en la declaracin del mtodo. Posteriormente son utilizados cuando se realiza una llamada al mtodo. La lista de parmetros que se declara en la cabecera de un mtodo estar compuesta por uno o ms parmetros separados por comas. La declaracin de cada uno de los parmetros tiene la siguiente estructura: TipoDato NombreParmetro [=Expresin] Es decir, los parmetros se declaran como si se tratar de una declaracin normal de variables. Como ejemplo de un mtodo que devuelve algo y utiliza parmetros podemos ver la declaracin del siguiente mtodo de la tabla CustTable:

Boolean chekDimension(Dimension dimension) { } El mtodo checkDimension devuelve un booleano y utiliza un parmetro del tipo de datos extendido Dimension, que es un vector de cadenas de caracteres.

3.2.

Parmetros opcionalesEs posible inicializar los parmetros en la declaracin. Esto convierte al parmetro en un parmetro opcional, de modo que si no es utilizado en la llamada al mtodo se utiliza el valor de la inicializacin.

Pgina 14 de 141

Mtodos

Veamos un ejemplo: Sea una clase Human, cuyo mtodo new tiene el siguiente aspecto (cuando veamos las clases hablaremos con ms detalle de este mtodo, de momento simplemente indicaremos que permite crear e inicializar las variables de un objeto): void new (Date _birthdate) { birthdate = _birthdate; } Es decir, al crear un objeto de la clase Human, simplemente estamos asignando el valor del parmetro a la variable birthdate. A continuacin, definimos un mtodo que calcula la edad en aos a partir de una fecha que se puede especificar como parmetro. Este parmetro es opcional, es decir, si no pasamos una fecha en la llamada al mtodo tomar como fecha de clculo la fecha de hoy: real age(date _calcDate = today()) { return (_calcDate - this.birthdate)/365; } Veamos las distintas posibilidades de llamada al mtodo:

Human kid = new Human(1/1/90); // Crea un objeto de tipo Human print kid.age(); //Imprime la edad a fecha de hoy print kid.age(1/1/1991); //Imprime la edad a fecha 1/1/91

4.

ModificadoresExisten diferentes modificadores que pueden ser aplicados en la declaracin de mtodos. Son los siguientes: a) Static Crea un mtodo de clase que no puede operar sobre un objeto. b) Final Crea un mtodo que no puede ser sobrecargado por subclases. No puede ser aplicado a los mtodos new y finalize. c) Display Los mtodos de este tipo siempre devuelven un valor. Se utilizan para asignar un valor a un campo en un informe o en un formulario. El campo no puede ser modificado.

Pgina 15 de 141

Mtodos

d)

Edit Los mtodos de este tipo siempre devuelven un valor. Se utilizan para asignar un valor a un en un formulario, que puede ser modificado.

Tal y como se vio en un apartado anterior, los modificadores forman parte de la cabecera de un mtodo, y se utilizan justo antes del tipo de datos de retorno. Como ejemplo, veamos algunas cabeceras de mtodos: static void ClassNoChange() final int DontAlterMe() display int Value() El modificador final se ver ms adelante, en el captulo dedicado a clases. Los modificadores display y edit tienen dedicado su propio captulo. Los mtodos de tipo static se describen en el siguiente apartado.

5.

Mtodos estticosLos mtodos estticos nunca operan sobre un objeto, es decir sobre una instancia de la clase en ejecucin. Podemos ver muy fcilmente con un ejemplo el significado de los mtodos estticos. Supongamos un mtodo exist que recibe como parmetro un cdigo de cliente y nos indica si el cliente existe o no. Si el mtodo actuara sobre un objeto, no tendra ningn sentido, ya que para ejecutar el mtodo debera existir el objeto y por lo tanto el resultado sera siempre s. La declaracin de este mtodo podra tener la siguiente cabecera: static Boolean exist (CustAccount _custAccount) Dado que un mtodo esttico no opera sobre un objeto, no podemos utilizar la variable this. Por otro lado, y dado que se trata de mtodos de clase, nunca pueden ser sobrecargados. Como regla general de diseo en un entorno orientado a objetos y cliente/servidor, un mtodo se declarar como esttico cuando no tiene acceso a los miembros (variables y mtodos) de la instancia y, por lo tanto no utiliza el puntero this, y no va a ser sobrecargado. Como los mtodos estticos no operan sobre los objetos, no pueden ser llamados como cualquier otro mtodo no esttico. Por lo tanto tenemos que llamarlos utilizando el operador de mbito (scope-operator) ::, como en el siguiente ejemplo: ClassName::myMethod() Dentro de una clase, es posible declarar un mtodo esttico y un mtodo no esttico con el mismo nombre. Como por ejemplo: void myMethod() { // Instrucciones }

Pgina 16 de 141

Mtodos

static void myMethod() { // Instrucciones } En este caso tendramos dos mtodos con el mismo nombre, sin embargo como uno de ellos es esttico no se invocaran de la misma manera. Por ejemplo, className.myMethod() invocara el mtodo de la instancia actual de la clase, es decir el mtodo del objeto, mientras que ClassName::myMethod() invocara el mtodo esttico de la clase, con lo que no existe confusin posible.

En un entorno cliente/servidor, es interesante reducir al mximo el trfico en la red. Desde este punto de vista, resulta ms baratos llamar a un mtodo esttico de forma remota que instanciar un objeto y despus llamar a uno de sus mtodos.

Contenedores y sus funciones1. DefinicinX++ tiene un tipo de datos general llamado contenedor (container), que puede ser considerado como un vector dinmico indefinido de tipos de datos primitivos, contenedores y vectores. Los contenedores pueden ser utilizados para guardar una lista de elementos de diferentes tipos y son especialmente tiles para situaciones intermedias. Los contenedores son dinmicos y no tienen lmite. Pueden contener elementos de casi todos los tipos de datos: booleano, entero, real, fecha, cadena, contenedor, vector, tablas y tipos de datos extendidos. Las variables de objetos y los campos de las tablas pueden ser declarados como contenedores.

2.

Declaracin de variables de tipo contenedorLos contenedores se declaran utilizando la palabra reservada container seguida de la variable que lo identifica. Ejemplos de declaracin de containers: container c1; // declaracin de un container container c2[]; // declaracin de un vector de containers dinmico container c3 = [ 1, 3.14, a]; // declaracin e inicializacin de un container con 3 elementos: un entero, un real, y una cadena.

Pgina 17 de 141

Mtodos

3.

Funciones que utiliza un contenedorEn la siguiente tabla se presentan algunas de las funciones que utilizan los contenedores. En el nodo Funciones de la Documentacin del sistema podemos encontrar ayuda acerca de estas funciones.

Nombre ConDel( container, int, int)

Descripcin Eliminacin de un nmero especfico de elementos de un contenedor. El primer entero especifica la posicin inicial a partir de la que se van a eliminar elementos. El segundo indica el nmero de elementos a borrar. Devuelve un contenedor.

ConFind ( container, element, Localiza la primera ocurrencia del elemento pasado como .) parmetro entre los elementos de un contenedor. Devuelve 0 si no ha encontrado el elemento, o el n de posicin que ste ocupa en el contenedor. ConIns element) (container, int, Inserta un elemento en un contenedor, en la posicin que le pasamos como parmetro. Devuelve el nuevo contenedor. Devuelve el nmero de elementos que tiene el contenedor. Devuelve un contenedor vaco. Devuelve el elemento del contenedor que ocupa la posicin que le hemos pasado como parmetro. int, Reemplaza el/los elemento/s del contenedor a partir de la posicin que se le pasa como parmetro. Si deseamos reemplazar varios elementos los pondremos seguidos de comas. Devuelve el contenedor con los elementos reemplazados.

ConLen ( container) ConNull ( ) ConPeek (container, int)

ConPoke element)

(container,

Pgina 18 de 141

Sentencias bsicas del lenguaje X++

Sentencias bsicas del lenguaje X++1. IntroduccinEl hecho de que X++ tenga una sintaxis muy similar a lenguajes ya existentes como C++, Java o SQL hace que X++ sea un lenguaje familiar para la mayora de desarrolladores de software. Esto significa que pueden migrar rpidamente a este nuevo lenguaje y pueden ser productivos desde el primer momento. En el presente captulo vamos a revisar brevemente algunas de las instrucciones ms comunes. Si se considera necesario, esta informacin se puede ampliar consultando la Gua de ayuda al desarrollador de Axapta.

2.

OperadoresSignificadoIgual a Distinto de Mayor que Mayor o igual que Menor que Menor o igual que No

Operador== != > >= < 4) print a; 2) if (Debtor.NameRef == Uptown Radio) print Great music; 3) if (bankAccountTrans) { sentencias} 4) if (!this.validation()) { throw error("@SYS18447"); }

Con Else 1) if (a>4) print a; else print 4 es mayor que a; 2) if (BankAccountTable::Find(AccountId).Name) print Cuenta existente; else print No existe la cuenta;

El lenguaje permite anidar sentencias if unas dentro de otras.

3.2.

Instruccin SWITCHLa sentencia switch es una sentencia de bifurcacin mltiple. Eso significa que podemos seguir ms de dos caminos utilizando esta sentencia, en contraste con la instruccin if. En una instruccin switch, normalmente queremos que ocurra algo por defecto, si no se elige ninguna de las alternativas correspondientes a los distintos caminos posibles a seguir. Por tanto, existe un camino por defecto que se sigue si no se ha elegido ninguno de los otros posibles.

Pgina 20 de 141

Sentencias bsicas del lenguaje X++

Dependiendo de una condicin que se evala, la ejecucin del programa salta al camino correcto y contina la ejecucin desde all. Si queremos que la ejecucin se pare en algn lugar determinado dentro de la instruccin switch debemos utilizar la sentencia break. La sintaxis es la siguiente: switch (Expresin) { case Expresin {, Expresin}: Instrucciones; [break;]

case ...

[defaut Instrucciones; ] }

Un ejemplo de una instruccin switch, en comparacin con una instruccin if, sera el siguiente: Ejemplo instruccin switch switch (i) { case 10: // Instrucciones A; break; case 20: // Instrucciones B; break; default: // Instrucciones C; break; } Ejemplo instruccin if if (i==10) // Instrucciones A; else if (i==20) // Instrucciones B;

Pgina 21 de 141

Sentencias bsicas del lenguaje X++

else //Instrucciones C; Como podemos ver, en estos casos la instruccin switch es mucho ms intuitiva y fcil de entender que la instruccin if. Es importante sealar que si no utilizramos la instruccin break, la ejecucin del programa continuara con las instrucciones correspondientes a los siguientes caminos de ejecucin definidos en la instruccin switch. Ejemplos de Switch 1) switch (budget.tableId) { case tablenum(LedgerBudget): return new BudgetExpansion(budget); case tablenum(ForecastSales),tablenum(ForecastPurch): return new ForecastExpand(budget); case tablenum(ProjBudgetEmpl): return new BudgetExpansion(budget); case tablenum(ProjBudgetCost): return new BudgetExpansion(budget); case tablenum(ProjBudgetRevenue): return new BudgetExpansion(budget); } 2) switch (f) { case 2 : label = rd.lookupLabel(literalStr("@SYS53635")); break; case 3 : label = rd.lookupLabel(literalStr("@SYS3794")); break; case 4 : label = rd.lookupLabel(literalStr("@SYS50253")); break; case 5 : label = rd.lookupLabel(literalStr("@SYS477")); break; case 6 : label = rd.lookupLabel(literalStr("@SYS6437")); break;

Pgina 22 de 141

Sentencias bsicas del lenguaje X++

Defualt : Throw error Caso desconocido; }

3.3.

Operador ternario: ?A veces necesitamos elegir entre dos expresiones dependiendo de alguna condicin concreta. Eso puede realizarse utilizando la instruccin if estndar antes comentada. Esto nos obligara a realizar dos grupos de instrucciones, sin embargo el operador ternario (?) se puede ahorrrar cdigo. La sintaxis de este operador se presenta a continuacin: Expresin ? Expresin : Expresin

Si la primera expresin es verdadera, devolveramos la expresin situada inmediatamente detrs del smbolo ?, por el contrario, si es falsa devolveramos la expresin situada detrs de los dos puntos (:). La funcionalidad es similar a la de la instruccin if, pero mientras que en sta podemos elegir entre dos grupos de instrucciones, con el operador ternario podemos elegir entre dos expresiones. Las ventajas del operador ternario con respecto a la instruccin if se ilustran en el siguiente ejemplo: Operador ternario int result; int choose = 3; ; result = choose > 3 ? 100 : 50; Instruccin if int result; int choose = 3; if (choose > 3) result = 100; else result = 50; Como podemos ver con el operador ternario el cdigo es ms corto y adems podemos devolver el resultado de una manera directa, lo que hace aconsejable su utilizacin en determinadas ocasiones.

4.4.1.

Sentencias de repeticinInstruccin WHILEA menudo necesitamos repetir algo mientras que una expresin sea verdadera. Si por ejemplo, estamos leyendo un fichero de texto, debemos seguir leyendo mientras haya ms texto en el fichero, es decir, antes de alcanzar el fin del fichero.

Pgina 23 de 141

Sentencias bsicas del lenguaje X++

Una instruccin while slo se ejecuta si la condicin es verdadera. Esto significa que una instruccin while puede ejecutarse varias veces, una vez o incluso ninguna, dependiendo de la condicin inicial. La sintaxis es la siguiente: while ( Expresin ) Instrucciones

Ejemplos de la instruccin while. 1) int n = 10; while (n > 1) { // Instrucciones n = n - 1; } 2) while (queryCust.next()) { Sentencias } 3) while select custInvoiceJour ==

where (custInvoiceJour.invoiceAccount custTable.accountNum && invoiceCustomer)

4.2.

Instruccin DO WHILELa instruccin dowhile tiene la misma funcionalidad bsica que la instruccin while, pero se diferencia en que la condicin se comprueba despus de las instrucciones. Esto significa que una instruccin dowhile al menos se ejecuta una vez, aunque puede hacerlo varias veces dependiendo de la condicin. La sintaxis es la siguiente: do { { Instrucciones } } while ( Expresin ) A continuacin presentamos un ejemplo de instruccin dowhile. int n = 1; do { // Instrucciones n = n + 1; } while (n < 1)

Pgina 24 de 141

Sentencias bsicas del lenguaje X++

En este caso el conjunto de instrucciones situadas dentro del cuerpo de la instruccin dowhile se ejecutara una vez.

4.3.

Instruccin FORLa instruccin for es una instruccin while extendida, que resulta especialmente til cuando estamos trabajando con vectores (arrays), ya que la condicin es una variable que se va incrementando en cada iteracin. Realmente, la instruccin for aade funcionalidad a la instruccin while, ya que nos da la posibilidad de asignar un valor inicial a la variable de control de la condicin y de definir una instruccin de incremento o decremento de dicha variable. En cualquier otro aspecto, una instruccin for puede ser considerada de la misma forma que una instruccin while. La sintaxis es la siguiente: for ( Inicializacin; Expresin; Actualizacin ) Instrucciones Es importante sealar que la inicializacin y la actualizacin son dos instrucciones regulares de X++, pero el uso normal de esas instrucciones en la sentencia for es inicializar y actualizar la variable de control respectivamente. Vamos a mostrar a continuacin un ejemplo que compara el uso de las instrucciones for con las instrucciones while. Instruccin for int i; for (i=1; i 100 select * from Custtable where AccountNo > 100;

// El cliente con el menor nmero > 100 es encontrado, // este es , CBS con el nmero 200. select * from Custtable order by AccountNo where AccountNo > 100; next Custtable; // El cliente siguiente en ser ledo, por Ejemplo Walt Disney

// El cliente con el mayor nmero de cuenta // (mayor de 100) es encontrado: Pentagon select * from Custtable order by AccountNo DESC where AccountNo > 100; next Custtable; // El siguiente registro ledo es (DESC) = Ford Motor

// El cliente con el mayor nmero de cuenta es: Pentagon select reverse Custtable order by AccountNo;

// EL cliente con el menor nombre y nmero de cuenta // en el intervalo ]100;1000[ es encontrado. Este es CBS. select * from Custtable order by NameRef where AccountNo > 100

Pgina 33 de 141

Instrucciones de acceso a registros

&& AccountNo < 1000;

// La seleccin COUNT retorna el nmero de clientes accountnumbers (clientes): 5 select count(AccountNo) from CustTable; print Custtable.AccountNo; // Imprime el resultado del count // (el cual est en AccountNo)

/* Retorna la suma de los balances para los clientes no bloqueados. El resultado es: SUM: $1,060,000 */ select sum(Balance) from Custtable where Blocked == DebCreBlocked::No; }

Una nota para el siguiente comando: Hay que darse cuenta que cuando el comando NEXT es usado sin estar precedido de un select, es tratado como si hubiera un comando SELECT implcito sin una clusula Where. Ejemplo: { MyTable T; // declara una instancia de MyTable Next T; // recupera el primer registro, si lo hay, de la tabla MyTable }

Esto equivale a:

{ MyTable T; // declara una instancia para MyTable Select T; // recupera el primer registro, si lo hay, de la tabla MyTable

Pgina 34 de 141

Instrucciones de acceso a registros

} En el ltimo ejemplo, una llamada a NEXT retornara el segundo registro del resultado. Field Select Nota que tambin es posible usar una sentencia select en un lookup en un campo: despus de un sentencia select que va a buscar un registro en una tabla, puedes escribir .nombre de campo para referenciarte a un campo de una tabla. Debajo encontrars ejemplos de esta seleccin de campos. Nota, que esas selecciones deben ser usadas en las expresiones! Void selectFieldExample () { //imprime el campo NameRef para el cliente seleccionado (el cual es CBS) print (select Custtable order by NameRef).NameRef; Usa el campo de balance para el cliente con una cuenta 5000 (Pentagon). //Imprime un mensaje. if ((select Custtable where AccountNo == 5000).Balance > 500000) print This customer has a balance above $500,000; } Date cuenta de la diferencia entre la seleccin normal y la de seleccin de campo. La se seleccin de campo opera directamente sobre la tabla mientras que la seleccin opera sobre una variable de la tabla.

4.

Instruccin WHILESELECTLa instruccin whileselect itera sobre un grupo de registros, que cumplen ciertas condiciones de seleccin, de manera que es posible realizar operaciones sobre cada registro. La ventaja de la instruccin whileselect, es que es capaz de desplazarse automticamente por todos los registros seleccionados (por tanto no necesitamos la instruccin next) y ejecuta instrucciones para cada uno de estos registros. Esta versin de instruccin de seleccin de registros es la ms utilizada en MorphX. Cuando estamos manipulando datos utilizando esta sentencia, normalmente debemos utilizar el concepto de transaccin para asegurarnos la integridad de los mismos. La sintaxis es la siguiente:

Pgina 35 de 141

Instrucciones de acceso a registros

while { }

InstruccinSelect

A continuacin presentamos un ejemplo: void selectRecords() { MyTable table;

while select * from table order by TableCode where TableCode > 100 { print table.TableCode; } } En este ejemplo seleccionaramos todos los registros de la tabla que tuvieran un valor mayor que 100 en el campo tableCode, ordenados por ese campo e imprimiramos su valor.

5.

Instruccin DELETE_FROMPodemos utilizar la instruccin delete_from para borrar todos los registros que cumplan una determinada condicin. Esta instruccin es equivalente a ejecutar una instruccin whileselect y realizar el borrado en cada uno de los registros. Instruccin whileselect { MyTable myTable;

while select myTable where ... { myTable.delete(); } } Instruccin delete_from { MyTable myTable;

Pgina 36 de 141

Instrucciones de acceso a registros

delete_from myTable where ...; } Como se aprecia en el ejemplo, utilizando la instruccin delete_from en lugar de la whileselect, podemos economizar instrucciones de cdigo X++ y conseguir el mismo efecto.

JOBSUn job es una porcin de cdigo la cual es ejecutada secuencialmente (desde arriba hasta abajo). Por defecto la siguiente lnea se encuentra en la parte superior de un nuevo job: Static void jobname (Args a) { } Los jobs que vers durante esta clase se parecern a este de aqu, excepto el nombre del job, el cual le dars t. Para aadir comentarios en el editor de texto se hace utilizando: //Este es un comentario de una sola lnea /* Para comentarios de ms de una lnea mejor utilizar esto*/ En ambos casos el texto cambiar de color a VERDE.

Pgina 37 de 141

Estndares para los mtodos de tablas

Estndares para los mtodos de las tablas1. IntroduccinEn un captulo anterior se indic que en Axapta podemos encontrar mtodos en todos los objetos de la aplicacin, y por lo tanto, en las tablas. stas disponen de una serie de mtodos que controlan su funcionalidad bsica, y que sern descritos en captulos posteriores. Adems de estos mtodos, el programador puede aadir aqullos que considere necesarios. Sin embargo, debe ajustarse a unos estndares de desarrollo. En Axapta, existen una serie de procedimientos de desarrollo estndar que son muy importantes. stos nos determinan la forma de trabajar, con el objetivo de facilitar la programacin, la comprensin del cdigo y la revisin del mismo por parte de personas distintas a las que han realizado el desarrollo inicial. Por eso es de vital importancia que siempre nos ajustemos lo ms posible a los estndares definidos. Un primer punto importante a sealar, es que no debemos escribir cdigo en X++ para solucionar problemas que pueden ser resueltos mediante las propiedades de los objetos, ya que es una prdida de tiempo y un esfuerzo de desarrollo intil. Por otro lado, el cdigo escrito en los mtodos de las tablas debe estar directamente relacionado con la tabla. Si no es as debemos plantearnos la posibilidad de escribir el cdigo en otras partes del sistema. Para aquellas tablas que tengan una clave primaria, SIEMPRE debemos crear los mtodos estndar que se describen en los siguientes apartados.

2.

Mtodo FINDEl mtodo find nos sirve para encontrar un registro determinado de una tabla, a partir de un valor del campo que sea la clave principal de la misma. Se trata de un mtodo esttico y que recibe los siguientes parmetros de entrada:

La clave de la tabla Un booleano opcional utilizado para indicar si se van a realizar una actualizacin del registro seleccionado El mtodo find de todas las tablas sigue la misma estructura. Veamos un ejemplo: Ejemplo static CustTable find(CustAccount boolean { CustTable custTable; ; custAccount, _forUpdate = false)

Pgina 38 de 141

Estndares para los mtodos de tablas

if (custAccount) { custTable.selectForUpdate(_forUpdate); select firstonly custTable index hint AccountIdx where custTable.accountNum == custAccount; } return custTable; } El hecho de que find sea un mtodo esttico nos facilita la tarea de buscar un registro de la tabla desde cualquier lugar del sistema, sin necesidad de tener una instancia de la tabla CustTable. La forma de ejecutar el mtodo sera por lo tanto la siguiente:

CustTable::find(customer) Donde customer sera una variable del tipo CustAccount que contendra el valor de la clave del registro que queremos buscar.

3.

Mtodo EXISTEl mtodo exist es un mtodo que nos indica si un registro determinado existe en la tabla, a partir de un valor del campo que sea la clave principal de la misma. Se trata de un mtodo esttico que tiene como parmetro de entrada el siguiente:

La clave de la tabla Ejemplo static boolean exist(CustAccount custAccount) { return (custAccount && CustTable::find(custAccount).recID != 0); } En el ejemplo se puede observar que se realiza una llamada al mtodo find. Resulta evidente que es mucho ms eficaz reutilizar el cdigo existente que reescribir la instruccin de seleccin.

4.

Mtodo TXTNOTEXISTEl mtodo TxtNotExist nos devuelve un texto esttico que utilizamos como mensaje de error. Ejemplo static str 80 txtNotExist()

Pgina 39 de 141

Estndares para los mtodos de tablas

{ return "@SYS9779"; } La etiqueta del ejemplo corresponde al texto La cuenta %1 no existe. Siempre que introduzcamos una cadena de texto en el cdigo deberemos utilizar etiquetas.

5.

Mtodo CHECKEXISTEl mtodo checkExist nos indica si un registro determinado existe en la tabla, a partir de un valor del campo que sea la clave principal de la misma. Si el registro no existe, devuelve un mensaje de error. Se trata de un mtodo esttico que recibe el siguiente parmetro de entrada:

La clave de la tabla Ejemplo static boolean checkExist(CustAccount custAccount) { if (custAccount && !CustTable::exist(custAccount))

return checkFailed(strfmt(CustTable::txtNotExist(),custAccount)); return true; } Como se observa en el ejemplo, el mtodo checkExist hace uso de los mtodos exist y txtNotExist descritos anteriormente. Tambin hace referencia a un metodo de la clase Global checkFailed

Pgina 40 de 141

Mtodos display y edit

Mtodos display y editLos trminos display y edit corresponden a modificadores de los mtodos, que dotan a stos de caractersticas especiales. Los mtodos de este tipo SIEMPRE deben tener un valor de retorno. En este captulo vamos a ver cmo y cundo se utilizan estos modificadores.

1.

Mtodos DISPLAYEl modificador display se utiliza para indicar que el valor de retorno del mtodo va a ser mostrado en un formulario o en un informe. Podemos utilizar este modificador en los mtodos de: Tablas Formularios Origen de datos de formularios Informes Diseo de informes

Siempre que sea posible, es aconsejable escribir los mtodos display en tablas, porque de esta forma puede utilizarse el mismo cdigo en varios formularios o informes.

1.1.

Definicin de un mtodo displayPara definir un mtodo display, es necesario escribir la palabra reservada display antes del tipo de retorno del mtodo. Por ejemplo: display Amount Amount() Existe un caso excepcional. Cuando definimos un mtodo display en el origen de datos de un formulario, se debe incluir dicho origen de datos como parmetro. Por ejemplo: display InventQty Accumulated(InventBudgetInvent Budget)

1.2.

Utilizacin de un mtodo displayNormalmente, los mtodos display se utilizan cuando queremos mostrar un campo calculado en un formulario o en un informe. No es recomendable, y de hecho no es estndar Axapta, almacenar en la base de datos valores calculados que cambian con el tiempo, como por ejemplo la deuda de un cliente. En estos casos el clculo debe realizarse en un mtodo display. Hay que tener en cuenta que al utilizar un mtodo display en un formulario, ste se ejecuta cada vez que el formulario se actualiza. Por lo tanto, el mtodo no debe realizar clculos que supongan un tiempo mayor al de una consulta directa a la base de datos.

Pgina 41 de 141

Mtodos display y edit

En los casos en que sea necesario realizar clculos costosos, es recomendable utilizar otro formulario para mostrar los valores calculados que se muestre al pulsar un botn. De este modo, slo se realizarn los clculos cuando el usuario lo solicite explcitamente. Veamos ahora cmo se utilizan los mtodos display. Una vez que se ha creado el mtodo, ste se utilizar en un control que se muestre en un formulario o en un informe. La forma de realizarlo es independiente del lugar donde se haya escrito el mtodo. Es necesario que el tipo de control y el tipo de retorno del mtodo sean idnticos. Esto significa que si, por ejemplo, tenemos en el formulario un control del tipo RealEdit, el mtodo display que estemos utilizando debe devolver un valor de tipo real. En un formulario, la propiedad DataSource indica donde est situado el mtodo, y la propiedad DataMethod indica el nombre del mtodo. Si la propiedad DataSource no tiene valor, el sistema asume que el mtodo ha sido definido en el formulario. En la siguiente figura se muestra la ventana de propiedades de un control de tipo real de un formulario:

En un informe, la propiedad DataMethod tambin indica el nombre del mtodo display. Si la propiedad Table no tiene valor, el sistema asume que el mtodo ha sido definido en el informe o en la clase de sistema ReportRun, donde tambin existen mtodos display. Por el contrario, cuando la propiedad Table tiene valor, el sistema busca el mtodo display en la tabla correspondiente. Si la propiedad ExtendedDataType tiene valor, el formato, el texto de ayuda, etc., se obtendrn del tipo de datos correspondiente. Si el mtodo display devuelve un vector, la propiedad ArrayIndex a 0 indica que todos los elementos del vector deben ser mostrados en el informe. Si, por ejemplo, ponemos la propiedad ArrayIndex a 2, solo el elemento nmero 2 del vector es mostrado.

Pgina 42 de 141

Mtodos display y edit

2.

Mtodos EDITEl modificador edit es una extensin del modificador display, de forma que los controles que utilizan un mtodo edit, adems de mostrar un valor aceptan la entrada de datos por parte del usuario. Puede utilizarse en mtodos de los siguientes elementos: Tablas Formularios Orgenes de datos de los formularios

2.1.

Definicin de un mtodo editEl formato de los parmetros en un mtodo edit es un poco diferente al de los mtodos display. Este es un ejemplo de un mtodo edit en una tabla: Edit FreeTxt TxtDefault(boolean Set, FreeTxt Txt) Utilizamos ambos parmetros cuando el mtodo est asociado a un control de un formulario. El parmetro booleano Set es verdadero si el usuario ha introducido algn valor en el control. El parmetro de texto Txt se utiliza para almacenar los valores que el usuario ha introducido en el control. El formato de parmetros para los mtodos edit que utilizamos en un formulario es idntico al utilizado en las tablas. Sin embargo, cuando utilizamos el mtodo edit como mtodo de un origen de datos de un formulario, dicho origen de datos debe aparecer tambin como parmetro, por ejemplo: edit Amount Settle(boolean set, CustTrans _custTrans, Amount u)

3.

Resumen del aspecto de los parmetros para los mtodos display y edit

Parmetros para display Mtodo en tabla Ninguno

Parmetros para edit

Boolean Set valor Boolean Set Ninguno Mtodo en formulario valor Boolean Set Origen de datos datos de un formulario Origen de datos valor Mtodo en un informe Ninguno No aplicable No aplicable

Mtodo en el diseo de Ninguno un informe

Pgina 43 de 141

Mtodos display y edit

Mtodos bsicos en tablas1. Definicin y modificacin de mtodos en tablasCuando se crea una nueva tabla en el Arbol de Objetos de la Aplicacin, MorphX automticamente crea una serie de mtodos para ella. Aadiendo cdigo X++ a estos mtodos podemos modificar el comportamiento predeterminado del sistema. Adems, podemos definir nuestros propios mtodos. Los mtodos de sistema y los definidos por el usuario comparten el mismo mbito, por lo tanto es posible aadir nuevos mtodos que pueden ser utilizados desde los mtodos definidos por el sistema. As como acceder a los mtodos de sistema desde cualquier nuevo mtodo. Es importante sealar que no podemos modificar el tipo de retorno, la lista de parmetros o el tipo de dichos parmetros en los mtodos definidos por el sistema, aunque podemos aadir parmetros adicionales siempre que declaremos un valor predeterminado para ellos.

2.

Mtodos de sistemaLos mtodos de sistema son ejecutados cuando se utiliza la tabla, por ejemplo, cuando introducimos, actualizamos o borramos datos. El cuerpo de estos mtodos inicialmente nicamente contiene una llamada al mtodo super(). En captulos posteriores se describir con ms detalle este mtodo. De momento nos basta con saber que corresponde al comportamiento predeterminado del sistema. Cuando se aade cdigo X++ a los mtodos definidos por el sistema, se sobrecarga este comportamiento. A continuacin se presentan la lista de mtodos de sistema de una tabla. En apartados posteriores se describirn con ms detalle los ms importantes. Mtodo Caption Se ejecuta cuando... se muestra la cabecera de un formulario. El texto se genera a partir de las propiedades de la tabla.

Clear

se borran los campos del registro actual (tienen valores NULL).

Delete

se elimina un registro.

HelpField

se muestra en la barra de estado el texto de ayuda de un campo, por ejemplo cuando pasamos al campo siguiente en un formulario.

InitValue

Inicializa los campos de un registro recin creado.

Pgina 44 de 141

Mtodos display y edit

Insert

se introduce un nuevo registro en la tabla.

Merge

se unen o combinan dos registros.

PostLoad

se carga un registro.

RenamePrimaryKey

se renombra la clave primaria de la tabla.

ReRead

se relee un registro.

ToolTipField

el puntero del ratn se sita en un campo de un formulario.

ToolTipRecord

se va a mostrar un consejo para el campo actual. El mtodo super() realiza una llamada a Caption.

Update

antes de modificar un registro existente.

ValidateDelete

se va a borrar un registro.

ValidateField

se abandona un campo, por ejemplo cuando saltamos al siguiente campo de un registro.

ValidateWrite

antes de escribir un registro en la base de datos.

2.1.

Mtodos de validacin en tablasLos mtodos de validacin permiten al programador comprobar que se cumplen ciertas condiciones antes de que se ejecute una accin. En Axapta, se pueden programar mtodos de validacin a dos niveles: Tabla Origen de datos de un formulario En este captulo slo veremos los mtodos de validacin en tablas. Sin embargo, es importante conocer que los mtodos de validacin de las tablas se ejecutan siempre que se introducen o borran registros. Mientras que si la validacin se realiza en el formulario, slo funcionar cuando estemos trabajando con ese formulario.

Siempre que sea posible, la validacin de datos debe realizarse en la tabla.

Pgina 45 de 141

Mtodos display y edit

2.1.1.

MtodosLos mtodos de validacin en tablas son los siguientes:

a)

ValidateField Se ejecuta cuando movemos el cursor desde un campo del formulario a otro, es decir, cuando abandonamos un campo. Devuelve un dato de tipo booleano. Si el resultado es falso, el cursor permanecer en el campo. La llamada al mtodo super() comprueba las relaciones de validacin, es decir, relaciones en un campo donde la propiedad Validate tiene valor afirmativo. Por lo tanto, debemos respetar la tarea realizada por dicho mtodo super(). No deben codificarse validaciones que puedan realizarse con alguna propiedad. As, evitaremos escribir cdigo en el mtodo ValidateField si las condiciones pueden comprobarse con la propiedad Validate de una relacin.

b)

ValidateWrite Se ejecuta antes de insertar o actualizar un registro en la tabla. Devuelve un dato de tipo booleano. Si devuelve falso, el registro no se inserta o actualiza. La llamada al mtodo super() examina todos los campos para comprobar el valor de la propiedad Mandatory. Por lo tanto, debemos respetar la tarea realizada por dicho mtodo super(). Evitaremos introducir cdigo que compruebe si un campo tiene valor, siempre que podamos utilizar la propiedad Mandatory.

c)

ValidateDelete

No hay que olvidar, que a menudo tambin queremos comprobar ciertas condiciones antes de borrar un registro de una tabla. Para hacer esto, utilizamos el mtodo ValidateDelete(). ValidateDelete() se llama automticamente desde formularios y es utilizado para comprobar si el registro actual puede ser borrado. La llamada al mtodo super() comprueba si hay registros relacionados en tablas con DeleteActions del tipo Restricted. Si ese es el caso, el mtodo super() devuelve falso. Por lo tanto, debemos respetar la tarea realizada por dicho mtodo. Siempre que podamos utilizar un DeleteAction, evitaremos introducir cdigo en el mtodo ValidateDelete.

Pgina 46 de 141

Mtodos display y edit

2.1.2.

Estructura de los mtodos de validacin

Para mantener una buena estructura de programacin, es recomendable que el cdigo para las comprobaciones no se site directamente en estos mtodos de validacin. Es ms conveniente que creemos mtodos de comprobacin que sern llamados desde los mtodos de validacin anteriormente descritos. Ejemplo de mtodo de validacin Boolean validateWrite() { Boolean ret;

ret = checkSomething() && checkSomethingElse();

return ret; } Cuando no se cumple alguna de las condiciones, el mtodo de comprobacin debe realizar dos cosas: presentar al usuario un mensaje de error devolver el valor falso como resultado El mtodo CheckFailed(Mensaje de error) escribe la cadena de texto que recibe como parmetro en la ventana de informacin (Infolog) y devuelve el valor falso. Por lo tanto, mediante la utilizacin de este mtodo, conseguimos simultneamente los dos objetivos. Ejemplo de utilizacin de CheckFailed Boolean checkSomething () { Boolean ret;

if (!something) { ret = checkFailed(Something is wrong); } return ret; } Podramos utilizar la estructura anterior, pero existen casos en los que nos interesa comprobar la misma condicin Something, presente en el mtodo CheckSomething(), sin presentar ningn mensaje al usuario. En este caso necesitaramos un mtodo adicional, que comprobara la condicin pero que no mostrara ningn mensaje.

Pgina 47 de 141

Mtodos display y edit

Sin embargo, esto no sera muy eficiente, porque estaramos duplicando el cdigo de comprobacin, por lo tanto es ms recomendable crear un mtodo llamado Something(), al que podremos llamar cuando queramos, que se encargar de realizar dicha comprobacin. Deberemos, adems, cambiar el mtodo CheckSomething(), para que realice una llamada a este nuevo mtodo. El mtodo CheckSomething() lo utilizaremos nicamente cuando queramos mostrar un mensaje al usuario. Ejemplo de validacin completa Boolean something () { if (!something) { return false; } return true; }

Boolean checkSomething () { Boolean ret;

if (!something()) { ret = checkFailed(Something is wrong); } return ret; } Podemos considerar un estndar de nomenclatura de Axapta, la utilizacin del prefijo Check, en el nombre de todos aquellos mtodos que hagan una llamada al mtodo global CheckFailed(). De esta forma sabremos qu mtodos presentan mensajes en la ventana Infolog.

2.2.

Mtodos de sistema ms utilizadosA continuacin vamos a describir algunos de los mtodos ms utilizados en las tablas, que por su importancia merecen un tratamiento algo ms exhaustivo. Los ejemplos de los mtodos han sido obtenidos a partir de la tabla CustTable. a) InitValue

Pgina 48 de 141

Mtodos display y edit

El mtodo InitValue se ejecuta cuando aadimos un nuevo registro. Tambin es llamado automticamente desde los formularios. Por lo tanto, utilizaremos el mtodo para asignar valores iniciales o por defecto en un nuevo registro. Ejemplo void initValue() { CustParameters custParameters;

super(); this.languageId = CustParameters::languageId(); this.currency = CompanyInfo::find().currencyCode; } Hay que sealar que la llamada al mtodo super() no hace nada. b) Insert El mtodo Insert se ejecuta cuando se introduce un nuevo registro en la tabla. Es muy importante asegurar cualquier transaccin relacionada para asegurar la integridad de la base de datos. Las tcnicas de control de transacciones se vern en un captulo posterior. Ejemplo void insert() { this.setNameAlias(); super(); } Si el registro no puede ser insertado en la tabla, la llamada al mtodo super() devuelve un error. c) Update El mtodo Update se ejecuta antes de modificar un registro existente en la tabla. En este caso, tambin es muy importante controlar cualquier transaccin relacionada para asegurar la integridad de la base de datos. Ejemplo void update() { CustTable this_Orig = this.orig();

ttsbegin; this.setNameAlias();

Pgina 49 de 141

Mtodos display y edit

super(); this.setAccountOnVend(this_Orig); if (this_Orig.custGroup != this.custGroup) ForecastSales::setCustGroupId(this.accountNum, this_Orig.custGroup, this.custGroup); ttscommit; } En el ejemplo se utiliza el mtodo orig(). ste mtodo nos da acceso al registro antes de la actualizacin. d) Delete El mtodo delete se ejecuta cuando se elimina un registro. Es muy importante asegurar cualquier transaccin relacionada para asegurarnos la integridad de la base de datos. Supongamos dos tablas relacionadas llamadas TableA y TableB. Si en TableA hemos definido un DeleteAction de tipo cascada (Cascade) con respecto a TableB, cuando se borre un registro de TableA se borrarn los registros relacionados en TableB. Por razones de rendimiento, se debe evitar escribir cdigo en el mtodo Delete de dichas tablas relacionadas (en el ejemplo, TableB). Si no se ha aadido cdigo, los borrados en cascada pueden ser realizados rpidamente por el sistema gestor de base de datos utilizando directamente instrucciones de borrado SQL. Sin embargo, si aadimos cdigo en esas tablas (lo que puede ser necesario en algunas ocasiones), el sistema crea una instruccin while select y ejecuta el mtodo Delete en todas las tablas hijas relacionadas. De esta forma el rendimiento es menor que cuando utilizamos directamente instrucciones de borrado en SQL.

Pgina 50 de 141

Control de transacciones

Control de transacciones1. IntroduccinUna transaccin es una unidad lgica de trabajo. Las transacciones son operaciones de todo o nada, que aseguran la integridad de los datos en las actualizaciones ms compelas. Consideremos el caso en el que queremos actualizar un grupo de registros. Si el sistema se estropea o el proceso es cancelado durante la operacin, algunos registros pueden haber sido actualizados y otros no. Si realizamos la actualizacin dentro de una transaccin, el sistema nos garantiza que o bien se actualiza completamente la totalidad de los registros o no se realiza ninguna operacin. Es decir, la actualizacin nicamente se consigue cuando la transaccin finaliza con xito. El uso de transacciones nos asegura, en caso de fallo del sistema, la recuperacin de los datos en su estado inicial, mediante un retroceso (rollback). Otro aspecto a tener en cuenta es que podra darse el caso de que dos procesos estuvieran accediendo a un mismo registro. Supongamos que el proceso A lee un registro y a continuacin un proceso B lee el mismo registro. En un instante posterior, el proceso A actualiza el registro y a continuacin el proceso B realiza la misma operacin. En este caso, los cambios realizados por el proceso A se perderan. La solucin a este problema es bloquear los registros o las tablas durante las transacciones de actualizacin (insert, update y delete). Esto podemos hacerlo mediante la sentencia select forUpdate.

2.

Instrucciones TTSLas instrucciones tts se utilizan para marcar el inicio y el final de una transaccin.

2.1.

Instruccin TTSBEGINUtilizamos la sentencia ttsbegin para marcar el comienzo de una transaccin. Esto nos asegura la integridad de datos y garantiza que todas las actualizaciones realizadas hasta la finalizacin de la transaccin son consistentes, o por el contrario no se realiza ninguna. La instruccin ttsbegin no tiene ningn sentido si no tenemos una instruccin de final de transaccin.

2.2.

Instruccin TTSCOMMITUtilizamos la sentencia ttscommit para indicar que una transaccin ha finalizado con xito. Esta instruccin termina una transaccin y lleva a cabo todas las actualizaciones realizadas. MorphX garantiza que una transaccin terminada con la instruccin ttscommit ser realizada por completo.

Pgina 51 de 141

Control de transacciones

2.3.

Instruccin TTSABORTLa sentencia ttsabort nos permite desechar todos los cambios realizados en la transaccin actual de una manera explcita. Esto trae como consecuencia la finalizacin de la transaccin y la vuelta de la base de datos a la situacin inicial, justo antes de comenzar la transaccin. Por lo tanto, es como si no hubiramos realizado ningn cambio. Normalmente, utilizaremos esta sentencia si detectamos que el usuario quiere detener la tarea actual. El uso de la instruccin ttsabort, nos asegura que la base de datos ser consistente. A menudo, la mejor solucin es utilizar las sentencias de gestin de excepciones en lugar de utilizar la sentencia ttsabort.

2.4.

Anidamiento de transaccionesLas instrucciones entre las sentencias ttsbegin y ttscommit, pueden incluir uno o ms bloques de transacciones, es decir podemos anidar dichas transacciones. A continuacin presentamos un ejemplo: Ejemplo de transacciones anidadas ttsbegin; // Instrucciones ttsbegin; // Instrucciones ttscommit; // Instrucciones ttscommit; En estos casos es importante sealar, que la transaccin que realmente importa es la ms externa, es decir la que abrimos en primer lugar. De forma que nada se actualiza hasta que finaliza con xito la ltima instruccin ttscommit.

3.

Control de la integridad de transaccionesAxapta dispone de tcnicas internas de control que aseguran la integridad de las transacciones codificadas por los programadores de X++.

3.1.

Control de seleccin ForUpdateEste tipo de control asegura que ningn registro puede ser actualizado o borrado si previamente no ha indicado explcitamente que se selecciona para ser actualizado. Un registro puede ser seleccionado para ser actualizado mediante la opcin forUpdate de la sentencia select o bien mediante el mtodo selectForUpdate de las tablas. Como ejemplo, Axapta generara un error ante la siguiente transaccin ya que el registro no se ha seleccionado para su actualizacin:

Pgina 52 de 141

Control de transacciones

ttsbegin; select * from myTable; myTable.myField = xyz; myTable.update(); ttscommit;

3.2.

Control a nivel de transaccin (tts)Este control asegura que un registro nicamente puede ser actualizado o borrado dentro de la transaccin en la que ha sido seleccionado para actualizacin. El siguiente ejemplo dara lugar a un error dado que la seleccin y la actualizacin se realizan en transacciones diferentes: ttsbegin; select forUpdate * from myTable; myTable.myField = xyz; ttscommit; ttsbegin; myTable.update();

Pgina 53 de 141

Herramientas de desarrollo

Herramientas de desarrollo1. El editorEl editor de cdigo se puede abrir pulsando dos veces con el ratn sobre el nombre de un mtodo, o bien seleccionando la opcin Edit del men contextual de dicho mtodo.

Icon

Description Crea un Nuevo mtodo o Job. Puedes tener varios mtodos/jobs abiertos al mismo tiempo en el editor. Cada mtodo tiene su propia pestaa con el nombre del Job como ttulo. Salva el cdigo. Si cierras el Job, el sistema te preguntar si quieres guardar los cambios. Ejecuta el Job. El Job es tambin compilado. Un Job con un error de compilacin no funcionar. Sita un punto de interrupcin que el Debugger reconoce. Compila el cdigo. El compilador chequea los errores que hay ahora en el cdigo. La ventana de mensaje nos mostrar si el error es, por ejemplo, de sintaxis, coherencia, ... Propiedades de los mtodos. Te da el perfil de parmetros de un mtodo. Muestra el editor de etiquetas. Esto te da el texto de la etiqueta de la etiqueta que est seleccionada. Este icono te dar una lista completa de todas las etiquetas disponibles. Ejecuta un script, por Ejemplo, para transformar una parte seleccionada del cdigo en un comentario., o para insertar una cabecera en el Job incluyendo informacin sobre cuando y por quin ha sido editado el Job. Ayuda. Mira entre otras cosas una lista de teclas de acceso rpido. Hay tecla de acceso rpido para listas por ejemplo, tablas clases, o Enums.

Pgina 54 de 141

Herramientas de desarrollo

Click en el botn derecho del ratn en cualquier lugar de la ventana del editor para recibir este men. Adems de repetir varias funciones en la barra de estado del editor, el men incluye un nmero de funciones. Usa este men para mostrar, por ejemplo, tablas, clases y Enums cuando ests escribiendo cdigo en el editor. Usando las teclas de acceso rpido. (como las descritas arriba) para acceder a la misma lista a travs del teclado.

El nombre del mtodo seleccionado se muestra dentro de una solapa. El editor facilita el trabajo con varios mtodos a la vez, ya que cada vez que editamos un mtodo de la misma clase, se crea una nueva solapa en la misma ventana. Por otro lado, permite utilizar las funciones de edicin estndar de Windows tales como copiar, cortar y pegar. La opcin IntelliSense resulta de gran ayuda al desarrollador, ya que cada vez que ste introduce el nombre de un objeto, le muestra su lista de miembros (variables y mtodos). De este modo, el programador no necesita recordarlos. Esta opcin est activa por defecto, pero puede desactivarse desde la ventana de opciones de desarrollo. Esta lista se presenta tambin, si el desarrollador marca el objeto con el ratn y selecciona la opcin Buscar propiedades/mtodos del men contextual o bien pulsa el botn de la barra de herramientas del editor. El resultado se muestra en la figura 1.

Figura 1. Opcin Buscar propiedades/mtodos.

Pgina 55 de 141

Herramientas de desarrollo

Si situamos el cursor sobre un objeto que no dispone de miembros, el sistema muestra un mensaje de ayuda emergente con informacin sobre el tipo de objeto, tal y como muestra la figura 2.

Figura 2. Opcin Buscar propiedades/mtodos.

Esta informacin tambin puede obtenerse mediante la combinacin de teclas CTRL+SPACE. El men contextual nos ofrece otras opciones de bsqueda, como Buscar etiqueta/texto que abre el generador de etiquetas. Este mismo resultado se obtiene pulsando sobre el botn de la barra de herramientas del editor.

Por ltimo, la opcin Buscar definicin ejecutada sobre un mtodo, abre este mtodo en una nueva ventana del editor. El editor tambin nos ofrece la posibilidad de utilizar la tecla F1 para obtener ayuda sensible al contexto. Si marcamos con el ratn un elemento cuya informacin de ayuda se encuentra en la Documentacin de sistema o bien en la Documentacin de la aplicacin y pulsamos F1, se mostrar esta ayuda. As, por ejemplo si marcamos una variable perteneciente a una clase de sistema y pulsamos F1, obtendremos ayuda acerca de esta clase. Si F1 se pulsa en un elemento del que no se dispone informacin, obtendremos ayuda acerca del uso del editor de texto. El men contextual nos ofrece otras utilidades como las listas de objetos. As, encontramos las siguientes opciones: Enumerar tablas Enumerar clases Enumerar tipos

Pgina 56 de 141

Herramientas de desarrollo

Listar enumeraciones Enumerar palabras reservadas Enumerar funciones incorporadas

Figura 3. Opcin Listar enumeraciones.

Cada una de estas opciones muestra la lista de objetos correspondiente, de la cual podemos seleccionar el que nos interese. En la figura siguiente podemos ver el resultado de seleccionar la opcin Listar enumeraciones. Como vemos, tenemos acceso a los elementos del enumerado seleccionado. Para salir del editor podemos pulsar la tecla ESC. Si hemos realizado cambios, el sistema preguntar si queremos guardar dichos cambios.

2.

El generador de etiquetasCuando tengamos la necesidad de introducir algn texto en nuestro cdigo lo haremos utilizando una etiqueta. Las etiquetas en Axapta son uno de los elementos fundamentales para asegurarnos que las aplicaciones realizadas sern multi-lenguaje, es decir, podremos elegir el idioma en el que queremos que aparezcan nuestros formularios, informes, cuadros de dilogo, etc. Para la creacin de etiquetas disponemos en Axapta de un generador de etiquetas que va a facilitar nuestro trabajo. Cuando pulsamos con el ratn sobre el botn , nos aparece esta herramienta, que nos permite buscar, crear e insertar etiquetas. Como hemos comentado en el apartado anterior, el generador de herramientas tambin se puede abrir mediante la opcin Buscar etiqueta/texto del men contextual.

Pgina 57 de 141

Herramientas de desarrollo

Figura 4. El generador de etiquetas.

La lista desplegable Idioma seleccionado, muestra el lenguaje que se seleccion al poner en funcionamiento la aplicacin. Cuando comenzamos la bsqueda de una cadena de texto determinada, este parmetro determina el fichero de etiquetas en el cual se realizar la bsqueda. El cuadro de texto Bsqueda de etiqueta, nos permite introducir la cadena de texto que queramos buscar en el fichero de etiquetas. La bsqueda encuentra todas las instancias de la cadena de texto. El botn de comando Buscar ahora, comienza la bsqueda de la cadena de texto que se haya introducido en el cuadro de texto que acabamos de describir. La lista en el cuadro de dilogo muestra el resultado de la bsqueda de la cadena de texto. Se nos muestran los nombres de todas las etiquetas, por las que nos podemos desplazar utilizando los botones Siguiente y Anterior. La casilla de verificacin Mostrar todos los idiomas, muestra las traducciones de la etiqueta actual en todos los lenguajes disponibles en nuestra instalacin de Axapta. La lista desplegable Archivo de etiquetas, nos muestra los caracteres que identifican un archivo de etiquetas. El nombre de los archivos de etiquetas se compone del siguiente modo: Ax.ald, donde ald es el acrnimo de application label data (datos de etiquetas de la aplicacin). En la aplicacin estndar, el identificador del archivo es SYS. En nuestros desarrollos podremos definir un archivo de etiquetas para el nivel en el que estemos trabajando o bien podemos utilizar otras tcnicas, tales como crear un archivo por cada aplicacin desarrollada.

Pgina 58 de 141

Herramientas de desarrollo

3.

El depuradorEl depurador es una herramienta de desarrollo presente en el entorno MorphX, como sucede en la mayora de entornos de programacin. La utilizacin del depurador va a ser muy til en tareas relacionadas con la programacin de aplicaciones, como la deteccin de errores, optimizacin de cdigo, etc. Con el depurador podemos realizar distintas operaciones, que pueden ser ejecutadas desde los botones de la barra de herramientas o bien mediante una combinacin de teclas. Estas operaciones son las siguientes: Ejecutar cdigo Ejecutar paso a paso las lneas de cdigo Introducir puntos de ruptura (breakpoints) Abrir una ventana de variables, donde se muestra una lnea para cada variable con su nombre, tipo, mbito y valor Ver la pila de llamadas Ver el estado del sistema Mostrar los nmeros de lneas en el cdigo Cuando elegimos la opcin de ejecutar nuestro cdigo con informacin de depuracin, las lneas de cdigo se muestran en la ventana del depurador. Para poder poner en marcha el depurador de cdigo debemos introducir un punto de ruptura o breakpoint. Podemos introducir un punto de ruptura directamente desde el editor de cdigo situando el cursor en la lnea en la que queremos que se detenga la ejecucin y pulsando con el ratn en el botn hacerlo apretando la tecla F9. de la barra de herramientas. Tambin podemos

Cuando ejecutemos el cdigo, la ejecucin se detendr en el punto de ruptura y se abrir el depurador. La siguiente figura muestra la apariencia del depurador:

Figura 5. El depurador.

Pgina 59 de 141

Herramientas de desarrollo

En la ventana de variables podemos ver cmo cambia el valor de las variables a medida que vamos ejecutando el cdigo paso a paso. Tambin podemos poner una o ms variables a un valor especfico, introduciendo ste en la columna Valor.

Figura 6. La ventana de variables del depurador.

Podemos activar la ventana de variables pulsando sobre el botn herramientas del depurador.

de la barra de

Cuando una lnea en la ventana de variables contiene un objeto compuesto, podemos situar el cursor en esa lnea y apretar la tecla ENTER. Se abrir una segunda ventana que mostrar el valor actual de cada uno de los elementos de dicho objeto.

Figura 7. Ventana de elementos de un objeto compuesto.

Pgina 60 de 141

Programacin de formularios

4.

Seguimientos o trazas

Si se quiere realizar una traza del programa en ejecucin necesitas activar las trazas. Para hacer esto debes ir al men de herramientas, seleccionar opciones, y una vez dentro de opciones marcar la pestaa de desarrollo., Aqu ves un grupo de traza (Seguimiento), en el que hay 4 opciones: Seguimiento de la base de datos. Seguimiento de los mtodos. Seguimiento de cliente/servidor. Seguimiento ActiveX. Cuando seleccionas un seguimiento de los mtodos una pantalla aparecer tan pronto se active uno de los controloes a los que estoy siguiendo. Nota: Hay que darse cuenta de que si seleccionas seguimiento de mtodos conseguirs mucha informacin muy rpido porque Axapta muestra todos los mtodos que son llamados, como OnMouseMove o OnMouseLeave.

Programacin de formularios1. IntroduccinComo ya hemos comentado, podemos introducir cdigo en lenguaje X++ en muchas partes del sistema. Los formularios no son una excepcin. Existen distintos mbitos en los formularios donde podemos aadir cdigo. Estos mbitos son los siguientes: Formulario propiamente dicho Origen de datos del formulario Controles del formulario Dependiendo de la funcionalidad que queramos implementar, escribiremos el cdigo en un mbito o en otro. No obstante, normalmente, se siguen las siguientes reglas: Codificamos en los mtodos del propio formulario, cuando queremos controlar la funcionalidad general del mismo. Codificamos en los mtodos del origen de datos, cuando queremos controlar la funcionalidad de los datos que aparecen en el formulario.

Pgina 61 de 141

Programacin de formularios

Codificamos en los controles, cuando queremos controlar la funcionalidad de alguno de los controles o elementos especficos que aparecen en el formulario.

Se debe tener en cuenta que el cdigo que se introduce en un formulario ser accesible nicamente desde el formulario. Cualquier funcionalidad que deba ser accesible desde otro elemento, debe codificarse fuera del formulario. La funcionalidad relacionada con los datos se codificar en la tabla siempre que sea posible. Si se trata de otro tipo de funcionalidad, puede implementarse una clase para ello.

2.

Variables del sistemaAnteriormente se dijo que todas las variables deben ser declaradas antes de poder ser utilizadas. Sin embargo, cuando trabajamos con los formularios, algunas variables son declaradas implcitamente por el sistema. Adems de estas variables, es conveniente recordar que en cualquier momento, la variable this nos da acceso al elemento al que pertenece el mtodo que estamos modificando. A continuacin se describen las variables de sistema de los formularios y los elementos a los que dan acceso: a) Formulario

Se trata de una variable de tipo FormRun, que recibe el nombre de element y que referencia al objeto formulario. Nos permite acceder a los mtodos definidos a nivel de formulario. La variable element se utiliza normalmente en asignaciones como la que mostramos a continuacin: Tb. Existe la variable form notifyDate = element.design().control(Control::NotifyDate); b) Tabla

Por cada uno de los orgenes de datos del formulario, disponemos de una variable llamada como stos, que nos referencia la tabla que utilizamos en dicho origen de datos. Por ejemplo, suponiendo que el origen de datos del formulario se llamara DatosFormulario, tendramos una variable con ese nombre que hara referencia a la tabla. En realidad, en un momento dado esta variable nos da acceso al registro activo de la tabla, de manera que podremos: 1. Llamar a un mtodo definido en la tabla. Por ejemplo: DatosFormulario.setDefault(ReadWrite::Write); 2. Hacer referencia a los campos individuales de la tabla. Por ejemplo: number = DatosFormulario.accountNo; c) Origen de datos

Pgina 62 de 141

Programacin de formularios

Tendremos tambin una variable llamada como el origen de datos del formulario con el sufijo _DS para hacer referencia a las propiedades y los mtodos de dicho origen de datos. Por ejemplo, en el caso de que nuestro origen de datos se llamara DatosFormulario, tendramos una variable llamada DatosFormulario_DS. Se trata de una variable de tipo FormDataSource que nos da la posibilidad de ejecutar directamente sus mtodos. Por ejemplo: DatosFormulario_DS.reSearch(); d) Consulta Existen dos variables que nos permiten acceder a la consulta de un formulario: Una variable de tipo Query llamada como el origen de datos del formulario con el sufijo _Q para hacer referencia a las propiedades y los mtodos de la consulta (query). Por ejemplo, en nuestro caso, tendramos una variable llamada DatosFormulario_Q. Esto nos da la posibilidad de ejecutar directamente sus mtodos. Por ejemplo: DatosFormulario_Q.levelNo(1); Una variable de tipo QueryRun llamada como el origen de datos del formulario con el sufijo _QR para hacer referencia a las propiedades y los mtodos de una instancia en ejecucin de la consulta de dicho origen de datos (queryRun). Por ejemplo, en nuestro caso, tendramos una variable llamada DatosFormulario_QR. Esto nos da la posibilidad de ejecutar directamente sus mtodos. Por ejemplo: DatosFormulario_QR.getNo(1); Es importante sealar que en versiones anteriores de Axapta, no existan las variables declaradas implcitamente para la consulta (_Q) y para la instancia en ejecucin de la consulta (_QR). Esto hace que nos podamos encontrar en muchos mtodos todava la forma tradicional de acceder a ellas desde cdigo. Para acceder a una consulta, debamos hacer una declaracin de variable, tras la cual podamos utilizar la variable declarada para acceder a los mtodos de dicha consulta. Por ejemplo, dentro de un origen de datos podramos acceder a su consulta de la siguiente forma: Ejemplo de declaracin de una consulta Query ; q = this.query(); q.levelNo(1); Para acceder a una instancia en ejecucin de una consulta, tambin debamos hacer una declaracin de variable. Siguiendo con el mismo ejemplo lo haramos de la forma siguiente: Ejemplo de declaracin de instancia en ejecucin de una consulta QueryRun ; qr = this.queryRun(); qr; q;

Pgina 63 de 141

Programacin de formularios

qr.getNo(1); En ambos casos la variable this hara referencia al objeto en ejecucin en ese momento, es decir, al origen de datos.

Siempre es ms aconsejable utilizar las variables implcitas declaradas por el sistema en lugar de definir nuevas variables, ya que de esta forma evitamos que existan variables iguales duplicadas en memoria.

3.

Mtodos del formularioCuando creamos un nuevo formulario el sistema genera automticamente un nodo de mtodos. Adems de modificar los mtodos creados por el sistema, el desarrollador puede aadir nuevos mtodos con el propsito de aadir funcionalidad lgica al formulario.

Es interesante recordar, que siempre que sea posible, se debe introducir el cdigo en la tabla de la que se obtienen los datos para el formulario. Los mtodos escritos en la tabla son accesibles desde cualquier formulario que utilice dicha tabla. En trminos de reutilizacin y herencia, aadir cdigo en los mtodos de un formulario es menos eficiente que introducirlo directamente en la tabla.

3.1.

Mtodos de sistemaEl nodo contiene lo que se llaman mtodos virtuales, que son mtodos implementados en MorphX, pero que pueden ser sobrecargados para cambiar el comportamiento por defecto de los formularios. En estos mtodos la funcin llamada super() activa la ejecucin del mtodo implementado por MorphX.

3.1.1.

Lista de mtodosLos formularios en MorphX tienen los siguientes mtodos de sistema:

Mtodo CanClose

Se ejecuta cuando... se cierra un formulario. Utilizaremos este mtodo, para aadir nuestras propias comprobaciones a las que realiza el sistema cuando cerramos un formulario. se cierra un formulario. Dependiendo del estado en el cual cierre el formulario, el mtodo Close se activa desde CloseCancel o desde CloseOK. el usuario pulsa con el ratn sobre el botn cancelar o cuando pulsamos le techa ESC. Cuando cerramos un formulario mediante el mtodo CloseCancel, no grabamos las modificaciones. el usuario pulsa con el ratn el botn Aceptar.

Close

CloseCancel

CloseOK

Pgina 64 de 141

Programacin de formularios

DoApply Finalize

el usuario cierra un formulario modal. se cierra el formulario. El objetivo de este mtodo es destruir el objeto y liberar la memoria. nos movemos al primer campo de un formulario. abrimos el formulario. nos movemos al ltimo campo de un formulario. nos movemos al siguiente campo dentro de un formulario. nos movemos al siguiente grupo de campos dentro de un formulario. nos movemos al campo anterior dentro de un formulario. nos movemos al grupo de campos anterior dentro de un formulario. abrimos el formulario, inmediatamente despus del mtodo Init, para mostrar el formulario. el usuario realiza alguna tarea en el formulario, como por ejemplo: utilizar la barra de herramientas, el men o el teclado.

FirstField Init LastField NextField NextGroup

PrevField PrevGroup Run

Task

3.1.2.

Mtodos principales y su funcin

A continuacin vamos a describir algunos de los mtodos ms utilizados en los formularios, que por su importancia merecen un tratamiento algo ms exhaustivo. a) Mtodo ClassDeclaration En este mtodo se definen las variables globales del formulario. Es decir, aqullas cuyo mbito es el formulario en su totalidad y, por lo tanto, pueden ser utilizadas en cualquier mtodo del formulario, de los orgenes de datos o de los controles. Como ejemplo, veamos el mtodo ClassDeclaration del formulario CustTable. Ejemplo de mtodo ClassDeclaration class FormRun extends ObjectRun { NumberSeq CustAccount FormStringControl FormStringControl } b) Mtodo Init numberSeq; numAllocated; contactPerson; contactPersonId;

Pgina 65 de 141

Programacin de formularios

Se ejecuta cuando abrimos el formulario. Se utiliza, bsicamente, para la inicializacin de variables. Debemos realizar una llamada al mtodo super(), ya que ste es el encargado de crear una instancia en ejecucin del formulario. Crea tambin el origen de datos, mediante una llamada al mtodo Init del origen de datos. Antes de la llamada al mtodo super(), podemos modificar el formulario mediante los mtodos de la clase FormBuild. Tras el mtodo super() y una vez creado el formulario, podemos inicializar variables. Como ejemplo, tenemos el mtodo Init del formulario CustTable. Ejemplo de mtodo Init void init() { super(); contactPersonId = element.control(control::ContactPersonId); TaxVATNumTable::enableLookupVatNum(vatNum); } c) Mtodo Run Se ejecuta cuando abrimos un formulario, inmediatamente despus del mtodo Init. La llamada al mtodo super() hace que la ventana aparezca en la pantalla, y realiza una bsqueda en la base de datos para obtener los datos que deben mostrarse en el formulario. La consulta la realiza activando el mtodo ExecuteQuery() del origen de datos. d) Mtodo Close Se ejecuta cuando cerramos un formulario. La llamada a super() cierra la ventana del formulario, realiza las actualizaciones en la base de datos y activa el indicador booleano Closed. Dependiendo del estado en el cual cierre el formulario, el mtodo Close se activa desde CloseCancel o desde CloseOK. Como ejemplo, tenemos el mtodo Close del formulario CustTable. Ejemplo de mtodo Close void close() { if (!custTable.recId && numberSeq) numberSeq.abort(); super(); }

Pgina 66 de 141

Programacin de formularios

3.2.

Acceso a los controles desde el cdigoDesde cualquier mtodo podemos acceder a las propiedades y mtodos de los controles del formulario. Para ello, necesitamos tener una referencia al control, que se puede obtener de dos formas: Mediante la propiedad Autodeclaration de los controles Mediante mtodos de las clases de sistema Todos los controles de un formulario tienen una propiedad llama