Importar arquivo texto é uma tarefa bem simples no Protheus, e a orientação é: use sempre em conjunto com o MSExecAuto para importar. Antes de criar uma rotina de importação verifique se a rotina padrão de cadastro a possui, como exemplo a rotina MATA030 - Cadastro padrão de clientes do sistema.Para quem não sabe o MSExecAuto, ou também conhecida como Rotina Automática, permite a execução derotinas do ambiente ERP Protheus por funções específicas, o que confere ao desenvolvedor apossibilidade de efetuar tratamentos específicos antes da execução da rotina padrão, e maisimportante, não perder nenhuma funcionalidade que a rotina padrão oferece. Permite via programação fazer a inclusão, alteração e a exclusão de registros dentro da tabela. [caption id="attachment_3136" align="aligncenter" width="1041"] Tela inicial e parametros[/caption] [caption id="attachment_3137" align="aligncenter" width="345"] Tela de processamento[/caption] [caption id="attachment_3140" align="aligncenter" width="438"] Tela de erros[/caption] A sintaxe para o cadastro de clientes do MSExecAuto: (http://tdn.totvs.com/display/public/PROT/MATA030+-+Cadastro+de+Clientes+ExecAuto) MSExecAuto({|x,y| mata030(x,y)},aArray,nOpcao) Onde: aArray = contempla os campos e os registros Exemplo: AADD(aCliente,{"A1_COD", "000001" NIL}) nOpcao = informa a opção que será executada 3 = inclusão 4 = alteração 5 = exclusão Então vamos ao que interessa:
#include "totvs.ch" #include "protheus.ch" User Function Exemp001() Local aArea := GetArea() Local cTitulo := "Importação Cadastro de Clientes" Local nOpcao := 0 Local aButtons := {} Local aSays := {} Local cPerg := "Exemp001" Private cArquivo:= "" Private oProcess Private lRenomear:= .F. Private lMsErroAuto := .F. ajustaSx1(cPerg) Pergunte(cPerg,.F.) AADD(aSays,OemToAnsi("Rotina para Importação de arquivo texto para tabela SA1")) AADD(aSays,"") AADD(aSays,OemToAnsi("Clique no botão PARAM para informar os parametros que deverão ser considerados.")) AADD(aSays,"") AADD(aSays,OemToAnsi("Após isso, clique no botão OK.")) AADD(aButtons, { 1,.T.,{|o| nOpcao:= 1,o:oWnd:End()} } ) AADD(aButtons, { 2,.T.,{|o| nOpcao:= 2,o:oWnd:End()} } ) AADD(aButtons, { 5,.T.,{| | pergunte(cPerg,.T.) } } ) FormBatch( cTitulo, aSays, aButtons,,200,530 ) if nOpcao = 1 cArquivo:= Alltrim(MV_PAR01) if Empty(cArquivo) MsgStop("Informe o nome do arquivo!!!","Erro") return Endif oProcess := MsNewProcess():New( { || Importa() } , "Importação de registros " , "Aguarde..." , .F. ) oProcess:Activate() EndIf RestArea(aArea) Return
Static Function Importa() Local cArqProc := cArquivo+".processado" Local cLinha := "" Local lPrim := .T. Local aCampos := {} Local aDados := {} Local aCliente := {} Local nCont := 1 Local nPosCod := 0 Local nPosLoja := 0 Local nPosNome := 0 Local nPosEst := 0 Local nPosCodMun := 0 Local nPessoa := 0 Private aErro := {} If !File(cArquivo) MsgStop("O arquivo " + cArquivo + " não foi encontrado. A importação será abortada!","[AEST904] - ATENCAO") Return EndIf FT_FUSE(cArquivo) //Abre o arquivo texto oProcess:SetRegua1(FT_FLASTREC()) //Preenche a regua com a quantidade de registros encontrados FT_FGOTOP() //coloca o arquivo no topo While !FT_FEOF() nCont++ oProcess:IncRegua1('Validando Linha: ' + Alltrim(Str(nCont))) cLinha := FT_FREADLN() cLinha := ALLTRIM(cLinha) If lPrim //considerando que a primeira linha são os campos do cadastros, reservar numa variavel aCampos := Separa(cLinha,";",.T.) lPrim := .F. Else// gravar em outra variavel os registros AADD(aDados,Separa(cLinha,";",.T.)) EndIf FT_FSKIP() EndDo FT_FUSE() //utilizaremos a aScan para localizar a posição dos campos na variavel que armazenará o nome dos campos nPosCod := aScan(aCampos,{ |x| ALLTRIM(x) == "A1_COD" }) nPosLoja := aScan(aCampos,{ |x| ALLTRIM(x) == "A1_LOJA" }) nPosNome := aScan(aCampos,{ |x| ALLTRIM(x) == "A1_NOME" }) nPosEst := aScan(aCampos,{ |x| ALLTRIM(x) == "A1_EST" }) nPosCodMun := aScan(aCampos,{ |x| ALLTRIM(x) == "A1_COD_MUN" }) nPessoa := aScan(aCampos,{ |x| ALLTRIM(x) == "A1_PESSOA" }) oProcess:SetRegua1(len(aDados)) //guardar novamente a quantidade de registros For i:=1 to Len(aDados) oProcess:IncRegua1("Importando clientes..."+aDados[i,nPosCod]+aDados[i,nPosLoja]) aCliente := {} dbSelectArea("SA1") dbSetOrder(1) dbGoTop() //Neste exemplo iremos incluir registros, portanto iremos validar se o mesmo não existe na tabela de clientes If !dbSeek(xFilial("SA1")+aDados[i,nPosCod]+aDados[i,nPosLoja]) oProcess:SetRegua2(len(aCampos)) For j:=1 to Len(aCampos) oProcess:IncRegua2('Processando coluna: ' + ALLTRIM(aCampos[j])) //Iremos verificar também se o campo existe, para evitar erros durante a importação //É importante tambem, validar o tipo que o campo é, pois quando importa um arquivo texto, o conteudo também será texto dbSelectArea("SX3") dbSetOrder(2) dbGoTop() If dbSeek(ALLTRIM(aCampos[j])) If ALLTRIM(aCampos[j]) != "A1_FILIAL" If ALLTRIM(aCampos[j]) == "A1_MUN" AADD(aCliente,{ALLTRIM(aCampos[j]), POSICIONE("CC2",1,xFilial("CC2")+aDados[i,nPosEst]+STRZERO(VAL(aDados[i,nPosCodMun]),5),"CC2_MUN"), NIL}) ElseIf ALLTRIM(aCampos[j]) == "A1_COD" AADD(aCliente,{ALLTRIM(aCampos[j]), STRZERO(VAL(aDados[i,j]),6), NIL}) ElseIf ALLTRIM(aCampos[j]) == "A1_LOJA" AADD(aCliente,{ALLTRIM(aCampos[j]), STRZERO(VAL(aDados[i,j]),2), NIL}) ElseIf ALLTRIM(aCampos[j]) == "A1_CGC" If aDados[i,nPessoa] == 'F' AADD(aCliente,{ALLTRIM(aCampos[j]), STRZERO(VAL(aDados[i,j]),11), NIL}) Else AADD(aCliente,{ALLTRIM(aCampos[j]), STRZERO(VAL(aDados[i,j]),14), NIL}) EndIf ElseIf ALLTRIM(aCampos[j]) == "A1_CODPAIS" AADD(aCliente,{ALLTRIM(aCampos[j]), STRZERO(VAL(aDados[i,j]),5), NIL}) ElseIf ALLTRIM(aCampos[j]) == "A1_COD_MUN" AADD(aCliente,{ALLTRIM(aCampos[j]), STRZERO(VAL(aDados[i,j]),5), NIL}) Else Do Case Case SX3->X3_TIPO == 'N' //numerico AADD(aCliente,{ALLTRIM(aCampos[j]), VAL(aDados[i,j]), NIL}) Case SX3->X3_TIPO == 'D' //data AADD(aCliente,{ALLTRIM(aCampos[j]), CTOD(aDados[i,j]), NIL}) Otherwise //outros AADD(aCliente,{ALLTRIM(aCampos[j]), aDados[i,j], NIL}) EndCase EndIF EndIf EndIf Next j lMsErroAuto := .F. //Utilizar o MsExecAuto para incluir registros na tabela de clientes, utilizando a opção 3 MSExecAuto({|x,y| mata030(x,y)},aCliente,3) //Caso encontre erro exibir na tela If lMsErroAuto MostraErro() MostraErro("\SYSTEM\LOG\",FUNNAME() + ".LOG") GravaErro(aDados[i,nPosCod],aDados[i,nPosLoja],aDados[i,nPosNome],NIL) DisarmTransaction() EndIf Else //Caso o registro exista, gravar o log GravaErro(aDados[i,nPosCod],aDados[i,nPosLoja],aDados[i,nPosNome],"O registro já está cadastrado!") EndIf Next i IF(MV_PAR02==1) If File(cArqProc) fErase(cArqProc) Endif fRename(Upper(cArquivo), cArqProc) Endif If Len(aErro) > 0 MostraLog() Else ApMsgInfo("Importação de clientes efetuada com sucesso!","SUCESSO") EndIf Return
Static Function GravaErro(cCod,cLoja,cNome,cMsg) Local cFile := "\SYSTEM\"+FUNNAME()+".LOG" Local cLine := "" DEFAULT cMsg := NIL If cMsg == NIL Begin Sequence IF !( lOk := File( cFile ) ) Break EndIF FT_FUSE(cFile) FT_FGOTOP() While !FT_FEOF() cLine += FT_FREADLN() + CHR(13)+CHR(10) FT_FSKIP() End While FT_FUSE() End Sequence cMsg := cLine EndIf AADD(aErro,{cCod,cLoja,cNome,cMsg}) Return
Static Function MostraLog() Local oDlg Local oFont Local cMemo := "" DEFINE FONT oFont NAME "Courier New" SIZE 5,0 DEFINE MSDIALOG oDlg TITLE "Importação Cadastros" From 3,0 to 400,417 PIXEL aCabec := {"Código","Loja","Nome"} cCabec := "{aErro[oBrw:nAT][1],aErro[oBrw:nAT][2],aErro[oBrw:nAT][3]}" bCabec := &( "{ || " + cCabec + " }" ) oBrw := TWBrowse():New( 005,005,200,090,,aCabec,,oDlg,,,,,,,,,,,,.F.,,.T.,,.F.,,,) oBrw:SetArray(aErro) oBrw:bChange := { || cMemo := aErro[oBrw:nAT][4], oMemo:Refresh()} oBrw:bLDblClick := { || cMemo := aErro[oBrw:nAT][4], oMemo:Refresh()} oBrw:bLine := bCabec @ 100,005 GET oMemo VAR cMemo MEMO SIZE 200,080 OF oDlg PIXEL oMemo:bRClicked := {||AllwaysTrue()} oMemo:lReadOnly := .T. oMemo:oFont := oFont oImprimir :=tButton():New(185,120,'Imprimir' ,oDlg,{|| fImprimeLog() },40,12,,,,.T.) oSair :=tButton():New(185,165,'Sair' ,oDlg,{|| ::End() },40,12,,,,.T.) ACTIVATE MSDIALOG oDlg CENTERED Return
Static Function fImprimeLog() Local oReport If TRepInUse() //verifica se relatorios personalizaveis esta disponivel oReport := ReportDef() oReport:PrintDialog() EndIf Return Static Function ReportDef() Local oReport Local oSection oReport := TReport():New(FUNNAME(),"Importação Cadastro de Fornecedores",,{|oReport| PrintReport(oReport)},"Este relatorio ira imprimir a relacao de erros encontrados durante o processo de importação dos dados.") oReport:SetLandscape() oSection := TRSection():New(oReport,,{}) TRCell():New(oSection,"CODIGO" ,,"Código") TRCell():New(oSection,"LOJA" ,,"Loja") TRCell():New(oSection,"NOME" ,,"Nome") TRCell():New(oSection,"DESCRI" ,,"Descrição do Erro") Return oReport Static Function PrintReport(oReport) Local oSection := oReport:Section(1) oReport:SetMeter(Len(aErro)) oSection:Init() For i:=1 to Len(aErro) If oReport:Cancel() Exit EndIf oReport:IncMeter() oSection:Cell("CODIGO"):SetValue(aErro[i,1]) oSection:Cell("CODIGO"):SetSize(20) oSection:Cell("LOJA"):SetValue(aErro[i,2]) oSection:Cell("LOJA"):SetSize(20) oSection:Cell("NOME"):SetValue(aErro[i,3]) oSection:Cell("NOME"):SetSize(50) oSection:Cell("DESCRI"):SetValue(aErro[i,4]) oSection:Cell("DESCRI"):SetSize(200) nTamLin := 200 nTab := 3 lWrap := .T. lPrim := .T. cObsMemo := aErro[i,4] nLines := MLCOUNT(cObsMemo, nTamLin, nTab, lWrap) For nCurrentLine := 1 to nLines If lPrim oSection:Cell("DESCRI"):SetValue(MEMOLINE(cObsMemo, nTamLin, nCurrentLine, nTab, lWrap)) oSection:Cell("DESCRI"):SetSize(300) oSection:PrintLine() lPrim := .F. Else oSection:Cell("CODIGO"):SetValue("") oSection:Cell("LOJA"):SetValue("") oSection:Cell("NOME"):SetValue("") oSection:Cell("DESCRI"):SetValue(MEMOLINE(cObsMemo, nTamLin, nCurrentLine, nTab, lWrap)) oSection:Cell("DESCRI"):SetSize(300) oSection:PrintLine() EndIf Next i oReport:SkipLine() Next i oSection:Finish() Return
Static Function ajustaSx1(cPerg) putSx1(cPerg, "01", "Arquivo" , "", "", "mv_ch1", "C", 99, 0, 0, "G", "", "DIR", "", "","mv_par01", "", "", "", "", "", "", "","", "", "", "", "", "", "", "", "", {"Informe o arquivo TXT que será","importado (Extensão CSV)",""}, {"","",""}, {"","",""}) PutSx1(cPerg, "02", "Renomear?", "", "", "mv_ch2", "N", 1, 0, 2, "C", "", "", "", "","mv_par02","Sim","Si","Yes","","Nao","No","No") Return