Sie sind auf Seite 1von 42

Familiarización con Dynamics NAV

Interfaz
Uno de los aspectos clave de Dynamics NAV es la consistencia de su interfaz, que está diseñada para
facilitar a los usuarios existentes entrenar a nuevos usuarios a usar el NAV. Existen lineamientos que un
desarrollador debe seguir para crear módulos para Dynamics NAV, lo que asegura que aunque se esté
trabajando con un producto de un tercero, el usuario no notará la diferencia. Para conocer un poco de
estos lineamientos, pueden visitar el siguiente enlace:

http://msdn.microsoft.com/en-us/library/jj128065(v=nav.70).aspx

Básicamente, hay tres tipos de páginas: Listas, Tarjetas, Documentos.


Página de Lista
Como un ejemplo de página de tipo lista, se muestra a continuación la lista de clientes. Las páginas de
tipo Lista despliegan un número de registros, tantos como la pantalla lo permita, de una tabla particular.
La página de lista es usada para buscar un registro en particular con el que se necesita trabajar.

En la mayoría de páginas, si hay información relevante asociada a un registro en particular, ésta puede
encontrarse al lado derecho de la página de lista. Estos cuadros se conocen como “FactBoxes”. Con la
opción de Personalización de páginas puede seleccionarse el orden de la lista, los campos que aparecen
en ésta, que factboxes queremos visualizar, etc. Cabe mencionar que estas opciones son predefinidas
por el desarrollador.

En la parte superior de toda página de lista hay controles para filtrar la información mostrada, donde
puede introducirse cadenas de búsqueda como las siguientes:

Entrada Encuentra
10000 Todo lo que sea igual a 10000
>10000 Todo valor mayor que 10000
>=10000 Todo valor mayor o igual que 10000
10000.. Todo valor mayor o igual que 10000
<10000 Todo valor menor que 10000
<=10000 Todo valor menor o igual que 10000
..10000 Todo valor menor o igual que 10000
<>10000 Todo valor distinto de 10000
10000..40000 Valores desde 10000 hasta 40000
<40000&>10000 Valores menores que 40000 y mayores que
10000
10000|40000 Valores iguales a 10000 y 40000, pero nada entre
esos valores
*00 Todo valor que termine en 00
10000..20000&*00 Desde 10000 hasta 20000 y que también
terminen en 00
P8 En campos de fecha, el octavo período de un año
fiscal
*co* Entradas de Texto que contengan “co”
Hans?n Para caracteres desconocidos, por ejemplo, tales
como Hanson o Hansen
Pagina de Tarjeta
La página de tarjeta proporciona información más detallada sobre un registro en particular. La página de
tarjeta es usada principalmente para insertar, eliminar o modificar un registro. Esta es como la página de
lista descrita anteriormente, a la derecho pueden verse los factboxes antes mencionados, relacionados
al registro en particular. Puede hacerse click sobre alguno de los valores que aparecen como enlaces
para invocar una lista para verificar de donde se origina el valor mostrado.

Para aprovechar el máximo el espacio en pantalla y para organizar la información de una mejor manera,
NAV agrupa la información usando FastTabs. Al expandir cada uno de los FastTabs, se revela la
información relacionada al respectivo FastTab.

Estos FastTabs pueden ser colapsados o expandidos. Algunos FastTabs presentan la opción “See more
fields” que expande aún más un FastTab para mostrar información siempre relevante pero que el
desarrollador no consideró necesario mantener visible todo el tiempo.
Pagina de Documento
Estas páginas son una combinación de las dos anteriores, y se usan cada vez que se necesita relacionar
información del tipo Encabezado/Detalle, tales como Órdenes de Compra, Facturas, Lista de Materiales,
etc.
Base de datos
Dynamics NAV almacena su información en un servidor de base de datos de SQL Server. Las tablas
pueden accederse de manera directa para fines de consulta rápida o incluso para ser accedidos desde
aplicaciones de terceros para reportes, etc. Sin embargo, no se recomienda modificar la información
fuera de la interfaz de Dynamics NAV, dado a que puede perderse la integridad de la información. El
cliente es configurado acerca de la base de datos a la que se conectará mediante la Aplicación de
Administración de Dynamics NAV.

El campo Database Name determina a que base de datos se va a conectar la aplicación, y el mismo
nombre aparece en la herramienta SQL Server Management Studio.
Microsoft Dynamics Development Environment
Como desarrolladores de NAV, esta es la aplicación donde pasaremos la mayoría de tiempo. En esta
aplicación están listados todos los objetos de NAV que podemos programar, así como también nos
permite crear nuevos objetos. Hay 7 tipos de objetos en NAV, siendo éstos

Tablas
Los objetos donde la información es guardada, y que al igual que cada uno de los objetos que revisamos
acá, puede programarse. La intención de programar una tabla es hacer validaciones para la integridad
de datos, y que dichas verificaciones se hagan a nivel de tabla para que, posteriormente, no importa
desde donde se crea, modifica o elimina un registro, dichas validaciones serán efectuadas.

Paginas
Son los formularios con los que interactúa el usuario final de NAV, asumen la interfaz y funcionalidad
que revisábamos anteriormente, y pueden ser listas, tarjetas, documentos, diálogos, páginas de roles,
etc.

Reportes
Son los reportes definidos en NAV, que primeramente definen el origen de los datos, el procesamiento
de los mismos, y los parámetros de éste, para construir un dataset que es presentado por un layout de
formato RDL, que es editable con el editor de reportes de SQL Reporting Services, o mediante Visual
Studio.

Codeunits

Son bibliotecas de código que nos permiten interactuar entre diferentes objetos (tablas, páginas,
reportes) para completar una tarea específica. Pueden instanciarse e invocarse desde cualquiera de los
otros tipos de objetos.

Query

Permite definir conjuntos de datos.

XMLPorts

Permiten generar conjuntos de datos para exportar e importar información de NAV en formato XML.

Menusuite

Permite modificar el menú de la aplicación, que en la pantalla principal del cliente de NAV, aparece en la
parte derecha de la ventana. Aquí es donde incorporamos cualquier formulario o reporte que hayamos
adicionado, y queramos hacer disponible al usuario final.
En la parte izquierda podemos definir qué tipo de objetos queremos visualizar, en la lista derecha
seleccionamos el objeto deseado y en la parte inferior aparecen los controles principales de lo que
podemos hacer con el objeto seleccionado: Diseñar (Editar), Ejecutar. O para crear uno nuevo. Click
derecho sobre un determinado objeto nos brinda más opciones, y las herramientas en la parte superior,
abajo del menú, nos ayudan a localizar un objeto determinado.

Identificación de Tablas y Formularios


Cuando nos pidan agregar una funcionalidad a algún proceso de NAV, podremos identificar donde hay
que modificar mediante la opción About this page, que accedemos de esta manera:
Que nos muestra el siguiente formulario:

Los campos en el FastTab Page Information nos proporcionan la identificación de la página a editar, en
este caso, la Pagina Sales Order con número 42. El campo Source Table nos identifica la tabla en la que
se basa dicho formulario, en este caso Sales Header, con número 36.

En el Development Environment, seleccionamos el tipo de objeto Page, y tenemos


Luego seleccionamos el tipo de objeto Table y tenemos

En cualquiera de ambos casos, damos click en el comando Design y podemos proceder a revisar el
código, para localizar el punto donde debemos hacer nuestra modificación.

Conceptos Básicos
C/AL
El Development Environment que hemos estado revisando, es conocido como C/SIDE (Client / Server
Integrated Development Environment), y su lenguaje de programación se conoce como C/AL (Client /
Server Application Language). Cada objeto accesible desde el IDE es programable, tiene eventos que
pueden programarse.

