advertisement

Programación con C/AL para Microsoft Business Solutions Navision

50 %
50 %
advertisement
Information about Programación con C/AL para Microsoft Business Solutions Navision

Published on May 9, 2007

Author: pabloesp

Source: slideshare.net

Description

Este pequeño curso toca todos los aspectos esenciales del lenguaje de programación C/AL dentro del entorno de Navision
advertisement

Programación en Lenguaje C/AL para Microsoft Business Solutions Navision Pablo Espada Bueno www.esbupa.com www.programadorautonomo.net Nota: Microsoft, Navision, C/AL, etc… son marcas registradas de Microsoft

Habitualmente me dedico a impartir formación y a labores de desarrollo y consultoría en .NET También imparto formaciones sobre Desarrollo en Navision Si desea que colabore con usted impartiéndoles una formación o desarrollando algún proyecto, puede contactarme: Web www.programadorautonomo.net www.esbupa.com Email [email_address] [email_address] Espero que les guste la presentación Contacto

Habitualmente me dedico a impartir formación y a labores de desarrollo y consultoría en .NET

También imparto formaciones sobre Desarrollo en Navision

Si desea que colabore con usted impartiéndoles una formación o desarrollando algún proyecto, puede contactarme:

Web

www.programadorautonomo.net

www.esbupa.com

Email

[email_address]

[email_address]

Espero que les guste la presentación

Lenguaje C/AL - Indice Tipos de datos Variables Funciones Operadores Sentencias Asignación Decisión (IF, CASE) Iteración (FOR, REPEAT, WHILE) Otras Comentarios Tablas Acceso a objetos Formularios Informes Unidades de código DataPorts Funciones comunes SumIndexFields Flowfields Diálogos Acceso a ficheros Depurador Seguimiento de Código Asistente para código OCX BLOB Formateo estándar

Tipos de datos

Variables

Funciones

Operadores

Sentencias

Asignación

Decisión (IF, CASE)

Iteración (FOR, REPEAT, WHILE)

Otras

Comentarios

Tablas

Acceso a objetos

Formularios

Informes

Unidades de código

DataPorts

Funciones comunes

SumIndexFields

Flowfields

Diálogos

Acceso a ficheros

Depurador

Seguimiento de Código

Asistente para código

OCX

BLOB

Formateo estándar

Introducción Lenguaje 4GL para trabajar en entorno Navision Especializado en trabajo sobre la BBDD relacional Integrado en entorno Windows OCX para acceso a datos de otras aplicaciones Acceso a ficheros

Lenguaje 4GL para trabajar en entorno Navision

Especializado en trabajo sobre la BBDD relacional

Integrado en entorno Windows

OCX para acceso a datos de otras aplicaciones

Acceso a ficheros

Tipos de datos Variables fundamentales: Numéricas Integer Números entre -2.147.483.647 y +2.147.483.647. BigInteger Número de 64 bits. Se usa L para indicar que es un entero largo: bi := 3983200032984209L. Decimal Números entre -10E63 y +10E63. 18 dígitos significativos. Char Un carácter entre 0 y 255, convertible libremente de entero a carácter. Operable como un integer o como un carácter: C := 'A'; C := S[2]; C := C + 1; Option Número de opción entre -2.147.483.647 y +2.147.483.647 , convertible libremente de entero a opción. Las opciones se declaran simbólicamente con la propiedad OptionString de la variable: OptionString = Oferta,Pedido,Factura,Abono

Variables fundamentales: Numéricas

Integer

Números entre -2.147.483.647 y +2.147.483.647.

BigInteger

Número de 64 bits.

Se usa L para indicar que es un entero largo: bi := 3983200032984209L.

Decimal

Números entre -10E63 y +10E63.

18 dígitos significativos.

Char

Un carácter entre 0 y 255, convertible libremente de entero a carácter.

Operable como un integer o como un carácter:

C := 'A';

C := S[2];

C := C + 1;

Option

Número de opción entre -2.147.483.647 y +2.147.483.647 , convertible libremente de entero a opción. Las opciones se declaran simbólicamente con la propiedad OptionString de la variable: OptionString = Oferta,Pedido,Factura,Abono

Tipos de datos (II) Variables fundamentales: De Cadena Text Cadenas de hasta 250 caracteres. Sus caracteres son indizables: Nombre[3] Code Cadenas de texto de hasta 250 caracteres. En mayúsculas. El sistema hace automáticamente la conversión, y quita espacios iniciales y finales. Sus caracteres son indizables: CodFormasPago[3]

Variables fundamentales: De Cadena

Text

Cadenas de hasta 250 caracteres.

Sus caracteres son indizables:

Nombre[3]

Code

Cadenas de texto de hasta 250 caracteres.

En mayúsculas.

El sistema hace automáticamente la conversión, y quita espacios iniciales y finales. Sus caracteres son indizables:

CodFormasPago[3]

Tipos de datos (III) Variables fundamentales: Fecha y Hora Date Almacena una fecha. Se inicializa con 0D. hoy := 220704D; Time Almacena una hora Se inicializa con 0T hora := 123000T; DateTime Almacena una hora UTC. Siempre se mostrará adaptada al horario local Se inicializa con 0T fechahora := December 31, 2004, 14:20:59.999.;

Variables fundamentales: Fecha y Hora

Date

Almacena una fecha.

Se inicializa con 0D.

hoy := 220704D;

Time

Almacena una hora

Se inicializa con 0T

hora := 123000T;

DateTime

Almacena una hora UTC. Siempre se mostrará adaptada al horario local

Se inicializa con 0T

fechahora := December 31, 2004, 14:20:59.999.;

Tipos de Datos (y IV) Variables fundamentales: Booleanas Boolean Valores lógicos: TRUE o FALSE

Variables fundamentales: Booleanas

Boolean

Valores lógicos: TRUE o FALSE

Tipos Complejos C/AL incluye un conjunto de tipos complejos utilizados en ciertos casos BLOB Se utiliza para almacenar valores binarios (imágenes, ficheros, videos, etc..) y se almacena de forma externa al registro de la base de datos. Tamaño máx 2GB Record Un record se asocia con un registro de cada tabla. El acceso a los campos se realiza escribiendo el nombre del registro, un punto y el nombre del campo: EJ: Customer.”No.”

C/AL incluye un conjunto de tipos complejos utilizados en ciertos casos

BLOB

Se utiliza para almacenar valores binarios (imágenes, ficheros, videos, etc..) y se almacena de forma externa al registro de la base de datos. Tamaño máx 2GB

Record

Un record se asocia con un registro de cada tabla.

El acceso a los campos se realiza escribiendo el nombre del registro, un punto y el nombre del campo:

EJ: Customer.”No.”

Tipos Complejos (II) Form Representa un Formulario. Cada formulario estará compuesto por un conjunto de controles Report Representa un Informe Codeunit Contenedores de código, organizado en funciones File Tipo Fichero. Permite acceder a un fichero del sistema de ficheros

Form

Representa un Formulario. Cada formulario estará compuesto por un conjunto de controles

Report

Representa un Informe

Codeunit

Contenedores de código, organizado en funciones

File

Tipo Fichero. Permite acceder a un fichero del sistema de ficheros

Tipos Complejos (III) Dialog Representa un cuadro de diálogo. DateFormula Representa una fórmula para la función CALCDATE GUID Identificador Único del sistema. 16 bytes: 12345678-1234-1234-1234-1234567890AB TableFilter Permite aplicar un filtro a una tabla. Sólo utilizado para Permisos

Dialog

Representa un cuadro de diálogo.

DateFormula

Representa una fórmula para la función CALCDATE

GUID

Identificador Único del sistema. 16 bytes:

12345678-1234-1234-1234-1234567890AB

TableFilter

Permite aplicar un filtro a una tabla. Sólo utilizado para Permisos

Tipos Complejos (IV) RecordRef Puntero a un Registro. Se diferencia con el tipo Record en que, a priori, desconocemos la tabla a la que va a apuntar. El equivalente para campos es el FieldRef El equivalente para claves es el KeyRef RecordID Almacena el ID de la Tabla junto con la Clave Primaria. InStream y OutStream Permiten leer y escribir BLOB’s Variant Tipo Indefinido necesario para el uso de OCX Contiene: record, file, action, codeunit, Automation, boolean, option, integer, decimal, char, text, code, date, time, binary, DateFormula, TransactionType, InStream and OutStream. BigText Similar al BLOB pero sólo para contenidos de texto. MAX 2GB

RecordRef

Puntero a un Registro. Se diferencia con el tipo Record en que, a priori, desconocemos la tabla a la que va a apuntar.

El equivalente para campos es el FieldRef

El equivalente para claves es el KeyRef

RecordID

Almacena el ID de la Tabla junto con la Clave Primaria.

InStream y OutStream

Permiten leer y escribir BLOB’s

Variant

Tipo Indefinido necesario para el uso de OCX

Contiene: record, file, action, codeunit, Automation, boolean, option, integer, decimal, char, text, code, date, time, binary, DateFormula, TransactionType, InStream and OutStream.

