HARBOUR: CONSULTAR CEP NA INTERNET C/ WEBSERVICE VIACEP

Foto de Anderson

Categoria: 

O exemplo abaixo utiliza o webservice grátis VIACEP para consultar o CEP dos Correios na internet e trazer o endereço para uma variável hash tornando muito mais simples a sua compreensão e utilização. Webservices costumam se conectar direto na fonte trazendo dados atualizadíssimos, confira no rodapé do site do VIACEP a data da base de dados.

Fiz 2 funções VIACEP() e VIACEP2(): a primeira quando se sabe o CEP e a segunda mais sofisticada que, se não souber o CEP ou for inválido, pesquisa pela UF, Cidade e Logradouro e retorna o CEP. Seja o mais preciso possível com o nome da rua senão irá retornar vários possíveis CEPs, mas se for o caso se abrirá uma janela com vários logradouros para selecionar qual seria aquele do CEP procurado, retornando todos os dados no hash da mesma maneira.

Vejamos o primeiro exemplo: Basta copiar a função VIACEP(). O restante do código é um mero exemplo de sua utilização. Funciona com Harbour e xHarbour.

FUNCTION MAIN(CEP)
SETMODE(25,80)
REQUEST HB_GT_WVT_DEFAULT
******************************** 
*** CODEPAGE E CHARSET PT-BR ***
******************************** 
REQUEST HB_LANG_PT
REQUEST HB_CODEPAGE_PT860  
HB_LangSelect("PT")
HB_SetCodePage("PT860")   
SET(_SET_LANGUAGE, "PT")  

CLS
cCEP    := SPACE(8)
cRUA    := SPACE(60)
cNUMERO := SPACE(6)
cCOMPL  := SPACE(15)
cBAIRRO := SPACE(45)
cCIDADE := SPACE(20)
cUF     := SPACE(2)
hCEP    := HASH()

@ 10,10 SAY "CEP.......:" GET cCEP PICTURE "@R 99999-999" VALID !EMPTY(hCEP:=VIACEP(cCEP)) ;
									MESSAGE "O endereço será preenchido automaticamente consultando a internet"
READ MSG AT 23,00,79

IF LASTKEY()#27
	cRUA   := hCEP["logradouro"]
	cCOMPL := hCEP["complemento"]
	cBAIRRO:= hCEP["bairro"]
	cCIDADE:= hCEP["localidade"] 
	cUF    := hCEP["uf"] 

	@ 11,10 SAY "Nº........:" GET cNUMERO MESSAGE "INFORME O NÚMERO DO ENDEREÇO"
	@ 12,10 SAY "Logradouro:" GET cRUA
	@ 13,10 SAY "Bairro....:" GET cBAIRRO
	@ 14,10 SAY "Cidade....:" GET cCIDADE
	@ 15,10 SAY "UF........:" GET cUF
	READ MSG AT 23,00,79
ELSE
	? "Abortado pelo usuário c/ ESC"
ENDIF
? "Fim"

FUNCTION VIACEP(cCEP)
******************************************************
* Usa o webservice gratuito: https://viacep.com.br/  *
* Programado por ANDERSON CARDOSO SILVA              *
* https://linguagemclipper.com.br/webservice/viacep  *
******************************************************
// Harbour: Incluir xhb.hbc na compilação
// HBMK2 VIACEP XHB.HBC

// Se o CEP for inválido retorna NIL
// Exemplo: @ 10,10 SAY "CEP.......:" GET cCEP PICTURE "@R 99999-999" VALID !EMPTY(hCEP:=VIACEP(cCEP))

cCEP := ALLTRIM(STRTRAN(cCEP, "-")) // REMOVE ESPAÇOS EM BRANCO E "-", DEIXA SÓ NÚMEROS
IF LEN(cCEP) # 8
	ALERT("O CEP precisa ter 8 números")
	RETURN nil
ENDIF	

http := CreateObject("MSXML2.ServerXMLHTTP")
http:Open("GET", "http://viacep.com.br/ws/"+cCEP+"/json/") // JSON

