Rotina para cadastros de parâmetros em AdvPL

Olá pessoal…

Hoje vou mostrar uma rotina que desenvolvi para cadastro de parâmetros (SX6) no Protheus, similar ao AxCadastro ou a mBrowse.

O intuito dessa rotina, é liberar o cadastro de parâmetros aos usuários, porém ressalto, que o ideal é liberar apenas acesso à parâmetros customizados.

A rotina, ela recebe 3 parâmetros para a montagem da tela, o primeiro, são os parâmetros que estarão disponíveis para cadastro (ou seja, mesmo que o usuário tente digitar outro parâmetro, só serão aceitos os que estiverem nesse array). O segundo parâmetro, é se o cadastro de parâmetros irá utilizar combo (com a listagem de parâmetros conforme array), ou se será usado um get. O último parâmetro, define se será possível excluir o registro.

A tela principal, mostra a listagem de parâmetros.

Tela principal

Tela principal

Ao clicar em Incluir, é necessário informar todos os campos (somente a filial que não é obrigatória), e o RecNO não pode ser preenchido.

Incluindo um parâmetro

Incluindo um parâmetro

Ao clicar em Alterar, somente é possível, alterar o conteúdo e a descrição, os outros campos são bloqueados para edição.

Alteração de parâmetros

Alteração de parâmetros

Abaixo o código fonte utilizado.

//Bibliotecas
#Include "Protheus.ch"

//Constantes
#Define CLR_AZUL      RGB(058,074,119)									//Cor Azul

//Variaveis
Static COL_T1 	:= 001				//Primeira Coluna da tela
Static COL_T2 	:= 123				//Segunda Coluna da tela
Static COL_T3 	:= 245				//Terceira Coluna da tela
Static COL_T4 	:= 367				//Quarta Coluna da tela
Static ESP_CAMPO	:= 038				//Espaçamento do campo para coluna
Static TAM_FILIAL	:= FWSizeFilial()	//Tamanho do campo Filial

/*/{Protheus.doc} zCadSX6
Lista parâmetros ao usuário com as opções de incluir, alterar e excluir
@author Atilio
@since 14/11/2014
@version 1.0
	@param aParams, Array, Parâmetros que serão listados ao usuário para edição
	@param lCombo, Lógico, Define se os parâmetros serão mostrados em combo quando houver inclusão
	@param lDelet, Lógico, Define se será possível a exclusão de parâmetros
	@example
	aParams := { "MV_X_AMBOF","MV_X_USERS"}
	u_zCadSX6(aParams, .T., .T.)
/*/

