Função que tira caracteres especiais dos Campos no Protheus

Olá pessoal…

Hoje vou mostrar uma rotina que foi desenvolvida, que ao informar algum conteúdo especial em algum campo, esse conteúdo é retirado (como acentos e outros caracteres).


Primeiramente, quero agradecer ao meu amigo Rafael Achôa, que me ajudou no desenvolvimento da rotina.

AdvPL

AdvPL

Foram desenvolvidas 2 rotinas, a primeira que substitui realmente os caracteres, a u_zLimpaEsp(), que pode ser colocada na validação de usuário de qualquer campo.

A segunda rotina, é uma rotina de atualização de campos, a u_zCarEspec(), que ao mesmo tempo, desabilita o parâmetro MV_ACENTO, e em seguida atualiza vários campos para não aceitar os caracteres especiais (adicionando o u_zLimpaEsp). Essa rotina pode ser executada no Fórmulas.

Abaixo o código fonte desenvolvido.

//Bibliotecas
#Include "Protheus.ch"

/*/{Protheus.doc} zLimpaEsp
Função que limpa os caracteres especiais dentro de um campo
@type function
@author Atilio / Achoa
@since 25/04/2016
@version 1.0
@param lEndereco, Lógico, Define se o campo é endereço (caso sim, o traço e vírgula serão ignorados)
	@example
	u_zLimpaEsp()
/*/