El C/AL está basado en PASCAL, por lo que usa la misma sintaxis, y su finalidad es permitir la creación de
funciones que extiendan la funcionalidad de NAV, tales como funciones especiales que pueden ser
usadas en cualquier lugar de la base de datos.
A través de C/AL, un desarrollador puede crear reglas de negocio para asegurar que la información
almacenada en las tablas tenga sentido y sea consistente con la forma en que los clientes hacen
negocios.

Tipos de Datos
En NAV 2016 hay una gran cantidad de tipos de datos, para efectos de este curso vamos a centrarnos en
los más comúnmente usados:

Decimal Puede contener números decimales dentro del rango desde -


999,999,999,999,999.99 hasta +999,999,999,999,999.99.
Integer Almacena valores enteros dentro del rango desde -2,147,483,647 hasta
2,147,483,647.
BigInteger Almacena valores enteros dentro del rango desde -
9,223,372,036,854,775,807 to 9,223,372,036,854,775,807.
Option En la propiedad OptionString del campo o variable de tipo option puede
especificarse los valores de la opción como una lista separada por
comas. El tipo Option es un enumerador con base cero, lo que significa
que los valores de la opción son asignados a números secuenciales,
comenzando con cero. Este tipo de datos puede convertirse a enteros.
Code Almacena una cadena de texto que es convertida a mayúsculas y a la
que se le remueve cualquier espacio.
Boolean Almacena solamente dos posibles valores, true o false.
Date Denota una fecha dentro del rango del 1 de Enero de 1753 al 31 de
Diciembre de 9999. El valor de esta tipo de datos cuando está vacío se
especifica como 0D.
Datetime Denota una fecha y hora dentro del rango desde 1 de Enero de 1753
00:00 al 31 de Diciembre. EL valor de este tipo cuando está vacío se
especifica como 0DT.
Time Denota una hora dentro del rango desde 00:00:00.000 to 23:59:59.999.
El valor de esta variable cuando se encuentra vacío es especificado por
0T.
Codeunit Este es un tipo de datos complejo que representan una instancia de una
Unidad de Código C/AL. Se usa para acceder a funciones definidas por el
usuario.
Page Este tipo complejo de datos almacena páginas. Un ejemplo común de su
uso es precargar un registro determinado antes de abrir una página.
Query Un tipo de datos complejo que almacena consultas de base de datos. Un
query permite recuperar datos de múltiples tablas y combinarlas en un
solo conjunto de datos.
Record Este tipo de datos complejo se corresponde con una fila en una tabla.
Cada registro consiste de campos que forman las columnas de la tabla.
Un registro se usa típicamente para contener información de una tabla y
acceder dichos campos.
Report Este tipo de datos complejo almacena reportes. Un uso típico para este
tipo de datos es ejecutar un reporte para un registro en específico, como
por ejemplo, imprimir la factura número 4567.
Definición de Objetos
Los objetos de la base de datos se definen desde el IDE, Development Environment, podemos
inspeccionar una tabla, por ejemplo Customer, que es la Tabla con correlativo número 18.
Seleccionamos la tabla en el IDE y presionamos el botón Design:

Cada campo tiene un número correlativo que es muy importante y que lo identifica únicamente dentro
del NAV. Igualmente tiene un nombre que puede contener espacios y caracteres especiales. Un tipo de
datos, Una longitud donde aplique, y una descripción.

Cada uno de estos campos, y la misma tabla, tienen propiedades que pueden cambiarse para lograr el
objetivo que perseguimos. Accedemos a las propiedades con Shit+F4, o con el icono en la barra de
herramientas.
Para acceder a las propiedades del objeto que estamos revisando, vamos a la última fila vacía y ahí
invocamos la ventana de propiedades:
Antes mencionamos que se puede codificar triggers para casi cualquier elemento de casi cualquier
objeto. Para ver el código relacionado a un campo, para continuar con nuestro ejemplo, seleccionamos
dicho campo en el diseñador y presionamos F9, o el icono relacionado en la barra de herramientas.

Si del código anterior observamos el trigger OnValidate del campo Contact, podemos notar la
instrucción:
IF RMSetup.GET THEN
RMSetup es una variable creada en el contexto de la tabla Customer, y podemos examinar su definición,
y la de las demás variables, yendo a View, C/AL GLobals o presionando Ctrl + G.

Asi podemos ver que RMSetup es una variable de tipo Record y que tiene un subtipo (la tabla a la que
hace referencia) Marketing Setup.

Ahora que hemos revisado el ambiente de diseño y desarrollo, veamos los tipos de objetos que
podemos definir en detalle.

Tablas
Como ya vimos, un objeto de tipo Tabla representa una tabla física en la base de datos. Los registros en
NAV se almacenan en tablas. Una tabla puede ser visualizada como una matriz de dos dimensiones,
consistente de columnas y filas. Cada fila es un solo registro, cada columna es un campo de dicho
registro.

Una tabla consiste de los datos de la tabla y la descripción de la tabla. Los datos contienen los registros y
sus campos, mientras que la descripción especifica el diseño y las propiedades de la tabla y sus campos.

La descripción de la tabla no es visible directamente al usuario. Cuando el desarrollador crea una tabla,
le asigna un nombre, una numero de ID, y campos. Esto constituye la descripción de la tabla. Las
características de los campos, como en nombre, numero de ID, tipo de datos, valor inicial, llaves
primarias y secundarias, también son parte de la descripción de la tabla.

La descripción de la tabla contiene propiedades, desencadenadores, campos y llaves.


Propiedades
La tabla descripción contiene algunas propiedades que están relacionadas a la tabla y otras que están
relacionadas a los campos o llaves de la tabla. Para acceder las propiedades de un campo, basta
seleccionar dicho campo y presionar Shift + F4, o el botón correspondiente de la barra de herramientas.

Para acceder a las propiedades de la tabla, hay que desplazarse hasta el final de los campos, a la primera
línea vacía y ahí presionar Shift + F4, o el botón de la barra de herramientas
Triggers
Los Triggers o desencadenadores son funciones predeterminadas que se ejecutan cuando ocurre un
evento determinado. El cuerpo de estas funciones está vacío inicialmente y el desarrollador debe
definirlos. Para definirlos, se usa código de C/AL. Para visualizar el código relacionado a un campo
determinado, se posiciona en dicho campo en la ventana de diseño de la tabla, y se presiona F9, o el
botón correspondiente en la barra de herramientas.

Existen triggers a nivel de tabla y a nivel de campos. Los triggers de tabla son por ejemplo OnInsert, que
contiene instrucciones que se ejecutan cada vez que un nuevo registro es insertado en la tabla.
OnModify, que se ejecuta cuando un registro de la tabla es modificado.

Campos
Una tabla debe tener al menos un campo. Los campos definen la información que se mantendrá en la
tabla. Cada campo tiene sus propiedades y desencadenadores.

Cada campo tiene un tipo de datos apropiado. Cada tipo de datos aloja una clase específica de
información, tal como texto, números, fechas, etc. A continuación los principales tipos de datos que
pueden usarse en la definición de tablas

Tipo de Datos Descripción