User Function zCadSX6(aParams, lCombo, lDelet)
	Local aArea   := GetArea()
	Local aAreaX6 := SX6->(GetArea())
	Local nAtual  := 0
	Local nColuna := 6
	Default lCombo := .T.
	Default lDelet := .F.
	Default aParams := {}
	Private lComboPvt := lCombo
	Private aParamsPvt := {}
	Private cParamsPvt := ""
	//Tamanho da Janela
	Private aTamanho := MsAdvSize()
	Private nJanLarg := aTamanho[5]
	Private nJanAltu := aTamanho[6]
	Private nColMeio := (nJanLarg)/4
	Private nEspCols := ((nJanLarg/2)-12)/4
	COL_T1 	:= 003
	COL_T2 	:= COL_T1+nEspCols
	COL_T3 	:= COL_T2+nEspCols
	COL_T4 	:= COL_T3+nEspCOls
	//Objetos gráficos
	Private oDlgSX6
	//GetDados
	Private oMsGet
	Private aHeader 	:= {}
	Private aCols		:= {}
	//Botões
	Private aButtons	:= {}
	aAdd(aButtons,{"Incluir",    "{|| fInclui()}", "oBtnInclui"})
	aAdd(aButtons,{"Alterar",    "{|| fAltera()}", "oBtnAltera"})
	aAdd(aButtons,{"Visualizar", "{|| fVisualiza()}", "oBtnVisual"})
	If lDelet
		aAdd(aButtons,{"Excluir",    "{|| fExclui()}", "oBtnExclui"})
	EndIf
	aAdd(aButtons,{"Sair", "{|| oDlgSX6:End()}", "oBtnSair"})
	
	//Se não tiver parâmetros
	If Len(aParams) <= 0
		MsgStop("Parâmetros devem ser informados!", "Atenção")
		Return
	Else
		aParamsPvt := aParams
		cParamsPvt := ""
		
		//Percorrendo os parâmetros e adicionando
		For nAtual := 1 To Len(aParamsPvt)
			cParamsPvt += aParamsPvt[nAtual]+";"
		Next
	EndIf
	
	//Adicionando cabeçalho
	aAdd(aHeader,{"Filial", 		"ZZ_FILIAL",	"@!",	TAM_FILIAL,	0,	".F.",	".F.",	"C",	"",	""	,})
	aAdd(aHeader,{"Parâmetro", 	"ZZ_PARAME",	"@!",	010,			0,	".F.",	".F.",	"C",	"",	""	,})
	aAdd(aHeader,{"Tipo",  		"ZZ_TIPO",		"@!",	001,			0,	".F.",	".F.",	"C",	"",	""	,})
	aAdd(aHeader,{"Descrição",  "ZZ_DESCRI",	"@!",	150,			0,	".F.",	".F.",	"C",	"",	""	,})
	aAdd(aHeader,{"Conteúdo",   "ZZ_CONTEU",	"@!",	250,			0,	".F.",	".F.",	"C",	"",	""	,})
	aAdd(aHeader,{"RecNo",      "ZZ_RECNUM",	"",		018,			0,	".F.",	".F.",	"N",	"",	""	,})
	
	//Atualizando o aCols
	fAtuaCols(.T.)
	
	//Criando a janela
	DEFINE MSDIALOG oDlgSX6 TITLE "Parâmetros:" FROM 000, 000  TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
		oMsGet := MsNewGetDados():New(	3,;										//nTop
    										3,;										//nLeft
    										(nJanAltu/2)-33,;						//nBottom
    										(nJanLarg/2)-3,;						//nRight
    										GD_INSERT+GD_DELETE+GD_UPDATE,;		//nStyle
    										"AllwaysTrue()",;						//cLinhaOk
    										,;										//cTudoOk
    										"",;									//cIniCpos
    										,;										//aAlter
    										,;										//nFreeze
    										999999,;								//nMax
    										,;										//cFieldOK
    										,;										//cSuperDel
    										,;										//cDelOk
    										oDlgSX6,;								//oWnd
    										aHeader,;								//aHeader
    										aCols)									//aCols  
    	oMsGet:lActive := .F.
	
		//Grupo Legenda
		@ (nJanAltu/2)-30, 003 	GROUP oGrpLeg TO (nJanAltu/2)-3, (nJanLarg/2)-3 	PROMPT "Ações: " 		OF oDlgSX6 COLOR 0, 16777215 PIXEL
		//Adicionando botões
		For nAtual := 1 To Len(aButtons)
			@ (nJanAltu/2)-20, nColuna  BUTTON &(aButtons[nAtual][3]) PROMPT aButtons[nAtual][1]   SIZE 60, 014 OF oDlgSX6  PIXEL
			(&(aButtons[nAtual][3]+":bAction := "+aButtons[nAtual][2]))
			nColuna += 63
		Next
	ACTIVATE MSDIALOG oDlgSX6 CENTERED
	
	RestArea(aAreaX6)
	RestArea(aArea)
Return