BigText

Similar al BLOB pero sólo para contenidos de texto. MAX 2GB

Variables Inicialización C/AL inicializa las variables por defecto a los siguientes valores: Boolean: FALSE Numeric: 0 Strings: '' Date: 0D Time: 0T

Inicialización

C/AL inicializa las variables por defecto a los siguientes valores:

Boolean: FALSE

Numeric: 0

Strings: ''

Date: 0D

Time: 0T

Variables (II) Definición Las variables en C/AL pueden ser : Locales : Su ámbito es la función donde se definen Globales : Su ámbito es el objeto donde se definen

Definición

Las variables en C/AL pueden ser :

Locales : Su ámbito es la función donde se definen

Globales : Su ámbito es el objeto donde se definen

Variables (III) Ejemplo: Crearemos una nueva CodeUnit Definiremos un conjunto de variables (locales y globales) Podemos crear una variable Option y mostrar sus valores así: MESSAGE('The value of %1 is %2','LoopNo',LoopNo);

Ejemplo:

Crearemos una nueva CodeUnit

Definiremos un conjunto de variables (locales y globales)

Podemos crear una variable Option y mostrar sus valores así:

MESSAGE('The value of %1 is %2','LoopNo',LoopNo);

Variables (IV) Arrays y matrices Se definen con la propiedad Dimensions de la variable Dimensions=4;3 Se las referencia con corchetes SaldoCtaBanco[2,2] los índices tienen rango 1…n Funciones: CLEAR (Borra todo el Array) ARRAYLEN (Devuelve la Longitud del Array)

Arrays y matrices

Se definen con la propiedad Dimensions de la variable

Dimensions=4;3

Se las referencia con corchetes

SaldoCtaBanco[2,2]

los índices tienen rango 1…n

Funciones:

CLEAR (Borra todo el Array)

ARRAYLEN (Devuelve la Longitud del Array)

Variables del Sistema Variables del sistema (system-defined variables) C/SIDE las crea y deja disponibles para el programador en ciertos contextos Rec Cuando se modifica un registro, Rec contiene el registro en su estado modificado. xRec Cuando se modifica un registro, xRec contiene el registro antes de la modificación. CurrForm Variable que representa el objeto Form actual. CurrReport Variable que representa el objeto Report actual. RequestOptionsForm Variable que representa el formulario de diálogo de entrada al objeto Report actual. CurrFieldNo El número de campo del campo actual desde el que se llamó al disparador.

Variables del sistema (system-defined variables)

C/SIDE las crea y deja disponibles para el programador en ciertos contextos

Rec

Cuando se modifica un registro, Rec contiene el registro en su estado modificado.

xRec

Cuando se modifica un registro, xRec contiene el registro antes de la modificación.

CurrForm

Variable que representa el objeto Form actual.

CurrReport

Variable que representa el objeto Report actual.

RequestOptionsForm

Variable que representa el formulario de diálogo de entrada al objeto Report actual.

CurrFieldNo

El número de campo del campo actual desde el que se llamó al disparador.

Funciones Definición La función se define con un nombre, una serie de parámetros opcionales y un valor de retorno opcional. Pueden tener variables locales. Los parámetros pueden ser por referencia (se modifica su valor, ej: “valor”) o por valor (no se altera el valor, ej: “flag”) Se pueden llamar desde otros objetos

Definición

La función se define con un nombre, una serie de parámetros opcionales y un valor de retorno opcional. Pueden tener variables locales.

Los parámetros pueden ser por referencia (se modifica su valor, ej: “valor”) o por valor (no se altera el valor, ej: “flag”)

Se pueden llamar desde otros objetos

Operadores Operador de C/AL Significado . campo de registro, control de formulario o informe ( ) paréntesis [ ] indización :: ámbito + suma - resta * multiplicación / división DIV división entera MOD resto > mayor que >= mayor o igual que < menor que <= menor o igual que = igual a <> diferente de IN pertenencia a un rango (conjunto) AND Y lógico OR O lógico NOT negación lógica XOR O excluyente lógico .. Rango

Operador de C/AL Significado

. campo de registro, control de formulario o informe

( ) paréntesis

[ ] indización

:: ámbito

+ suma

- resta

* multiplicación

/ división

DIV división entera

MOD resto

> mayor que

>= mayor o igual que

< menor que

<= menor o igual que

= igual a

<> diferente de

IN pertenencia a un rango (conjunto)

AND Y lógico

OR O lógico

NOT negación lógica

XOR O excluyente lógico

.. Rango

Operadores (II) 1. . campo de un registro [] indización () paréntesis :: ámbito 2. NOT negación lógica - inversión de signo o signo negativo + signo positivo 3. * multiplicación / división decimal DIV división entera MOD resto AND Y lógico XOR O excluyente lógico 4. + suma - resta OR O lógico 5. > mayor que < menor que >= mayor o igual que <= menor o igual que = igual que <> distinto de IN pertenencia a conjunto 6. .. rango Precedencia

1. . campo de un registro

[] indización

() paréntesis

:: ámbito

2. NOT negación lógica

- inversión de signo o signo negativo

+ signo positivo

3. * multiplicación

/ división decimal

DIV división entera

MOD resto

AND Y lógico

XOR O excluyente lógico

Operadores (III)

Ejemplos Creamos un nuevo formulario tipo Ficha Añadimos 3 TextBox y un Botón (Ejecutar) Asociamos los 3 TextBox con 3 variables: Value1: Integer Value2: Integer Result: Boolean Al pulsar Ejecutar, realizamos las siguientes comparaciónes: Result := Value1 > Value2; Result := (Value1 >= Value2) AND (Value1 <= Value2 * 2)

Creamos un nuevo formulario tipo Ficha

Añadimos 3 TextBox y un Botón (Ejecutar)

Asociamos los 3 TextBox con 3 variables:

Value1: Integer

Value2: Integer

Result: Boolean

Al pulsar Ejecutar, realizamos las siguientes comparaciónes:

Result := Value1 > Value2;

Result := (Value1 >= Value2) AND (Value1 <= Value2 * 2)

Sentencias - Normas Notación y reglas Una sentencia comienza en ; como separador de la anterior. La parte ELSE de las sentencias IF es parte de la misma sentencia. [ ] indica opcionalidad en esa parte de la sentencia. Un bloque de sentencias contiene un conjunto de sentencias entre BEGIN y END; Begin <sentencia> <sentencia> .. End; Una <expresion> devuelve un valor. Una <expr-asignación> asigna el valor resultado de la expresión a una variable. El nombre de los campos, si contiene espacios o caracteres especiales, se escribe entre “comillas”

Notación y reglas

Una sentencia comienza en ; como separador de la anterior.

La parte ELSE de las sentencias IF es parte de la misma sentencia.

[ ] indica opcionalidad en esa parte de la sentencia.

Un bloque de sentencias contiene un conjunto de sentencias entre BEGIN y END;

Begin

<sentencia>

<sentencia>

..

End;

Una <expresion> devuelve un valor.

Una <expr-asignación> asigna el valor resultado de la expresión a una variable.

El nombre de los campos, si contiene espacios o caracteres especiales, se escribe entre “comillas”

Sentencias (I) Asignación Operador de asignación hoy := 220704D; valor := 4; Como consecuencia de llamada a función Valor de retorno de una función Function Cuadrado (valor : Integer) cuad : Integer Begin cuad := valor * valor End; valor := Cuadrado(3); // Valor será igual a 9 Paso de parámetro por referencia a una función Function Cubo (VAR valor : Integer) Begin valor := valor * valor * valor End; valor := 2; Cubo(valor); // Valor será igual a 8

Asignación

Operador de asignación

hoy := 220704D;

valor := 4;

Como consecuencia de llamada a función

Valor de retorno de una función

Function Cuadrado (valor : Integer) cuad : Integer

Begin

cuad := valor * valor

End;

valor := Cuadrado(3); // Valor será igual a 9

Paso de parámetro por referencia a una función

Function Cubo (VAR valor : Integer)

Begin

valor := valor * valor * valor

End;

valor := 2;

Cubo(valor); // Valor será igual a 8

Operador de Cadenas El símbolo ‘+’ se utiliza para concatenar cadenas ¿Qué ocurre si realizamos una asignación de una cadena con el resultado de concatenar otras dos, y dicho resultado es de mayor tamaño que la cadena? Se produce un error de ejecución Lo podemos solucionar comprobando primero dicho desbordamiento: MAXSTRLEN nos devuelve el tamaño máximo de cadena COPYSTR nos permite copiar n caracteres de una cadena a otra. Usar F5 (Symbol Menu) para ayudarse

El símbolo ‘+’ se utiliza para concatenar cadenas

¿Qué ocurre si realizamos una asignación de una cadena con el resultado de concatenar otras dos, y dicho resultado es de mayor tamaño que la cadena?

Se produce un error de ejecución

Lo podemos solucionar comprobando primero dicho desbordamiento:

MAXSTRLEN nos devuelve el tamaño máximo de cadena

COPYSTR nos permite copiar n caracteres de una cadena a otra.

