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:

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):

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