No artigo de hoje, irei mostrar para vocês como importar um arquivo csv ou txt via AdvPL.
Muitos alunos me perguntam como seria a lógica para importar registros em AdvPL com o conteúdo de um arquivo txt ou csv.
Então jovens, a lógica seria assim:
- Buscar o caminho do arquivo apontado pelo usuário (TFileDialog)
- Tentar realizar a abertura do arquivo (FWFileReader)
- Ler todas as linhas do arquivo (While com método HasLine)
- Na linha atual, transformar o texto em um array (StrTokArr ou Separa)
- Tentar posicionar no registro (DbSeek)
- Fazer a gravação dos dados (via MsExecAuto ou RecLock)
Com esse contexto acima, iremos montar um exemplo, onde no arquivo CSV, existam as seguintes colunas:
- Código do Fornecedor (A2_COD)
- Loja do Fornecedor (A2_LOJA)
- Razão Social (A2_NOME)
- Observações (A2_X_OBS) – campo customizado que será gravado
//Bibliotecas #Include "TOTVS.ch" #Include "TopConn.ch" //Posições do Array Static nPosCodigo := 1 //Coluna A no Excel Static nPosLojFor := 2 //Coluna B no Excel Static nPosRazSoc := 3 //Coluna C no Excel Static nPosObserv := 4 //Coluna D no Excel /*/{Protheus.doc} zImpCSV Função para importar informações do fornecedor via csv @author Atilio @since 07/06/2021 @version 1.0 @type function /*/ User Function zImpCSV() Local aArea := GetArea() Private cArqOri := "" //Mostra o Prompt para selecionar arquivos cArqOri := tFileDialog( "CSV files (*.csv) ", 'Seleção de Arquivos', , , .F., ) //Se tiver o arquivo de origem If ! Empty(cArqOri) //Somente se existir o arquivo e for com a extensão CSV If File(cArqOri) .And. Upper(SubStr(cArqOri, RAt('.', cArqOri) + 1, 3)) == 'CSV' Processa({|| fImporta() }, "Importando...") Else MsgStop("Arquivo e/ou extensão inválida!", "Atenção") EndIf EndIf RestArea(aArea) Return /*-------------------------------------------------------------------------------* | Func: fImporta | | Desc: Função que importa os dados | *-------------------------------------------------------------------------------*/ Static Function fImporta() Local aArea := GetArea() Local cArqLog := "zImpCSV_" + dToS(Date()) + "_" + StrTran(Time(), ':', '-') + ".log" Local nTotLinhas := 0 Local cLinAtu := "" Local nLinhaAtu := 0 Local aLinha := {} Local oArquivo Local aLinhas Local cCodForn := "" Local cLojForn := "" Local cObserv := "" Local cRazaoSoc := "" Private cDirLog := GetTempPath() + "x_importacao\" Private cLog := "" //Se a pasta de log não existir, cria ela If ! ExistDir(cDirLog) MakeDir(cDirLog) EndIf //Definindo o arquivo a ser lido oArquivo := FWFileReader():New(cArqOri) //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(cArqOri) oArquivo:Open() //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 := StrTokArr(cLinAtu, ";") //Se não for o cabeçalho (encontrar o texto "Código" na linha atual) If "código" $ Lower(cLinAtu) //Zera as variaveis cCodForn := aLinha[nPosCodigo] cLojForn := aLinha[nPosLojFor] cRazaoSoc := aLinha[nPosRazSoc] cObserv := aLinha[nPosObserv] DbSelectArea('SA2') SA2->(DbSetOrder(1)) // Filial + Código + Loja //Se conseguir posicionar no fornecedor If SA2->(DbSeek(FWxFilial('SA2') + cCodForn + cLojForn)) cLog += "+ Lin" + cValToChar(nLinhaAtu) + ", fornecedor [" + cCodForn + cLojForn + " - " + Upper(SA2->A2_NREDUZ) + "] " +; "a observação foi alterada, antes: [" + Alltrim(SA2->A2_X_OBS) + "], agora: [" + Alltrim(cObserv) + "];" + CRLF //Realiza a alteração do fornecedor RecLock('SA2', .F.) SA2->A2_X_OBS := cObserv SA2->(MsUnlock()) Else cLog += "- Lin" + cValToChar(nLinhaAtu) + ", fornecedor e loja [" + cCodForn + cLojForn + "] não encontrados no Protheus;" + CRLF EndIf Else cLog += "- Lin" + cValToChar(nLinhaAtu) + ", linha não processada - cabeçalho;" + CRLF EndIf EndDo //Se tiver log, mostra ele If ! Empty(cLog) cLog := "Processamento finalizado, abaixo as mensagens de log: " + CRLF + cLog MemoWrite(cDirLog + cArqLog, cLog) ShellExecute("OPEN", cArqLog, "", cDirLog, 1) EndIf Else MsgStop("Arquivo não tem conteúdo!", "Atenção") EndIf //Fecha o arquivo oArquivo:Close() Else MsgStop("Arquivo não pode ser aberto!", "Atenção") EndIf RestArea(aArea) Return
Obs.: No nosso exemplo, fizemos um RecLock, pois iremos gravar um campo customizado na SA1, o A1_X_OBS. Se no seu caso for uma inclusão em tabela padrão ou alteração de campos padrões, tente utilizar o ExecAuto por boas práticas.
Bom pessoal, por hoje é só.
Abraços e até a próxima.