BigInteger Entero de 64 bits. Se usa para almacenar números enteros grandes.
Binary Datos binarios. El valor correspondiente en SQL es VARBINARY.
BLOB (Binary Large Object) Se usa para almacenar bitmaps y memos. El tipo de
datos correspondiente de SQL Server es IMAGE.
Boolean Este tipo de datos indica los valores TRUE o FALSE. Al formatearse, un
Boolean despliega Yes o No. El tipo de datos correspondiente en SQL
Server es TINYINT.
Code Este tipo de datos representa un tipo especial de cadena alfanumérica
cuyo contenido es convertido a mayúsculas al ingresarse. El tamaño
puede ser de entre 1 a 250 caracteres. EL tipo de datos correspondiente
en SQL Server es NVARCHAR.
Date Este tipo de datos indica un valor de fecha en el rango desde 1 de enero
de 1753 al 31 de diciembre de 9999. Una fecha indefinida es expresada
como 0D. EL tipo de datos correspondiente en SQL Server es DATETIME.
DateFormula Este tipo de datos es usado para contener una fórmula de tipo fecha que
tiene las mismas capacidades que una cadena común de entrada para la
función CALCDATE.
DateTime Este tipo de datos representa un punto en el tiempo combinando fecha
y hora. Un campo datetime es almacenado en la base de datos como un
Coordinated Universal Time (UTC) y siempre es desplegado como hora
local en Dynamics NAV. La hora local es determinada por la
configuración regional de hora de la PC donde corre el cliente. La hora se
introduce como hora local y NAV la convierte en UTC al momento de
almacenarla a la base de datos de manera automática.
Decimal Denota un número decimal desde -999,999,999,999,999.99 to
+999,999,999,999,999.99.
Duration Este tipo de datos representa la diferencia entre dos puntos en tiempo
en milisegundos. Este valor puede ser negativo.
GUID Un identificador globalmente único (GUID) se usa para la identificación
de objetos, programas, registros, etc.
Integer Este tipo de datos almacena un numero entero entre -2,147,483,647 y
2,147,483,647. El tipo correspondiente de datos en SQL Server es
INTEGER.
Option Este tipo de datos almacena un valor de opción entero. Un campo de
opción se define usando una cadena de opción. Esta es una lista de
cadenas separada por comas, que representa cada valor válido del
campo. Esta cadena se usa cuando un campo Option es formateado y su
valor es convertido en cadena. Por ejemplo:
• El campo Option Color está definido usando la cadena
‘Rojo,Verde,Azul’
• Los valores válidos del campo son entonces 0, 1 y 2.
• Cuando el campo Color es formateado, 0 se convierte en Rojo, 1
en Verde y 2 en Azul.
RecordID Este tipo de datos contiene el número de tabla y la llave primaria de la
tabla.
TableFilter Este tipo de datos se usa para aplicar un filtro a otra tabla. Este puede
ser usado para aplicar filtros de seguridad desde la tabla Permission.
Text Denota una cadena alfanumérica. La cadena debe definirse con una
longitud desde 1 a 250 caracteres. Una cadena de texto vacía tiene una
longitud de cero. El tipo de datos de SQL Server es NVARCHAR.
Time Indica cualquier hora en el rango de 00:00:00 hasta 23:59:59.999. Una
hora indefinida se expresa como 0T. El tipo de datos correspondiente en
SQL Server es DATETIME.

Llaves
La descripción de la tabla contiene una lista de llaves. Una llave es una secuencia de uno o más ID de
campos de la tabla. Se puede asociar hasta 40 llaves a una tabla. Las llaves se usan para definir el
método de ordenamiento de los registros en una tabla, aunque este no es el único uso de las tablas.

Grupos de Campos
Algunos campos están activados con una funcionalidad de filtro-al-escribir. Cuando se ingresa datos en
uno de estos campos, un control dropdown aparece que despliega los datos de la tabla de origen. Para
especificar que campos se despliegan en este control dropdown, se debe usar Grupos de Campos.

Llaves Primarias
La base de datos mantiene control de cada registro usando la llave primaria del registro. Se puede
considerar la llave primaria como el nombre del registro. El identificador de cada registro en una tabla
particular debe ser único. Este identificador es cómo SQL Server recupera y actualiza registros.

La llave primaria puede estar compuesta hasta por 20 campos en un registro. La combinación de valores
en los campos de la llave primaria hace posible que SQL Server ejecute una identificación única de cada
registro. La llave primaria determina el orden lógico en que los registros están almacenados, sin
importar su ubicación física en el disco.

Llaves Secundarias
Las llaves secundarias se usan para visualizar los registros en un orden diferente de aquel en que los
registros están ordenados de acuerdo a la llave primaria.

El número de campos en una llave primaria, más los campos de cada llave secundaria, no debe exceder
de 20. Cada llave secundaria puede contener hasta 20 campos únicos, sin embargo, estos 20 campos
deben incluir todos los campos de la llave primaria. Los campos de la llave primaria no se mencionan
específicamente en la llave secundaria, éstos son agregados por SQL Server.

Relaciones
Hay tres tipos de relaciones entre tablas de una base de datos:

• De una a muchas
• De muchas a muchas
• De una a una

La más común de estas es De una a muchas. Si una base de datos contiene tablas con datos
relacionados, los desarrolladores pueden definir una relación entre ellas. Las tablas se relacionan al
especificar uno o más campos que contienen el mismo valor en registros relacionados. Estos campos
correspondientes con frecuencia tienen el mismo nombre en cada tabla. Los campos pueden usar
relaciones para hacer lo siguiente:

• Validar entrada de datos


• Ejecutar lookup en otras tablas
• Propagar automáticamente cambios de una a otras tablas

Las relaciones se definen usando la propiedad TableRelation. Esta propiedad permite a los
desarrolladores definir relaciones de tabla simples y avanzadas. Una relación simple consiste de una sola
tabla y un campo opcional, mientras que una relación de tabla avanzada típicamente comienza con una
instrucción condicional e incluye filtros.

(Ejemplos: Sales Header, Sales Line)

Campos Especiales
Además de los campos de datos convencionales que almacenan valores, hay tres tipos de campos
especializados que están disponibles para recuperación de datos:

• SumIndexFields
• FlowFields
• FlowFilter Fields

FlowFields
Un FlowField es un campo virtual que extiende los datos de la tabla. Es una característica poderosa de
Dynamics NAV, y es usada para calcular valores desde otra tabla. La información en los FlowField solo
existe en tiempo de ejecución.
Para actualizar un FlowField, se usa la función CALCFIELDS. Cuando se usa un FlowField en una página,
reporte, query o XMLport, éste se calcula de manera automática.

Tipos de FlowField

FlowField Tipo de Datos Descripcion


Sum Decimal La suma de un conjunto especificado en una columna de
una tabla
Average Decimal El valor promedio de un conjunto especificado en una
columna de una tabla
Exist Boolean Indica si algún registro existe en un conjunto especifico
en una tabla
Count Integer El número de registros en un conjunto específico de una
tabla
Min Cualquera El valor mínimo en una columna de un conjunto de
datos en una tabla
Max Cualquiera EL valor máximo en una columna de un conjunto de
datos en una tabla
Lookup Cualquiera Busca un valor en una columna de otra tabla

Fórmulas de Cálculo y la propiedad CalcFormula

Un FlowField siempre se asocia con una fórmula de cálculo que determina como se calcula el valor del
campo. Ejemplo Sales Header.

FlowFilter
Los usuarios podrían querer limitar los cálculos de forma que incluyan solo aquellos valores en una
columna que tienen algunas propiedades específicas. Por ejemplo, el usuario podría querer sumar
solamente los montos de entradas de clientes de Abril. Esto puede lograrse si la aplicación es diseñada
usando campos FlowFilter para los FlowFields.

El FlowFilter debe existir en la misma tabla que el FlowField y aparecerá automáticamente en todas las
páginas con esta tabla como fuente en el filtro Limit totals to.

SumIndexFields

Un SumIndexField es un campo decimal que puede ser anexado a una definición de llave. Esta es la
característica fundamental de Dynamics NAV que constituye la base para los FlowFields. Los campos
SumIndexFields permiten cálculos rápidos de columnas numéricas en las tablas, aún en tablas con miles
de registros. Esto es porque los SumIndexFields son actualizados cuando el registro de la base de datos
es actualizado.