// Envia e recebe a resposta
http:send()
RESPONSE := http:responseText

// DEFINE VARIÁVEL DO TIPO HASH VAZIA PARA ARMAZENAR TODOS OS CAMPOS DE RETORNO
hCEP := HASH()

// DECODIFICA JSON
hb_jsondecode( response, @hCEP )

IF LEN(hCEP) = 1
	ALERT("CEP inválido!")
	RETURN nil
ENDIF	

/*
? "TODAS AS INFORMACOES DO VIACEP"
? "Os campos hash sao case-sensitive, devem ficar em letras minusculas"
?
? hCEP["cep"] 
? hCEP["logradouro"]
? hCEP["complemento"]
? hCEP["bairro"]
? hCEP["localidade"] // CIDADE
? hCEP["uf"] 
? hCEP["ibge"]
? hCEP["gia"] 
? hCEP["ddd"]
? hCEP["siafi"]
INKEY(0)
*/
RETURN hCEP

Vejamos o segundo exemplo com a função VIACEP2(), não se esqueça de copiar a função SCROLLBAR() que trabalha com o VIACEP2(). Essa aqui ficou demais!!!

FUNCTION MAIN(CEP)
SETMODE(25,80)
SET SCOREBOARD OFF
SET CONFIRM ON
REQUEST HB_GT_WVT_DEFAULT
******************************** 
*** CODEPAGE E CHARSET PT-BR ***
******************************** 
REQUEST HB_LANG_PT
REQUEST HB_CODEPAGE_PT860  
HB_LangSelect("PT")
HB_SetCodePage("PT860")   
SET(_SET_LANGUAGE, "PT")  

CLS
cCEP    := SPACE(8)
cRUA    := SPACE(50)
cNUMERO := SPACE(6)
cCOMPL  := SPACE(15)
cBAIRRO := SPACE(45)
cCIDADE := SPACE(20)
cUF     := SPACE(2)
hCEP    := HASH() // CONTERÁ TODOS OS DADOS QUE VIACEP RETORNA

@ 10,10 SAY "CEP.......:" GET cCEP PICTURE "@R 99999-999" VALID !EMPTY(hCEP:=VIACEP2(cCEP)) ;
									MESSAGE "O endereço será preenchido automaticamente consultando a internet"
READ MSG AT 23,00,79

IF LASTKEY()#27
	cCEP   := hCEP["cep"]
	cRUA   := hCEP["logradouro"]
	cCOMPL := hCEP["complemento"]
	cBAIRRO:= hCEP["bairro"]
	cCIDADE:= hCEP["localidade"] 
	cUF    := hCEP["uf"] 
	@ 10,10 SAY "CEP.......: " + cCEP
	@ 11,10 SAY "Nº........:" GET cNUMERO MESSAGE "INFORME O NÚMERO DO ENDEREÇO"
	@ 12,10 SAY "Logradouro:" GET cRUA
	@ 13,10 SAY "Bairro....:" GET cBAIRRO
	@ 14,10 SAY "Cidade....:" GET cCIDADE
	@ 15,10 SAY "UF........:" GET cUF
	READ MSG AT 23,00,79
ELSE
	? "Abortado pelo usuário c/ ESC"
ENDIF
? "Fim"

FUNCTION VIACEP2(cCEP)
******************************************************
* Usa o webservice gratuito: https://viacep.com.br/  *
* Programado por ANDERSON CARDOSO SILVA              *
* https://linguagemclipper.com.br/webservice/viacep  *
******************************************************
// Harbour: Incluir xhb.hbc na compilação
// HBMK2 VIACEP2 XHB.HBC

cCEP := ALLTRIM(STRTRAN(cCEP, "-")) // REMOVE ESPAÇOS EM BRANCO E "-", DEIXA SÓ NÚMEROS
IF LEN(cCEP) # 8
	ALERT("O CEP precisa ter 8 números")
	RETURN nil
ENDIF	

http := CreateObject("MSXML2.ServerXMLHTTP")
http:Open("GET", "http://viacep.com.br/ws/"+cCEP+"/json/") // JSON

