Pragiva — Tecnologia na prática

Perguntas (SX1): o grupo de perguntas de relatórios e rotinas

Perguntas (SX1): como a tabela guarda as perguntas de um relatório, o que Get e Combo mudam e como o fonte lê as respostas em mv_par01, mv_par02.

Protheus Referência técnica 10 min de leitura

Assista o vídeo

Resposta rápida

Onde fica
na SX1, uma linha por pergunta, agrupadas por X1_GRUPO e ordenadas por X1_ORDEM.
Como o fonte lê
Pergunte("ZA1REL", .T.) abre a tela e preenche mv_par01, mv_par02… na ordem das perguntas.
Get ou Combo
X1_GSC G é campo digitável; C é lista de até cinco opções.
O combo devolve
a posição da opção escolhida, não o texto dela.
Armadilha
mv_par01 não é parâmetro da SX6 — é variável de memória, criada pelo Pergunte() ou pelo ParamBox(), e não existe antes disso.
Consulta rápida9 seções

A tela de “Parâmetros” de um relatório ou de uma rotina de processamento costuma ser um grupo de perguntas — é o uso que a documentação da SX1 recomenda. O grupo vive na SX1, uma linha por pergunta; o fonte chama Pergunte() com o nome do grupo e lê as respostas em variáveis mv_par01, mv_par02 e assim por diante.

Não é a única forma. O padrão também monta telas de parâmetros com ParamBox(), que recebe as perguntas num array no próprio fonte e não lê a SX1. Se o grupo de uma tela não aparece na SX1, confira se ela não é um ParamBox().

Como o padrão faz

O pedido de venda (MATA410) tem o grupo MTA410; o relatório MATR410, o grupo MTR410. Duas perguntas de cada, como estão no dicionário:

GrupoOrdemPerguntaTipoX1_GSCX1_PRESELOpções / X1_F3
MTA41001Sugere Qtde Liber. ?C 1C1Sim / Nao
MTA41002Prc.venda c/Substit ?N 1C2Sim / Nao
MTR41001Data de ?D 8G0—
MTR41005OP De ?C 14G0F3

Na coluna Tipo, a letra é o X1_TIPO e o número, o X1_TAMANHO.

Para ver o grupo inteiro de qualquer rotina no seu ambiente:

Confira no seu ambienteSQL
SELECT X1_ORDEM, X1_PERGUNT, X1_TIPO, X1_TAMANHO, X1_DECIMAL,
       X1_GSC, X1_PRESEL, X1_VAR01,
       X1_DEF01, X1_DEF02, X1_DEF03, X1_DEF04, X1_DEF05,
       X1_CNT01, X1_F3, X1_VALID
  FROM SX1010
 WHERE X1_GRUPO = 'MTA410'
   AND D_E_L_E_T_ = ' '
 ORDER BY X1_ORDEM

O 010 é o sufixo da empresa; no seu ambiente pode ser outro.

Para descobrir o grupo de uma tela, a documentação da TOTVS indica: pressione F1 sobre o campo da pergunta. A informação exibida mostra o código do grupo de perguntas e a ordem da pergunta. Como atalho, o nome do grupo do padrão costuma ser o nome da rotina abreviado — o MATA410 usa o MTA410; o MATR410, o MTR410 —, mas o F1 é a confirmação.

A consulta mostra o que está no dicionário. Ela pode não mostrar a última resposta de um usuário: veja Onde fica a última resposta.

O que cada coluna decide

ColunaO que decide
X1_GRUPOO nome do grupo. É o que vai no Pergunte().
X1_ORDEMA posição da pergunta: 01 vira mv_par01, 02 vira mv_par02.
X1_PERGUNTO texto que o usuário lê.
X1_TIPO, X1_TAMANHO, X1_DECIMALO tipo da resposta (C, L, D, N ou M) e o tamanho.
X1_GSCO objeto na tela: G get, C combo, R range.
X1_DEF01 a X1_DEF05As opções do combo. São cinco colunas: o combo tem no máximo cinco opções.
X1_PRESELNo combo, a opção selecionada.
X1_CNT01O conteúdo inicial da variável. Não é, necessariamente, a última resposta do usuário.
X1_F3A consulta padrão da lupa (SC2 no exemplo do MTR410).
X1_VALID, X1_PICTUREValidação e máscara, como nos campos.
X1_VAR01O nome declarado da variável. A documentação da SX1 pede o modelo MV_PARXXX (sequencial numérico).

