Gravando a quantidade da População de uma Cidade na tabela CC2 | Ti Responde 0209

No vídeo de hoje, vamos demonstrar em como gravar o número de habitantes de uma cidade (população) no cadastro de cidades (CC2) importando do IBGE.

A dúvida de hoje, nos perguntaram, se seria possível gravar a população de habitantes de uma cidade na tabela CC2 do Protheus importando direto do IBGE.

 

Pensando nisso, montamos um exemplo, onde vamos mostrar em como baixar o CSV dos estados do IBGE, e fazer assim a importação para um campo customizado, chamado CC2_X_POPU.

 

Segue abaixo o vídeo exemplificando:

 

E abaixo o código fonte desenvolvido:

//Bibliotecas
#Include "tlpp-core.th"

//Declaração da namespace
Namespace custom.terminal.youtube

#Define CRLF Chr(13) + Chr(10) //Carriage Return Line Feed

/*/{Protheus.doc} User Function video0209
Importação de População das Cidades
@author Atilio
@since 11/09/2024
@version 1.0
@type function
@example custom.terminal.youtube.u_video0209()
@obs Criar os campos:
    + CC2_X_POPU do tipo Numérico, Tamanho 10, Decimal 0, Máscara @E 9,999,999,999
    + CC2_X_DATA do tipo Data, Tamanho 8

    Os CSVs dos estados podem ser baixados direto no site do IBGE, exemplo:
    https://ibge.gov.br/cidades-e-estados/sp.html
    https://ibge.gov.br/cidades-e-estados/ac.html
    https://ibge.gov.br/cidades-e-estados/rj.html

    Ao baixar os CSVs, deixe eles em uma pasta, com o nome do estado respectivo, por exemplo, C:\pasta\rj.csv
/*/

User Function video0209()
	Local aArea           := FWGetArea()                                    As Array
	Local cInitDirectory  := GetTempPath()                                  As Character
	Local cTypeFile       := ''                                             As Character
	Local cTitle          := 'Seleção de Pasta para ler os os arquivos CSV' As Character
	Local lSave           := .F.                                            As Logical
	Local cFolder         := ''                                             As Character
 
	//Se não estiver sendo executado via job
	If ! IsBlind()
		cFolder := tFileDialog(;
			cTypeFile,;              // Filtragem de tipos de arquivos que serão selecionados
			cTitle,;                 // Título da Janela para seleção dos arquivos
			,;                       // Compatibilidade
			cInitDirectory,;         // Diretório inicial da busca de arquivos
			lSave,;                  // Se for .T., será uma Save Dialog, senão será Open Dialog
			GETF_RETDIRECTORY;       // 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
		)

		//Tratativa para add barra na direita
		cFolder := Alltrim(cFolder)
		If Right(cFolder, 1) != "\"
			cFolder += "\"
		EndIf

		//Se a pasta existir
		If ! Empty(cFolder) .And. ExistDir(cFolder)
	        Processa({|| importFolderFiles(cFolder) }, 'Importando...')
	    EndIf
	EndIf
	
	FWRestArea(aArea)
Return
	
/*/{Protheus.doc} importFolderFiles
Função que processa o arquivo e realiza a importação para o sistema
@author Atilio
@since 11/09/2024
@version 1.0
@type function
/*/