Usar F5 (Symbol Menu) para ayudarse

Sentencias (II) Decisión IF Evalúa la condición, si es cierta se ejecuta el bloque de sentencias del IF , en otro caso el de la parte ELSE. IF <condición> THEN <bloque de sentencias> [ ELSE <bloque de sentencias> ] Ejemplo IF (Cantidad = 0) AND (&quot;Cantidad facturada&quot; <> 0) THEN TESTFIELD(&quot;Nº orden mov. producto asoc.&quot;) ELSE BEGIN IF Cantidad <> &quot;Cantidad facturada&quot; THEN TESTFIELD(&quot;Cantidad facturada&quot;,0); TESTFIELD(&quot;Nº orden mov. producto asoc.&quot;,0); END;

Decisión

IF

Evalúa la condición, si es cierta se ejecuta el bloque de sentencias del IF , en otro caso el de la parte ELSE.

IF <condición> THEN

<bloque de sentencias>

[ ELSE

<bloque de sentencias> ]

Ejemplo

IF (Cantidad = 0) AND (&quot;Cantidad facturada&quot; <> 0) THEN

TESTFIELD(&quot;Nº orden mov. producto asoc.&quot;)

ELSE BEGIN

IF Cantidad <> &quot;Cantidad facturada&quot; THEN

TESTFIELD(&quot;Cantidad facturada&quot;,0);

TESTFIELD(&quot;Nº orden mov. producto asoc.&quot;,0);

END;

Ejemplos Modificaremos el formulario anterior de la siguiente forma: Definición Variables Execute OnPush Execute Clear

Modificaremos el formulario anterior de la siguiente forma:

Ejemplos Añadir lo necesario para calcular la media de unidades vendidas/compradas Contadores de veces que se compra/vende Totales de Ventas/Compras

Añadir lo necesario para calcular la media de unidades vendidas/compradas

Contadores de veces que se compra/vende

Totales de Ventas/Compras

Ejemplos Sobre el ejemplo anterior, añadimos la opción una lista de 10 TextBox y un Array de 10 decimales Debemos hacer que cada vez que pulsemos el botón Ejecutar, el resultado se muestre en una posición distinta del Array

Sobre el ejemplo anterior, añadimos la opción una lista de 10 TextBox y un Array de 10 decimales

Debemos hacer que cada vez que pulsemos el botón Ejecutar, el resultado se muestre en una posición distinta del Array

Sentencias (III) Decisión CASE Evalúa la expresión y ejecuta el bloque de sentencias del valor correspondiente. Si no hay un valor igual, ejecuta el bloque de sentencias del ELSE . CASE <expresión> OF <valor>: <bloque de sentencias>; … <valor>: <bloque de sentencias> [ ELSE <bloque de sentencias> ] END; Ejemplo CASE &quot;Tipo importe&quot; OF &quot;Tipo importe&quot;::Saldo: ValorCol := CGCta.&quot;Importe pptdo.&quot;; &quot;Tipo importe&quot;::Debe : BEGIN ValorCol := CGCta.&quot;Debe presupuestado&quot;; Debe := TRUE; END ELSE ValorCol := CGCta.&quot;Haber presupuestado&quot;; END;

Decisión

CASE

Evalúa la expresión y ejecuta el bloque de sentencias del valor correspondiente. Si no hay un valor igual, ejecuta el bloque de sentencias del ELSE .

CASE <expresión> OF

<valor>: <bloque de sentencias>;



<valor>: <bloque de sentencias>

[ ELSE <bloque de sentencias> ]

END;

Ejemplo

CASE &quot;Tipo importe&quot; OF

&quot;Tipo importe&quot;::Saldo: ValorCol := CGCta.&quot;Importe pptdo.&quot;;

&quot;Tipo importe&quot;::Debe :

BEGIN

ValorCol := CGCta.&quot;Debe presupuestado&quot;;

Debe := TRUE;

END

ELSE ValorCol := CGCta.&quot;Haber presupuestado&quot;;

END;

Sentencias (IV) Iteración FOR Repite un conjunto de sentencias hasta que el resultado de la expresión de asignación alcance el valor indicado FOR <expr-asignación> TO/DOWNTO <valor> DO < bloque de sentencias > Ejemplo FOR j := Tareas DOWNTO 1 DO BEGIN Inclinacion[j] := Inclinacion[j - 1]; Constante[j] := Constante[j - 1]; MaxValImport[j] := MaxValImport[j - 1]; END;

Iteración

FOR

Repite un conjunto de sentencias hasta que el resultado de la expresión de asignación alcance el valor indicado

FOR <expr-asignación> TO/DOWNTO <valor> DO

< bloque de sentencias >

Ejemplo

FOR j := Tareas DOWNTO 1 DO BEGIN

Inclinacion[j] := Inclinacion[j - 1];

Constante[j] := Constante[j - 1];

MaxValImport[j] := MaxValImport[j - 1];

END;

Sentencias (V) Iteración REPEAT .. UNTIL Repite un conjunto de sentencias hasta que la expresión evalúe a TRUE . REPEAT <bloque de sentencias> UNTIL <expresión> Ejemplo IF CGCta.FIND('-') THEN REPEAT Result := Result + CalcCGCta(CGCta,ColumEsqCta); Num := Num + 1; UNTIL CGCta.NEXT = 0;

Iteración

REPEAT .. UNTIL

Repite un conjunto de sentencias hasta que la expresión evalúe a TRUE .

REPEAT

<bloque de sentencias>

UNTIL <expresión>

Ejemplo

IF CGCta.FIND('-') THEN

REPEAT

Result := Result + CalcCGCta(CGCta,ColumEsqCta);

Num := Num + 1;

UNTIL CGCta.NEXT = 0;

Sentencias (VI) Iteración WHILE .. DO Repite el conjunto de sentencias hasta el siguiente END si la expresión evalúa a TRUE WHILE <expresión> DO <bloque de sentencias> [ END; ] Ejemplo LinComentVenta.SETRANGE(&quot;Tipo documento&quot;,&quot;Tipo documento&quot;); LinComentVenta.SETRANGE(&quot;Nº&quot;,&quot;Nº&quot;); WHILE LinComentVenta.FIND('-') DO BEGIN LinComentVenta.DELETE; LinComentVenta.&quot;Tipo documento&quot; := CabVta.&quot;Tipo documento&quot;; LinComentVenta.&quot;Nº&quot; := CabVta.&quot;Nº&quot;; LinComentVenta.INSERT; END;

Iteración

WHILE .. DO

Repite el conjunto de sentencias hasta el siguiente END si la expresión evalúa a TRUE

WHILE <expresión> DO

<bloque de sentencias>

[ END; ]

Ejemplo

LinComentVenta.SETRANGE(&quot;Tipo documento&quot;,&quot;Tipo documento&quot;);

LinComentVenta.SETRANGE(&quot;Nº&quot;,&quot;Nº&quot;);

WHILE LinComentVenta.FIND('-') DO BEGIN

LinComentVenta.DELETE;

LinComentVenta.&quot;Tipo documento&quot; := CabVta.&quot;Tipo documento&quot;;

LinComentVenta.&quot;Nº&quot; := CabVta.&quot;Nº&quot;;

LinComentVenta.INSERT;

END;

Sentencias (y VII) Otras WITH Las sentencias dentro del WITH se refieren al registro, formulario, etc. WITH Clie DO BEGIN &quot;No.&quot; := '1'; Name := 'Pepe'; Address := 'Rue del Percebe, nº 13'; City := 'Niu llor'; END; EXIT Salir de un segmento de código o función (se puede retornar el valor) FUNCTION Absoluto (valor : Integer) ret : Integer BEGIN IF (valor < 0) THEN BEGIN ret := -valor; EXIT; END; EXIT(valor); END;

Otras

WITH

Las sentencias dentro del WITH se refieren al registro, formulario, etc.

WITH Clie DO BEGIN

&quot;No.&quot; := '1';

Name := 'Pepe';

Address := 'Rue del Percebe, nº 13';

City := 'Niu llor';

END;

EXIT

Salir de un segmento de código o función (se puede retornar el valor)

FUNCTION Absoluto (valor : Integer) ret : Integer

BEGIN

IF (valor < 0) THEN BEGIN

ret := -valor;

EXIT;

END;

EXIT(valor);

END;

Comentarios // - Una sola línea // Find next register no. IF ItemReg.FIND(‘+’) THEN ItemRegNo := ItemReg.”Nº” + 1 ELSE ItemRegNo := 1; {} – Varias líneas { Find next register no. } IF ItemReg.FIND(‘+’) THEN ItemRegNo := ItemReg.”Nº” + 1 ELSE ItemRegNo := 1;

// - Una sola línea

// Find next register no.

IF ItemReg.FIND(‘+’) THEN

ItemRegNo := ItemReg.”Nº” + 1

ELSE

ItemRegNo := 1;

{} – Varias líneas

{ Find next

register no. }

IF ItemReg.FIND(‘+’) THEN

ItemRegNo := ItemReg.”Nº” + 1

ELSE

