Pragiva — Tecnologia na prática

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.

Protheus Tutorial 5 min de leitura

Assista o vídeo

Nesta página7 seções

Antes de começar

  • Tabela customizada criada no dicionário (no exemplo, a ZA1 — Cadastro de motoristas)
  • Acesso ao Configurador com permissão de alterar o dicionário de dados

No cadastro de clientes, A1_MSBLQL = '2' quer dizer “Ativo”. No cadastro de fornecedores, A2_MSBLQL = '2' quer dizer “Nao” — não bloqueado. O mesmo 2, gravado em dois campos de bloqueio, com descrições diferentes. Quem traduz o código é a lista do combo, e dá para a SQL ler essa lista direto da SX3, sem CASE escrito à mão — a consulta está mais abaixo.

Combo não é um tipo de campo. É um campo comum — quase sempre caractere — que tem uma lista de opções na coluna X3_CBOX da SX3, no formato 1=Proprio;2=Agregado;3=Terceiro. O usuário vê e escolhe a descrição, à direita do =; o banco grava só o valor, à esquerda. Cada opção é separada da seguinte por ;. Quem escolhe “Agregado” grava 2.

Essa diferença entre o que se vê e o que se grava é a origem de quase toda dúvida com combo: o relatório que mostra 2 em vez de “Agregado”, o filtro SQL escrito com a descrição, a importação que manda o texto no lugar do código.

A ficha do ZA1_VINC

O vínculo do motorista com a transportadora — próprio, agregado ou terceiro — é o combo da série. O campo é criado em Base de Dados > Dicionário > Arquivos, editando a tabela ZA1 e incluindo o campo na pasta Campos. A tela de inclusão do campo é dividida nas pastas Campo, Informações, Opções, Validações, Uso e Módulos.

Propriedade (coluna da SX3)Valor
Tipo (X3_TIPO)C
Tamanho (X3_TAMANHO)1
Título (X3_TITULO)Vinculo
Listas (X3_CBOX, X3_CBOXSPA, X3_CBOXENG)no bloco abaixo
Inicializador padrão (X3_RELACAO)"1"
Validação (X3_VALID)Pertence("123")
Obrigatório (pasta Uso)marcado
Browse (X3_BROWSE)S
Contexto (X3_CONTEXT)R
Proprietário (X3_PROPRI)U
TEXT
X3_CBOX (português)
1=Proprio;2=Agregado;3=Terceiro

X3_CBOXSPA (espanhol)
1=Propio;2=Agregado;3=Tercero

X3_CBOXENG (inglês)
1=Own;2=Aggregate;3=Third party

Caractere de uma posição, porque os valores são 1, 2 e 3. As listas em espanhol e inglês servem aos ambientes nesses idiomas. Motorista novo nasce como próprio, todo motorista tem um vínculo, e o vínculo na lista ajuda a filtrar.

O desenho é o mesmo dos campos de bloqueio do padrão, os _MSBLQL:

CampoX3_CBOXX3_RELACAOX3_VALID
1=Sim;2=Não"2"pertence("12")
1=Inativo;2=Ativo"2"pertence("12")
1=Sim;2=Nao"2"pertence("12")

É o contraste do começo: sem ler a lista, ninguém adivinha o que o 2 quer dizer. O campo de bloqueio tem artigo próprio em Campos reservados.

O tamanho do valor

O valor à esquerda do = é o que vai para a coluna. Neste artigo, a recomendação é o valor ter o tamanho do campo: com tamanho 1, 1, 2, 3; com tamanho 2, 01, 02, 03. Valor mais curto que o campo normalmente fica gravado com brancos à direita: o DBAccess completa o valor até o tamanho do campo, e 1 num campo de duas posições vira 1 no banco. A exceção é o ambiente com a chave TrimRightSpace ativa no DBAccess: com ela, os brancos à direita não são gravados. Em colunas char e varchar do SQL Server, = e LIKE ignoram o branco final do valor gravado; concatenação e arquivo exportado, não. O próprio padrão tem os dois jeitos: há campos de duas posições com lista 01=... e outros, também de duas posições, com 1=SIM;2=NAO.

O valor também não precisa ser número. O usa letras: F=Fisica;J=Juridica. O também: C=CIF;F=FOB;T=Por conta terceiros;.... Letra que lembra a descrição ajuda quem lê o dado cru no banco.

Por que ter validação além da lista

Quando o valor chega sem tela — numa rotina automática, por exemplo —, não há lista para escolher, e é a validação que confere. O padrão reforça o combo com Pertence(), que verifica se o valor está contido numa lista de caracteres — Pertence("12") aceita 1 ou 2.

Mantenha a lista da validação igual à do combo. Opção nova no X3_CBOX sem atualizar o Pertence() é opção que a tela oferece e a validação recusa.

Caractere ou numérico

O padrão usa caractere em quase todos os combos do dicionário. Prefira caractere: aceita letra como valor, aceita zero à esquerda e não entra por engano numa soma.

Lista que não cabe na coluna

