A sintaxe formal da estrutura de controle de fluxo é:
For(Variável_Contador;Expressão_inicial;Expressão_final{;Expressão_incremento}) instrução(ções) End for
O loop é um loop controlado por uma variável de contador:
A variável contador Variável_Contador é uma variável numérica (Real, Inteiro, ou Inteiro Longo) que o loop inicializa com o valor especificado por Expressão_inicial.
Cada vez que o loop é executado, a variável contador é incrementada pelo valor especificado no valor opcional Expressão_incremento. Se você não especificar Expressão_incremento, a variável contador é incrementada por um (1), que é o padrão.
Quando a variável contador passa o valor Expressão_final, o loop para.
Importante: A expressão numérica Expressão_inicial , Expressão_final e Expressão_incremento são avaliadas uma única vez no início do loop. Caso essas expressões sejam variáveis, mudar uma dessas variáveis no loop não afeta o loop.
Dica: No entanto, para fins especiais, você pode alterar o valor da variável contador Variável_Contador dentro do loop, o que afetará o loop
Normalmente Expressão_inicial é inferior a Expressão_final.
Se Expressão_inicial e Expressão_final são iguais, o loop será executado uma única vez.
Se Expressão_inicial é maior do que Expressão_final, o loop não será executado a menos que você especifique um Expressão_incremento negativo. Veja os exemplos.
2. O exemplo a seguir passa por todos os elementos do array umArray:
For($vlElem;1;Size of array(umArray)) ` Faça alguma coisa com o elemento
umArray{$vlElem}:=... End for
3. O exemplo a seguir passa por todos os caracteres do texto vtTexto:
For($vlCar;1;Length(<span class="rte4d_prm">vtTexto</span><gen9>)) `Faça alguma coisa com o caractere, se for um TAB If(Character code(</gen9><span class="rte4d_prm">vtTexto</span><gen9>[[$vlCar]])=Tab) ` ... End if End for</gen9>
4. O exemplo a seguir percorre os registros selecionados para a tabela [umaTabela]:
FIRST RECORD([<span class="rte4d_prm">umaTabela</span><gen9>]) For($vlRegistro;1;Records in selection([</gen9><span class="rte4d_prm">umaTabela</span><gen9>])) ` Faça alguma coisa com o registro SEND RECORD([</gen9><span class="rte4d_prm">umaTabela</span><gen9>]) ` ... ` Vai para o próximo registro NEXT RECORD([</gen9><span class="rte4d_prm">umaTabela</span><gen9>]) End for</gen9>
A maioria dos loops que você vai escrever em seus bancos de dados vai funcionar como os listados nesses exemplos.
Em alguns casos, você pode querer ter um loop cuja variável contador está diminuindo ao invés de aumentar. Para fazer isso, você deve especificar Expressão_inicial superior a Expressão_final e um Expressão_incremento negativo. Os exemplos a seguir faz a mesma coisa, como nos exemplos anteriores, mas em ordem inversa:
5. O exemplo a seguir executa 100 iterações:
For(vCounter;100;1;-1) ` Faça alguma coisa End for
6. O exemplo a seguir passa por todos os elementos do array umArray:
For($vlElem;Size of array(umArray);1;-1) `Faça alguma coisa com o elemento
umArray{$vlElem}:=... End for
7. O exemplo a seguir passa por todos os caracteres do texto vtTexto:
For($vlCar;Length(<span class="rte4d_prm">vtTexto</span><gen9>);1;-1) ` Faça alguma coisa com o caractere, se for um TAB If(ASCII(</gen9><span class="rte4d_prm">vtTexto</span><gen9>≤$vlCar≥)=Tab) ` ... End if End for</gen9>
8. O exemplo a seguir percorre os registros selecionados para a tabela [umaTabela]:
LAST RECORD([<span class="rte4d_prm">umaTabela</span><gen9>]) For($vlRecord;Records in selection([</gen9><span class="rte4d_prm">umaTabela</span><gen9>]);1;-1) ` Faça alguma coisa com o registro SEND RECORD([</gen9><span class="rte4d_prm">umaTabela</span><gen9>]) ` ... ` Ir ao registro anterior PREVIOUS RECORD([</gen9><span class="rte4d_prm">umaTabela</span><gen9>]) End for</gen9>
Em alguns casos, você pode querer executar um loop por um determinado número de iterações, mas, em seguida, sair do loop quando uma outra condição se tornar verdadeira. Para fazer isso, você pode testar esta condição dentro do loop e se ela se torna realidade, definir explicitamente a variável do contador para um valor que excede a expressão final.
10. No exemplo a seguir, uma seleção de registros é percorrida até que isso seja realmente feito ou até que a variável interprocesso <>vbWeStop, inicialmente definido como FALSE, se torne TRUE. Esta variável é tratada por um método de projeto ON EVENT CALL que lhe permite interromper a operação:
<>vbWeStop:=False ON EVENT CALL("GESTION STOP") ` HANDLE STOP define <>vbWeStop como True se Ctrl-ponto final (Windows) ou Cmd-Ponto final (Macintosh) for pressionado $vlNumRegistros:=Records in selection([umaTabela]) FIRST RECORD([umaTabela]) For($vlRegistro;1;$vlNumRegistros) ` Faça alguma coisa com o registro SEND RECORD([umaTabela]) ` ... ` Vai para o próximo registro If(<>vbWeStop) $vlRecord:=$vlNbRecords+1 ` Força a variável do contador para sair do loop Else NEXT RECORD([umaTabela]) End if End for ON EVENT CALL("") If(<>vbStop) ALERT("A operação foi interrompida.") Else ALERT("A operação foi concluída com sucesso.") End if
É interessante ver como o loop e como o loop realizam a mesma ação.
Aqui é o equivalente :
$i :=1 `Inicializar o contador While($i<=100) ` Loop 100 vezes ` Faça alguma coisa $i :=$i +1 ` É necessário incrementar o contador End while
Aqui está o equivalente :
$i :=1 ` Inicializar o contador Repeat `Faça alguma coisa $i :=$i +1 ` É necessário incrementar o contador Until($i=100) ` Loop 100 vezes
Conselho: O loop For...End for é geralmente mais rápido do que a e , porque 4D testa a condição internamente para cada ciclo do loop e incrementa o contador. Portanto, use o loop , sempre que possível.
Você pode utilizar Real, Inteiro, Inteiro Longo e variáveis, bem como as variáveis interprocesso, processo e contadores com uma variável local. Por loops longos e repetitivos, especialmente no modo compilado, use as variáveis locais Long Integer.
11. Aqui está um exemplo:
C_LONGINT($vlContador) ` use variáveis locais Inteiro Longo<gen9>For ($vlContador;1;10000) ` Faça alguma coisa End for</gen9>
Você pode aninhar quantas estruturas de controle quanto você (razoavelmente) precisa. Isso inclui aninhamento para loops . Para evitar erros, certifique-se utilizar diferentes variáveis de contador para cada estrutura de looping
Aqui estão dois exemplos:
12. O exemplo a seguir passa por todos os elementos de um array bidimensional:
For($vlElem;1;Size of array(umArray)) ` ... ` Faça alguma coisa com a linha ` ... For($vlSubElem;1;Size of array(umArray{$vlElem})) ` Faça alguma coisa com o elemento
umArray{$vlElem}{$vlSubElem}:=... End for End for
13. O exemplo a seguir cria um array de ponteiros para todos os campos de data presentes no banco de dados:
ARRAY POINTER($apCamposData;0) $vlElem:=0 For($vlTabela;1;Count table) For($vlCampo;1;Count fields($vlTabela)) $vpCampo:=Field($vlTabela;$vlCampo) If(Type($vpCampo->)=Is date) $vlElem:=$vlElem+1 INSERT IN ARRAY($apCamposData;$vlElem) $apCamposData{$vlElem}:=$vpCampo End if End for End for