No vídeo de hoje, vou demonstrar em como importar uma pré nota de entrada (SF1 e SD1) via csv ou txt.
Hoje, a dúvida foi feita pelo grande Roberto, onde ele tinha uma dúvida, em como fazer uma importação de csv ou txt para uma pré nota de entrada (SF1 e SD1).
Com isso em mente, fiz um vídeo explicando como fazer a leitura linha a linha e acionar a importação dos dados de forma correta via ExecAuto.
E abaixo o código fonte desenvolvido para exemplificar:
//Bibliotecas #Include "TOTVS.ch" /*/{Protheus.doc} User Function zVid0013 Função que realiza a importação do CSV como Pré Nota @type Function @author Atilio @since 23/02/2022 /*/ User Function zVid0013() Local aArea := FWGetArea() Local cDirIni := GetTempPath() Local cTipArq := "Arquivos com separações (*.csv)" 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 Static Function fImporta(cArqSel) Local cDirLog := GetTempPath() Local cArqLog := "zFat07Im_" + dToS(Date()) + "_" + StrTran(Time(), ':', '-') + ".log" Local nTotLinhas := 0 Local cLinAtu := "" Local nLinhaAtu := 0 Local aLinha := {} Local oArquivo Local aLinhas Local aLinhaSD1 := {} Local cItem := StrTran(Space(TamSX3('D1_ITEM')[01]), ' ', '0') //Primeira coluna do Excel, será o tipo da linha Private nPosTip := 1 //SF1 ou SD1 //Posições do Cabeçalho (SF1) Private nCabTipo := 2 //F1_TIPO Private nCabForm := 3 //F1_FORMUL Private nCabDocu := 4 //F1_DOC Private nCabSeri := 5 //F1_SERIE Private nCabEmis := 6 //F1_EMISSAO Private nCabForn := 7 //F1_FORNECE Private nCabLoja := 8 //F1_LOJA Private nCabEspe := 9 //F1_ESPECIE Private nCabCond := 10 //F1_COND //Posições dos Itens (SD1) Private nIteProd := 2 //D1_COD Private nIteQtde := 3 //D1_QUANT Private nIteVUni := 4 //D1_VUNIT Private nIteTpES := 5 //D1_TES //Variáveis do ExecAuto Private aCabecSF1 := {} Private aItensSD1 := {} Private lMSHelpAuto := .T. Private lAutoErrNoFile := .T. Private lMsErroAuto := .F. Private cLog := "" Private cChaveSF1 := "" //Abre as tabelas que serão usadas DbSelectArea('SF1') SF1->(DbSetOrder(1)) //F1_FILIAL + F1_DOC + F1_SERIE + F1_FORNECE + F1_LOJA + F1_TIPO SF1->(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 := StrTokArr(cLinAtu, ";") //Se houver posições no array If Len(aLinha) > 0 //Se for cabeçalho If Upper(aLinha[nPosTip]) == "SF1" //Se tiver cabeçalho e itens, chama a rotina para acionar o ExecAuto fPreNota() //Zera as variáveis aCabecSF1 := {} aItensSD1 := {} cItem := StrTran(Space(TamSX3('D1_ITEM')[01]), ' ', '0') cChaveSF1 := "" //Se tiver o mesmo numero de colunas, adiciona no array da sf1, e monta a chave que será pesquisada no seek If Len(aLinha) == nCabCond //Transforma a data If "/" $ aLinha[nCabEmis] aLinha[nCabEmis] := cToD(aLinha[nCabEmis]) Else aLinha[nCabEmis] := sToD(aLinha[nCabEmis]) EndIf aAdd(aCabecSF1, {"F1_TIPO" , aLinha[nCabTipo] , Nil}) aAdd(aCabecSF1, {"F1_FORMUL" , aLinha[nCabForm] , Nil}) aAdd(aCabecSF1, {"F1_DOC" , aLinha[nCabDocu] , Nil}) aAdd(aCabecSF1, {"F1_SERIE" , aLinha[nCabSeri] , Nil}) aAdd(aCabecSF1, {"F1_EMISSAO" , aLinha[nCabEmis] , Nil}) aAdd(aCabecSF1, {"F1_FORNECE" , aLinha[nCabForn] , Nil}) aAdd(aCabecSF1, {"F1_LOJA" , aLinha[nCabLoja] , Nil}) aAdd(aCabecSF1, {"F1_ESPECIE" , aLinha[nCabEspe] , Nil}) aAdd(aCabecSF1, {"F1_COND" , aLinha[nCabCond] , Nil}) cChaveSF1 := FWxFilial("SF1") +; PadR(aLinha[nCabDocu], TamSX3("F1_DOC")[1], ' ') +; PadR(aLinha[nCabSeri], TamSX3("F1_SERIE")[1], ' ') +; PadR(aLinha[nCabForn], TamSX3("F1_FORNECE")[1], ' ') +; PadR(aLinha[nCabLoja], TamSX3("F1_LOJA")[1], ' ') +; PadR(aLinha[nCabTipo], TamSX3("F1_TIPO")[1], ' ') EndIf //Se for itens (e tiver todas as posições) ElseIf Upper(aLinha[nPosTip]) == "SD1" .And. Len(aLinha) == nIteTpES //Campos numéricos, retira ponto, transforma vírgula em ponto e converte para numérico aLinha[nIteQtde] := Alltrim(aLinha[nIteQtde]) aLinha[nIteQtde] := StrTran(aLinha[nIteQtde], ".", "") aLinha[nIteQtde] := StrTran(aLinha[nIteQtde], ",", ".") aLinha[nIteQtde] := Val(aLinha[nIteQtde]) aLinha[nIteVUni] := Alltrim(aLinha[nIteVUni]) aLinha[nIteVUni] := StrTran(aLinha[nIteVUni], ".", "") aLinha[nIteVUni] := StrTran(aLinha[nIteVUni], ",", ".") aLinha[nIteVUni] := Val(aLinha[nIteVUni]) //Adiciona no array de Itens cItem := Soma1(cItem) aLinhaSD1 := {} aAdd(aLinhaSD1, {"D1_ITEM" , cItem , Nil} ) aAdd(aLinhaSD1, {"D1_COD" , aLinha[nIteProd] , Nil} ) aAdd(aLinhaSD1, {"D1_QUANT" , aLinha[nIteQtde] , Nil} ) aAdd(aLinhaSD1, {"D1_VUNIT" , aLinha[nIteVUni] , Nil} ) aAdd(aLinhaSD1, {"D1_TOTAL" , aLinha[nIteQtde] * aLinha[nIteVUni] , Nil} ) aAdd(aLinhaSD1, {"D1_TES" , aLinha[nIteTpES] , Nil} ) aAdd(aItensSD1, aClone(aLinhaSD1)) EndIf EndIf EndDo //Chama novamente a rotina de pré-nota pois pode ser que sobrou um cabec e itens para processar fPreNota() End Transaction //Se tiver log, mostra ele If ! Empty(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 Return Static Function fPreNota() Local cPastaErro := "" Local cNomeErro := "" Local cTextoErro := "" Local aLogErro := {} Local nLinhaErro := 0 //Se tiver cabeçalho e itens If Len(aCabecSF1) > 0 .And. Len(aItensSD1) > 0 //Se conseguir posicionar na nota, grava no log que já existe If SF1->(MsSeek(cChaveSF1)) cLog += "- NF já existe na base, chave de pesquisa: " + cChaveSF1 + CRLF //Aciona o ExecAuto Else lMsErroAuto := .F. MSExecAuto({|x, y, z| MATA140(x, y, z)}, aCabecSF1, aItensSD1, 3) //Se houve erro, gera o log If lMsErroAuto cPastaErro := "\x_logs\" cNomeErro := "pre_nota_" + 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 NF, chave de pesquisa: " + cChaveSF1 + ", arquivo de log em '" + cPastaErro + cNomeErro + "' " + CRLF Else cLog += "- NF incluida como pré-nota, chave de pesquisa: " + cChaveSF1 + CRLF EndIf EndIf EndIf Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Como sempre, mais um excelente artigo.
Opa, obrigado pelo comentário e feedback Roberto.
Abraços.
Este artigo foi muito útil para nossa empresa, gostaria de saber se aceita proposta para desenvolver e incluir mais algumas necessidades nesse fonte
Boa tarde Leandro, tudo bem?
Claro, nós atendemos sob demanda, nos mande um email com sua necessidade, segue o link com o nosso contato: https://atiliosistemas.com/contato/
Abraços.
Bom dia Dan, tudo bem?
Achei esse vídeo porque é o fim para os meios que eu preciso rs… porém eu estive pensando em outra coisa, e não sei se já fez algo do tipo.
Tem conhecimento de algum ponto de entrada na MATA103/MATA140 onde eu posso trazer os itens de uma devolução porém todos deletados, para que eu possa desmarcar manualmente? No caso da devolução seria usando o Retornar (devolução de vendas).
Obrigado pelo post!
Boa noite Felipe, tudo joia graças a Deus e você?
Eu nunca precisei fazer um p.e. para esse caso. Tentei procurar e não consegui encontrar.
Caso não encontre, você pode utilizar o ChkExec e adicionar um atalho, por exemplo, um F8 ou F9, ai ao pressionar, ele excluiria tudo da grid para o usuário depois selecionar.
Grande abraço.
Fala Dan! Achei outra forma de fazer isso. O deletar é típico do aHeader, até aí ok.. mas pra validar os valores do aCols quando eu desmarco, precisei passar o MaFisDel ali pois ele não estava considerando pro F1_TOTAL e pra SF3 também.
Segue o que customizei:
User Function DeletaLinha
Local nX
If FwIsInCallStack(“SA103Devol”)
For nX := 1 to Len(aCols)
aCols[nX][Len(aHeader)+1] := .T.
MaFisDel(nX,aCols[nX][Len(aCols[nX])])
Next
EndIf
Return
Grande Felipe, tudo joia?
Opa, obrigado pelo feedback e pelo exemplo enviado.
Um grande abraço.