ItemRegNo := 1;

Ejemplos Modificar el formulario para que se muestren siempre los 10 últimos resultados, mostrando siempre en la primera posición (la superior) el último resultado obtenido

Modificar el formulario para que se muestren siempre los 10 últimos resultados, mostrando siempre en la primera posición (la superior) el último resultado obtenido

Ejemplos Añadimos al formulario un botón “Ordenar” y realizaremos una ordenación de los elementos a través del método de la burbuja

Añadimos al formulario un botón “Ordenar” y realizaremos una ordenación de los elementos a través del método de la burbuja

Ejemplos Repetimos la ordenación hasta que el array está ordenado

Ejemplos Mejoramos el Algoritmo sabiendo que en cada iteración el último elemento siempre queda “ordenado”

Tablas Dónde introducir código Disparadores de tabla: OnInsert . Se ejecuta al insertar un registro en la tabla. OnModify . Se ejecuta al modiicar un campo de un registro de la tabla. OnDelete . Se ejecuta al borrar un registro de la tabla. OnRename . Se ejecuta al modificar un campo que forma parte de la clave primaria de un registro de la tabla. Disparadores de campos en la tabla: OnValidate . Se ejecuta al modificar el valor de un campo. OnLookup . Se ejecuta al pulsar F6 sobre el campo para buscar un valor. Funciones definidas en una tabla Se pueden definir funciones en la tabla y llamarlas desde el propio objeto o desde otros objetos.

Dónde introducir código

Disparadores de tabla:

OnInsert . Se ejecuta al insertar un registro en la tabla.

OnModify . Se ejecuta al modiicar un campo de un registro de la tabla.

OnDelete . Se ejecuta al borrar un registro de la tabla.

OnRename . Se ejecuta al modificar un campo que forma parte de la clave primaria de un registro de la tabla.

Disparadores de campos en la tabla:

OnValidate . Se ejecuta al modificar el valor de un campo.

OnLookup . Se ejecuta al pulsar F6 sobre el campo para buscar un valor.

Funciones definidas en una tabla

Se pueden definir funciones en la tabla y llamarlas desde el propio objeto o desde otros objetos.

Tablas (II) Para acceder a tablas se definen variables tipo Record Modificación de campos de la tabla: Mediante asignación de valores. Clie : Record (Cliente); // Variable Clie de tipo registro de // tabla cliente Clie.”Nº” := ‘10’; Clie.”Nombre” := ‘Pepe’; Con la sentencia Validate, asigna el valor y ejecuta el disparador OnValidate de cada campo asignado de la tabla Cliente. Clie : Record (Cliente); Clie.VALIDATE(“Nº”, ’10’); Clie.VALIDATE(Nombre, ‘Pepe’);

Para acceder a tablas se definen variables tipo Record

Modificación de campos de la tabla:

Mediante asignación de valores.

Clie : Record (Cliente); // Variable Clie de tipo registro de // tabla cliente

Clie.”Nº” := ‘10’;

Clie.”Nombre” := ‘Pepe’;

Con la sentencia Validate, asigna el valor y ejecuta el disparador OnValidate de cada campo asignado de la tabla Cliente.

Clie : Record (Cliente);

Clie.VALIDATE(“Nº”, ’10’);

Clie.VALIDATE(Nombre, ‘Pepe’);

Tablas (III) Trabajo con registros de la tabla: Inicialización. Se establece cada campo del registro a su valor por defecto dependiendo de su tipo. Clie : Record (Cliente); Clie.INIT; Inserción de registros en la tabla. Con la sentencia INSERT y un párámetro que indica si se ejecuta el disparador OnInsert de la tabla o no. Clie.VALIDATE(“Nº”, ‘10’); Clie.VALIDATE(Nombre, ‘Pepe’); … Clie.INSERT(TRUE); Modificación de registros de la tabla. Sentencia MODIFY con un parámetro que indica si se ejecuta el disparador OnModify de la tabla. Clie.VALIDATE(Nombre, ‘Luis’); Clie.MODIFY(TRUE);

Trabajo con registros de la tabla:

Inicialización. Se establece cada campo del registro a su valor por defecto dependiendo de su tipo.

Clie : Record (Cliente);

Clie.INIT;

Inserción de registros en la tabla. Con la sentencia INSERT y un párámetro que indica si se ejecuta el disparador OnInsert de la tabla o no.

Clie.VALIDATE(“Nº”, ‘10’);

Clie.VALIDATE(Nombre, ‘Pepe’);



Clie.INSERT(TRUE);

Modificación de registros de la tabla. Sentencia MODIFY con un parámetro que indica si se ejecuta el disparador OnModify de la tabla.

Clie.VALIDATE(Nombre, ‘Luis’);

Clie.MODIFY(TRUE);

Tablas (IV) Trabajo con registros de la tabla: Borrado de registros en la tabla. Con la sentencia DELETE y un párámetro que indica si se ejecuta el disparador OnDelete de la tabla o no. Clie.DELETE(TRUE); Modificación de campos de registros de la tabla que forman parte de la clave primaria. Sentencia RENAME con un parámetro que indica si se ejecuta el disparador OnRename de la tabla. Clie.VALIDATE(“Nº”, ‘21’); Clie.RENAME(TRUE);

Trabajo con registros de la tabla:

Borrado de registros en la tabla. Con la sentencia DELETE y un párámetro que indica si se ejecuta el disparador OnDelete de la tabla o no.

Clie.DELETE(TRUE);

Modificación de campos de registros de la tabla que forman parte de la clave primaria. Sentencia RENAME con un parámetro que indica si se ejecuta el disparador OnRename de la tabla.

Clie.VALIDATE(“Nº”, ‘21’);

Clie.RENAME(TRUE);

Tablas (V) Buscar registros en una tabla: Obtener un registro de una tabla por su clave primaria. Job.GET(“Job Nº.”); Job.TESTFIELD(Blocked,FALSE); Con las sentencias anteriores obtenemos un registro de la tabla Job (sentencia GET) y comprobamos que uno de los campos del registro tenga el valor indicado (TESTFIELD) Obtener uno o varios registro de una tabla por claves secundarias. Clie.RESET; Clie.SETCURRENTKEY(Name,Address,City); Clie.SETRANGE(Name,’Luis’); Clie.SETFILTER(City, ‘%1 | %2’, ‘Paris’, ‘Roma’); Primero actuamos sobre la variable Clie eliminando todos los filtros y rangos anteriores ( RESET ). Activamos una clave por la que vamos a buscar ( SETCURRENTKEY ) para que el establecimiento de rangos y la búsqueda de registro se base en índices para esta clave y sea mucho más efectiva. Se establecen filtros con dos funciones: SETRANGE y SETFILTER , básicamente iguales aunque SETFILTER permite establecer condiciones más complejas. Es recomendable establecer los filtros sobre los campos en el orden en que aparecen en la clave primaria. En este momento Clie contiene todos los registros que cumplen las condiciones indicadas en los filtros.

Buscar registros en una tabla:

Obtener un registro de una tabla por su clave primaria.

Job.GET(“Job Nº.”);

Job.TESTFIELD(Blocked,FALSE);

Con las sentencias anteriores obtenemos un registro de la tabla Job (sentencia GET) y comprobamos que uno de los campos del registro tenga el valor indicado (TESTFIELD)

Obtener uno o varios registro de una tabla por claves secundarias.

Clie.RESET;

Clie.SETCURRENTKEY(Name,Address,City);

Clie.SETRANGE(Name,’Luis’);

Clie.SETFILTER(City, ‘%1 | %2’, ‘Paris’, ‘Roma’);

Primero actuamos sobre la variable Clie eliminando todos los filtros y rangos anteriores ( RESET ). Activamos una clave por la que vamos a buscar ( SETCURRENTKEY ) para que el establecimiento de rangos y la búsqueda de registro se base en índices para esta clave y sea mucho más efectiva. Se establecen filtros con dos funciones: SETRANGE y SETFILTER , básicamente iguales aunque SETFILTER permite establecer condiciones más complejas. Es recomendable establecer los filtros sobre los campos en el orden en que aparecen en la clave primaria. En este momento Clie contiene todos los registros que cumplen las condiciones indicadas en los filtros.

 

Tablas (VI) Buscar registros en una tabla: Recorrer registros de la tabla IF Clie.FIND(‘-’) THEN REPEAT <tratar registro> UNTIL Clie.NEXT = 0; FIND permite obtener un registro dentro del filtro establecido. El parámetro indica: ‘ -’ toma el primer registro del filtro ‘ +’ toma el último registro del filtro ‘ =‘ toma el registro que es igual a los valores de las claves (por defecto) FIND devuelve un valor Boolean y si no encuentra un registro que cumpla con las condiciones del filtro provoca un error de ejecución. Para evitar este error se puede encerrar en una sentencia IF . NEXT toma el siguiente registro del filtro y toma un parámetro: > 0 busca el siguiente registro saltando el número indicado < 0 busca el registro anterior saltando el número indicado Por defecto busca el siguiente registro.

Buscar registros en una tabla:

Recorrer registros de la tabla

IF Clie.FIND(‘-’) THEN

REPEAT

<tratar registro>

UNTIL Clie.NEXT = 0;

FIND permite obtener un registro dentro del filtro establecido. El parámetro indica:

‘ -’ toma el primer registro del filtro

‘ +’ toma el último registro del filtro

‘ =‘ toma el registro que es igual a los valores de las claves (por defecto)

FIND devuelve un valor Boolean y si no encuentra un registro que cumpla con las condiciones del filtro provoca un error de ejecución. Para evitar este error se puede encerrar en una sentencia IF .

NEXT toma el siguiente registro del filtro y toma un parámetro:

> 0 busca el siguiente registro saltando el número indicado

< 0 busca el registro anterior saltando el número indicado

Por defecto busca el siguiente registro.

Tablas (y VII) OnLookup : Buscar valores de campos en otra tabla. Clie.SETCURRENTKEY(&quot;Nº&quot;); Clie.SETFILTER(&quot;Nº&quot;,'<40000'); ListaClientes.SETTABLEVIEW(Clie); IF Clie.FIND('-') THEN; ListaClientes.SETRECORD(Clie); ListaClientes.LOOKUPMODE(TRUE); IF ListaClientes.RUNMODAL = ACTION::LookupOK THEN BEGIN ListaClientes.GETRECORD(Clie); cliente.validate(Clie.&quot;Nº “); CLEAR(ListaClientes); END; Se establecen los filtros adecuados en la variable Clie de tipo Record de Clientes . ListaClientes es de tipo Form . SETTABLEVIEW establece la vista del formulario ListaClientes y establecemos el cliente activo mediante SETRECORD . LOOKUPMODE hace que el formulario sirva para obtener datos. GETRECORD obtiene el registro marcado. CLEAR elimina el formulario.

OnLookup :

Buscar valores de campos en otra tabla.

Clie.SETCURRENTKEY(&quot;Nº&quot;);

Clie.SETFILTER(&quot;Nº&quot;,'<40000');

ListaClientes.SETTABLEVIEW(Clie);

IF Clie.FIND('-') THEN;

ListaClientes.SETRECORD(Clie);

ListaClientes.LOOKUPMODE(TRUE);

IF ListaClientes.RUNMODAL = ACTION::LookupOK THEN BEGIN

ListaClientes.GETRECORD(Clie);

cliente.validate(Clie.&quot;Nº “);

CLEAR(ListaClientes);

END;

Se establecen los filtros adecuados en la variable Clie de tipo Record de Clientes .

ListaClientes es de tipo Form .

SETTABLEVIEW establece la vista del formulario ListaClientes y establecemos el cliente activo mediante SETRECORD .

LOOKUPMODE hace que el formulario sirva para obtener datos.

GETRECORD obtiene el registro marcado.

CLEAR elimina el formulario.

Acceso a Objetos Form: Acceso directo: CGMov.FIND(‘-’); FORM.RUN (FORM::&quot;Movs. contabilidad&quot;, CGMov); IF FORM.RUNMODAL (216, LinPptoProy)=ACTION::LookupOK THEN BEGIN &quot;Cód. fase&quot; := LinPptoProy.&quot;Cód. fase&quot;; &quot;Cód. subfase&quot; := LinPptoProy.&quot;Cód. subfase&quot;; &quot;Cód. tarea&quot; := LinPptoProy.&quot;Cód. tarea&quot;; END; Acceso con variable: ListCtaCG : Form “Lista de Cuentas”; ListCtaCG.LOOKUPMODE(TRUE); IF ListCtaCG. RUNMODAL = ACTION::LookupOK THEN … FormNavegar : Form “Navegar”; FormNavegar.DefDoc(&quot;Fecha registro&quot;,&quot;Nº&quot;); FormNavegar. RUN ;

Form:

Acceso directo:

CGMov.FIND(‘-’);

FORM.RUN (FORM::&quot;Movs. contabilidad&quot;, CGMov);

IF FORM.RUNMODAL (216, LinPptoProy)=ACTION::LookupOK THEN BEGIN

&quot;Cód. fase&quot; := LinPptoProy.&quot;Cód. fase&quot;;

&quot;Cód. subfase&quot; := LinPptoProy.&quot;Cód. subfase&quot;;

&quot;Cód. tarea&quot; := LinPptoProy.&quot;Cód. tarea&quot;;

END;

Acceso con variable:

ListCtaCG : Form “Lista de Cuentas”;

ListCtaCG.LOOKUPMODE(TRUE);

IF ListCtaCG. RUNMODAL = ACTION::LookupOK THEN …

FormNavegar : Form “Navegar”;

FormNavegar.DefDoc(&quot;Fecha registro&quot;,&quot;Nº&quot;);

FormNavegar. RUN ;

Acceso a Objetos (II) Report: Acceso directo: Clie.SETRECFILTER; // coloca un filtro (en la clave primaria) // para que el Report se ejecute sólo sobre el // Cliente actual REPORT. RUN (REPORT::&quot;Inf-ejemplo&quot;,ReqForm,FALSE,Clie); REPORT. RUNMODAL (REPORT::&quot;Inf-ejemplo&quot;,FALSE,Impresora,Clie); Acceso con variable: r : Report “Proveedor - Líneas pedidos”; CLEAR(r); Prov.SETRECFILTER; r.SETTABLEVIEW(Prov); r. RUNMODAL ; … r. RUN ;

Report:

Acceso directo:

Clie.SETRECFILTER; // coloca un filtro (en la clave primaria) // para que el Report se ejecute sólo sobre el // Cliente actual

REPORT. RUN (REPORT::&quot;Inf-ejemplo&quot;,ReqForm,FALSE,Clie);

REPORT. RUNMODAL (REPORT::&quot;Inf-ejemplo&quot;,FALSE,Impresora,Clie);

Acceso con variable:

r : Report “Proveedor - Líneas pedidos”;

CLEAR(r);

Prov.SETRECFILTER;

r.SETTABLEVIEW(Prov);

r. RUNMODAL ;



r. RUN ;

Acceso a Objetos (y III) Codeunit: Se ejecuta la función RUN de la Codeunit Acceso directo: IF CODEUNIT. RUN (22, LinDiaProd) THEN … Acceso con variable: DiaGenTestLin : Codeunit “Dia. Gen-Test línea”; DiaGenTestLin. RUN (LinDiaGen); // LinDiaGen puede haber cambiado (VAR)

Codeunit:

Se ejecuta la función RUN de la Codeunit

Acceso directo:

IF CODEUNIT. RUN (22, LinDiaProd) THEN



Acceso con variable:

DiaGenTestLin : Codeunit “Dia. Gen-Test línea”;

DiaGenTestLin. RUN (LinDiaGen);

// LinDiaGen puede haber cambiado (VAR)

Formularios Dónde introducir código Disparadores de formulario: OnAfterGetRecord . Se ejecuta al recurperar un registro de la tabla, pero antes de mostrar el registro en el formulario. Disparadores de controles del formulario. Botones del formulario: Command Button Menu Button: En cada uno de los Menu Items Funciones definidas en un formulario: Se pueden definir funciones en el formulario y llamarlas desde el propio objeto o desde otros objetos. ¡¡ En cualquier caso el código debe escribirse en la tabla si es posible !!

Dónde introducir código

Disparadores de formulario:

OnAfterGetRecord . Se ejecuta al recurperar un registro de la tabla, pero antes de mostrar el registro en el formulario.

Disparadores de controles del formulario.

Botones del formulario:

Command Button

Menu Button: En cada uno de los Menu Items

Funciones definidas en un formulario:

Se pueden definir funciones en el formulario y llamarlas desde el propio objeto o desde otros objetos.

¡¡ En cualquier caso el código debe escribirse en la tabla si es posible !!

Formularios (II) Después de recuperar un registro de la tabla, pero antes de mostrarlo en el formulario se ejecuta el trigger OnAfterGetRecord. Ej: Antes de mostrar el registro, aplica un filtro y calcula el valor de un SumIndexField que mostrará en el formulario.

Después de recuperar un registro de la tabla, pero antes de mostrarlo en el formulario se ejecuta el trigger OnAfterGetRecord.

Ej: Antes de mostrar el registro, aplica un filtro y calcula el valor de un SumIndexField que mostrará en el formulario.

Formularios (y III) Al pulsar sobre un botón o sobre una opción de menú en un botón desplegable se ejecuta el trigger OnPush . Ej: Podemos invocar una función en un Codeunit con un parámetro.

Al pulsar sobre un botón o sobre una opción de menú en un botón desplegable se ejecuta el trigger OnPush .

Ej: Podemos invocar una función en un Codeunit con un parámetro.

Informes Dónde introducir código Disparadores del informe: OnPreReport . Se procesa antes de ejecutar el informe. Disparadores de cada DataItem: OnPreDataItem. Se ejecuta antes de que el DataItem se procese. OnAfterGetRecord. Se ejecuta cada vez que se obtiene un registro. OnPostDataItem. Se ejecuta después del procesamiento del DataItem. Request Form del informe. Funciones definidas en un informe. Secciones del formulario: OnPreSection. Se ejecuta antes de que una sección sea procesada. OnPostSection. Se ejecuta después de que una sección sea procesada.

