Pragiva — Tecnologia na prática

Inicializador padrão e de browse: quando cada um roda

X3_RELACAO dá o valor inicial na tela; X3_INIBRW é o que o virtual mostra no browse. Por que o inicializador não recalcula um campo real na alteração.

Protheus Referência técnica 6 min de leitura

Assista o vídeo

Resposta rápida

Inicializador padrão
coluna X3_RELACAO — o valor com que o campo aparece na tela de cadastro.
Inicializador de browse
coluna X3_INIBRW — o que um campo virtual mostra no browse da tabela.
Em campo real
o inicializador padrão preenche o registro novo; depois disso, a tela mostra o que foi gravado.
Em campo virtual
o inicializador padrão é a fonte do dado sempre que a tela abre; no browse, quem responde é o X3_INIBRW.
Armadilha
esperar que o inicializador recalcule um campo real na alteração. Ele não recalcula.
Consulta rápida6 seções

Um campo do Protheus tem dois inicializadores, e eles respondem por lugares diferentes. O inicializador padrão (X3_RELACAO) age na tela de cadastro — incluir, alterar, visualizar. O inicializador de browse (X3_INIBRW) age na lista de registros da rotina. O que decide o quanto cada um importa é o contexto do campo.

O inicializador padrão em campo real

Num campo real, o inicializador dá o valor do registro novo. Os usos do dicionário padrão mostram bem o papel dele:

Campo (real)X3_RELACAO
ddatabase
"N"
"2"
Date()
LEFT(TIME(),5)

O pedido de venda nasce com a data-base do sistema como emissão e o tipo N; o produto nasce desbloqueado ("2"); os dois últimos gravam a data do dia e a hora no formato HH:MM. O número do pedido segue a mesma lógica: o inicializador do é GetSXENum("SC5","C5_NUM"), que sugere o próximo número da sequência. Repare que tudo ali é informação do momento da criação: número, data, hora, situação inicial. É o uso certo.

Na alteração e na visualização, um campo real mostra o que está gravado no registro. O próprio padrão deixa isso explícito nas rotinas que montam a tela à mão: ao carregar um registro existente, o campo real é lido da tabela, e só o campo virtual passa por CriaVar() — a função que cria a variável do campo aplicando o inicializador padrão.

Daí saem duas consequências práticas:

  • O inicializador não recalcula. Se você mudar o inicializador de um campo real, só os registros incluídos dali em diante recebem a regra nova.
  • O inicializador não preenche o passado. Campo real novo, criado numa tabela que já tem dados, nasce vazio nos registros antigos. Se eles precisam de valor, isso é uma carga à parte.

No padrão, o C5_NUM traz GetSXENum direto no X3_RELACAO. Para a ZA1, o cadastro de motoristas do exemplo da série, o X3_RELACAO do ZA1_COD é U_ZA1NUM(), uma função que só chama GetSXENum na inclusão — o desenho está em Campo caractere: código sequencial.

O que acontece com o número reservado quando o usuário desiste da inclusão está em Controle de numeração.

O inicializador padrão em campo virtual

No virtual, o inicializador não é “valor inicial”: é a fonte do dado. O campo não existe na tabela, então toda vez que a tela abre, é o X3_RELACAO que diz o que mostrar. A documentação TOTVS de um campo virtual do padrão (, nome do agente) descreve exatamente isso: é o inicializador padrão que traz o nome quando o registro é alterado ou visualizado.

E ele roda também na inclusão — por isso os virtuais do padrão se protegem:

TEXT
If( INCLUI,'',Posicione( 'TMA', 1, xFilial( 'TMA' ) + TN0->TN0_AGENTE, 'TMA_NOMAGE'))

Na inclusão, TN0-> aponta para qualquer registro que estiver posicionado, não para o que está sendo digitado. Sem o teste de INCLUI, a tela nova abriria mostrando o nome de outro registro.

O inicializador de browse

O browse é a lista de registros da rotina. A documentação da SX3 define o X3_INIBRW como a função chamada na inicialização do browse da tabela, “obrigatoriamente utilizada em campo de contexto Virtual”. Para o campo aparecer no browse, ele precisa estar marcado para isso (X3_BROWSE = 'S'; branco conta como não).

Compare os dois inicializadores de um mesmo virtual do padrão, (descrição do produto):

TEXT
X3_RELACAO  If(!INCLUI,Posicione("SB1",1,xFilial("SB1")+AA3->AA3_CODPRO,"B1_DESC"),"")
X3_INIBRW   POSICIONE("SB1",1,XFILIAL("SB1")+AA3->AA3_CODPRO,"B1_DESC")

A diferença é o teste de inclusão. No browse não há inclusão em andamento: cada linha é um registro gravado, e neste par a expressão lê o código direto do alias (AA3->AA3_CODPRO).