/*---------------------------------------------------------------------*
 | Func:  fInclui                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  14/11/2014                                                   |
 | Desc:  Função de inclusão de parâmetro                              |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function fInclui()
	Local nAtual   := oMsGet:nAt
	Local aColsAux := oMsGet:aCols
	Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" })
	
	fMontaTela(3, 0)
Return

/*---------------------------------------------------------------------*
 | Func:  fAltera                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  14/11/2014                                                   |
 | Desc:  Função de alteração de parâmetro                             |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function fAltera()
	Local nAtual   := oMsGet:nAt
	Local aColsAux := oMsGet:aCols
	Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" })
	
	//Se tiver recno válido
	If aColsAux[nAtual][nPosRecNo] != 0
		fMontaTela(4, aColsAux[nAtual][nPosRecNo])
	EndIf
Return

/*---------------------------------------------------------------------*
 | Func:  fExclui                                                      |
 | Autor: Daniel Atilio                                                |
 | Data:  14/11/2014                                                   |
 | Desc:  Função de exclusão de parâmetro                              |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function fExclui()
	Local nAtual   := oMsGet:nAt
	Local aColsAux := oMsGet:aCols
	Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" })
	
	//Se tiver recno válido
	If aColsAux[nAtual][nPosRecNo] != 0
		fMontaTela(5, aColsAux[nAtual][nPosRecNo])
	EndIf
Return

/*---------------------------------------------------------------------*
 | Func:  fVisualiza                                                   |
 | Autor: Daniel Atilio                                                |
 | Data:  14/11/2014                                                   |
 | Desc:  Função de visualização de parâmetro                          |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function fVisualiza()
	Local nAtual   := oMsGet:nAt
	Local aColsAux := oMsGet:aCols
	Local nPosRecNo:= aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" })
	
	//Se tiver recno válido
	If aColsAux[nAtual][nPosRecNo] != 0
		fMontaTela(2, aColsAux[nAtual][nPosRecNo])
	EndIf
Return

/*---------------------------------------------------------------------*
 | Func:  fAtuaCols                                                    |
 | Autor: Daniel Atilio                                                |
 | Data:  14/11/2014                                                   |
 | Desc:  Função que atualiza o aCols com os parâmetros                |
 | Obs.:  Como a intenção é ter poucos parâmetros, sempre ele irá      |
 |        percorrer a SX6 e adicionar no aCols                         |
 *---------------------------------------------------------------------*/

Static Function fAtuaCols(lFirst)
	Local aAreaSX6 := SX6->(GetArea())
	aCols := {}
	
	//Selecionando a tabela de parâmetros e indo ao topo
	DbSelectArea("SX6")
	SX6->(DbGoTop())
	
	//Percorrendo os parâmetros, e adicionando somente os que estão na filtragem
	While !SX6->(EoF())
		If Alltrim(SX6->X6_VAR) $ cParamsPvt
			aAdd( aCols, {	SX6->X6_FIL,;											//Filial
								SX6->X6_VAR,;											//Parâmetro
								SX6->X6_TIPO,;										//Tipo
								SX6->X6_DESCRIC+SX6->X6_DESC1+SX6->X6_DESC2,;		//Descrição
								SX6->X6_CONTEUD,;										//Conteúdo
								SX6->(RecNo()),;										//RecNo
								.F.})													//Excluído?
		EndIf
	
		SX6->(DbSkip())
	EndDo

	//Se tiver zerada, adiciona conteúdo em branco
	If Len(aCols) == 0
		aAdd( aCols, {	"",;		//Filial
							"",;		//Parâmetro
							"",;		//Tipo
							"",;		//Descrição
							"",;		//Conteúdo
							0,;			//RecNo
							.F.})		//Excluído?
	EndIf

	//Senão for a primeira vez, atualiza grid
	If !lFirst
		oMsGet:setArray(aCols)
	EndIf

	RestArea(aAreaSX6)
Return