Dónde introducir código

Disparadores del informe:

OnPreReport . Se procesa antes de ejecutar el informe.

Disparadores de cada DataItem:

OnPreDataItem. Se ejecuta antes de que el DataItem se procese.

OnAfterGetRecord. Se ejecuta cada vez que se obtiene un registro.

OnPostDataItem. Se ejecuta después del procesamiento del DataItem.

Request Form del informe.

Funciones definidas en un informe.

Secciones del formulario:

OnPreSection. Se ejecuta antes de que una sección sea procesada.

OnPostSection. Se ejecuta después de que una sección sea procesada.

Informes (II) Antes de la ejecución de un Report se ejecuta el trigger OnPreReport. Ej: Podemos utilizarlo para obtener los filtros con los que el Report se ha llamado, y después imprimirlos en una sección Header (FiltClient y FiltMovProducto) .

Antes de la ejecución de un Report se ejecuta el trigger OnPreReport.

Ej: Podemos utilizarlo para obtener los filtros con los que el Report se ha llamado, y después imprimirlos en una sección Header (FiltClient y FiltMovProducto) .

Informes (III) Antes de la ejecución de un DataItem se dispara OnPreDataItem. Ej: Podemos utilizarlo para mantener totales de un campo para una sección FOOTER con la función CREATETOTALS . También se puede establecer un registro por página con la función NEWPAGEPERRECORD , si hemos elegido la opción en el Request Form. Después de obtener un registro del DataItem se ejecuta OnAfterGetRecord . Ej: Podemos hacer cálculos para algún valor que se va a imprimir ( Bfº bruto ). También se puede llamar a NEWPAGE desde este disparador para cambiar de página. Con CurrReport.SKIP podemos saltar la iteración del DataItem.

Antes de la ejecución de un DataItem se dispara OnPreDataItem.

Ej: Podemos utilizarlo para mantener totales de un campo para una sección FOOTER con la función CREATETOTALS . También se puede establecer un registro por página con la función NEWPAGEPERRECORD , si hemos elegido la opción en el Request Form.

Después de obtener un registro del DataItem se ejecuta OnAfterGetRecord .

Ej: Podemos hacer cálculos para algún valor que se va a imprimir ( Bfº bruto ). También se puede llamar a NEWPAGE desde este disparador para cambiar de página.

Con CurrReport.SKIP podemos saltar la iteración del DataItem.

Informes (y IV) Antes de mostrar una sección se ejecuta OnPreSection. Ej: Podemos querer mostrar la sección o no (con la función SHOWOUTPUT ), o realizar los cáculos para un valor a imprimir.

Antes de mostrar una sección se ejecuta OnPreSection.

Ej: Podemos querer mostrar la sección o no (con la función SHOWOUTPUT ), o realizar los cáculos para un valor a imprimir.

Unidades de Código Donde introducir código Función OnRun : Se crea por defecto con una nueva codeunit. Es el punto de entrada para su ejecución por defecto . Puede tener como parámetro una registro. Funciones de la Codeunit: Si se crea una función en una Codeunit se puede invocar desde otros objetos: DiaGenTestLin : Codeunit “Dia. Gen-Test línea”; DiaGenTestLin. Testear (LinDiaGen);

Donde introducir código

Función OnRun :

Se crea por defecto con una nueva codeunit.

Es el punto de entrada para su ejecución por defecto .

Puede tener como parámetro una registro.

Funciones de la Codeunit:

Si se crea una función en una Codeunit se puede invocar desde otros objetos:

DiaGenTestLin : Codeunit “Dia. Gen-Test línea”;

DiaGenTestLin. Testear (LinDiaGen);

DataPorts Dónde introducir código Disparadores de DataPort OnPreDataport . Antes de la ejecución del Dataport. OnPostDataport. Después de la ejecución del Dataport. Disparadores de DataItem OnPreDataItem(). Antes de procesar el DataItem. OnBeforeExportRecord(). Antes de exportar un registro. OnAfterExportRecord(). Después de exportar un registro. OnBeforeImportRecord(). Antes de importar un registro. OnAfterImportRecord(). Después de importar un registro. OnPostDataItem(). Después de procesar un DataItem. Request form del Dataport Funciones del Dataport

Dónde introducir código

Disparadores de DataPort

OnPreDataport . Antes de la ejecución del Dataport.

OnPostDataport. Después de la ejecución del Dataport.

Disparadores de DataItem

OnPreDataItem(). Antes de procesar el DataItem.

OnBeforeExportRecord(). Antes de exportar un registro.

OnAfterExportRecord(). Después de exportar un registro.

OnBeforeImportRecord(). Antes de importar un registro.

OnAfterImportRecord(). Después de importar un registro.

OnPostDataItem(). Después de procesar un DataItem.

Request form del Dataport

Funciones del Dataport

DataPorts (II) Un Dataport puede importar datos y añadirlos a una tabla. Ej: Añade registros a un diario. Necesita antes de comenzar saber que “Nº línea” tendrá el primer registro de los importados

Un Dataport puede importar datos y añadirlos a una tabla.

Ej: Añade registros a un diario. Necesita antes de comenzar saber que “Nº línea” tendrá el primer registro de los importados

DataPorts (III) Antes de procesar un DataItem. Ej: Una función del Dataport es llamada antes de invocar el Dataport, después se ejecuta el Dataport y se establece un filtro sobre un campo del DataItem. La variable FiltroNoCampaña no pierde su valor entre las dos llamadas si no se ejecuta CLEAR .

Antes de procesar un DataItem.

Ej: Una función del Dataport es llamada antes de invocar el Dataport, después se ejecuta el Dataport y se establece un filtro sobre un campo del DataItem. La variable FiltroNoCampaña no pierde su valor entre las dos llamadas si no se ejecuta CLEAR .

DataPorts (y IV) Después de importar el registro, y antes de insertarlo en la tabla. Ej: Se busca un nuevo número de línea y se rellenan los campo de descripción.

Después de importar el registro, y antes de insertarlo en la tabla.

Ej: Se busca un nuevo número de línea y se rellenan los campo de descripción.

Funciones Comunes Otras funciones comunmente usadas: RESET Elimina filtros y selección de claves en una variable Record DesdeLMComp.RESET; DesdeLMComp.SETRANGE(&quot;Nº L.M.&quot;,&quot;Nº producto&quot;); DesdeLMComp.SETRANGE(Tipo,DesdeLMComp.Tipo::Producto); DesdeLMComp.FIND('-'); NoSigLin := &quot;Nº línea“ COUNT Cuenta el número de registros. DesdeLMComp.SETRANGE(&quot;Nº L.M.&quot;,&quot;Nº producto&quot;); DesdeLMComp.SETRANGE(Tipo,DesdeLMComp.Tipo::Producto); NoCompoLM := DesdeLMComp.COUNT;

Otras funciones comunmente usadas:

RESET

Elimina filtros y selección de claves en una variable Record

DesdeLMComp.RESET;

DesdeLMComp.SETRANGE(&quot;Nº L.M.&quot;,&quot;Nº producto&quot;);

DesdeLMComp.SETRANGE(Tipo,DesdeLMComp.Tipo::Producto);

DesdeLMComp.FIND('-');

NoSigLin := &quot;Nº línea“

COUNT

Cuenta el número de registros.

DesdeLMComp.SETRANGE(&quot;Nº L.M.&quot;,&quot;Nº producto&quot;);

DesdeLMComp.SETRANGE(Tipo,DesdeLMComp.Tipo::Producto);

NoCompoLM := DesdeLMComp.COUNT;

Funciones Comunes (II) COPY Copia una variable Record en otra de la misma tabla, incluyendo filtros y claves activas. NuevoClie := COPY(Clie); TRANSFERFIELDS Copia el contenido de los campos de una variable Record a otra que no tiene que ser de la misma tabla. Tiene en cuenta para ello el número de campo.Los campos que no tengan correspondencia de número se establecen a sus valores por defecto. RegHasta := TRANSFERFIELDS (RegDesde);

COPY

Copia una variable Record en otra de la misma tabla, incluyendo filtros y claves activas.

NuevoClie := COPY(Clie);

TRANSFERFIELDS

Copia el contenido de los campos de una variable Record a otra que no tiene que ser de la misma tabla. Tiene en cuenta para ello el número de campo.Los campos que no tengan correspondencia de número se establecen a sus valores por defecto.

RegHasta := TRANSFERFIELDS (RegDesde);

Funciones Comunes (III) EVALUATE Convertir un valor de un tipo a otro. Valor := '010196'; // Tipo cadena Ok := EVALUATE(VarInteger, Valor); // Entero = 10196 Ok := EVALUATE(VarDate, Valor); // Fecha = 010196D FORMAT Convertir un valor en una cadena de texto MESSAGE('Today is %1', FORMAT(TODAY ));

EVALUATE

Convertir un valor de un tipo a otro.

