Usar instrucciones repetitivas
Puede usar instrucciones repetitivas cuando quiera repetir la implementación de una o más instrucciones. Los cinco tipos diferentes de instrucciones repetitivas que se pueden usar son:
for-to-do
for-downto-do
foreach-in-do
while-do
repeat-until
Instrucción for
Una de las instrucciones repetitivas más utilizadas es la instrucción for. Si usa la instrucción for, ya debería saber cuántas veces va a repetir la implementación de instrucciones.
En el siguiente ejemplo, la instrucción for se utiliza para hacer un bucle cinco veces. La variable intCount cuenta el número de veces que se ha hecho el bucle.
var
intCount: Integer;
total: Integer;
begin
for intCount := 1 to 5 do
total := total + 3;
end;
En el siguiente ejemplo, el número de bucles se fija mediante un número (como 5). También puede usar otra variable integral en lugar de un valor fijo. En cualquier caso, la instrucción for sabe con antelación cuántas veces tendrá que hacer el bucle.
var
intCount: Integer;
numberOfLoops: Integer;
total: Integer;
begin
numberOfLoops := 5;
for intCount := 1 to numberOfLoops do
total := total + 3;
end;
La instrucción for solo puede ejecutar una instrucción. Si quiere ejecutar más de una instrucción, debe usar una instrucción compuesta con begin y end.
Instrucción for downto
Con la instrucción for, está contando hacia arriba, es decir, la instrucción for aumenta el valor de la variable. También puede disminuir utilizando la instrucción for downto, que cuenta hacia abajo.
De modo similar a la instrucción for, que solo puede ejecutar una instrucción, la instrucción for downto solo ejecuta una instrucción. En el siguiente ejemplo se muestra el uso de la instrucción compuesta.
var
intCount: Integer;
totalSales: Integer;
numberSales: Integer;
sales: array[5] of Integer;
begin
GetSales(sales);
for intCount := 5 downto 1 do begin
totalSales := totalSales + sales[intCount];
numberSales := numberSales + 1;
end;
end;
Instrucción foreach
La instrucción foreach solo se puede usar en colecciones del tipo Enumerable (List of y Dictionary of), y no se puede usar con matrices.
Con cada instrucción foreach, la variable obtendrá el valor de un artículo determinado de las colecciones. A todos los bucles se les asigna el siguiente valor.
var
stringList: List of [Text[20]];
stringItem: Text[20];
begin
foreach stringItem in stringList do
Message(stringItem);
end;
Instrucción while
La instrucción while comprueba primero si la condición es true antes de iniciar el bucle. Si la condición es true, sigue ejecutando las instrucciones en el bloque de while.
Por lo tanto, es posible que las instrucciones no se ejecuten si la condición no es true la primera vez.
var
index: Integer;
totalSales: Integer;
sales: array[5] of Integer;
begin
GetSales(sales);
while totalSales < 8 do begin
index := index + 1;
totalSales := totalSales + sales[index];
end;
end;
Si quiere ejecutar varias instrucciones, debe usar una instrucción compuesta.
Instrucción repetir hasta
La instrucción while comprueba primero si existe una condición válida antes de iniciar el bucle, mientras que la instrucción repeat until se ejecuta primero y después comprueba una condición. Se repite en bucle hasta que la condición es válida, lo que significa que las instrucciones repeat until se ejecutan al menos una vez. El bucle continuará siempre que la condición no sea válida.
La instrucción repeat until es una sola instrucción, y usted pone sus propias instrucciones dentro del bloque. Esto implica que no tiene que usar una instrucción compuesta si quiere ejecutar varias instrucciones.
var
index: Integer;
totalSales: Integer;
sales: array[5] of Integer;
begin
GetSales(sales);
repeat
index := index + 1;
totalSales := totalSales + sales[index];
until totalSales >= 8;
end;
La instrucción repeat until se suele usar cuando se quiere realizar un bucle por un conjunto de registros. En el siguiente ejemplo, realizará un bucle por todas las filas de la tabla MyTable.
var
myTable: Record MyTable;
begin
myTable.FindSet();
repeat
myTable.Amount := 100;
until myTable.Next() = 0;
end;
Instrucción with
La instrucción with se usa a veces en combinación con una instrucción repetitiva, pero también se puede usar de forma independiente. El propósito de la instrucción with es reducir el uso de las variables del registro. Esta estructura se ilustra en el siguiente ejemplo, donde se crea una variable myTable y se asigna un valor a todos los campos de la tabla.
var
myTable: Record MyTable;
begin
myTable."No." := 1;
myTable.Amount := 100;
myTable.Credits := 10;
myTable."Document Type" := myTable."Document Type"::Invoice;
myTable.Reason := myTable.Reason::Return;
myTable.Refund := 100;
end;
En lugar de volver a escribir la palabra myTable, puede usar la instrucción with.
var
myTable: Record MyTable;
begin
with myTable do begin
"No." := 1;
Amount := 100;
Credits := 10;
"Document Type" := "Document Type"::Invoice;
Reason := Reason::Return;
Refund := 100;
end;
end;
Depreciación de instrucciones with explícitas e implícitas
El modelo de extensibilidad y el lenguaje de programación AL sustituyen al lenguaje C/AL. Hasta ahora, la instrucción with ha sido compatible en AL.
El uso de la instrucción with podría dificultar la lectura del código. También puede evitar que el código de Business Central se actualice sin cambios en el código o que se actualice con un comportamiento cambiado, lo que es peor.
Hay dos tipos de instrucciones with: el tipo with explícito, con la palabra clave, y el with implícito, que no se expresa directamente en el código. En las siguientes secciones, se describen estas instrucciones.
Instrucciones with explícitas
En Business Central Online, el código se vuelve a compilar cuando se actualizan las versiones de la plataforma y la aplicación. La recompilación garantiza que está funcionando y regenera los artefactos de runtime para que coincidan con la nueva plataforma. No está permitido hacer cambios importantes sin la debida advertencia, pero el uso de la instrucción with hace que Microsoft no pueda ni siquiera añadir cosas de un modo intrascendente. Este problema no se limita a los cambios realizados por Microsoft; cualquier cambio aditivo puede romper una instrucción with en el código de consumo.
En el siguiente ejemplo se ilustra el código escrito usando la instrucción with; en este contexto se denomina instrucción with explícita:
codeunit 50140 MyCodeunit
{
procedure DoStuff()
var
Customer: Record Customer;
begin
with Customer do begin
// Do some work on the Customer record.
Name := 'Foo';
if IsDirty() then
Modify();
end;
end;
local procedure IsDirty(): Boolean;
begin
exit(false);
end;
}
Los procesos del procedimiento DoStuff() funcionan en el registro Customer, y este procedimiento llama a un procedimiento local IsDirty() para verificar si se actualiza el registro o no. Al observar el código anterior, parece que no haya nada, ya que IsDirty() devuelve falso, suponiendo que la llamada IsDirty() (línea 11) esté llamando al procedimiento local IsDirty().
Búsquedas de símbolos
Pensemos de nuevo en el ejemplo de código anterior: ¿qué pasaría con ese código si IsDirty se agregara a la aplicación base entre dos versiones? Para entenderlo, debemos observar cómo los compiladores convierten la sintaxis en símbolos. Cuando el compilador AL cumple con la llamada IsDirty, se debe vincular el nombre de la sintaxis a un símbolo de procedimiento.
Cuando el compilador AL busca el símbolo IsDirty() en el ejemplo anterior, buscará en el siguiente orden:
1- Tabla Customer
Miembros definidos por el usuario en la tabla Customer y extensiones de la tabla Customer
Miembros definidos por la plataforma, por ejemplo, FindFirst() o Modify()
2- Codeunit MyCodeunit
- Miembros definidos por el usuario, por ejemplo, IsDirty()
- Miembros definidos por la plataforma
3- Miembros definidos globalmente
La primera vez que la búsqueda de IsDirty encuentra el nombre IsDirty, no continuará con el siguiente grupo de nivel superior. Eso significa que si se introduce un procedimiento denominado IsDirty en la tabla Cliente (plataforma o aplicación), ese procedimiento se encontrará en lugar del procedimiento en MyCodeunit.
La solución para el with explícito es dejar de usarlo. El uso de la instrucción with puede hacer que su código sea vulnerable a los cambios anteriores. En el siguiente ejemplo se ilustra cómo reescribir la muestra usando La instrucción with explícita.
// Safe version
codeunit 50140 MyCodeunit
{
procedure DoStuff()
var
Customer: Record Customer;
begin
// Do some work on the Customer record.
Customer.Name := 'Foo';
if IsDirty() then
Customer.Modify();
end;
local procedure IsDirty(): Boolean;
begin
exit(false);
end;
}
Instrucción with implícita
El with implícito es inyectado automáticamente por el compilador en determinadas situaciones. Las siguientes secciones describen el funcionamiento de esto en codeunits y páginas.
Codeunits
Cuando una codeunit tiene establecida la propiedad TableNo, hay un with implícito alrededor del código dentro del desencadenador OnRun. Esto se indica con los comentarios en el ejemplo de código siguiente.
codeunit 50140 MyCodeunit
{
TableNo = Customer;
trigger OnRun()
begin
// with Rec do begin
SetRange("No.", '10000', '20000');
if Find() then
repeat
until Next() = 0;
if IsDirty() then
Error('Something is not clean');
// end;
end;
local procedure IsDirty(): Boolean;
begin
exit(false);
end;
}
Como ocurre con la instrucción with explícita, parece que el código llama al método local IsDirty. Sin embargo, en función de la tabla Customer, las extensiones de la tabla y los métodos integrados, es posible que ese no sea el caso. Si alguna de estas implementa un método IsDirty con una firma idéntica que devuelva true, el ejemplo anterior generará un error. Si se implementa un método IsDirty con una firma diferente, el código no se compilará ni se actualizará.
Páginas
Las páginas de las tablas tienen el mismo tipo de with implícito, pero alrededor de todo el objeto. En cualquier lugar dentro del objeto de la página, los campos y métodos de las tablas de origen están disponibles directamente sin ningún prefijo.
page 50143 ImplicitWith
{
SourceTable = Customer;
layout
{
area(Content)
{
field("No."; "No.") { }
field(Name; Name)
{
trigger OnValidate()
begin
Name := 'test';
end;
}
}
}
trigger OnInit()
begin
if IsDirty() then Insert()
end;
local procedure IsDirty(): Boolean
begin
exit(Name <> '');
end;
}
En las páginas, no solo abarca el código de los desencadenadores y los procedimientos con el with implícito en el registro de origen; también se cubren las expresiones de origen para los campos.
Con o sin, esa no es la cuestión
Aquí, en este repositorio de GitHub, puede encontrar más ejemplos y código: BCTech/samples/WithOrWithout/
Instrucción break
Si quiere detener la ejecución de un bucle, puede usar la instrucción break.
var
intCount: Integer;
total: Integer;
begin
for intCount := 1 to 5 do begin
if (total > 8) then
break;
total := total + 3;
end;
end;