Sobre o X1_GSC, a documentação da SX1 lista os objetos aceitos: G Edit, S Text, C Combo, R Range, File, Expression e K Check. Em branco, é tratado como Edit, e o combo tem no máximo cinco itens. G e C são os objetos das perguntas mostradas neste artigo.

O combo devolve a posição

É a diferença que mais pega quem vem do cadastro de campos. No campo combo da SX3, a lista é 1=Proprio;2=Agregado;3=Terceiro e o banco grava o valor à esquerda do igual. Na pergunta, não existe valor=descrição: cada opção é só um texto em X1_DEF01…X1_DEF05, e a resposta é a posição da opção escolhida.

O código do padrão mostra isso de dois jeitos:

  • Para saber a opção que está marcada numa pergunta combo, o padrão lê o X1_PRESEL e compara com um número (== 1, == 2).
  • Para obter o texto da resposta, monta o nome da coluna com "X1_DEF" mais a posição em dois dígitos e lê a coluna com macro na SX1 posicionada: SX1->&("X1_DEF" + StrZero(mv_par01, 2)). Com mv_par01 igual a 2, a leitura é do X1_DEF02.

O tipo mais comum para combo no padrão é numérico de tamanho 1 — o MTA410 tem vários. Mas não é o único: a ordem 01 do próprio MTA410 é combo de tipo caractere. Recomendação: faça combo numérico de tamanho 1, que é o formato predominante e o que devolve um número direto para o If.

O grupo ZA1REL

No exemplo da série, um relatório de motoristas da tabela ZA1 pede a faixa de códigos e o vínculo:

X1_ORDEMX1_PERGUNTTipoTamX1_GSCX1_VAR01OpçõesX1_F3
01Motorista de ?C6Gmv_par01—ZA1
02Motorista ate ?C6Gmv_par02—ZA1
03Vinculo ?N1Cmv_par03Proprio / Agregado / Terceiro / Todos—

O grupo é criado e mantido no Configurador. A página do TDN que descreve a inclusão de perguntas indica: no Configurador, selecione Arquivos, clique sobre a empresa desejada e em Perguntas, clique em Incluir e preencha os campos. Para o ZA1REL, cada linha da tabela acima vira uma inclusão:

Campo da telaO que informar no ZA1REL
GrupoZA1REL — o nome do conjunto de perguntas.
OrdemDefinido pelo sistema: é a ordem de apresentação na tela.
PerguntaMotorista de ?, Motorista ate ?, Vinculo ?.
Tipo / Tamanho / DecimalCaracter 6 nas duas primeiras; Numérico 1 na terceira.
Objeto1 = Edit nas duas primeiras; 3 = Combo na terceira.
Consulta Padrão (Edit)ZA1 nas duas primeiras.
Pré-seleção (Combo)Só na terceira, porque o campo exige 3 = Combo: o número da opção que a tela traz marcada, como 4 para abrir em Todos. Com 0, o TDN indica que aparece o primeiro item.
Item 1 a 5 (Combo)Proprio, Agregado, Terceiro, Todos, sem pular a sequência.

Essa página do TDN foi atualizada pela última vez em 2018 e descreve o menu Arquivos. Para um grupo que já existe, a Central de Atendimento documenta outro caminho, e ele é de alteração: Base de Dados > Dicionário > Base de Dados, selecionar Perguntas e o ícone da lupa; inserir o grupo desejado, selecionar o ícone de editar, alterar a pergunta e confirmar. Nenhuma das duas páginas descreve a inclusão de um grupo novo nesse segundo caminho: se o seu Configurador não tiver o menu Arquivos, confira no próprio ambiente onde fica a inclusão.

O X1_F3 com ZA1 põe a lupa nas duas primeiras perguntas; a consulta padrão ZA1 está em Consulta padrão (F3).

A ordem das opções do combo não é por acaso: as três primeiras seguem o ZA1_VINC da tabela (1=Proprio;2=Agregado;3=Terceiro). Posição 2 na pergunta é o valor 2 no campo, e o fonte converte sem tabela de tradução.

Sobre o nome: crie um grupo seu, e não mexa num do padrão. A documentação da SX1 avisa que perguntas e helps podem ser sobrescritos em qualquer atualização do sistema e recomenda, para customização, criar um novo grupo de perguntas. Recomendação: comece os seus pelo alias da sua tabela, como ZA1REL. O nome não colide com uma rotina da TOTVS e diz de onde vem o relatório. Na base consultada, a coluna X1_GRUPO tem dez caracteres (confira o tamanho no seu ambiente).