Valor := '010196'; // Tipo cadena

Ok := EVALUATE(VarInteger, Valor); // Entero = 10196

Ok := EVALUATE(VarDate, Valor); // Fecha = 010196D

FORMAT

Convertir un valor en una cadena de texto

MESSAGE('Today is %1', FORMAT(TODAY ));

Funciones Comunes (IV) DELETEALL Borrar una serie de registros de una tabla LinExtCtaBanco.SETRANGE(&quot;Nº banco&quot;,&quot;Nº banco&quot;); LinExtCtaBanco.SETRANGE(&quot;Nº extracto&quot;,&quot;Nº extracto&quot;); LinExtCtaBanco.DELETEALL; MODIFYALL Modificar una serie de registros de una tabla CGMov.RESET; CGMov.SETCURRENTKEY(&quot;Nº cuenta&quot;); CGMov.SETRANGE(&quot;Nº cuenta&quot;,CGCta.&quot;Nº&quot;); CGMov.MODIFYALL(&quot;Nº cuenta&quot;,'');

DELETEALL

Borrar una serie de registros de una tabla

LinExtCtaBanco.SETRANGE(&quot;Nº banco&quot;,&quot;Nº banco&quot;);

LinExtCtaBanco.SETRANGE(&quot;Nº extracto&quot;,&quot;Nº extracto&quot;);

LinExtCtaBanco.DELETEALL;

MODIFYALL

Modificar una serie de registros de una tabla

CGMov.RESET;

CGMov.SETCURRENTKEY(&quot;Nº cuenta&quot;);

CGMov.SETRANGE(&quot;Nº cuenta&quot;,CGCta.&quot;Nº&quot;);

CGMov.MODIFYALL(&quot;Nº cuenta&quot;,'');

Funciones Comunes (V) COPYFILTER[S] Copia los filtros de una variable a otra de tipo Record de la misma tabla (COPYFILTER sólo copia los filtros de un campo) Clie1.SETFILTER(&quot;No.&quot;, '<1000'); Clie1.SETRANGE(Group, 1); Clie2.COPYFILTERS(Clie1); TESTFIELD Comprueba que un campo contenga un valor dado. Si se omite el segundo parámetro se comprueba que contenga un valor distinto de 0 o blanco. Si esto no se cumple muestra un mensaje de ERROR. Clie.TESTFIELD(Bloqueado, FALSE); Clie.TESTFIELD(“Nº”);

COPYFILTER[S]

Copia los filtros de una variable a otra de tipo Record de la misma tabla (COPYFILTER sólo copia los filtros de un campo)

Clie1.SETFILTER(&quot;No.&quot;, '<1000');

Clie1.SETRANGE(Group, 1);

Clie2.COPYFILTERS(Clie1);

TESTFIELD

Comprueba que un campo contenga un valor dado. Si se omite el segundo parámetro se comprueba que contenga un valor distinto de 0 o blanco. Si esto no se cumple muestra un mensaje de ERROR.

Clie.TESTFIELD(Bloqueado, FALSE);

Clie.TESTFIELD(“Nº”);

Funciones Comunes (VI) LOCKTABLE Bloquea una tabla para procesos transaccionales FIELDNAME Obtiene el nombre de un campo

LOCKTABLE

Bloquea una tabla para procesos transaccionales

FIELDNAME

Obtiene el nombre de un campo

SumIndexFields [Ok :=] Record. CALCSUMS (Campo1 [, Campo2] ,...) Devuelve la suma para uno (o varios) SumIndexField. Debe estar activa una clave para la que se haya definido el campo. No debe haber filtros en campos fuera de la clave. Si no se cumplen las condiciones anteriores, se devuelve FALSE (o se lanza un mensaje de error). MovCli.SETCURRENTKEY(&quot;Nº cliente&quot;,&quot;Fecha registro&quot;); MovCli.SETRANGE(&quot;Nº cliente&quot;, 'AAA 1050'); MovCli.SETRANGE(&quot;Fecha registro&quot;, 010199D, 123102D); MovCli.CALCSUMS(Importe);

[Ok :=] Record. CALCSUMS (Campo1 [, Campo2] ,...)

Devuelve la suma para uno (o varios) SumIndexField.

Debe estar activa una clave para la que se haya definido el campo.

No debe haber filtros en campos fuera de la clave.

Si no se cumplen las condiciones anteriores, se devuelve FALSE (o se lanza un mensaje de error).

MovCli.SETCURRENTKEY(&quot;Nº cliente&quot;,&quot;Fecha registro&quot;);

MovCli.SETRANGE(&quot;Nº cliente&quot;, 'AAA 1050');

MovCli.SETRANGE(&quot;Fecha registro&quot;, 010199D, 123102D);

MovCli.CALCSUMS(Importe);

FlowFields [Ok :=] Record. CALCFIELDS (Campo1 [, Campo2] ,...) Los campos de una tabla que son FlowFields se deben recalcular al aplicar filtros. Cliente.SETRANGE(&quot;Filtro fechas&quot;,010199D,123102D); Cliente.CALCFIELDS(Saldo,&quot;Saldo periodo&quot;);

[Ok :=] Record. CALCFIELDS (Campo1 [, Campo2] ,...)

Los campos de una tabla que son FlowFields se deben recalcular al aplicar filtros.

Cliente.SETRANGE(&quot;Filtro fechas&quot;,010199D,123102D);

Cliente.CALCFIELDS(Saldo,&quot;Saldo periodo&quot;);

Diálogos Mensajes: Mensaje asíncrono MESSAGE MESSAGE('Mensaje asíncrono informativo'); ERROR. Provoca Rollback. ERROR('ERROR: Esto ejecuta RollBack'); . FIELDERROR. Muestra el Campo Erroneo Mensaje + Ok/Cancel CONFIRM IF CONFIRM ('Desea continuar') THEN <Código para SI> ELSE <Código para NO>

Mensajes:

Mensaje asíncrono

MESSAGE

MESSAGE('Mensaje asíncrono informativo');

ERROR. Provoca Rollback.

ERROR('ERROR: Esto ejecuta RollBack');

. FIELDERROR. Muestra el Campo Erroneo

Mensaje + Ok/Cancel

CONFIRM

IF CONFIRM ('Desea continuar') THEN

<Código para SI>

ELSE

<Código para NO>

Diálogos (II) Mensajes: Menú de opciones STRMENU CASE STRMENU('&Insertar,&Modificar,&Borrar,&Terminar' ,4) OF 1: <Código para Insertar> 2: <Código para Modificar> 3: <Código para Borrar> 4: <Código para Terminar> ELSE <Código para Cancelar> END;

Mensajes:

Menú de opciones

STRMENU

CASE STRMENU('&Insertar,&Modificar,&Borrar,&Terminar' ,4) OF

1: <Código para Insertar>

2: <Código para Modificar>

3: <Código para Borrar>

4: <Código para Terminar>

ELSE <Código para Cancelar>

END;

