Como inserir campos customizados na tela de Documento de Entrada

Hoje vou mostrar como criar uma nova aba no rodapé do Documento de Entrada e inserir campos nessa aba.

Muitos alunos me perguntam se é possível incluir campos na tela do Documento de entrada, sem ser pelo intermédio de algum botão.

E sim, é possível. O que devemos fazer basicamente é:

  1. Utilizar a variável oFolder que esta em memória, antes da tela carregar os valores, e o melhor P.E. para tratar isso é o MA103BUT que é responsável por criar outras ações na tela de manipulação, mas antes de liberar pro usuário digitar
  2. Nesse ponto iremos adicionar uma nova aba através do método AddItem
  3. Então, iremos usar uma variável pública (lembre-se que não é recomendado usar escopo Public, estamos usando aqui para testes, e se for usar ai, use nome esdrúxulos como por exemplo com dois underlines) que no nosso caso será do campo F1_X_CAMPO
  4. Iremos criar um MSGET com as informações do campo F1_X_CAMPO
  5. Por último, iremos criar um segundo P.E. que será após a gravação da SF1, e nele iremos testar, se tiver a variável pública criada no passo 3, iremos gravar no campo F1_X_CAMPO

Resumidamente então, iremos usar outro ponto de entrada, para manipular o Folder do rodapé, e adicionar campo(s) nessa aba criada.

Abaixo um print do resultado:

Exemplo de aba criada no Documento de Entrada

E abaixo o código fonte dos dois P.E.:

//Bibliotecas
#Include "TOTVS.ch"

/*/{Protheus.doc} User Function MA103BUT
P.E. para adicionar opções dentro da tela de manipulação do Doc. de Entrada
@type  Function
@author Atilio
@since 08/07/2021
@version version
@see https://tdn.totvs.com/pages/releaseview.action?pageId=102269141
/*/

User Function MA103BUT()
    Local aArea := GetArea()
    Local lEdit
    Local nAba
    Local oCampo
    Public __cCamNovo := ""

    //Adiciona uma nova aba no documento de entrada
    oFolder:AddItem("* Customizados", .T.)
    nAba := Len(oFolder:aDialogs)

    //Se for inclusão, irá criar a variável e será editável, senão irá buscar do banco e não será editável
    If INCLUI
        __cCamNovo := CriaVar("F1_X_CAMPO",.F.)
        lEdit := .T.
    Else
        __cCamNovo := SF1->F1_X_CAMPO
        lEdit := .F.
    EndIf
 
    //Criando na janela o campo OBS
    @ 003, 003 SAY Alltrim(RetTitle("F1_X_CAMPO")) OF oFolder:aDialogs[nAba] PIXEL SIZE 050,006
    @ 001, 053 MSGET oCampo VAR __cCamNovo SIZE 100, 006 OF oFolder:aDialogs[nAba] COLORS 0, 16777215  PIXEL
    oCampo:bHelp := {|| ShowHelpCpo( "F1_X_CAMPO", {GetHlpSoluc("F1_X_CAMPO")[1]}, 5  )}
 
    //Se não houver edição, desabilita os gets
    If ! lEdit
        oCampo:lActive := .F.
    EndIf

    RestArea(aArea)
Return Nil

/*/{Protheus.doc} User Function SF1100I
P.E. após inclusão da SF1
@type  Function
@author Atilio
@since 08/07/2021
@version version
/*/

User Function SF1100I()
    Local aArea := GetArea()

    //Se a variável pública existir
    If Type("__cCamNovo") != "U"

        //Grava o conteúdo na SF1
        RecLock("SF1", .F.)
            SF1->F1_X_CAMPO := __cCamNovo
        SF1->(MsUnlock())
    EndIf

    RestArea(aArea)
Return

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan Atilio (Daniel Atilio)
Especialista em Engenharia de Software pela FIB. Entusiasta de soluções Open Source. E blogueiro nas horas vagas.

8 Responses

  1. MARCOS BISPO ABRAHAO disse:

    Bom dia Daniel! Ótima dica, mas teria como fazer este procedimento também na Pré-Nota?

  2. Michael Fernando Camilo disse:

    Olá Daniel! Excelente dica! Poderia usar escopo private para a variável __cCamNovo?

    • Opa, eu que agradeço pelo comentário Michael.
      No caso, no exemplo do artigo não, pois, uma variável Private fica disponível para a função que a criou e para todas as que forem acionadas internamente por ela.
      Então ela só vai existir até o Return da função que a criou. Por isso foi necessário criar uma Public, para que ela ficasse na memória do sistema.
      Grande abraço.

  3. MARCOS BISPO ABRAHAO disse:

    Obrigado Daniel!

  4. Daniele Diniz Magalhães disse:

    Estou tentando usar o código, mas criando dois campos, fazendo no mesmo padrão que você fez só um. O problema é que a informação que coloco no primeiro campo, preenche automaticamente o segundo campo. Teria ideia do que eu posso estar fazendo de errado?

    • Você criou uma segunda variável pública, por exemplo, __cCamNov2 para usar no seu campo?
      No caso, como as variáveis em AdvPL tem limitação de 10 caracteres, veja isso também, pois se estiver com o nome __cCamNovo2, ele irá considerar até a última letra “o”.

Deixe uma resposta