En una aplicación típica de base de datos, para saber el total de la columna Amount, SQL Server debe
leer todos los registros y sumarlos. Pero en NAV, solamente dos accesos se usan para sumar los montos
de estos registros. Esta estructura especial de índice, un SumIndexField, está asociado con una llave.
Cada llave puede tener hasta 20 SumIndexFields. Durante el diseño de la base de datos, un campo
decimal puede asociarse con una llave como un SumIndexField. Esto le indica a SQL Server que debe
crear y mantener una estructura que contenga la suma acumulada de valores en una columna.
Ejemplos de campos especiales: Tabla Customer; Balance (LCY) es un FlowField de tipo Sum. Se calcula
sumando el campo Amount de la tabla Detailed Cust. Ledger Entry, filtrada por los campos Customer
No., Dimensions Filter y Currency Filter. Estos campos son campos FlowFilter en la tabla Customer y se
usan para filtrar los cálculos del FLowField Balance (LCY). Sin embargo, el campo SumIndexField Amount
está ubicado en las llaves de la tabla Detailed Cust. Ledger Entry.

Paginas
Las páginas contienen propiedades, triggers y controles que definen el comportamiento de la página. La
página se muestra en el cliente, sin embargo, la lógica de aplicación en los triggers de la página se
ejecuta en la capa de servicios de NAV.

Propiedades
Las propiedades definen el comportamiento de las páginas, por ejemplo, propiedades como
InsertAllowed, ModifyAllowed, DeleteAllowed, especifican si se usa una página solamente para
desplegar información, o si se puede insertar nuevos registros, actualizarlos o eliminarlos.

Triggers
En una página hay eventos predefinidos que desencadenan la ejecución de código C/AL, estos
desencadenadores pueden ser de los siguientes tipos:

• Triggers de Pagina
• Triggers de Control
• Triggers de Acción

Controles
Los controles se usan para definir el diseño de una página. Algunos controles pueden agrupar u ordenar
otros controles o desplegar información en una página. Los controles pueden desplegar datos de las
siguientes fuentes:

• Un campo de tabla de base de datos


• El valor de una expresión C/AL
• Imágenes Bitmap
• Información estática tal como un texto descriptivo
• Otras páginas
• Características predefinidas del sistema, tales como Outlook o Record Links

Dependiendo del tipo de página y sus controles padre, ciertos controles podrían no estar disponibles
todo el tiempo. Por ejemplo, usar FastTabs solo en Cards, ListPlus y páginas de Documentos.

Acciones
En el cliente, los botones están ubicados en la cinta de opciones. Cuando un usuario hace click en una
acción, ésta inicia una actividad definida del sistema o ejecuta un trigger. Las Acciones se crean y
modifican desde el Diseñador de Acciones, al que se accede desde el Diseñador de Pagina. Las acciones
tienen sus propias propiedades y triggers.
Las Acciones pueden ser de Página o de Controles. Las de página son desplegadas en la cinta en la parte
superior de la página. La mayoría de los tipos de página soportan acciones de página. Las acciones de
Control se despliegan en el control mismo, y solo el control CueGroup soporta acciones de control.

Tipos de Páginas
Una de las propiedades más importantes de una página es PageType que se usa para especificar el tipo
de página. El tipo de página determina cómo se despliega la página en el cliente. También controla
ciertas características de comportamiento de la página.

Card Page
Una página de tipo Tarjeta permite al usuario visualizar y editar un registro a la vez. Se usa cuando hay
muchos campos para visualizar en una sola línea. Una página de tarjeta siempre usa al menos un
FastTab.

Como regla general, se usa el nombre de la tabla asociada para nombrar las páginas de tarjeta, seguidas
por la palabra “Card”. Por ejemplo, la página de tarjeta asociada a la tabla Customer es llamada
Customer Card.

List Page
Una página de lista es una página multi-registros que permite a los usuarios ver múltiples registros
desde una tabla al mismo tiempo. Si la tabla no es editable, por lo general se nombra en base a la tabla
asociada, seguido por la palabra “List”. Por ejemplo, la página de lista asociada a la tabla Customer se
llama Customer List. Si la lista es editable, se nombra con el plural del nombre de la tabla asociada, por
ejemplo, la página de lista asociada con la tabla Currency se llama Currencies.

CardPart Page
Se usa una página CardPart para desplegar campos o un control especial como un visualizador de
imágenes, en un FactBox. Use una página CardPart para crear FactBox de una sola columna. Las páginas
CardPart se nombran con la información asociada, seguido de la palabra FactBox. Por ejemplo, el
historial de ventas de un vendedor se llama Sales Hist. Sell-to FactBox.

ListPart Page
Se usa una página ListPart para desplegar subpáginas para documentos. También se puede usar una
página ListCard como un FactBox para desplegar múltiples filas y columnas desde una sola tabla. Cuando
se usan como FactBoxes, se nombran a partir de la información asociada y la palabra “FactBox”. Por
ejemplo, la página ListPart que despliega las dimensiones se llama Dimensions FactBox. Cuando se usa
una ListPart como subpáginas para documentos, se nombra con el nombre del documento asociado,
seguido de la palabra “Subform” o “Subpage”. Por ejemplo la PartList que despliega las líneas en la Sales
Order se llama Sales Order Subform.

Worksheet Page
Worksheet es una página de multiples registros que permite a los usuarios verlos y editarlos. Un
ejemplo de uso son las paginas Journals. Son nombradas de acuerdo al propósito de la tabla asociada.
Para tablas Journal, el nombre de la página termina con la palabra Journal. Por ejemplo, General Journal.
Document Page
Una página de documento contiene una serie de FastTabs y una PagePart con líneas en la misma página.
Despliega información de dos tablas con relación encabezado-detalle, tales como las tablas Sales Header
y Sales Line, o Purchase Header y Purchase Line. El nombre de las páginas de documento es la función
que representa, tales como Sales Order.

Reportes
Los reportes imprimen, estructuran y resumen información. Se usa reportes para imprimir documentos
como facturas, y para procesar datos sin imprimir.

Revisemos algunos tipos de reportes:

• Esctructurar información de una base de datos, por ejemplo, reporte 108, Customer – Order
Detail, que lista todos los clientes y todas las ordenes de ventas para cada cliente.
• Imprimir y desplegar documentos en la aplicación, por ejemplo, el reporte 206, Sales – Invoice,
que imprime una factura junto con su información relevante.
• Automatizar tareas repetitivas, como actualizar los precios en una lista de artículos. Esto puede
hacerse usando código C/AL en una codeunit, pero un reporte lo hace más fácil debido a la
modelación de datos que está disponible para el diseño de los reportes, tales como el reporte
794, Adjust Item Costs/Prices

Un reporte consiste de la descripción que especifica cómo se recopila la información, se presenta en la


pantalla, o se imprime en papel cuando se ejecuta el reporte.

Programación
El C/AL permite a los desarrolladores crear funciones que extienden la funcionalidad de Dynamics NAV,
tales como funciones especiales que se pueden usar en cualquier lugar de la base de datos.

Además, el C/AL nos permite hacer lo siguiente:

• Diseñar funciones personalizadas.


• Conectar objetos de base de datos
• Leer, escribir y cambiar datos.

El propósito principal del lenguaje de programación de Dynamics NAV es manipulación de datos. A


través de C/AL, los desarrolladores pueden crear reglas de negocios para asegurarse que los datos
almacenados en las tablas tengan sentido y sean consistentes con la forma en que nuestros clientes
hacen negocios. A través de programación, los desarrolladores pueden:

• Agregar datos nuevos o transferir datos de una tabla a otra, como por ejemplo transferir de un
journal a una tabla de diario.
• Combinar datos de múltiples tablas en un reporte o desplegarlos en una página.

El código de C/AL podemos usarlo en los triggers de tabla, páginas y campos en los diferentes objetos
que hemos revisado hasta este momento, así como en CodeUnits.
Tipos de datos Intrínsecos
Los datos son piezas de información. Los tipos de datos son la clasificación de esta información. La
clasificación de datos es importante porque indica cómo la aplicación debe manejar los datos cuando
ejecuta el código.

Diferentes tipos de datos tienen valores diferentes y significados diferentes para dichos valores. Los
tipos de datos se manejan de manera diferente. Los tipos de datos pueden ser numéricos o de texto. Por
ejemplo, se tienen dos valores, 25 y 37 y se quieren sumar. El resultado que obtengamos depende del
tipo de datos que los contengan. Si los valores son numéricos, el resultado es 62, sin embargo, si son
texto, el resultado podría ser 2537.