// Envia e imprime a resposta
http:send()
RESPONSE := http:responseText

// DEFINE VARIÁVEL DO TIPO HASH VAZIA PARA ARMAZENAR TODOS OS CAMPOS DE RETORNO
hCEP := HASH()

// DECODIFICA JSON
hb_jsondecode( response, @hCEP )

IF LEN(hCEP) = 1 // hCEP["erro"]=.T.
	IF (ALERT("CEP inválido! Pesquisa o CEP?", {"Sim", "Não"}))=1
		aGETLIST := GETLIST
		GETLIST  := {}
		cTT := SAVESCREEN()
		cCOLOR :=SETCOLOR()
		SETCOLOR("W+/B")
		@ 10,05 CLEAR TO 15,75
		@ 10,05 TO 15,75
		@ 10,06 SAY PADC("PESQUISA DE CEP", 63, "─")
		/*
		Para consultar um CEP na base de dados são necessários três parâmetros obrigatórios
		(UF, Cidade e Logradouro), sendo que para Cidade e Logradouro também é obrigatório 
		um número mínimo de três caracteres a fim de evitar resultados extremamente abrangentes.
		
		Exemplo: https://viacep.com.br/ws/AL/Maceio/avenida da paz/json/
		*/		
		@ 11,07 SAY "Informe a UF (Estado), Cidade e o Logradouro"
		@ 12,07 SAY "Logradouro:" GET cRUA
		@ 13,07 SAY "Cidade....:" GET cCIDADE
		@ 14,07 SAY "UF........:" GET cUF
		READ
		IF LASTKEY()#27
			http := CreateObject("MSXML2.ServerXMLHTTP")
			http:Open("GET", "http://viacep.com.br/ws/"+cUF+"/"+ALLTRIM(cCIDADE)+"/"+ALLTRIM(cRUA)+"/json/") // JSON

			// Envia e imprime a resposta
			http:send()
			RESPONSE2 := http:responseText

			// DEFINE VARIÁVEL DO TIPO HASH VAZIA PARA ARMAZENAR TODOS OS CAMPOS DE RETORNO
			hCEPS := HASH()

			// DECODIFICA JSON
			hb_jsondecode( response2, @hCEPS )

			nCEPS1 := 1
			IF LEN(hCEPS) > 1 // Há mais de 1 CEP possível		
				// VAMOS MOSTRAR UMA JANELA COM TODOS OS POSSÍVEIS CEPs
				nCEPS := LEN(hCEPS)
				aCEPS := {}
				FOR X=1 TO nCEPS
					cCOMPL := hCEPS[X]["complemento"]
					IF SUBSTR(cCOMPL,1,1)="(" // TEM COMPLEMENTO QUE VEM ENTRE PARÊNTESES
						cCOMPL := STRTRAN(cCOMPL,"(")
						cCOMPL := STRTRAN(cCOMPL,")")
					ENDIF
					cOPCAO := hCEPS[X]["cep"]+"│"+ hCEPS[X]["logradouro"] +IIF(!EMPTY(cCOMPL), " ("+cCOMPL+")", "")
					cOPCAO := LEFT(cOPCAO, 77)
					aADD(aCEPS, cOPCAO)
				NEXT
				
				// SE TIVER MAIS DE 10 CEPs NÃO ULTRAPASSA A LINHA 10
				nLL := 18-nCEPS
				IF nCEPS > 10
					nLL := 10
				ENDIF
				
				// MONTA JANELA QUE VAI SE ACOMODAR À QUANTIDADE DE CEPs
				SETCOLOR("W+/BG")
				@ nLL,00 CLEAR TO 20,79
				@ nLL,00 TO 20,79	
				@ nLL+1,01 SAY PADC("CEP",8)+" │"+PADC("LOGRADOURO (Complemento)",68) COLOR "W+/B"
				@ nLL,06 SAY PADC( ALLTRIM(STR(nCEPS))+" CEPs ENCONTRADOS", 63, "─")
				@ 20,06 SAY PADC( "ENCONTRE O CEP CORRETO E PRESSIONE [ENTER]", 63, "─")
				
				// SE TIVER MAIS DE 10 CEPs COLOCA UMA BARRA DE ROLAGEM VERTICAL (SCROLLBAR)
				IF nLL=10
					cCOR1 := SETCOLOR()
					DISPBEGIN() // DESENHA O SCROLLBAR
					SETCOLOR("N/W")
					nL1    := nLL+1
					FOR T=nL1 TO 19
						@ T,79 SAY CHR(219) COLOR "N+/W"
					NEXT
					@ nL1,79 SAY CHR(30) // 24↑ ou 30▲
					@ 19,79  SAY CHR(31) // 25↓ ou 31▼
					SETCOLOR(cCOR1)
					DISPEND()
					cBARRAS := SAVESCREEN(nL1,79,19,79)   // SALVA O DESENHO DA BARRA DE ROLAGEM
					@ nL1+1,79 SAY CHR(254) COLOR "W/N+*" // 219█ 254■
				ENDIF
				nCEPS1 := aCHOICE(nLL+2,01,19,78, aCEPS,,"SCROLLBAR")
				IF LASTKEY()=27
					RETURN "00000000"
				ENDIF				
			ENDIF			
			SETCOLOR(cCOLOR)
			RESTORE SCREEN FROM cTT
			GETLIST := aGETLIST
			IF nCEPS1 > 0
				RETURN hCEPS[nCEPS1]
			ENDIF
		ENDIF		
	ELSE
		RETURN "00000000"
	ENDIF