Para o C5_XNOMMOT — o nome do motorista no pedido de venda, virtual, do exemplo da série —, os dois ficam assim:

TEXT
X3_RELACAO  IIF(!INCLUI,Posicione("ZA1",1,xFilial("ZA1")+SC5->C5_XMOTOR,"ZA1_NOME"),"")
X3_INIBRW   Posicione("ZA1",1,xFilial("ZA1")+SC5->C5_XMOTOR,"ZA1_NOME")

Aqui o xFilial("ZA1") sem segundo parâmetro basta: a ZA1 do exemplo é compartilhada, e para tabela compartilhada a função devolve brancos, qualquer que seja a filial. Quando a tabela buscada é exclusiva, veja a primeira armadilha abaixo.

Armadilhas

xFilial() no browse olha a filial corrente, não a da linha. A assinatura é xFilial(cAlias, cFil), e sem o segundo parâmetro ela usa a filial em que o usuário está logado. Se o browse mostra registros de várias filiais e a tabela buscada é exclusiva, a busca de todas as linhas sai com a filial de quem está olhando. A Central de Atendimento TOTVS orienta, para carregar informação de outras filiais no browse, usar no X3_INIBRW o campo de filial da própria tabela em vez de xFilial().

Antes de trocar, veja o que a documentação diz sobre a pesquisa do browse. Ele pode incluir campos virtuais na pesquisa, desde que a opção “Habilitar pesquisa com campo virtual” esteja marcada na configuração da tabela (Pesquisa e filtros). A página TDN “Posicione com Campo Virtual” lista as chaves aceitas no Posicione para isso: um campo que possua todas as informações do índice (Posicione('SA1',1,C5_CAMPO,'A1_NOME')), a combinação de um campo de filial mais outro campo com o restante (Posicione('SA1',1,xFilial('SA1') + C5_CAMPO,'A1_NOME')) ou a chave completa do índice. Sobre a filial, a regra é condicional: “Ao utilizar a função xFilial a mesma deve possuir somente o primeiro parâmetro. Não utilizar a função FwXFilial.” Se o Posicione não atende essas condições, o campo continua mostrando o conteúdo, mas não entra na pesquisa. Quando separam a filial, os exemplos da página a obtêm por xFilial; ela não trata da forma recomendada pela Central (campo de filial da própria tabela mais o código), então o efeito dessa forma na pesquisa não está documentado. Se você usa essa pesquisa, confira no seu ambiente. A mesma página avisa que habilitar a pesquisa com campo virtual pode deixar o browse lento.

Tipo do inicializador diferente do tipo do campo. A Central de Atendimento TOTVS documenta o erro em CriaVar causado por inicializador com conteúdo incompatível com o campo — o caso mais comum é campo caractere com inicializador 1, sem aspas. Campo C recebe "1"; campo N recebe 1; campo D recebe data (dDataBase, Date()), nunca o texto "20260926".

Static Function no inicializador. A documentação da SX3 é explícita: a função chamada no X3_RELACAO ou no X3_INIBRW deve ser Function (do produto) ou User Function (do cliente); Static Function não pode ser usada.

Função própria no inicializador

Quando a regra do valor inicial não cabe numa linha legível, escreva uma User Function que devolva o valor no tipo do campo — a documentação da SX3 exige User Function para a função do cliente. No inicializador, ela é chamada como qualquer User Function do ADVPL, com o prefixo U_: U_NomeDaFuncao(). Vale a mesma regra do tipo: a função devolve C para campo caractere, N para numérico, D para data.

Conferindo no banco

Os dois inicializadores de uma tabela, com o contexto ao lado. O sufixo 010 é o do exemplo; o seu depende da empresa.

Confira no seu ambienteSQL
SELECT X3_CAMPO, X3_CONTEXT, X3_RELACAO, X3_INIBRW, X3_BROWSE
  FROM SX3010
 WHERE X3_ARQUIVO = 'SC5'
   AND (X3_RELACAO <> ' ' OR X3_INIBRW <> ' ')
   AND D_E_L_E_T_ = ' '
 ORDER BY X3_ORDEM

Olhe primeiro os virtuais (X3_CONTEXT = 'V'): neles, é da coluna X3_RELACAO que vem o valor mostrado quando a tela abre.

Se um inicializador está trazendo valor errado e você não acha de onde, fale com a gente.

Referências

  1. TDNtdn.totvs.com

    TDN — SX3, Campos das tabelas
  2. TDNtdn.totvs.com

    TDN — MDT0060 Inicializador Padrão do Campo de Nome do Agente
  3. TDNtdn.totvs.com

    TDN — Posicione com Campo Virtual
  4. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Função xFilial para o campo X3_INIBRW
  5. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Argument error in function Len() on CRIAVAR

Continue por aqui