Constantes

Las constantes son valores de datos que son escritos directamente en líneas de programación. Se llaman
constantes porque sus valores nunca cambian mientras la aplicación corre. Para cambiar sus valores,
debe cambiarse el código C/AL.

Tipos de datos simples


Son tipos que solo tienen un valor. No pueden separarse en otros valores de diferentes tipos.

Tipos de datos numéricos


• Integer
• Big Integer
• Decimal
• Option
• Char

Tipos de datos de cadena


• Texto
• Codigo

Tipos de datos lógicos


• Boolean

Tipos de datos de Fecha


• Date
• Time
• DateTime

Tipos de datos complejos


• Registro
• Pagina
• Codeunit
• File
• Dialog
• Report
• DateFormula
• GUID
• TableFilter
• RecordRef
• RecordID
• FieldRef
• KeyRef
• Instream y OutStream
• Variant
• BigText

Identificadores, Variables y Sintaxis


Un identificador es el nombre de un elemento de programación. Una variable es una ubicación en
memoria donde datos de valores variables son almacenados. La sintaxis en nuestro caso se define como
las reglas gramaticales para usar identificadores y variables.

Identificador
Un identificador es un nombre que identifica o etiqueta ya sea un objeto único o una clase de objetos
única. Los objetos, variables, campos y funciones tienen todos identificadores. Algunos elementos de un
programa no tienen identificadores, tales como constantes, operadores y ciertas palabras reservadas. Se
refiere a ellas directamente. Los elementos de programación que se refieren a datos almacenados en
memoria requieren un identificador para acceder dichos datos; los elementos de programación que
existen en el código de programación mismo no se refieren a datos y por lo tanto no necesitan un
identificador.

Variable
Una variable es un valor que puede cambiar dentro del alcance de un conjunto dado de operaciones.
Adicionalmente, una variable tiene las siguientes características:

• Referencia a una ubicación de memoria donde los datos están almacenados.


• Un nombre, también conocido como identificador, que el programador usa en lugar de la
dirección de memoria
• Tipo de datos que describe el tipo de datos que puede ser almacenado en la dirección de
memoria.
• Valor de los datos actualmente almacenados en dicha dirección de memoria.

Sintaxis
Es un conjunto de reglas gramaticales que definen el lenguaje de programación. Se dice que las líneas de
programación o código que sigue estas reglas siguen una sintaxis correcta. La computadora no entiende
código que no siga una sintaxis correcta y no compila o ejecuta dicho código.

Expresiones, Términos y Operadores


Expresiones, términos y operadores son partes de las instrucciones. Un operador opera en uno o más
términos que conforman una expresión que luego se evalúa en un valor.
Expresión
Una expresión especifica la información que genera un valor deseado. Similar a una variable o
constante, una expresión tiene un tipo y un valor. El valor de una constante siempre es conocido; el
valor de una variable es determinado en tiempo de ejecución. El sistema debe acceder la memoria para
recuperar el valor de constantes y variables. Sin embargo, una expresión es evaluada en tiempo de
ejecución para determinar su valor. Los siguientes son ejemplos de expresiones:

• FuncionX + 7
• Quantity * UnitCost

Evaluación
Evaluar una expresión significa seguir las instrucciones establecidas en la fórmula exactamente, y
entonces determinar el valor y tipo de la expresión en dicho momento. Dependiendo de los valores de
las variables incluidas en la expresión, el valor puede ser diferente cada vez que la expresión es
evaluada, aunque su tipo no cambia.

Términos
Un término es una parte de una expresión que se evalúa en un valor. Puede ser una variable, una
constante o una llamada a una función, siempre que dicha función devuelva un valor. Un término puede
también ser otra expresión que se encierra entre paréntesis. Este tipo de término también se conoce
como una sub expresión. Según los ejemplos previos, tenemos los siguientes términos:

• FuncionX
• 7
• Quantity
• UnitCost

Operador
Un operador es una parte de la expresión que actúa sobre los términos que le siguen directamente (un
operador unario), o los términos a cada lado de él (un operador binario). Los operadores se representan
por símbolos, tales como +, >, / e =. O por palabras reservadas, tales como DIV y MOD. Son definidos por
C/AL y un programador no puede agregarlos ni cambiarlos.

Tipo de Operador Sintaxis Valida


Operador unario +, -, NOT
Operador de cadena +
Operador aritmético +, -, *, /, DIV, MOD
Operadores relacionales <, >, =, <=, >=, <>, IN
Operadores lógicos NOT, OR, AND, XOR

El Operador de Cadena
EL signo más es el único operador de cadena, e indica concatenación. Es un operador binario, lo que
significa que actúa sobre el término que le antecede y el que le sigue, dando como resultado una sola
cadena. Ambos términos deben ser cadenas de tipo Code o Text. Si ambos términos son de tipo Code, la
concatenación resultante es de tipo Code, de lo contrario, es de tipo Text. Debe observarse que cuando
el resultado de la concatenación excede la longitud máxima de una variable de cadena, un error se
genera, por lo que hay que procurar evitar este tipo de errores.

Llamadas a Funciones en las Expresiones


Para el caso mencionado arriba, llamar a una función dentro de una expresión ayuda a solucionar el
problema, teniendo en cuenta que, como veíamos antes, una función es un término siempre y cuando
devuelva un valor, y en este caso, de tipo cadena.

La función MAXSTRLEN
Es una función que devuelve la longitud máxima definida de una variable de cadena.

La función COPYSTR
Es una función que copia una subcadena de cualquier longitud, desde una posición específica en una
cadena (text o code) a una nueva cadena. Esta función tiene tres parámetros:

• La cadena a copiar
• Posición del primer carácter a copiar, basado en 1.
• Numero de caracteres a copiar. Opcional. Si no se especifica, se copia desde la posición inicial
hasta el final de la cadena.

El valor de retorno es una cadena ya sea text o code, dependiendo del tipo de la cadena original del
primer parámetro.

Ejemplo:
Description := COPYSTR(‘EL mensaje es: ‘ + CodeB, 1, MAXSTRLEN(Description));

Expresiones Numéricas

Las expresiones numéricas resultan en un valor numérico. Los términos individuales en una expresión
numérica no necesariamente deben ser numéricos. Usan al menos un operador aritmético. Al ser
evaluadas, devuelven un tipo numérico, que puede ser decimal, integer, option o char.

Precedencia de los operadores


La precedencia de los operadores es el orden en que los operadores son evaluados en una expresión.
Los operadores con una precedencia más alta se evalúan antes que los operadores con una precedencia
menor. Por ejemplo, el operador de multiplicación (*) tiene una mayor precedencia que el operador de
suma (+), por lo tanto, la expresión 5 + 2 + 3 se evalúa como 11, en lugar de 21.

Expresiones Relacionales y Lógicas


Son las que resultan en un valor Booleano. Estas expresiones usan operadores lógicos o relacionales
para determinar su valor. Cuando las expresiones lógicas y relacionales son evaluadas, el resultado es
siempre, ya sea, TRUE o FALSE.

Ejemplos de expresiones lógicas

• TRUE AND FALSE


• FALSE OR NOT FALSE
• (Quantity > 5) OR (Quantity <= 10) OR (Price < 100))
Precedencia Lógica de Operadores

Tipo de Operador Operador Comentarios


Términos o () Las subexpresiones en paréntesis son
Subexpresiones [] evaluadas primero
.
::
Unarios + La precedencia más alta en una expresión
+
NOT
Multiplicación *
/
DIV
MOD
AND
Suma +
-
OR
XOR
Relacionales < Precedencia más baja en una expresión
<=
=
>
>=
<>
IN
Rango .. Usada en un Conjunto de Constantes