/*---------------------------------------------------------------------*
 | Func:  fMontaTela                                                   |
 | Autor: Daniel Atilio                                                |
 | Data:  14/11/2014                                                   |
 | Desc:  Função que atualiza o aCols com os parâmetros                |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function fMontaTela(nOpcP, nRecP)
	Local nColuna := 6
	Local nEsp := 15
	Private nOpcPvt := nOpcP
	Private nRecPvt := nRecP
	Private aOpcTip := {" ", "C - Caracter", "N - Numérico", "L - Lógico", "D - Data", "M - Memo"}
	Private oFontNeg := TFont():New("Tahoma")
	Private oDlgEdit
	//Campos
	Private oGetFil, cGetFil
	Private oGetPar, cGetPar
	Private oGetTip, cGetTip
	Private oGetDes, cGetDes
	Private oGetCon, cGetCon
	Private oGetRec, nGetRec
	//Botões
	Private aBtnPar	:= {}
	aAdd(aBtnPar,{"Confirmar",   "{|| fBtnEdit(1)}", "oBtnConf"})
	aAdd(aBtnPar,{"Cancelar",    "{|| fBtnEdit(2)}", "oBtnCanc"})

	//Se não for inclusão, pega os campos conforme array
	If nOpcP != 3
		aColsAux := oMsGet:aCols
		nLinAtu  := oMsGet:nAt
		nPosFil  := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_FILIAL" })
		nPosPar  := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_PARAME" })
		nPosTip  := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_TIPO" })
		nPosDes  := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_DESCRI" })
		nPosCon  := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_CONTEU" })
		nPosRec  := aScan(aHeader,{|x| AllTrim(x[2]) == "ZZ_RECNUM" })

		//Atualizando gets
		cGetFil := aColsAux[nLinAtu][nPosFil]
		cGetPar := aColsAux[nLinAtu][nPosPar]
		cGetTip := aColsAux[nLinAtu][nPosTip]
		cGetDes := aColsAux[nLinAtu][nPosDes]
		cGetCon := aColsAux[nLinAtu][nPosCon]
		nGetRec := aColsAux[nLinAtu][nPosRec]

		//Caracter
		If cGetTip == "C"
			cGetTip := aOpcTip[2]
		//Numérico
		ElseIf cGetTip == "N"
			cGetTip := aOpcTip[3]
		//Lógico
		ElseIf cGetTip == "L"
			cGetTip := aOpcTip[4]
		//Data
		ElseIf cGetTip == "D"
			cGetTip := aOpcTip[5]
		//Memo
		ElseIf cGetTip == "M"
			cGetTip := aOpcTip[6]
		EndIf

	//Senão, deixa os campos zerados
	Else
	
		//Atualizando gets
		cGetFil := Space(TAM_FILIAL)
		cGetPar := Space(010)
		cGetTip := aOpcTip[1]
		cGetDes := Space(150)
		cGetCon := Space(250)
		nGetRec := 0
	EndIf

	oFontNeg:Bold := .T.

	//Criando a janela
	DEFINE MSDIALOG oDlgEdit TITLE "Dados:" FROM 000, 000  TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
		nLinAux := 6
			//Filial
			@ nLinAux    , COL_T1						SAY				oSayFil PROMPT	"Filial:"						SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL							PIXEL
			@ nLinAux-003, COL_T1+ESP_CAMPO				MSGET			oGetFil VAR		cGetFil						SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215						PIXEL
			//Parâmetro
			@ nLinAux    , COL_T2						SAY				oSayPar PROMPT	"Parâmetro:"					SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL		FONT oFontNeg		PIXEL
			If lComboPvt
				@ nLinAux-003, COL_T2+ESP_CAMPO			MSCOMBOBOX		oGetPar VAR		cGetPar ITEMS aParamsPvt		SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215						PIXEL
			Else
				@ nLinAux-003, COL_T2+ESP_CAMPO			MSGET			oGetPar VAR		cGetPar						SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215	VALID (cGetPar $ cParamsPvt)	PIXEL
			EndIf
			//Tipo
			@ nLinAux    , COL_T3						SAY				oSayTip PROMPT	"Tipo:"						SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL		FONT oFontNeg		PIXEL
    		@ nLinAux-003, COL_T3+ESP_CAMPO				MSCOMBOBOX		oGetTip VAR		cGetTip ITEMS aOpcTip		SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215						PIXEL
			//RecNo
			@ nLinAux    , COL_T4						SAY				oSayRec PROMPT	"RecNo:"						SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL							PIXEL
			@ nLinAux-003, COL_T4+ESP_CAMPO				MSGET			oGetRec VAR		nGetRec						SIZE 060, 010 OF oDlgEdit COLORS 0, 16777215						PIXEL
		nLinAux += nEsp
			//Descrição
			@ nLinAux    , COL_T1						SAY				oSayDes PROMPT	"Descrição:"					SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL		FONT oFontNeg		PIXEL
			@ nLinAux-003, COL_T1+ESP_CAMPO				MSGET			oGetDes VAR		cGetDes						SIZE 300, 010 OF oDlgEdit COLORS 0, 16777215						PIXEL
		nLinAux += nEsp
			//Conteúdo
			@ nLinAux    , COL_T1						SAY				oSayCon PROMPT	"Conteúdo:"					SIZE 040, 007 OF oDlgEdit COLORS CLR_AZUL		FONT oFontNeg		PIXEL
			@ nLinAux-003, COL_T1+ESP_CAMPO				MSGET			oGetCon VAR		cGetCon						SIZE 300, 010 OF oDlgEdit COLORS 0, 16777215						PIXEL
	
		//Grupo Legenda
		@ (nJanAltu/2)-30, 003 	GROUP oGrpLegEdit TO (nJanAltu/2)-3, (nJanLarg/2)-3 	PROMPT "Ações (Confirmação): " 		OF oDlgEdit COLOR 0, 16777215 PIXEL
		//Adicionando botões
		For nAtual := 1 To Len(aBtnPar)
			@ (nJanAltu/2)-20, nColuna  BUTTON &(aBtnPar[nAtual][3]) PROMPT aBtnPar[nAtual][1]   SIZE 60, 014 OF oDlgEdit  PIXEL
			(&(aBtnPar[nAtual][3]+":bAction := "+aBtnPar[nAtual][2]))
			nColuna += 63
		Next
		
		//Se for visualização ou exclusão, todos os gets serão desabilitados
		If nOpcP == 2 .Or. nOpcP == 5
			oGetFil:lActive := .F.
			oGetPar:lActive := .F.
			oGetTip:lActive := .F.
			oGetDes:lActive := .F.
			oGetCon:lActive := .F.
		Else
			//Se for alteração, desabilita a Filial, Parâmetro e Tipo
			If nOpcP == 4
				oGetFil:lActive := .F.
				oGetPar:lActive := .F.
				oGetTip:lActive := .F.
			EndIf
		EndIf
		
		//Campo de RecNo sempre será desabilitado
		oGetRec:lActive := .F.
	ACTIVATE MSDIALOG oDlgEdit CENTERED
Return

/*---------------------------------------------------------------------*
 | Func:  fBtnEdit                                                     |
 | Autor: Daniel Atilio                                                |
 | Data:  16/12/2014                                                   |
 | Desc:  Função que confirma a tela                                   |
 | Obs.:  /                                                            |
 *---------------------------------------------------------------------*/