O X3_CBOX tem tamanho limitado. Na base que conferimos, a coluna tem 128 caracteres — o mesmo vale para X3_CBOXSPA e X3_CBOXENG. O próprio padrão esbarra nisso: a lista do ocupa os 128 caracteres e termina cortada em 06=Cancelado por outro Us. Confira o limite no seu ambiente:

Tamanho da coluna X3_CBOXSQL
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
  FROM INFORMATION_SCHEMA.COLUMNS
 WHERE TABLE_NAME = 'SX3010'
   AND COLUMN_NAME IN ('X3_CBOX', 'X3_CBOXSPA', 'X3_CBOXENG')

Para lista que não cabe, a saída é uma função. Quando X3_CBOX começa com #, o que segue é uma expressão que devolve a lista no mesmo formato valor=descrição;... — o padrão usa isso em listas montadas por código. Para uma lista fixa e curta, texto direto é mais simples de manter.

A SQL que traduz o código

No banco está só o valor. A lista que traduz o valor já está na SX3, então a própria SQL pode lê-la: STRING_SPLIT separa o X3_CBOX nas opções, e o = de cada opção separa valor e descrição.

Traduza o código pela própria SX3SQL
WITH OPCOES AS (
  SELECT RTRIM(LEFT(S.value, CHARINDEX('=', S.value) - 1)) AS VALOR,
         SUBSTRING(S.value, CHARINDEX('=', S.value) + 1, LEN(S.value)) AS DESCRICAO
    FROM SX3010 X
   CROSS APPLY STRING_SPLIT(RTRIM(X.X3_CBOX), ';') S
   WHERE X.X3_CAMPO = 'ZA1_VINC'
     AND X.D_E_L_E_T_ = ' '
     AND CHARINDEX('=', S.value) > 0
)
SELECT Z.ZA1_COD, Z.ZA1_NOME, Z.ZA1_VINC,
       ISNULL(O.DESCRICAO, 'Fora da lista') AS VINC_DESC
  FROM ZA1010 Z
  LEFT JOIN OPCOES O ON O.VALOR = RTRIM(Z.ZA1_VINC)
 WHERE Z.D_E_L_E_T_ = ' '
 ORDER BY Z.ZA1_NOME

A consulta acompanha a lista: enquanto ela couber na coluna, opção nova no X3_CBOX já sai traduzida, sem mexer na SQL. Opção cortada no fim da lista sai com a descrição truncada ou como “Fora da lista”. Para outro campo, troque 'ZA1_VINC' e a tabela. Ela não serve para lista que começa com # (a SX3 guarda a expressão, não as opções).

Em banco abaixo disso, ou para uma lista curta que não muda, traduza com CASE:

Confira no seu ambienteSQL
SELECT ZA1_COD, ZA1_NOME, ZA1_VINC,
       CASE ZA1_VINC
            WHEN '1' THEN 'Proprio'
            WHEN '2' THEN 'Agregado'
            WHEN '3' THEN 'Terceiro'
            ELSE 'Nao informado'
       END AS VINC_DESC
  FROM ZA1010
 WHERE D_E_L_E_T_ = ' '
 ORDER BY ZA1_NOME

O 010 do nome da tabela é o sufixo da empresa e muda de ambiente para ambiente. Troque pelo seu.

O filtro também usa o valor, nunca a descrição: agregados são WHERE ZA1_VINC = '2', e não = 'Agregado'.

Descobrir o que um código quer dizer

Chegou um 2 num relatório e ninguém sabe o que é? A lista está na SX3. Esta consulta devolve todos os combos de uma tabela, com a lista, o tamanho e a validação lado a lado:

Todos os combos de uma tabelaSQL
SELECT X3_CAMPO, X3_TITULO, X3_TAMANHO, X3_CBOX, X3_VALID
  FROM SX3010
 WHERE X3_ARQUIVO = 'ZA1'
   AND X3_CBOX <> ' '
   AND D_E_L_E_T_ = ' '
 ORDER BY X3_ORDEM

Troque 'ZA1' pela tabela que interessa — 'SA1' mostra, entre outros, o A1_PESSOA e o A1_MSBLQL. Para um campo só, filtre por X3_CAMPO; para ver as listas em espanhol e inglês, acrescente X3_CBOXSPA e X3_CBOXENG. Quando a lista começa com #, a consulta mostra a expressão, não as opções.

Combo com poucas opções que nunca mudam fica bem no X3_CBOX. Lista que cresce, ou que o usuário precisa manter sem mexer no dicionário, pede outra solução: Tabelas genéricas (SX5). Para pergunta de relatório, o combo funciona diferente e está em Perguntas (SX1).

Referências

  1. TDNtdn.totvs.com

    TDN — Campos (CFGX034 - SIGACFG)
  2. TDNtdn.totvs.com

    TDN — Pasta Validações (CFGX034 - SIGACFG)
  3. TDNtdn.totvs.com

    TDN — SX3 - Campos das tabelas
  4. TDNtdn.totvs.com

    TDN — DNG-275 Adequações TrimRightSpace em querys

Continue por aqui