No artigo de hoje, iremos demonstrar em como atualizar o cadastro de cidades (CC2) no Protheus.
Antes do tutorial abaixo, é necessário baixar o código fonte zImpCC2 e compilar na sua base, o código está disponível abaixo:
//Bibliotecas
#Include "Totvs.ch"
/*/{Protheus.doc} User Function zImpCC2
Importação de Municípios
@author Atilio
@since 13/11/2022
@version 1.0
@type function
/*/
User Function zImpCC2()
Local aArea := FWGetArea()
Local cDirIni := GetTempPath()
Local cTipArq := 'Arquivos com separações (*.csv) | Arquivos texto (*.txt) | Todas extensões (*.*)'
Local cTitulo := 'Seleção de Arquivos para Processamento'
Local lSalvar := .F.
Local cArqSel := ''
//Se não estiver sendo executado via job
If ! IsBlind()
//Chama a função para buscar arquivos
cArqSel := tFileDialog(;
cTipArq,; // Filtragem de tipos de arquivos que serão selecionados
cTitulo,; // Título da Janela para seleção dos arquivos
,; // Compatibilidade
cDirIni,; // Diretório inicial da busca de arquivos
lSalvar,; // Se for .T., será uma Save Dialog, senão será Open Dialog
; // Se não passar parâmetro, irá pegar apenas 1 arquivo; Se for informado GETF_MULTISELECT será possível pegar mais de 1 arquivo; Se for informado GETF_RETDIRECTORY será possível selecionar o diretório
)
//Se tiver o arquivo selecionado e ele existir
If ! Empty(cArqSel) .And. File(cArqSel)
Processa({|| fImporta(cArqSel) }, 'Importando...')
EndIf
EndIf
FWRestArea(aArea)
Return
/*/{Protheus.doc} fImporta
Função que processa o arquivo e realiza a importação para o sistema
@author Atilio
@since 13/11/2022
@version 1.0
@type function
/*/
Static Function fImporta(cArqSel)
Local cDirTmp := GetTempPath()
Local cArqLog := 'importacao_' + dToS(Date()) + '_' + StrTran(Time(), ':', '-') + '.log'
Local nTotLinhas := 0
Local cLinAtu := ''
Local nLinhaAtu := 0
Local aLinha := {}
Local oArquivo
Local cPastaErro := '\x_logs\'
Local cNomeErro := ''
Local cTextoErro := ''
Local aLogErro := {}
Local nLinhaErro := 0
Local cLog := ''
//Variáveis do ExecAuto
Private aDados := {}
Private lMSHelpAuto := .T.
Private lAutoErrNoFile := .T.
Private lMsErroAuto := .F.
//Variáveis da Importação
Private cAliasImp := 'CC2'
Private cSeparador := ';'
//Abre as tabelas que serão usadas
DbSelectArea(cAliasImp)
(cAliasImp)->(DbSetOrder(1))
(cAliasImp)->(DbGoTop())
//Definindo o arquivo a ser lido
oArquivo := FWFileReader():New(cArqSel)
//Se o arquivo pode ser aberto
If (oArquivo:Open())
//Se não for fim do arquivo
If ! (oArquivo:EoF())
//Definindo o tamanho da régua
aLinhas := oArquivo:GetAllLines()
nTotLinhas := Len(aLinhas)
ProcRegua(nTotLinhas)
//Método GoTop não funciona (dependendo da versão da LIB), deve fechar e abrir novamente o arquivo
oArquivo:Close()
oArquivo := FWFileReader():New(cArqSel)
oArquivo:Open()
DbSelectArea("CC2")
CC2->(DbSetOrder(1)) // CC2_FILIAL + CC2_EST + CC2_CODMUN
//Enquanto tiver linhas
While (oArquivo:HasLine())
//Incrementa na tela a mensagem
nLinhaAtu++
IncProc('Analisando linha ' + cValToChar(nLinhaAtu) + ' de ' + cValToChar(nTotLinhas) + '...')
//Pegando a linha atual e transformando em array
cLinAtu := oArquivo:GetLine()
aLinha := Separa(cLinAtu, cSeparador)
//Se houver posições no array e somente a partir da linha 2
If Len(aLinha) > 0 .And. nLinhaAtu >= 2
//Busca o estado conforme o código
cEstado := Lj901AUF(aLinha[1])
//Somente se não encontrar a cidade ja cadastrada
If ! CC2->(MsSeek(FWxFilial("CC2") + cEstado + aLinha[11]))
//Monta o array de importação
aDados := {}
aAdd(aDados, {'CC2_EST', cEstado, Nil})
aAdd(aDados, {'CC2_CODMUN', aLinha[11], Nil})
aAdd(aDados, {'CC2_MUN', aLinha[13], Nil})
lMsErroAuto := .F.
MSExecAuto({|x, y| FISA010(x, y)}, aDados, 3)
//Se houve erro, gera o log
If lMsErroAuto
cPastaErro := '\x_logs\'
cNomeErro := 'erro_' + cAliasImp + '_lin_' + cValToChar(nLinhaAtu) + '_' + dToS(Date()) + '_' + StrTran(Time(), ':', '-') + '.txt'
//Se a pasta de erro não existir, cria ela
If ! ExistDir(cPastaErro)
MakeDir(cPastaErro)
EndIf
//Pegando log do ExecAuto, percorrendo e incrementando o texto
cTextoErro := ""
aLogErro := GetAutoGRLog()
For nLinhaErro := 1 To Len(aLogErro)
cTextoErro += aLogErro[nLinhaErro] + CRLF
Next
//Criando o arquivo txt e incrementa o log
MemoWrite(cPastaErro + cNomeErro, cTextoErro)
cLog += '- Falha ao incluir registro, linha [' + cValToChar(nLinhaAtu) + '], arquivo de log em ' + cPastaErro + cNomeErro + CRLF
Else
cLog += '+ Sucesso no Execauto na linha ' + cValToChar(nLinhaAtu) + ';' + CRLF
EndIf
EndIf
EndIf
EndDo
//Se tiver log, mostra ele
If ! Empty(cLog)
MemoWrite(cDirTmp + cArqLog, cLog)
ShellExecute('OPEN', cArqLog, '', cDirTmp, 1)
EndIf
Else
FWAlertError('Arquivo não tem conteúdo!', 'Atenção')
EndIf
//Fecha o arquivo
oArquivo:Close()
Else
FWAlertError('Arquivo não pode ser aberto!', 'Atenção')
EndIf
Return
Agora, siga o passo a passo abaixo:
- Acesse o site https://www.ibge.gov.br/explica/codigos-dos-municipios.php e clique no botão Download da tabela de códigos
- Abra o arquivo RELATORIO_DTB_BRASIL_MUNICIPIO
- Clique em Arquivo > Salvar Como e escolha a extensão CSV
- Agora execute a função zImpCC2 no seu Protheus, será solicitado o arquivo para selecionar
- Ao confirmar, será exibido uma régua de carregamento
- Por último será aberto uma tela com os logs, com os detalhes de sucesso ou falha do Execauto, sendo que onde houver falha, será gerado um log dentro da pasta \x_logs\ na Protheus Data
Bom pessoal, por hoje é só.
Abraços e até a próxima.






Muito bom. Ótimo trabalho que voce faz. Ajuda muito quem esta começando. Infelizmente ainda não consigo ser premium, mas um dia chego lá. Muito obrigado
Bom dia Vicente, tudo joia?
Opa, muito obrigado pelo comentário e feedback, é muita generosidade sua.
Um grande abraço.
Atilio não é um dev, é um prefeito.
Bom dia mano Súlivan, tudo joia?
Opa, obrigado pelo comentário, é muita bondade e generosidade sua.
Tenha uma ótima e abençoada quinta feira.
Um forte abraço.