Instrucciones
Instrucciones Condicionales y Expresiones Booleanas
Una instrucción condicional prueba una condición y ejecuta una o más instrucciones basadas en la
condición. La instrucción condicional más frecuentemente usada es la instrucción IF. Se usa cuando hay
solamente dos posibles valores para la condición: TRUE o FALSE. Una expresión Booleana resulta en un
valor Booleano, tal como una variable o constante booleana, una expresión relacional, o una expresión
lógica.

Instrucción IF
Se usa la instrucción IF para controlar si una parte de un programa se ejecuta. Si la condición es TRUE,
un conjunto de una o más instrucciones se ejecuta, y si la condición es FALSE, otro conjunto de una o
más instrucciones se ejecuta.

Ejemplo
IF <expresión-booleana> THEN <instrucción>

IF Quantity < 0 THEN


UnitPrice := TotalPrice / Quantity
ELSE
UnitPrice := 0;

La instrucción EXIT
El código en un desencadenador se ejecuta secuencialmente desde el inicio hasta el final. Un
programador podría no querer ejecutar el resto del código en un disparador. La instrucción EXIT se usa
para este propósito. Cuando una instrucción EXIT se ejecuta, el programa sale del desencadenador
actual y regresa al objeto que lo llamó, si lo hay, o vuelve al usuario.
IF Quantity = 0 THEN
EXIT;
UnitPrice := TotalPrice / Quantity;

La instrucción CASE
Se usa la instrucción condicional CASE cuando hay más de dos posible valor para la condición.
CASE <expresión> OF
<conjunto de valores 1>: <instrucción 1>;
<conjunto de valores 2>: <instrucción 2>;
<conjunto de valores n>: <instrucción n>;
[ELSE <instrucción n+1>]
END
Un conjunto de valores se parece al conjunto de constantes usado para el operador IN, excepto que el
conjunto de valores no tiene corchetes. Los conjuntos de valores pueden ser cualquiera de

• Un valor simple
• Múltiples valores separados por comas
• Rangos de valores
• Múltiples rangos separados por comas

Todos los valores en los conjuntos deben tener un tipo comparable con el tipo de la expresión. En la
mayoría de los casos, el tipo de datos de los conjuntos de valores son convertidos al tipo de datos de la
expresión evaluada. La única excepción es una variable Code, en cuyo caso los conjuntos de valores no
son convertidos al tipo de datos Code.

La cláusula ELSE es opcional.

Cuando una instrucción CASE se ejecuta, la expresión es evaluada primero. Luego, cada valor o conjunto
de valores es evaluado en orden. Si uno de los valores del primer conjunto de datos concuerda con el
valor de la expresión, el primer conjunto de instrucciones se ejecuta, en caso contrario, se verifica el
segundo conjunto de valores, y si algún valor de éste concuerda, el segundo conjunto de instrucciones
se ejecuta, y así hasta el final.

Si el ultimo conjunto de valores se alcanza y ningún conjunto de instrucciones se ha ejecutado, se