Static Function fBtnEdit(nConf)
	Local aAreaAux := GetArea()
	
	//Se for o Cancelar
	If nConf == 2
		oDlgEdit:End()
	//Se for o Confirmar
	ElseIf nConf == 1
		//Se for visualizar
		If nOpcPvt == 2
			oDlgEdit:End()
			
		//Senão for visualizar
		Else
			//Se for exclusão
			If nOpcPvT == 5
				SX6->(DbGoTo(nRecPvt))
				RecLock("SX6", .F.)
					DbDelete()
				SX6->(MsUnlock())
				oDlgEdit:End()
			Else
				//Descrição ou conteúdo em branco?
				If Empty(cGetDes) .Or. Empty(cGetCon)
					If !MsgYesNo("O campo <b>Descrição</b> e/ou <b>Conteúdo</b> estão com conteúdo em branco!<br>Deseja continuar?", "Atenção")
						Return
					EndIf
				EndIf
				
				//Se for inclusão
				If nOpcPvt == 3
					//Tipo e parâmetro em branco?
					If Empty(cGetTip) .Or. Empty(cGetPar)
						MsgAlert("O campo <b>Parâmetro</b> e/ou <b>Tipo</b> estão com conteúdo em branco!", "Atenção")
						Return
					EndIf
					
					//Já existe registro?
					SX6->(DbGoTop())
					If (SX6->(DbSeek(cGetFil+cGetPar)))
						MsgAlert("Filial e Parâmetro já existem!", "Atenção")
						Return
					EndIf
					
					//Travando tabela para inclusão
					RecLock("SX6", .T.)
					X6_FIL			:= cGetFil
					X6_VAR			:= cGetPar
					X6_TIPO		:= cGetTip
				//Se for alteração, trava tabela para alteração
				ElseIf nOpcPvt == 4
					SX6->(DbGoTo(nRecPvt))
					RecLock("SX6", .F.)
				EndIf
				
				//Gravando informações
				X6_DESCRIC		:= SubStr(cGetDes,001,50)
				X6_DESC1		:= SubStr(cGetDes,051,50)
				X6_DESC2		:= SubStr(cGetDes,101,50)
				X6_CONTEUD		:= cGetCon
				SX6->(MsUnlock())
				
				oDlgEdit:End()
			EndIf
		EndIf
		
		//Atualizando a grid
		fAtuaCols(.F.)
	EndIf
	
	RestArea(aAreaAux)