ENDIF	

/*
? "TODAS AS INFORMACOES DO VIACEP"
? "Os campos hash sao case-sensitive, devem ficar em letras minusculas"
?
? hCEP["cep"] 
? hCEP["logradouro"]
? hCEP["complemento"]
? hCEP["bairro"]
? hCEP["localidade"] // CIDADE
? hCEP["uf"] 
? hCEP["ibge"]
? hCEP["gia"] 
? hCEP["ddd"]
? hCEP["siafi"]
INKEY(0)
*/
RETURN hCEP

FUNCTION SCROLLBAR( nMode, nElement, nRow )
#include "Achoice.ch"
#include "Inkey.ch"

LOCAL nKey := LastKey()
LOCAL nRet := AC_CONT
LOCAL cMsg

DO CASE
	CASE nMode == AC_IDLE
		// MOSTRAR BARRA DE ROLAGEM VERTICAL
		IF nLL=10
			RESTSCREEN(nL1,79,19,79, cBARRAS) // RESEDENHA A BARRA DE ROLAGEM
			// MOVIMENTA O SCROLLBAR
			nVALOR := 19-nL1-2 // AMPLITUDE DA BARRA
			// nCEPS 100%
			// nELEMENT = POSIÇÃO			
			nPOS := (nELEMENT/nCEPS) * nVALOR // PERCENTUAL DA BARRA (POSIÇÃO)
			@ nL1+1+nPOS,79 SAY CHR(254) COLOR "W/N+*" // 219█ 254■
			SETCOLOR(cCOR1)
		ENDIF
	CASE nMode == AC_EXCEPT
		// key handling for unknown keys
		IF nKey == K_ESC
			nRet := AC_ABORT
		ELSEIF nKey == K_RETURN .OR. nKey == K_LDBLCLK
			nRet := AC_SELECT
		ELSEIF nKey > 31 .AND. nKey < 255
			nRet := AC_GOTO
		ENDIF
ENDCASE
RETURN nRet

Colocando o logradouro completo poderá dar apenas 1 ou 2 opções de CEP, observe:

2ceps

Neste caso, como a Avenida da Paz é grande ela tem 2 CEPs: do número 1 ao 1250 e do número 1252 até o final.

Agora olhe como fica se eu colocar apenas "da paz", "maceio" e "al" (não é case-sensitive):

ceps

Retornou 45 CEPs possíveis! Por isso sempre coloque o nome do logradouro completo sempre que possível.

Downloads: 

viacep.prg — Baixado 32 vezes
viacep2.prg — Baixado 13 vezes
Total votes: 0