Função para procurar produtos em uma grid de forma rápida

Hoje vou mostrar uma rotina que foi desenvolvida para encontrar rapidamente um produto em um grid no Pedido de Vendas ou de Compras.

Apesar de a funcionalidade padrão existir (clicar em Outras Ações, Pesquisar, Digitar o código e clicar em confirmar – Função GDSeek), ela acaba sendo bastante extensa em ser utilizada, quando se tem um número grande de pedidos que precisam ser manipulados.

Pensando nisso, foi criado a zFindProd, onde ao colocar em um atalho, por exemplo, Ctrl+Y, é mostrado uma tela que é necessário apenas digitar parte do código e pressionar -Enter-.

Foi montado a tela se baseando nos modelos antigos que ainda usam aCols e aHeader. O Fonte trata apenas do Pedido de Venda e do Pedido de Compra, mas é possível adicionar outras rotinas que tenham o código de produto na grid.

Abaixo o código fonte completo desenvolvido.

//Bibliotecas
#Include "Protheus.ch"

/*/{Protheus.doc} zFindProd
Função feita para agilizar a procura de produtos na grid de rotinas padrões
@author Atilio
@since 31/10/2018
@version undefined
@type function
@example Inserir em um ponto de entrada no carregamento do sistema, por exemplo:

	User Function AfterLogin()
		SetKey(K_CTRL_Y, { || u_zFindProd() })  //Ctrl + Y
	Return

@obs Essa rotina foi feita usando o padrão de grids que usam aCols e aHeader, se for em MVC, para posicionar na linha seria algo +- assim:

	...
	oModelPad  := FWModelActive()
	oModelGrid := oModelPad:GetModel('XXXDETAIL')
	oModelGrid:GoLine(nLinhaNew)
	...
/*/

User Function zFindProd()
	Private nPosProd   := 0
	Private cCampo     := ""
	Private oPai       := GetWndDefault()
	Private aControles := oPai:aControls

	//Se for chamada pela tela de pedido de vendas, o campo será o C6_PRODUTO
	If IsInCallStack("MATA410")
		cCampo := "C6_PRODUTO"

	//Senão, se for chamada pela tela de pedido de compras, o campo será o C7_PRODUTO
	ElseIf IsInCallStack("MATA121")
		cCampo := "C7_PRODUTO"
	EndIf

	//Se houver campo, será carregado a tela
	If ! Empty(cCampo)
		//Pega a posição do aCols
		nPosProd := GDFieldPos(cCampo)

		//Chama a função de procura
		fProcura()

	Else
		MsgStop("Procura de Produtos não pode ser chamada!", "Atenção")
	EndIf

Return

/*---------------------------------------*
 | Func.: fProcura                       |
 | Desc.: Função que procura o registro  |
 *---------------------------------------*/

Static Function fProcura()
	//Variáveis da tela
	Private oDlgPesq
	Private oGrpPesq
	Private oGetPesq
	Private cGetPesq := Space(TamSX3('B1_COD')[01])
	Private oBtnExec
	//Tamanho da Janela
	Private nJanLarg := 500
	Private nJanAltu := 065

	//Criando a janela
	DEFINE MSDIALOG oDlgPesq TITLE "zFindProd - Pesquisa de Produtos" FROM 000, 000  TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
		//Grupo Fórmula com o Get
		@ 003, 003  GROUP oGrpPesq TO (nJanAltu/2)-3, (nJanLarg/2)-1        PROMPT "Produto: " OF oDlgPesq COLOR 0, 16777215 PIXEL
			@ 010, 006  MSGET oGetPesq VAR cGetPesq SIZE (nJanLarg/2)-29, 013 OF oDlgPesq COLORS 0, 16777215 VALID (fConfirma()) PIXEL
			oGetPesq:cPlaceHold := "Insira o código do Produto ou um trecho do código..."

			@ 010, (nJanLarg/2)-21 BUTTON oBtnExec PROMPT "OK" SIZE 016, 015 OF oDlgPesq ACTION(fConfirma()) PIXEL

	//Ativando a janela
	ACTIVATE MSDIALOG oDlgPesq CENTERED

Return

/*---------------------------------------*
 | Func.: fConfirma                      |
 | Desc.: Efetua a busca na grid         |
 *---------------------------------------*/

Static Function fConfirma()
	Local nLinNov   := 0
	Local cPesquisa := Alltrim(cGetPesq)

	//Primeiro tenta encontrar exatamente igual
	nLinNov := aScan(aCols, {|x| AllTrim(x[nPosProd]) == cPesquisa})

	//Se não encontrou, busca pelo trecho
	If nLinNov == 0
		nLinNov := aScan(aCols, {|x| cPesquisa $ AllTrim(x[nPosProd])})
	Endif

	//Se mesmo assim não encontrou, mostra mensagem
	If nLinNov == 0
		MsgStop("Trecho '" + cPesquisa + "' não foi encontrado!", "Atenção")

	//Do contrário, posiciona na linha correta e encerra a tela
	Else
		fPosiciona(nLinNov)
		oDlgPesq:End()
	EndIf
Return

/*---------------------------------------*
 | Func.: fPosiciona                     |
 | Desc.: Posiciona na linha correta     |
 *---------------------------------------*/

Static Function fPosiciona(nLinhaNew)
	Local nAtual     := 0
	Local oGrid

	//Percorrendo os objetos criados da tela
	For nAtual := 1 To Len(aControles)

		//Se tiver Colunas, é uma grid
		If Type("aControles[" + cValToChar(nAtual) + "]:aColumns") != "U"

			//Se tiver o mesmo número de colunas que o aHeader
			If Len(aControles[nAtual]:aColumns) == Len(aHeader)

				//Pega a Grid
				oGrid := aControles[nAtual]

				//Muda a Linha atual
				n := nLinhaNew
				oGrid:nAt := n

				//Atualiza a grid
				oGrid:Refresh()
				oGrid:SetFocus()
			EndIf
		EndIf
	Next
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.

2 Responses

  1. Armando Neto disse:

    Excelente recurso. Obrigado Atílio.

Deixe uma resposta