Static Function importFolderFiles(cFolder)
	Local cLogFolder       := GetTempPath()                                                              As Character
    Local dToday           := Date()                                                                     As Date
	Local cLogFile         := 'importacao_' + dToS(dToday) + '_' + StrTran(Time(), ':', '-') + '.log' As Character
	Local nTotalLines      := 0                                                                          As Numeric
	Local cCurrentLine     := ''                                                                         As Character
	Local nCurrentLine     := 0                                                                          As Numeric
	Local aCurrentContent  := {}                                                                         As Array
	Local oFile                                                                                          As Object
	Local cLog             := ''                                                                         As Character
    Local cCityId          := ''                                                                         As Character
    Local nPopulation      := 0                                                                          As Numeric
    Local cState           := ''                                                                         As Character
	Local cCurrentFile     := ''                                                                         As Character
	Local aFiles           := {}                                                                         As Array
	Local nCurrentFile     := 0                                                                          As Numeric
	//Variáveis da Importação
	Private cTableAlias    := 'CC2'                                                                      As Character
	Private cSeparator     := ','                                                                        As Character

	//Abre as tabelas que serão usadas
	DbSelectArea(cTableAlias)
	(cTableAlias)->(DbSetOrder(1)) // CC2_FILIAL + CC2_EST + CC2_CODMUN
	(cTableAlias)->(DbGoTop())

	//Pega todos os arquivos
	aFiles := Directory(cFolder + "*.csv")

	//Percorre eles
	For nCurrentFile := 1 To Len(aFiles)
		cCurrentFile := cFolder + aFiles[nCurrentFile][1]

		//Definindo o arquivo a ser lido
		oFile := FWFileReader():New(cCurrentFile)

		//Se o arquivo pode ser aberto
		If (oFile:Open())

			//Se não for fim do arquivo
			If ! (oFile:EoF())

				//Pegando a sigla do estado
				cNome := ""
				SplitPath(cCurrentFile, /*@cDrive*/, /*@cDiretorio*/, @cNome, /*@cExtensao*/)
				cState := Upper(cNome)

				//Definindo o tamanho da régua
				aLinhas := oFile:GetAllLines()
				nTotalLines := Len(aLinhas)
				ProcRegua(nTotalLines)

				//Método GoTop não funciona (dependendo da versão da LIB), deve fechar e abrir novamente o arquivo
				oFile:Close()
				oFile := FWFileReader():New(cCurrentFile)
				oFile:Open()

				//Iniciando controle de transação
				Begin Transaction

					//Enquanto tiver linhas
                    nCurrentLine := 0
					While (oFile:HasLine())

						//Incrementa na tela a mensagem
						nCurrentLine++
						IncProc('Analisando linha ' + cValToChar(nCurrentLine) + ' de ' + cValToChar(nTotalLines) + '...')

						//Pegando a linha atual e transformando em array
						cCurrentLine := oFile:GetLine()
						aCurrentContent  := Separa(cCurrentLine, cSeparator)

						//Se for as linhas de cabeçalho
						If nCurrentLine <= 2
							Loop

                        //Se na linha tual, tiver tag em html, vai pular
                        ElseIf "<td>" $ cCurrentLine
                            Loop

						//Se houver posições no array
						ElseIf Len(aCurrentContent) >= 6
							cCityId    := SubStr(aCurrentContent[2], 3)
							nPopulation := Val(aCurrentContent[6])

							If (cTableAlias)->(MsSeek(FWxFilial("CC2") + cState + cCityId))
								cLog += '+ Cidade ' + cCityId + ' atualizada com sucesso (linha ' + cValToChar(nCurrentLine) + ') do arquivo ' + cCurrentFile + ';' + CRLF
								RecLock(cTableAlias, .F.)
									CC2_X_POPU := nPopulation
									CC2_X_DATA := dToday
								(cTableAlias)->(MsUnlock())
							Else
								cLog += '- Cidade ' + cCityId + ' não foi encontrada no cadastro (linha ' + cValToChar(nCurrentLine) + ') do arquivo ' + cCurrentFile + ';' + CRLF
							EndIf

						EndIf

					EndDo
				End Transaction
			EndIf

			//Fecha o arquivo
			oFile:Close()
		EndIf
	Next

	//Se tiver log, mostra ele
	If ! Empty(cLog)
		MemoWrite(cLogFolder + cLogFile, cLog)
		ShellExecute('OPEN', cLogFile, '', cLogFolder, 1)
	EndIf

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.

Deixe uma resposta

Terminal de Informação