chequea la cláusula ELSE y si existe, se ejecuta.
Comentarios
Un comentario es una descripción que el programador escribe en su código. El propósito es para explicar
el código, documentar quien hizo una modificación, o el porqué de la modificación. Dado a que el
comentario es una descripción, y no una parte del programa, no queremos que el compilador lo lea. Dos
signos slash (//) o un conjunto de llaves ({}) le indican al compilador que estas líneas son comentarios, y
no deberían ser compiladas.

Instrucciones compuestas
Una instrucción compuesta es un conjunto de instrucciones. Amplía las capacidades de las instrucciones
condicionales. Por ejemplo, cuando en una instrucción IF una condición se evalúa TRUE, se puede usar
una instrucción compuesta para ejecutar más de una instrucción. Usualmente, después del THEN,
solamente se ejecuta una instrucción. Sin embargo, si la instrucción es compuesta, múltiples
instrucciones pueden ejecutarse.
IF Quantity <> 0 THEN BEGIN
UnitPrice := ExtendedPrice / Quantity;
TotalPrice := TotalPrice + ExtendedPrice;
END;

IF Quantity <> 0 THEN BEGIN


UnitPrice := ExtendedPrice / Quantity;
TotalPrice := TotalPrice + ExtendedPrice;
END ELSE BEGIN
UnitPrice := 0;
EXIT;
END;

Arreglos
Los arreglos son variables complejos que contienen un grupo de variables con el mismo tipo de datos.
Son variables especiales que tienen más funcionalidad que las variables discutidas previamente. Este
grupo completo se define con un solo identificador y un solo tipo de datos. Por ejemplo, un
programador puede crear una variable como un arreglo:

• Identificador: QunatityArray
• Tipo de datos: Integer
• Elementos: 5

Un elemento es una variable dentro del arreglo. Un arreglo consiste de uno o más elementos.

Un índice se usa para referirse a un solo elemento del arreglo. Para acceder un elemento del arreglo, se
usa el nombre identificador en conjunto con el índice. Para acceder el cuarto elemento en el arreglo
anterior se usa:

• QuantityArray[4]

Un arreglo puede tener una o más dimensiones. El arreglo más simple es un arreglo de una sola
dimensión. En C/AL los arreglos pueden tener hasta 10 dimensiones.
Las variables de cadena, text o code, son en realidad arreglos de caracteres. Por lo tanto, pueden
accederse a ellos como elementos en un arreglo:
Str := “Walk in the park”;
Str[13] := ‘d’;
MESSAGE(Str);

El mensaje resultante sería “Walk in the dark”.

Sin embargo, para conocer el máximo elemento de un arreglo, usamos ARRAYLEN, para saber la longitud
de una cadena usamos STRLEN.

Instrucciones repetitivas
Una instrucción repetitiva es una que permite la ejecución de una o más instrucciones más de una vez.
Hay varios tipos de instrucciones repetitivas. La diferencia entre instrucciones repetitivas está en el
número de veces que son ejecutadas y en cómo se determina ese número. Una instrucción repetitiva se
conoce como un loop, porque cuando la ejecución alcanza el fin de la instrucción repetitiva, regresa al
inicio de dicha instrucción.

La instrucción FOR
Se usa una instrucción FOR cuando una instrucción se ejecuta un número predeterminado de veces.

Sintaxis:

FOR <variable de control> := <valor inicial> TO <valor final> DO <instrucción>

La variable de control debe ser una variable de tipo Boolean, Date, Time o cualquier tipo numérico. Los
valores inicial y final deben ser valores o expresiones del mismo tipo que la variable de control.
FOR idx := 4 TO 8 DO BEGIN
Total := Total + 2.5;
GrandTotal := GrandTotal + Total;
END;

FOR idx := 9 DOWNTO 1 DO BEGIN


TotalSales := TotalSales + Sales[idx];
NumberSales := NumberSales + 1;
END;

Instrucción WHILE..DO

Se usa una instrucción WHILE cuando una instrucción debe ejecutarse mientras se cumpla una
condición. Un lazo WHILE tiene la siguiente sintaxis:
WHILE <expresión lógica> DO <instrucciones>

Ejemplo:
WHILE Sales[idx + 1] <> 0 DO BEGIN
Idx := idx + 1;
TotalSales := TotalSales + Sales[idx];
END;
Instrucción REPEAT..UNTIL
Use la instrucción REPEAT cuando una o más instrucciones se ejecutan hasta que una condición sea
TRUE, y tiene la siguiente sintaxis:
REPEAT <instrucción> {; <instrucción>} UNTIL <expresión lógica>

• Puede haber más de una instrucción entre REPEAT y UNTIL, aún sin usar BEGIN..END
• La expresión lógica es evaluada hasta el final, luego que las instrucciones se han ejecutado una
vez.
• Cuando la expresión lógica se evalúa, retorna al inicio si resulta FALSE. Si la expresión se evalúa
como TRUE, finaliza el ciclo.

Ejemplo
REPEAT
Idx := idx + 1;
TotalSales := TotalSales + Sales[idx];
UNTIL Sales[idx] = 0;

Instrucción WITH

Se usa la instrucción WITH para facilitar la codificación con variables de tipo Record. El comprende cómo
funcionan las variables record es importante para entender la instrucción WITH.

Una variable de tipo record es un tipo de datos complejo, similar a un arreglo. Un registro contiene
múltiples valores. En un arreglo, todos los valores tienen el mismo nombre y tipo y se distinguen
mediante su índice. En un registro, cada valor, conocido como campo, tiene su propio nombre y tipo.
Para distinguir estos valores, se usa un punto para separar el nombre de la variable del nombre del
campo. Por lo tanto, si un registro llamado Customer tiene un campo llamado Name, se usa
Customer.Name para acceder al valor del campo.

Un record representa una fila o registro en una tabla de la base de datos. Los campos que son parte de
un registro están definidos al usar un objeto de tabla.

Sin WITH
Custome.Name := Txt[1];
Customer.Address := Txt[2];
Customer.City := Txt[3];
Customer.Contact := Txt[4];
Customer.”Phone No.” := Txt[5];

Usando WITH
WITH Customer DO BEGIN
Name := Txt[1];
Address := Txt[2];
City := Txt[3];
Contact := Txt[4];
“Phone No.” := Txt[5];
END;
Instrucciones WITH implícitas
En varias ubicaciones del código no aparece una instrucción WITH. Estas ubicaciones usan instrucciones
WITH implícitas. Por ejemplo en el código de las tablas hay un WITH implícito que cubre el objeto
completo. Cada referencia a un campo que está definido en dicha tabla tiene el nombre de registro
implícito, conocido como Rec.

Funciones y Parámetros
Las funciones son un concepto fundamental de programación. Una función es una parte del programa
con un nombre, conocido también como subprograma o subrutina. Cuando el código que está corriendo
alcanza una función, la aplicación principal es pausada mientras se ejecuta el código de la función. La
función “regresa” al lugar donde fue invocada. El modo en que se invoca una función determine lo que
pasa cuando regresa.

• Llamada a una función en una expresión.


TotalCost := Quantity * CalculatePrice;

• Instrucción de llamada a función


IF Quantity > 5 THEN
RunFUnction;
• Llamada a función con parámetros
CubeVolume := POWER(SideLength, 3);

• Usar la expresión como un parámetro

GrossVolume := POWER(SideLength + PackagingThickness * 2, 3);

Parámetros
Un parámetro es una o más variables o expresiones que son enviados a la función a través de la llamada.
El parámetro proporciona información a la función, y la función puede cambiar esa información. Si una
función tiene parámetros, el identificador de la función tiene un conjunto de paréntesis que le sigue.
Dentro de estos paréntesis hay uno o más parámetros. Si hay más de un parámetro, se separan por
comas.

Pasar parámetros por valor

Cuando un parámetro solo envía una pieza de información a una función, el parámetro se pasa por
valor. El parámetro sólo conoce el valor de la variable o expresión que se usa para dicho parámetro.
Dado a que es solamente un valor, cualquier cambio que la función haga no afecta ninguna variable en
el disparador que la llamó.

Parar parámetros por referencia

Cuando un parámetro se pasa a la función y la función cambia ese parámetro, el parámetro es pasado
por referencia. El parámetro conoce la ubicación de memoria donde el valor está almacenado, y pasa la
ubicación de memoria a la nueva función. Cualquier cambio que la función haga a este tipo de
parámetro es permanente y afecta las variables en el disparador que la llama.

Funciones Internas
MESSAGE

ERROR

DATE2DMY

GET
La función GET recupera uno o más registros, basado en el valor de la llave primaria. La función GET
produce un error en tiempo de ejecución si falla. El valor de retorno no es inspeccionado por el código.
IF CustRec.GET(‘4711’) THEN
// Hacer algo
ELSE
// Hacer algo diferente

FIND
Las diferencias entre la función GET y FIND son las siguientes:

• La función FIND respeta (y está limitada por) la configuración actual de filtros.


• La función FIND puede usarse para buscar registros conde el valor de la llave sea igual, mayor, o
menor que los valores actuales de la llave del registro
• La función FIND puede encontrar el último registro, dentro del orden definido por la llave actual
SalesOrderLine.SETCURRENTKEY(“Document Type”, “No.”);
SalesOrderLine.SETRANGE(“Document Type”, “SalesOrderLine.”Document Type”::Order);
SalesOrderLine.SETRANGE(Type, SalesOrderLine.Type::Item);
SalesOrderLine.SETRANGE(“No.”, “No.”);
IF SalesOrderLine.FIND(‘-‘) THEN
ERROR(‘You cannot delete because there are one or more outstanding sales order
that include this ítem.’);

FIND, FINDFIRST, FINDLAST, FINDSET

Para encontrar el primer registro en una tabla, dependiendo del ordenamiento actual y filtro, se usa la
función FINDFIRST, cuando solo se necesita el primer registro. Si se necesita iterar sobre todos los
registros localizados, usar FIND(‘-‘)

Para encontrar el último registro en una tabla, dependiendo de llave y filtros, usar FINDLAST cuando solo
se necesita el último registro. Si se desea iterar, usar FIND(‘+’)

Para encontrar un conjunto de registros en una tabla dependiendo de los filtros, se usa FINDSET, este
permite iterar el recordset en combinación con un REPEAT..UNTIL. FINDSET solo permite iterar desde el
primer al último registro. Para iterar desde el ultimo al primero, usar FIND(‘+’)
NEXT

La función NEXT se usa frecuentemente con FIND y FINDSET para desplazarse a través de los registros de
una tabla. Ejemplo:

FINDSET;

REPEAT

// procesar registros

UNTIL NEXT = 0;

Funciones de Ordenamiento y Filtrado


SETCURRENTKEY
Se usa SETCURRENTKEY para seleccionar una llave para un registro. Esto establece el ordenamiento
usado para la tabla asociada. Tiene la siguiente sintaxis:

Record.SETCURRENTKEY(Campo1, [Campo2], …);

SETCURRENTKEY busca índices que contengan los campos indicados y usa dichos índices para el
ordenamiento. En versiones anteriores que NAV 2016, si no existe dicho índice o llave, se produce un
error en tiempo de ejecución. A partir de NAV 2016, no es necesario que exista una llave que incluya
dicho campo, pero el desempeño de la aplicación sufrirá porque será necesario ordenar la tabla, lo que
ocupará más recursos dependiendo del tamaño del resultset obtenido.

SETRANGE
Establece un filtro, tal como un rango simple o un solo valor, en un campo.

Record.SETRANGE(Campo, ValorInicial [, ValorFinal])

SETFILTER

La función SETFILTER establece un filtro de un modo más general al de SETRANGE. Permite especificar
expresiones de filtrado que incluyen parámetros, y caracteres wildcard.

Record.SETFILTER(Campo, Cadena, [Valor], …)

Ejemplo:

Customer.SETFILTER(“No.”, ‘>10000 & <> 20000’);

Selecciona los registros cuyo valor en el campo “No.” Es mayor que 10000 y diferente de 20000.

Customer.SETFILTER(“N0.”, ‘> %1 & <> %2’, Valor1, Valor2);

GETRANGEMIN y GETRANGEMAX

Recuperan los valores máximo y mínimo del filtro actualmente en efecto.

ValorMin := Record.GETRANGEMIN(Campo);

ValorMax := Record.GETRANGEMAX(Campo);
Funciones de Manipulación de Datos
INSERT
Inserta un registro en una tabla. INSERT devuelve un valor booleano que indica si la operación fue
exitosa.
Customer.INIT;
Customer.”No.” := ‘4711’;
Customer.Name := ‘John Doe’;
Customer.INSERT;

MODIFY
Cambia un registro existente. MODIFY devuelve un valor booleano para indicar si la actualización fue
exitosa.
Customer.GET(‘4711’);
Customer.Name := ‘Richard Roe’;
Customer.MODIFY;

MODIFYALL
Efectúa una actualización masiva de registros. También establece el valor del campo especificado al
valor proporcionado, para todos los registros respecto del filtro actual. MODIFYALL no devuelve ningún
valor ni genera error.
Customer.SETRANGE(“Salesperson Code”, ‘PS’);
Customer.MODIFYALL(“Salesperson Code”, ‘JR’);

DELETE
Elimina un registro de la base de datos. El registro a eliminar debe ser especificado usando los valores de
la llave primaria.
Customer.”No.” := ‘4711’;
Customer.DELETE;

DELETEALL
Eliminar todos los registros seleccionados por el filtro actual. Si no hay filtro establecido, se eliminan
todos los registros de la tabla.

Customer.SETRANGE(“Salesperson Code”, ‘PS’, ‘PS’);

Customer.DELETEALL;

Funciones de Campos.
CALCFIELDS
Se usa para calcular FlowFields. Cuando un reporte o página incluye un FlowField, este se calcula de
forma automática. Sin embargo, cuando se usa en código, deben calcularse explícitamente para poder
usarlos.
SETRANGE(“Date Filter”, 0D, TODAY);
CALCFIELDS(Balance, “Balance Due”);
SETAUTOCALCFIELDS
Especifica los FlowField que son calculados automáticamente cuando un registro es recuperado de la
base de datos. Usar SETAUTOCALCFIELDS tiene la ventaja sobre CALCFIELDS que mejora el desempeño,
dado a que se reduce el número de accesos a la base de datos. Con CALCFIELDS, recuperación y cálculo
son procesos separados. SETAUTOCALCFIELDS recupera los valores para los FlowFields en la misma
operación SQL Server que los otros campos en el registro.

Ejemplo comparativo:
// Usando CALCFIELDS
If Customer.FINDSET THEN REPEAT
Customer.CALCFIELDS(Balance, “Net Change”);
// Procesos normales
UNTIL Customer.NEXT = 0;
// Usando SETAUTOCALCFIELDS
Customer.SETAUTOCALCFIELDS(Balance, “Net Change”);
IF Customer.FINDSET THEN REPEAT
// Procesos normales
UNTIL Customer.NEXT = 0;

CALCSUMS
Calcula el total de una columna en una tabla, considerando los filtros aplicados.

FIELDERROR
Detiene la ejecución del código causando un error en tiempo de ejecución.

IF Item.”Unit Price” < 10 THEN

Item.FIELDERROR(“Unit Price”, ‘debe ser mayor que 10’);

FIELDCAPTION
Devuelve el texto descriptivo de un campo. Al usar FIELDCAPTION nos aseguramos que los mensajes
mostrados al usuario reflejan exactamente la descripción de un campo aunque este sea cambiado
posteriormente.

FIELDERROR(Quantity, ‘no debe ser menor que ‘ + FIELDCAPTION(“Quantity Shipped”));

INIT
Inicializa un registro asignándole los valores por defecto a todos los campos que no forman parte de la
llave primaria. Si se ha definido un valor por defecto en la propiedad InitValue de algún campo, este
valor es usado en la inicialización; de lo contrario, el valor por defecto de cada tipo de datos es usado.

TESTFIELD
Prueba si el valor de un campo concuerda con el valor especificado. Si los valores no son el mismo, la
prueba falla, un mensaje de error se despliega, y un error en tiempo de ejecución se genera. Si no se
proporciona un valor de prueba, entonces la función evalúa si hay algún valor en el campo.

VALIDATE
Invoca el trigger OnValidate de un campo. Acepta un parámetro opcional que puede usarse para
establecer el valor en el campo a un valor especificado, y entonces invoca al trigger OnValidate.

Funciones de interacción con el usuario


MESSAGE
Despliega una cadena de texto en una ventana de mensaje.

MESSAGE(Texto [, Valor1, …])

Ejemplo:
ValorDec := 12345.678;
ValorBool := TRUE;
MESSAGE(‘ValorDec es %1\ValorBool es %2’, ValorDec, ValorBool);

CONFIRM
Crea una ventana de diálogo que pregunta al usuario una respuesta en la forma de un Si o No. La
ventana de diálogo es centrada en la pantalla.

Ok := Dialog.CONFIRM(Texto [, Default] [, Valor1] [,…])

Ejemplo:
IF NOT CONFIRM(‘Desea eliminar este %1?’, FALSE, Customer.TABLECAPTION) THEN
EXIT;
Customer.DELETE;

STRMENU
Crea una ventana de menú que despliega una serie de opciones a partir de una cadena delimitada por
comas.

OpcionNumero := STRMENU(CadenaDeOpciones [, NumeroPorDefecto] [, Instrucción])

Devuelve el número de opción elegida por el usuario, siendo la primera opción 1. Si el usuario presiona
CANCEL o ESC, devuelve cero.

Dias := ‘Domingo,Lunes,Martes,Miercoles,Jueves,Viernes,Sabado’;

Seleccion := STRMENU(Dias, 1, ‘Que día es hoy?’);

ERROR
La función ERROR despliega un mensaje de error y finaliza la ejecución de código C/AL.
Funciones Locales, Variables y la Instrucción EXIT
Funciones Locales
Una función local solamente puede ser llamada dentro del objeto donde es definida.

Variables Locales
Una variable local es una variable con el ámbito limitado a un solo trigger. Esto significa que el código
en una determinada función puede acceder a una variable local y usarla como cualquier otra variable.
Sin embargo, el código en otras funciones del objeto no puede accederlas. Si el nombre de una variable
local es invocado fuera de la función en que está declarada, ocurre un error en tiempo de compilación.
Los parámetros formales también son tratados como variables locales en dicha función.

EXIT
La instrucción EXIT detiene la ejecución de un trigger o función. En las funciones, se usa también para
devolver un valor desde la función.

EXIT(<expresión>)

Si en la expresión se usa una llamada a otra función, ésta debe devolver un valor de un tipo compatible.

Reportes
Un reporte en NAV consiste en una descripción que especifica cómo se recopilan los datos, y como es
presentado cuando se ejecuta. La descripción del reporte no es visible al usuario. Cuando los
desarrolladores crean reportes, ejecutan una serie de tareas para establecer la descripción de estos:

• Asignar un nombre e Id
• Especificar fuentes de datos
• Diseñar la presentación del reporte

La descripción del reporte contiene lo siguiente:

• Propiedades
• Triggers
• Controles
• Fuentes de Datos
• Columnas
• Páginas de parámetros
• Diseño

El siguiente diagrama muestra las partes de un reporte y como se relacionan.

Propiedades
La descripción del reporte contiene propiedades que están relacionadas al reporte, y propiedades que
están relacionadas a otros componentes del reporte, tales como fuentes de datos, columnas y páginas
de parámetros. Una propiedad es un atributo de un objeto o sus componentes que caracteriza y
especifica el comportamiento del objeto, como por ejemplo si es visible o no.
Triggers
Ciertos eventos predefinidos que ocurren en un reporte y que pueden programarse con código C/AL.

Fuentes de datos

El modelo de datos de un reporte se construye a partir de fuentes de datos, que se corresponden con
tablas. Cuando un reporte corre, los registros de las fuentes de datos son iterados.

Columnas
Pueden ser campos de una tabla, variables, expresiones, o labels.

Página de parámetros
Recoge las opciones del usuario antes de que la ejecución del reporte comience.
Diseño
Los reportes en NAV pueden ser impresos o sin impresión. Un reporte sin impresión puede usarse para
procesar tareas que no producen una salida de datos. Un reporte impreso resulta en la generación de
datos en pantalla o impresor. Esta salida es definida en la definición del reporte (Report Definition
Language Client-Side, o RDLC).

Para definir el diseño del reporte se usa Visual Studio Report Designer.