No vídeo de hoje, vamos demonstrar em como importar um arquivo XLS (do Excel) via AdvPL.
Hoje, a dúvida foi feita por alguns alunos, se existia alguma forma de importar um Excel sem ter que salvar manualmente com a extensão CSV.
Então foi criado um batch com um script que converte automaticamente o arquivo selecionado de XLS para CSV e assim realiza a importação.
E abaixo o código fonte desenvolvido para exemplificar:
//Bibliotecas #Include "TOTVS.ch" /*/{Protheus.doc} User Function zVid0040 Função que realiza a leitura de um XLS convertendo ele para CSV para importar os dados (como se fosse um CSV) @type Function @author Atilio @since 01/09/2022 @obs Pessoal, essa função é um paliativo de exemplo, para ler um XLS transformando ele em CSV Caso você queira se aprofundar, ou ver uma classe que vai além, com opção de leitura e escrita, eu recomendo que você conheça a YExcel, que é um projeto excelente do Saulo Martins + Link para download: https://github.com/saulogm/advpl-excel/blob/master/src/YEXCEL.prw + Link de exemplo: https://github.com/saulogm/advpl-excel/blob/master/exemplo/tstyexcel.prw + Documentação: https://github.com/saulogm/advpl-excel /*/ User Function zVid0040() Local aArea := FWGetArea() Local cDirIni := GetTempPath() Local cTipArq := 'Arquivos Excel (*.xlsx) | Arquivos Excel 97-2003 (*.xls)' Local cTitulo := 'Seleção de Arquivos para Processamento' Local lSalvar := .F. Local cArqSel := '' Private cArqCSV := "" //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) //Faz a conversão de XLS para CSV cArqCSV := fXLStoCSV(cArqSel) //Se o arquivo XLS existir If File(cArqCSV) Processa({|| fImporta(cArqCSV) }, 'Importando...') EndIf EndIf EndIf FWRestArea(aArea) Return /*/{Protheus.doc} fImporta Função que processa o arquivo e realiza a importação para o sistema @author Daniel Atilio @since 16/07/2022 @version 1.0 @type function @obs Codigo gerado automaticamente pelo Autumn Code Maker @see http://autumncodemaker.com /*/ 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 := 'SBM' 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() //Iniciando controle de transação Begin Transaction //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 If Len(aLinha) > 0 aDados := {} aAdd(aDados, {'BM_GRUPO', aLinha[1], Nil}) aAdd(aDados, {'BM_DESC', aLinha[2], Nil}) lMsErroAuto := .F. MSExecAuto({|x, y| MATA035(x, y)}, aDados, 3) //Se houve erro, gera o log If lMsErroAuto cPastaErro := '\x_logs\' cNomeErro := 'erro_' + cAliasImp + '_' + 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 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 EndDo End Transaction //Se tiver log, mostra ele If ! Empty(cLog) MemoWrite(cDirTmp + cArqLog, cLog) ShellExecute('OPEN', cArqLog, '', cDirTmp, 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 Return //Essa função foi baseada como referência no seguinte link: https://stackoverflow.com/questions/1858195/convert-xls-to-csv-on-command-line Static Function fXLStoCSV(cArqXLS) Local cArqCSV := "" Local cDirTemp := GetTempPath() Local cArqScript := cDirTemp + "XlsToCsv.vbs" Local cScript := "" Local cDrive := "" Local cDiretorio := "" Local cNome := "" Local cExtensao := "" //Monta o Script para converter cScript := 'if WScript.Arguments.Count < 2 Then' + CRLF cScript += ' WScript.Echo "Error! Please specify the source path and the destination. Usage: XlsToCsv SourcePath.xls Destination.csv"' + CRLF cScript += ' Wscript.Quit' + CRLF cScript += 'End If' + CRLF cScript += 'Dim oExcel' + CRLF cScript += 'Set oExcel = CreateObject("Excel.Application")' + CRLF cScript += 'Dim oBook' + CRLF cScript += 'Set oBook = oExcel.Workbooks.Open(Wscript.Arguments.Item(0))' + CRLF cScript += 'oBook.SaveAs WScript.Arguments.Item(1), 6' + CRLF cScript += 'oBook.Close False' + CRLF cScript += 'oExcel.Quit' + CRLF MemoWrite(cArqScript, cScript) //Pega os detalhes do arquivo original em XLS SplitPath(cArqXLS, @cDrive, @cDiretorio, @cNome, @cExtensao) //Monta o nome do CSV, conforme os detalhes do XLS cArqCSV := cDrive + cDiretorio + cNome + ".csv" //Executa a conversão, exemplo: // c:\totvs\Testes\XlsToCsv.vbs "C:\Users\danat\Downloads\tste2.xls" "C:\Users\danat\Downloads\tst2_csv.csv" ShellExecute("OPEN", cArqScript, ' "' + cArqXLS + '" "' + cArqCSV + '"', cDirTemp, 0 ) Return cArqCSV
Observação:
Pessoal, essa função é um paliativo de exemplo, para ler um XLS transformando ele em CSV.
Caso você queira se aprofundar, ou ver uma classe que vai além, com opção de leitura e escrita, eu recomendo que você conheça a YExcel, que é um projeto excelente do Saulo Martins
- Link para download: https://github.com/saulogm/advpl-excel/blob/master/src/YEXCEL.prw
- Link de exemplo: https://github.com/saulogm/advpl-excel/blob/master/exemplo/tstyexcel.prw
- Documentação: https://github.com/saulogm/advpl-excel
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Muito bom !!!
Opa, obrigado pelo comentário Marcos.
Forte abraço.