User Function zLimpaEsp(lEndereco)
	Local aArea       := GetArea()
	Local cCampo      := ReadVar()
	Local cConteudo   := &(cCampo)
	Local nTamOrig    := Len(cConteudo)
	Default lEndereco := .F.
	
	//Retirando caracteres
	cConteudo := StrTran(cConteudo, "'", "")
	cConteudo := StrTran(cConteudo, "#", "")
	cConteudo := StrTran(cConteudo, "%", "")
	cConteudo := StrTran(cConteudo, "*", "")
	cConteudo := StrTran(cConteudo, "&", "E")
	cConteudo := StrTran(cConteudo, ">", "")
	cConteudo := StrTran(cConteudo, "<", "")
	cConteudo := StrTran(cConteudo, "!", "")
	cConteudo := StrTran(cConteudo, "@", "")
	cConteudo := StrTran(cConteudo, "$", "")
	cConteudo := StrTran(cConteudo, "(", "")
	cConteudo := StrTran(cConteudo, ")", "")
	cConteudo := StrTran(cConteudo, "_", "")
	cConteudo := StrTran(cConteudo, "=", "")
	cConteudo := StrTran(cConteudo, "+", "")
	cConteudo := StrTran(cConteudo, "{", "")
	cConteudo := StrTran(cConteudo, "}", "")
	cConteudo := StrTran(cConteudo, "[", "")
	cConteudo := StrTran(cConteudo, "]", "")
	cConteudo := StrTran(cConteudo, "/", "")
	cConteudo := StrTran(cConteudo, "?", "")
	cConteudo := StrTran(cConteudo, ".", "")
	cConteudo := StrTran(cConteudo, "\", "")
	cConteudo := StrTran(cConteudo, "|", "")
	cConteudo := StrTran(cConteudo, ":", "")
	cConteudo := StrTran(cConteudo, ";", "")
	cConteudo := StrTran(cConteudo, '"', '')
	cConteudo := StrTran(cConteudo, '°', '')
	cConteudo := StrTran(cConteudo, 'ª', '')
	
	//Se não for endereço, retira também o - e a ,
	If !lEndereco
		cConteudo := StrTran(cConteudo, ",", "")
		cConteudo := StrTran(cConteudo, "-", "")
	EndIf
	
	//Adicionando os espaços a direita
	cConteudo := Alltrim(cConteudo)
	cConteudo += Space(nTamOrig - Len(cConteudo))
	
	//Definindo o conteúdo do campo
	&(cCampo+" := '"+cConteudo+"' ")
	
	RestArea(aArea)
Return .T.

/*/{Protheus.doc} zCarEspec
Script para atualização de campos que terão sua validação de usuário alterada
@type function
@author Atilio
@since 25/04/2016
@version 1.0
/*/

User Function zCarEspec()
	Local aArea     := GetArea()
	Local aTexto    := {}
	Local aBotoes   := {}
	Local lContinua := .F.
	
	//Adicionando textos da rotina
	aAdd(aTexto, 'Esta rotina tem por objetivo atualizar campos para ')
	aAdd(aTexto, 'não aceitar caracteres especiais em cadastros.')
	aAdd(aTexto, '')
	aAdd(aTexto, 'Será atualizado:')
	aAdd(aTexto, 'Parâmetro MV_ACENTO')
	aAdd(aTexto, 'Tabelas SA1, SA2, SA4 e SB1')

	//Adicionando os botões da rotina
	aAdd(aBotoes, {1, .T., {|| lContinua := .T., FechaBatch()}})
	aAdd(aBotoes, {2, .T., {|| lContinua := .F., FechaBatch()}})

	//Mostra o batch esperando interação do usuário
	FormBatch("Atualização de campos", aTexto, aBotoes) 
		
	//Se for para continuar o processamento
	If lContinua
		Processa({|| fAtualiza()}, "Processando...")
	EndIf
	
	RestArea(aArea)
Return

/*---------------------------------------------------------------------*
 | Func:  fAtualiza                                                    |
 | Autor: Daniel Atilio                                                |
 | Data:  25/04/2016                                                   |
 | Desc:  Função que atualiza os dados                                 |
 *---------------------------------------------------------------------*/

Static Function fAtualiza()
	Local aAreaX3    := SX3->(GetArea())
	Local aCampos    := {}
	Local aCamposEnd := {}
	Local cValidUsr  := ""
	Local nAtual     := 0
	
	DbSelectArea('SX3')
	SX3->(dbSetOrder(2)) // X3_CAMPO
	ProcRegua(3)
	
	//Campos normais
	aAdd(aCampos, 'A1_NOME')
	aAdd(aCampos, 'A1_NREDUZ')
	aAdd(aCampos, 'A1_BAIRRO')
	aAdd(aCampos, 'A1_MUN')
	aAdd(aCampos, 'A2_NOME')
	aAdd(aCampos, 'A2_NREDUZ')
	aAdd(aCampos, 'A2_BAIRRO')
	aAdd(aCampos, 'A2_MUN')
	aAdd(aCampos, 'A4_NOME')
	aAdd(aCampos, 'A4_NREDUZ')
	aAdd(aCampos, 'A4_BAIRRO')
	aAdd(aCampos, 'B1_DESC')
	
	//Campos de endereço
	aAdd(aCamposEnd, 'A1_END')
	aAdd(aCamposEnd, 'A2_END')
	aAdd(aCamposEnd, 'A4_END')
	
	//Atualiza o MV_ACENTO para não aceitar acentuação no sistema
	IncProc("Atualizando parâmetro...")
	PutMV('MV_ACENTO', 'N')
	
	//Percorrendo os campos normais
	IncProc("Atualizando campos normais...")
	SX3->(DbGoTop())
	For nAtual := 1 To Len(aCampos)
		//Se conseguir posicionar
		If SX3->(DbSeek(aCampos[nAtual]))
			cValidUsr := Alltrim(SX3->X3_VLDUSER)
			
			//Se já tiver, pula o campo
			If "U_ZLIMPAESP" $ Upper(cValidUsr)
				nAtual++
				Loop
			EndIf
			
			//Se tiver conteúdo, adiciona .And. no valid
			If !Empty(cValidUsr)
				cValidUsr += ".And."
			Endif
			
			//Definindo a expressão
			cValidUsr += "u_zLimpaEsp()"
			
			//Atualiza no banco
			RecLock('SX3', .F.)
				X3_VLDUSER := cValidUsr
			SX3->(MsUnlock())
		EndIf
	Next
	
	//Percorrendo os campos de endereço
	IncProc("Atualizando campos de endereço...")
	SX3->(DbGoTop())
	For nAtual := 1 To Len(aCamposEnd)
		//Se conseguir posicionar
		If SX3->(DbSeek(aCamposEnd[nAtual]))
			cValidUsr := Alltrim(SX3->X3_VLDUSER)
			
			//Se já tiver, pula o campo
			If "U_ZLIMPAESP" $ Upper(cValidUsr)
				nAtual++
				Loop
			EndIf
			
			//Se tiver conteúdo, adiciona .And. no valid
			If !Empty(cValidUsr)
				cValidUsr += ".And."
			Endif
			
			//Definindo a expressão
			cValidUsr += "u_zLimpaEsp(.T.)"
			
			//Atualiza no banco
			RecLock('SX3', .F.)
				X3_VLDUSER := cValidUsr
			SX3->(MsUnlock())
		EndIf
	Next
	
	RestArea(aAreaX3)
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.

14 Responses

  1. Rafael Achôa disse:

    Top, Atílio!
    Funcionando perfeitamente aqui na Jolie Café!

    Abraços,

  2. Roberval disse:

    Valew Daniel féra como sempre, o Achôa é gente boa hem… Parabéns pelo post…

  3. Carlos Alberto disse:

    Parabéns Atílio !

    Quando se propaga conhecimento, o propagador jamais será esquecido. Continue assim, com esse espírito de compartilhar conhecimento.

  4. Antonio Remigio disse:

    Muito top, mas quando coloco na validação do usuario do campo B1_COD, no debug faz corretamente mas salva com espaço, teria algo a mais a ser feito?

  5. Douglas da Silva disse:

    Showwww muito bom, resolvi um problema com as APIs que alguns cadastros tinha caracteres como “” isso quebrava o meu JSON, parabéns por disponibilizar esse conhecimento.

  6. Tiago Fonseca Lima disse:

    Boa tarde, Alguem em 2022 conseguiu usar o fonte? deu erro na linha 19 no meu

    • Bom dia Tiago.
      Você consegue nos disponibilizar como você testou o fonte? Se foi em um valid de usuário de campo, valid de pergunta, direto em um dialog?
      Se possível nos mande um doc do word detalhando o procedimento que fez para testar.
      Ficamos no aguardo.

  7. Caio disse:

    No inicializador de usuário, como eu teria declarar lá para chamar a função?

    • Bom dia Caio, tudo joia?

      No caso, você quer mesmo usar em um Inicializador? Pois só vai ser acionado se o usuário clicar em incluir (campo real) ou nas outras opções se for um campo virtual. Nesse artigo eu explico um pouco sobre o conceito de inicialização dos campos: https://terminaldeinformacao.com/2021/07/07/para-que-serve-e-como-criar-um-ini-padrao-de-campo/

      Dito isso, essa rotina de tirar caracteres foi pensada em ser usada na validação do campo (X3_VLDUSER), onde ao usuário preencher uma informação e dar um -enter- ou -tab- automaticamente os caracteres serem alterados. Então para isso, basta você ir no campo e na Validação de Usuário, você colocar a chamada dela: u_zLimpaEsp()

      Agora se realmente você tem um cenário de campo Virtual onde você precisa sempre que o usuário clicar em visualizar ou alterar, você fazer essa tratativa, ai você precisaria adaptar a rotina, para que ela não lesse do ReadVar() , mas sim do conteúdo que você esta inicializando.

      Ah e se quiser também, no nosso curso de Configurador, nós explicamos sobre Contexto, Inicialização, Validação e Modo de Edição de campos nas aulas 22 a 25 – https://terminaldeinformacao.com/2022/03/14/curso-configurador-sigacfg/

      Um grande abraço.

Deixe uma resposta

Terminal de Informação