Diálogos (y III) Mensajes: Objetos de tipo Dialog Ventana.OPEN('#1############################apos;+ 'Cliente #2###############apos;+ 'Nuevo Nombre #3###############apos;+ '@4@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'); Num := 0; Ventana.UPDATE(1, 'Tabla Cliente'); Clie.RESET; IF Clie.FIND('-') THEN REPEAT Num := Num + 1; Ventana.UPDATE(2, Clie.Nombre); Ventana.INPUT(3, NuevoNombre); Ventana.UPDATE(4, ROUND((Num / Clie.COUNT) * 10000)); Clie.VALIDATE(“Nombre”, NuevoNombre); UNTIL Clie.NEXT = 0; Ventana.CLOSE;

Mensajes:

Objetos de tipo Dialog

Ventana.OPEN('#1############################apos;+

'Cliente #2###############apos;+

'Nuevo Nombre #3###############apos;+

'@4@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@');

Num := 0;

Ventana.UPDATE(1, 'Tabla Cliente');

Clie.RESET;

IF Clie.FIND('-') THEN

REPEAT

Num := Num + 1;

Ventana.UPDATE(2, Clie.Nombre);

Ventana.INPUT(3, NuevoNombre);

Ventana.UPDATE(4, ROUND((Num / Clie.COUNT) * 10000));

Clie.VALIDATE(“Nombre”, NuevoNombre);

UNTIL Clie.NEXT = 0;

Ventana.CLOSE;

Acceso a Ficheros Escribir en un fichero: IF NombArch = '' THEN ERROR('Introduzca el nombre del archivo.'); CLEAR(FicMovCont); FicMovCont.TEXTMODE := TRUE; FicMovCont.WRITEMODE := TRUE; FicMovCont.QUERYREPLACE := TRUE; FicMovCont.CREATE(NombArch); FicMovCont.WRITE( STRSUBSTNO( '#1#################### #2####### #3####### #4#', COMPANYNAME, FechInicConsol, FechFinConsol, FORMAT(TransfPorDia,0,2))); FicMovCont.CLOSE;

Escribir en un fichero:

IF NombArch = '' THEN

ERROR('Introduzca el nombre del archivo.');

CLEAR(FicMovCont);

FicMovCont.TEXTMODE := TRUE;

FicMovCont.WRITEMODE := TRUE;

FicMovCont.QUERYREPLACE := TRUE;

FicMovCont.CREATE(NombArch);

FicMovCont.WRITE(

STRSUBSTNO(

'#1#################### #2####### #3####### #4#',

COMPANYNAME, FechInicConsol, FechFinConsol, FORMAT(TransfPorDia,0,2)));

FicMovCont.CLOSE;

Acceso a Ficheros (y II) Leer de un fichero: IF NombArch = '' THEN ERROR('Introduzca el nombre del archivo.'); CLEAR(FicMovCont); FicMovCont.TEXTMODE := TRUE; FicMovCont.OPEN(NombArch); WHILE FicMovCont.POS <> FicMovCont.LEN DO BEGIN FicMovCont.READ(LinTexto); CodEmpr.“Nombre&quot; := DELCHR(COPYSTR(LinTexto,1,30),'>'); EVALUATE(FechInicConsol,COPYSTR(LinTexto,32,9)); EVALUATE(FechFinConsol,COPYSTR(LinTexto,42,9)); EVALUATE(TransfPorDia,COPYSTR(LinTexto,52,3)); END; FicMovCont.CLOSE;

Leer de un fichero:

IF NombArch = '' THEN

ERROR('Introduzca el nombre del archivo.');

CLEAR(FicMovCont);

FicMovCont.TEXTMODE := TRUE;

FicMovCont.OPEN(NombArch);

WHILE FicMovCont.POS <> FicMovCont.LEN DO BEGIN

FicMovCont.READ(LinTexto);

CodEmpr.“Nombre&quot; := DELCHR(COPYSTR(LinTexto,1,30),'>');

EVALUATE(FechInicConsol,COPYSTR(LinTexto,32,9));

EVALUATE(FechFinConsol,COPYSTR(LinTexto,42,9));

EVALUATE(TransfPorDia,COPYSTR(LinTexto,52,3));

END;

FicMovCont.CLOSE;

Constantes Globales del Sistema USERID . Identificador del usuario que inició la sesión Str := USERID; COMPANYNAME . Devuelve la empresa actual Str := COMPANYNAME; OSVERSION. Devuelve una cadena indicando el sistema operativo actual Str := OSVERSION; WORKDATE . Devuelve la fecha de trabajo actual TFecha := WORKDATE; TODAY . Devuelve la fecha del sistema operativo Fecha := TODAY; TIME . Devuelve la hora del sistema operativo Hora := TIME;

USERID . Identificador del usuario que inició la sesión

Str := USERID;

COMPANYNAME . Devuelve la empresa actual

Str := COMPANYNAME;

OSVERSION. Devuelve una cadena indicando el sistema operativo actual

Str := OSVERSION;

WORKDATE . Devuelve la fecha de trabajo actual

TFecha := WORKDATE;

TODAY . Devuelve la fecha del sistema operativo

Fecha := TODAY;

TIME . Devuelve la hora del sistema operativo

Hora := TIME;

Funciones de Cadena STRPOS Posición de una cadena en otra COPYSTR Copia una cadena en otra STRLEN Tamaño de una Cadena PADSTR Añade caracteres a una Cadena MAXSTRLEN Tamaño máximo de una Cadena LOWERCASE/UPPERCAS Conversión a Mayúsculas/Minúsculas

STRPOS

Posición de una cadena en otra

COPYSTR

Copia una cadena en otra

STRLEN

Tamaño de una Cadena

PADSTR

Añade caracteres a una Cadena

MAXSTRLEN

Tamaño máximo de una Cadena

LOWERCASE/UPPERCAS

Conversión a Mayúsculas/Minúsculas

Funciones de Cadena (II) CONVERTSTR Sustituye un conjunto de caracteres por otro, dentro de una cadena DELCHR Borra un conjunto de caracteres dentro de una cadena INCSTR Incrementa numéricamente una cadena SELECTSTR Devuelve una subcadena, dentro de un conjunto de cadenas separadas por comas STRCHECKSUM Calcula un Checksum para una cadena de números

CONVERTSTR

Sustituye un conjunto de caracteres por otro, dentro de una cadena

DELCHR

Borra un conjunto de caracteres dentro de una cadena

INCSTR

Incrementa numéricamente una cadena

SELECTSTR

Devuelve una subcadena, dentro de un conjunto de cadenas separadas por comas

STRCHECKSUM

Calcula un Checksum para una cadena de números

Funciones de Fecha DATE2DMY Obtiene Día, Mes o Año de una Fecha DATE2DWY Obtiene Día, Semana o Año de una Fecha CALCDATE Calcula una Fecha en Base a una Fecha inicial y una DateFormula

DATE2DMY

Obtiene Día, Mes o Año de una Fecha

DATE2DWY

Obtiene Día, Semana o Año de una Fecha

CALCDATE

Calcula una Fecha en Base a una Fecha inicial y una DateFormula

Funciones de Fecha (II) NORMALDATE Convierte una Fecha a “Normal Date” CLOSINGDATE Convierte una Fecha a “Closing Date”

NORMALDATE

Convierte una Fecha a “Normal Date”

CLOSINGDATE

Convierte una Fecha a “Closing Date”

Funciones Matemáticas ABS Valor Absoluto POWER Potencia ROUND Redondeo RANDOMIZE Planta una semilla para el generador de números aleatorios RANDOM Obtiene un número aleatorio

ABS

Valor Absoluto

POWER

Potencia

ROUND

Redondeo

RANDOMIZE

Planta una semilla para el generador de números aleatorios

RANDOM

Obtiene un número aleatorio

Funciones de Arrays ARRAYLEN Devuelve el número de elementos de un array COMPRESSARRAY Elimina elementos blancos de un array de texto COPYARRAY Copia elementos de un array a otro

ARRAYLEN

Devuelve el número de elementos de un array

COMPRESSARRAY

Elimina elementos blancos de un array de texto

COPYARRAY

Copia elementos de un array a otro

Ejemplos Modificar el código del ejemplo anterior (Botón Execute) para dividirlo en funciones/procedimientos

Modificar el código del ejemplo anterior (Botón Execute) para dividirlo en funciones/procedimientos

Depurador Se activa en: Tools / Debugger / Active Breakpoint on Triggers detiene la ejecución en cada disparador o función. Se pueden establecer puntos de ruptura para detener la ejecución (F9) Código Variables Pila Otras expresiones Mensajes de salida

Se activa en: Tools / Debugger / Active

Breakpoint on Triggers detiene la ejecución en cada disparador o función.

Se pueden establecer puntos de ruptura para detener la ejecución (F9)

Código

Variables

Pila

Otras expresiones

Mensajes de salida

Seguimiento de código Se activa en : Tools / Debugger / Code Coverage Seguimiento del código ejecutado entre Start y Stop En Negro las sentencias ejecutadas, en Rojo las no ejecutadas

Se activa en : Tools / Debugger / Code Coverage

Asistente para código Se activa en: View / C/AL Symbol Menu (F5) Muy útil para no cometer errores sintácticos Nos mu

Add a comment

Related pages

Navision Que Es Navision La Web Del Programador | Share ...

Programación con c/al para microsoft business solutions navision 1. programación en lenguaje c/al para microsoft business solutions navision pablo ...
Read more

Curso Dynamics NAV / Navision para programación IT

Nunsys Formación le ofrecemos un Curso Bonificado de Programación en Dynamics NAV (Navision) para ... Microsoft Business ... Comprender el lenguaje C/AL.
Read more

Curso de Navision / Dynamics NAV para programación

NUNSYS Formación te da con su curso de Navision para programación la ... Microsoft Business ... C/AL con Dynamics NAV. Introducción a C/AL;
Read more

Service Pack 1 para Microsoft Business Solutions-Navision 4.0

Service Pack 1 para Microsoft Business Solutions-Navision ... programación mínima. Employee Portal se proporciona con Web rts basados en Microsoft ...
Read more

Ver C. (lenguaje de programación) TUTORIAL Parte 32 /40 ...

Programación con c/al para microsoft business solutions, Programación con c/al para microsoft business solutions navision 1. programación en lenguaje c ...
Read more

Curso de Navision. Nav00 - Microsoft Dynamics Nav ...

... del ERP Microsoft® Business Solutions - Navision ... de Navision, o también se puede enfocar para la ... Programación con Microsoft ...
Read more

ixpunt: Microsoft Dynamics NAV

... Navision Navision Tarragona ... Programación.Para llevar adelante todo esto, contamos con un equipo con más de 8 años de experiencia implantando y ...
Read more

Microsoft Dynamics NAV - Wikipedia, la enciclopedia libre

... Microsoft Business Solutions Navision y ... solutions Navision Edition se han usado para ... programación C/AL fue introducido junto con ...
Read more

Planificación de la producción industrial con PlannerOne y ...

Demo de Planner One y Microsoft Dynamics NAV para la gestión productiva de empresas industriales. Compruebe cómo la planificación, la ...
Read more