Lendo as respostas no fonte

ADVPL / TLPP
#Include "Protheus.ch"

/*/{Protheus.doc} ZA1RMOT
Lista motoristas da ZA1 conforme o grupo de perguntas ZA1REL.
@type user function
/*/
User Function ZA1RMOT()

    Local cPerg     := "ZA1REL"
    Local cAliasQry := ""
    Local cVinc     := ""
    Local nTotal    := 0

    // .T. abre a tela de perguntas; sem confirmação, não segue
    If !Pergunte(cPerg, .T.)
        Return
    EndIf

    // mv_par03 é a POSIÇÃO escolhida no combo (1 a 4), não o texto.
    // 1, 2 e 3 coincidem com os valores do ZA1_VINC; 4 = Todos.
    If mv_par03 == 4
        cVinc := "%"
    Else
        cVinc := cValToChar(mv_par03)
    EndIf

    cAliasQry := GetNextAlias()

    BeginSql Alias cAliasQry
        SELECT ZA1_COD, ZA1_NOME, ZA1_VINC
          FROM %Table:ZA1%
         WHERE ZA1_FILIAL = %xFilial:ZA1%
           AND ZA1_COD BETWEEN %Exp:mv_par01% AND %Exp:mv_par02%
           AND ZA1_VINC LIKE %Exp:cVinc%
           AND %NotDel%
    EndSql

    While !(cAliasQry)->(Eof())
        nTotal++
        (cAliasQry)->(DbSkip())
    EndDo
    (cAliasQry)->(DbCloseArea())

    MsgInfo(cValToChar(nTotal) + " motorista(s) na faixa informada.", "ZA1REL")

Return

O esqueleto segue o formato que o padrão usa (If !Pergunte(cPerg, .T.) seguido de Return); a contagem no fim só existe para o exemplo ter resultado visível. Compile e teste no seu ambiente antes de usar.

Três comportamentos de que o exemplo depende:

  • Pergunte(cPergunta, lPerg, cTitulo) devolve lógico. A Central de Atendimento documenta esses três argumentos; o padrão, em algumas rotinas, chama com mais — não conte que a lista acaba no terceiro. Com o segundo argumento .T., mostra a tela; se o usuário confirma, as variáveis são atualizadas e a resposta é gravada. Onde ela é gravada depende do cadastro do usuário (veja a seção seguinte).
  • Com .F., não mostra tela nenhuma e só carrega as respostas gravadas. É assim que o próprio padrão lê as opções do pedido de venda em outras rotinas: Pergunte("MTA410", .F.). Serve para processamento sem tela e para ler a configuração de outro grupo.
  • As variáveis seguem a ordem, não o X1_VAR01. No MTR410, a ordem 01 tem X1_VAR01 igual a mv_dta_de, e o relatório lê a data em mv_par01: quem define o mv_par01 é a ordem — a documentação da SX1 diz que a ordem é importante para a criação das variáveis MV_PAR??. O X1_VAR01 é só o nome declarado. Recomendação: nos seus grupos, siga o modelo que a documentação pede e preencha X1_VAR01 com mv_par mais a ordem. Além de o dicionário e o fonte dizerem a mesma coisa, há rotinas do padrão que leem a resposta pelo nome declarado, com &(SX1->X1_VAR01), e essa leitura depende do nome gravado ali.

Onde fica a última resposta

A resposta não vai sempre para a SX1. Segundo a Central de Atendimento, “nas versões recentes de Lib”, o local de gravação das perguntas informadas nos parâmetros de um relatório é definido pelas opções de restrição de acesso no cadastro do usuário:

  • o acesso 108 — Gravar resposta parâmetros indica se as respostas às perguntas (SX1) das rotinas serão gravadas no profile do usuário;
  • quando os acessos 108 e 150 — Gravar resposta parâmetros por empresa estão marcados, os últimos dados informados nos parâmetros são gravados no profile do usuário.

O caminho indicado é Configurador > Usuários > Senhas, selecionar o usuário, Alterar, Restrições de Acessos, aba Acesso.

Na prática: com esses acessos marcados, a consulta à SX1 pode não mostrar a última resposta daquele usuário, e cada usuário passa a ter os seus parâmetros. Se, mesmo com o acesso marcado, as respostas continuarem compartilhadas entre usuários, a Central orienta limpar o profile do usuário — o procedimento está em Manutenção de Profile.

mv_par01 não é parâmetro

