Importando arquivo texto utilizando o MSExecAuto MATA030 - Cadastro de Clientes


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 fuões espeficas, o que confere ao desenvolvedor apossibilidade de efetuar tratamentos espeficos antes da execã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"]importartxtsaiexecautomat03001 Tela inicial e parametros[/caption] [caption id="attachment_3137" align="aligncenter" width="345"]importartxtsaiexecautomat03002 Tela de processamento[/caption] [caption id="attachment_3140" align="aligncenter" width="438"]importartxtsaiexecautomat03003 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:

Tela inicial

#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

Processamento do arquivo texto e validações

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

Função para gravar erros encontrados

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

Função para mostrar o log em tela

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

Função para mostrar o log impresso

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