A validação de colunas é especificada em dicField.CustomConstraint.

Estão disponíveis todos os recursos do ArScript, além de:

  • As colunas da tabela sendo alterada como variáveis variants (escrita e leitura)
  • A variável x, somente leitura, com o novo valor da coluna.

Se ocorrer um erro imprevisto na execução do script, Argow mostra a seguinte mensagem:

Ocorreu um erro ao avaliar a restrição dos valores válidos da coluna %s ...
Por esta razão, não é possível determinar a validade dos dados modificados.

e o usuário pode optar por atualizar a tabela ou não. Para não dar esta alternativa e evitar a gravação, atribua T na variável de configuração global SCRIPT_ONERROR_STOP.

A forma de escrever a validação pode ser:

  • In-line,
  • Notação rápida, e
  • Referência a dicScript

In-line

Nesta notação o script está em dicField.CustomConstraint. O script deve conter uma função, chamada Constraint, que retorna um valor booleano e recebe um parâmetro, o valor da coluna, como variant. Para ser reconhecida como in-line a primeira palavra do texto deve ser function.

O código abaixo verifica a validade de um código de contêiner (ou container ou contentor) seguindo o algoritmo de identificação (note a semelhança com Delphi):

dicField
tableNamefieldNamecustomConstraintconstraintErrorMessage
tbCLIENTECPFfunctio _codigo... 

function _codigo( const c: char ): double;
begin

  result:= -1;
  case c of
   'A': result:= 10;
   'B'.. 'K': result:= Ord( c ) - 54;
   'L'.. 'U': result:= Ord( c ) - 53;
   'V'.. 'Z': result:= Ord( c ) - 52;
   '0'.. '9': result:= Ord( c ) - 48;
  end;

end;
//---------------------------------------------------------------
function digitoVerificador( const cId: string): char;
  var
    i: integer;
    d: double;
begin

  result:= #0;
  d:= 0;
  for i:= 1 to 10 do d:= d + _codigo( cId[i] ) * power( 2, double(i-1) );
  if ( d > 0 ) then begin
    i:= round( d ) - ( trunc( d / 11 ) * 11 );
    result:= chr(i+48);
  end;

end;
//---------------------------------------------------------------
function _tipo( const cId: string; const iIni, iEnd: integer; const c1, c2: char ): boolean;
  var i: integer;
begin

  result:= true;
  i:= iIni;
  while ( i <= iEnd ) and result do begin
    result:= ( c1 <= cId[i] ) and ( cId[i] <= c2 );
    inc( i );
  end;

end;
//---------------------------------------------------------------
//-- Valida Container -------------------------------------------
//---------------------------------------------------------------
function validaContainer( const cId: string ): boolean;
  var cMsg: string;
begin

  result:= false;
  cMsg:= 'Código de Container inválido, favor informar de novo';

  if ( length( cId ) < 11 ) then begin
    cMsg:= cMsg + ' (faltam digitos).'
  end else if ( length( cId ) > 11 ) then begin
    cMsg:= cMsg + ' (sobram digitos).'
  end else if not _tipo( cId, 5, 11, '0', '9' ) then begin
    cMsg:= cMsg + ' (números esperados).'
  end else if not _tipo( cId, 1, 4, 'A', 'Z' ) then begin
    cMsg:= cMsg + ' (letras esperadas).'
  end else if not ( digitoVerificador( cId ) = cId[11] ) then begin
    cMsg:= cMsg + '.'
  end else begin
    result:= true;
  end;

  if not result then sf.shell.sayWarn( cMsg, 'Container' );

end;

//---------------------------------------------------------------
//-- Constraint -------------------------------------------------
//---------------------------------------------------------------
function constraint( const x: variant ): boolean;
begin

  result:= validaContainer( x );

end;

No exemplo a seguir, não é feita exatamente uma validação, mas é aproveitado o contexto (antes da atualização da tabela) para mudar o valor de uma coluna DATA_MODIF se a coluna STATUS mudou de valor ou estiver sendo inserida:

function Constraint( x: variant ): boolean;
begin
  if sf.ActiveDataSet.isAppending then begin
    DATA_MODIF:= now;
  end else if not ( x = sf.ActiveDataSet.oldValue['STATUS'] ) then begin
    DATA_MODIF:= now;
  end;
  result:= true;
end;

Notação rápida

A notação rápida foi projetada para facilitar as validações simples. O script, composto de uma só linha, deve resultar em uma expressão booleana. O valor da coluna sendo validada está representado por x.

length( x ) > 4

Se a condição não é cumprida, Argow mostra uma mensagem com o texto de dicField.ConstraintErrorMessage.

Internamente, Argow converte a linha informada, em um script in-line, com as seguintes características:

{$I {configuração global SCRIPT_INCLUDE} }
function Constraint( x: variant ): boolean;
begin
  result:= {dicField.CustomConstraint};
  if not result then msg_warning( [ {dicField.ConstraintErrorMessage} ], {Nome da Tabela});
end;

Se dicField.ConstraintErrorMessage não for especificado, Argow fornece a mensagem: 'A restrição para os valores válidos da coluna "%s" não é satisfeita com os dados informados.'.

Referências a outras colunas podem ser feitas pelos nomes, levando em consideração que podem ser Nulos.

Referência

Nesta notação o valor de dicField.CustomConstraint e uma referência à tabela dicScript, com a seguinte notação:

scriptName[.functionName]

Onde scriptName é uma entrada em dicScript, e functionName é a função, contida em dicScript.scriptBody, que retorna um valor booleano e recebe um parâmetro, o valor da coluna, como variant. Se functionName não for especificado, será utilizado Constraint.