O nome engana: mv_par01 parece um MV_ da SX6, mas não é. É a variável que o Pergunte() cria em memória para a resposta — e o ParamBox() cria variáveis com o mesmo nome, uma por item do array. Não existe cadastro dela, não dá para lê-la com SuperGetMV e ela não existe antes de uma dessas duas chamadas.

A SX6 tem, sim, parâmetros cujo nome começa por MV_PAR — é um deles —, e nenhum deles tem relação com perguntas:

Confira no seu ambienteSQL
SELECT X6_VAR, X6_TIPO, X6_DESCRIC
  FROM SX6010
 WHERE X6_VAR LIKE 'MV[_]PAR%'
   AND D_E_L_E_T_ = ' '
 ORDER BY X6_VAR

No dicionário padrão, essa consulta traz parâmetros como o MV_PARICMS e nenhum MV_PAR01. O [_] é a forma de o SQL Server tratar o sublinhado como caractere, e não como curinga. Parâmetros de verdade estão em Parâmetros (SX6).

Quando o que se quer é travar a resposta

Se o objetivo não é criar um grupo, e sim impedir que o usuário mude a resposta de uma pergunta existente, o caminho é a rotina de Configuração de Perguntas do Configurador. Segundo a documentação da TOTVS, ela serve para definir uma resposta padrão e deixá-la bloqueada para o usuário. O acesso indicado é:

TEXT
Configurador > Usuário > Senhas > Configuração de Perguntas

Em Incluir, informe o código do grupo em Grupo e escolha o usuário ou o grupo de usuários a que a regra se aplica. As perguntas do grupo aparecem na seção Perguntas; para bloquear uma, clique sobre ela e pressione DEL. Para definir o valor padrão, digite-o na coluna Conteúdo ou, no combo, selecione a opção. A documentação também avisa que a regra trabalha com usuários e grupos de usuários, e que o grupo tem prioridade na busca.

Posicionando a SX1 no fonte

Uma última armadilha, que não tem relação com o bloqueio acima: quem posiciona a SX1 com DbSeek precisa completar o nome do grupo com espaços até o tamanho do campo antes de juntar a ordem. Numa rotina do padrão, a busca pela primeira pergunta de um grupo é escrita assim:

ADVPL / TLPP
dbSeek(Padr("CFG051",Len(SX1->X1_GRUPO), " ") +"01")

Na base consultada, o X1_GRUPO tem dez posições; sem o Padr(), a chave montada seria CFG05101, e não o nome do grupo completado com espaços seguido de 01.

Para só ler a definição de um grupo, sem posicionar a SX1, a TOTVS documenta a classe FWSX1Util, que retorna os campos da SX1 cadastrados para o grupo pedido. AddGroup() adiciona o grupo a pesquisar, SearchGroup() pesquisa os grupos adicionados e GetGroup() devolve um array: na posição [1], o nome do grupo; na [2], um array de objetos com as perguntas. Se a posição 2 vier vazia, o grupo não foi localizado na SX1.

ADVPL / TLPP
Local oSX1      := FWSX1Util():New()
Local aPergunte := {}

oSX1:AddGroup("ZA1REL")
oSX1:SearchGroup()
aPergunte := oSX1:GetGroup("ZA1REL")

If Empty(aPergunte[2])
    MsgAlert("Grupo ZA1REL não encontrado na SX1.")
EndIf

Entre os campos que a classe retorna estão X1_ORDEM, X1_PERGUNT, X1_TIPO, X1_GSC, X1_VAR01 e X1_DEF01 a X1_DEF05. Nas rotinas do padrão, cada pergunta é lida como propriedade do objeto, com o prefixo C: aPergunte[2][1]:CX1_PERGUNT, aPergunte[2][1]:CX1_VAR01.

Referências

  1. TDNtdn.totvs.com

    TDN — SX1, Perguntas do usuário
  2. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Qual função permite acessar e editar um grupo de perguntas SX1 (Pergunte)
  3. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Pergunta de relatório do tipo Range (X1_GSC = R)
  4. TDNtdn.totvs.com

    TDN — Configuração de Perguntas, Bloquear Parâmetros
  5. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Bloquear resposta de Perguntas
  6. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Parametrizações de relatórios por usuário (acesso 108)
  7. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Como remover parâmetros duplicados por usuário em relatórios
  8. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Como alterar o grupo de perguntas (SX1) pelo Configurador
  9. TDNtdn.totvs.com

    TDN — Perguntas (CFGX031 - SIGACFG)
  10. TDNtdn.totvs.com

    TDN — FWSX1Util

Continue por aqui