Return

Bom pessoal, por hoje é só.
Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

11 Responses

  1. Alan Rigueto disse:

    Olá Dan, espero que tudo bem. Primeiramente parabéns pelos seus artigos …! 🙂
    Eu preciso somente de permitir alteração de parâmetro para prorrogar prazo para cancelamento de NF´s
    AlteraR o parâmetro MV_SPEDEXC. DE 24 PARA X HORAS (48,72, 96 …)
    AlteraR o parâmetro MV_CANCEXT de 5 para 7 dias….

    Eu localizei um artigo da UserFunction (E PEDI O FONTE POR E-MAIL) baseado neste seu que sugere esta parte de permitir somente algum
    parâmetro específico (segue para conhecimento):
    https://userfunction.com.br/infraestrutura/sigacfg/protheus_tela_parametros/#wpcf7-f659-p10096-o1
    Apresenta estas mensagens na compilação:
    W0003 Local variable NATUAL never used
    W0003 Local variable ACOLSAUX never used
    W0003 Local variable NPOSRECNO never used
    W0004 For variable is not Local. This warning may be an error in future version.

    Eu PRETENDO tentar assim:

    User Function AltMVHORAS()
    u_zCadSX6({“MV_SPEDEXC”}, .t., .f.)
    Return

    User Function AltMVDIAS()
    u_zCadSX6({” MV_CANCEXT”}, .t., .f.)
    Return

    Porém no seu fonte antes de começar a mexer eu simplesmente copiei e colei o seu fonte e compilei (obs.: No VSCode) e já apresentou mensagem abaixo:

    variable is not Local

    [{
    “resource”: “/D:/Alan Rigueto/Documentos/Protheus/Projetos/Faturamento/zCadSX6.prw”,
    “owner”: “AdvPL”,
    “severity”: 8,
    “message”: “variable is not Local”,
    “source”: “Linter”,
    “startLineNumber”: 358,
    “startColumn”: 1,
    “endLineNumber”: 359,
    “endColumn”: 1
    }]

    Por favor orientar como corrigir e se não for pedir muito um fonte “exemplo” somente com opção de alteração, não de criação e exclusão de parâmetros
    Desde já agradeço
    Abs.
    Att.

  2. Alan Rigueto disse:

    Atualizando o post anterior:

    Olá,

    A princípio ao compilar o fonte sem alterar nada (Obs.: Via VScode) estava apresentando mensagem:
    warning W0004 For variable is not Local
    Consultando solução localizei a sugestão:
    A variável utilizada no For, não foi declarada localmente, é necessário declarar ela
    Nota.: No fonte já está declarada na User Function Local nAtual := 0, conforme trecho do fonte original abaixo:
    User Function zCadSX6(aParams, lCombo, lDelet)
    Local aArea := GetArea()
    Local aAreaX6 := SX6->(GetArea())
    Local nAtual := 0

    Mesmo assim declarei Local nAtual neste trecho da função “MontaTela”:

    Static Function fMontaTela(nOpcP, nRecP)
    //nAtual := 1 ou 0 ou Local nAtual := oMsGet:nAt ?
    Local nColuna := 6
    Local nEsp := 15
    Local nAtual

    E a partir dai pelo menos compilou porém quando chamo a função zCadSX6 já na aplicação do Protheus apresenta mensagem:

    Parâmetros devem ser informados

    Já tentei declarar destas 3 formas:
    Local nAtual := 1
    Local nAtual := 0
    Local nAtual := oMsGet:nAt

    O que seria o corrreto?

    Aguardo orientações

    Desde já agradeço
    Abs.
    Att.

    • Bom dia Alan, tudo joia?

      Certo, vamos lá, primeiro sobre os warnings / errors, os que tiverem “variable never used”, você pode comentar a linha de declaração. Já o For variable is not local, você declara a variável usada no for dentro da function como Local.

      Como esse é um fonte antigo (de 2014), faz tempo que não reviso ele, ainda mais que nas versões mais novas do Protheus, a manipulação do dicionário não é mais recomendada.

      Agora, para acionar a função, você deve fazer da seguinte forma:

      u_zCadSX6({"MV_SPEDEXC", "MV_CANCEXT"}, .T., .F.)
      

      Pois se você acionar direto a função, vai ocasionar a mensagem “Parâmetros devem ser informados”, por isso que acima nós passamos um array com o nome dos parâmetros da SX6.

      Deixo ainda uma sugestão, caso você já queira fazer um código que não use a manipulação direta do dicionário, crie uma função que use PutMV, por exemplo:

      #Include "TOTVS.ch"
      
      User Function zFuncao()
      	Local cConteudo := FWInputBox("Informe o conteúdo do parâmetro")
      	
      	//Se o usuário informou
      	If ! Empty(cConteudo)
      	
      		//Atualiza o parâmetro, convertendo de texto para numérico
      		PutMV("MV_SPEDEXC", Val(cConteudo))
      	EndIF
      Return
      

      Ai, basta você acionar essa sua zFuncao, que irá aparecer uma tela para digitar o valor do parâmetro.

  3. Alan Rigueto disse:

    Q bom, tdo joia tbém
    Opa, já testei aqui no ambiente de validação e funcionou o parâmetro MV_SPEDEXC. DE 24 PARA X HORAS (48,72, 96 …)
    Vou fazer mais alguns ajustes, e seguir a mesma lógica também para o parâmetro MV_CANCEXT de 5 para X dias …
    para colocar em PROD
    Valew

  4. Alan Rigueto disse:

    Lega. Muito obrigado. Funcionou certinho!
    Dan, aproveitando você tem algo para atender Endereçamento de Produto:
    Objeto: MATA265
    NECESSIDADE:
    EXIBIR AVISO QUANDO TENTAR ENDERECAR PRODUTO QUE JA EXISTE EM OUTRO ENDERECO
    USER FUNCTION (abaixo) COMPILADA no ambiente validacão no projeto Estoque atualizações
    MAS NÃO SURTIU EFEITO

    Acredito que seja algo neste sentido:


    User Function vldProd()
    Local lReturn := .F.
    Local aArea := GetArea()
    Local cEndereco := IIF( AllTrim(Upper(ReadVar())) == “M->DB_LOCALIZ”, &(ReadVar()), GdFieldGet(“DB_LOCALIZ”) ) // Descubro se a funcao foi chamada via interface, ou se devo buscar o produto na linha do Grid
    Local cSeek
    dbSelectArea(“SBF”)
    SBF->( dbSetOrder(1) )
    cSeek:=xFilial(“SBF”)+ cEndereco+SDA->DA_LOCAL+SDA->DA_PRODUTO
    If SBF->( dbSeek(cSeek) )
    Alert(“Produto ” + SDA->DA_PRODUTO + ” encontrado no endereço ” + cEndereco)
    Else
    EndIf
    RestArea(aArea)
    Return (lReturn)


    Desde já agradeço
    Até
    Abs.
    Att.

    • Nunca precisei fazer algo nesse sentido Alan.
      Essa função vldProd, você está acionando na validação de usuário ao digitar o campo produto ou em um ponto de entrada?
      Pois aparentemente parece que a lógica está correta mesmo, olhando por cima (o que eu recomendaria seria usar FWxFilial, FWGetArea, FWRestARea e MsSeek no lugar das funções que vocês esta usando, além de ter um else sem nenhum comando dentro).

  5. Paulo Marcelo disse:

    Bom dia Daniel, tudo bem? Ao passar pelo CodeAnalysis esse fonte gera o erro: Direct Access not allowed in data dictionary., Você compatibilizou este fonte para o dicionário de dados depois da migração para o banco de dados?

  6. Paulo Marcelo disse:

    Obrigado pelo retorno Daniel, o fonte era muito bom, o putmv é por filial desta forma quando o parâmetro é exclusivo é mais operacional mas tem que se adaptar as novas regras.

Deixe uma resposta para Alan RiguetoCancelar resposta

Terminal de Informação