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 |
|---|---|
C5_EMISSAO | ddatabase |
C5_TIPO | "N" |
B1_MSBLQL | "2" |
ABR_DTMAN | Date() |
A1S_HORA | 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 C5_NUM é 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
(TN0_NOMAGE, 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:
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, AA3_DESPRO
(descrição do produto):
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:
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.
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_ORDEMOlhe 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
TDNtdn.totvs.com
TDN — SX3, Campos das tabelasTDNtdn.totvs.com
TDN — MDT0060 Inicializador Padrão do Campo de Nome do AgenteTDNtdn.totvs.com
TDN — Posicione com Campo VirtualCentral de Atendimentocentraldeatendimento.totvs.com
Central de Atendimento TOTVS — Função xFilial para o campo X3_INIBRWCentral de Atendimentocentraldeatendimento.totvs.com
Central de Atendimento TOTVS — Argument error in function Len() on CRIAVAR
Continue por aqui
- Vídeo
ProtheusTutorial
Campo combo: a lista de opções em valor=descrição
Campo combo no Protheus é quase sempre caractere, com a lista em X3_CBOX no formato valor=descrição. O que grava no banco e a SQL que traduz o código.