Rotina automática - MATA241


Dias atrás um amigo perguntou se era possível fazer importação de um arquivo texto no qual se era possível importar diversas linhas para a rotina movimentação interna modelo 2 (Movimentação Múltipla). Iremos usar o Ponto de Entrada da rotina MATA241 Sintaxe: MSExecAuto({|X,Y,Z| MATA241(X,Y,Z)}, aCabecalho, aItens, nOpção) Onde: aCabecalho = Array contendo os dados do cabeçalho aItens = Array contendo os dados do item nOpção = 3 para inclusão, 4 para alteração e 5 para exclusão. O processo de importação de um arquivo texto, continua sendo sempre o mesmo, um formato simples é no formato CSV separando por ponto e virgula cada coluna. Usando a função fOpen (https://www.blogadvpl.com/importando-arquivo-texto) para abrir o arquivo texto e a função ParamBox (https://www.blogadvpl.com/inputbox-no-protheus/) para mostrar a tela que irá selecionar o arquivo.

User Function AEST003
    Local cTitulo	:= "[AEST003] Importar Registros"
    Local nOpcao 	:= 0
    Local aButtons 	:= {}
    Local aSays    	:= {}
    Private cArea	:= GetArea()
    Private cPerg 	:= Padr("AEST003",10)
    Private lMsErroAuto := .F.
    Private lMsHelpAuto	:= .T.

    AADD(aSays,OemToAnsi("Esta rotina tem como objetivo de importar os produtos vindos de um arquivo CSV."))
    AADD(aSays,"")	
    AADD(aSays,OemToAnsi("Clique no botão PARAM para informar o arquivo que será importado."))
    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.,{||  ajustaSx1(cPerg)  } } )
    
    //Para mostrar uma mensagem na tela e as opções disponíveis para o usuário. (https://tdn.totvs.com/pages/viewpage.action?pageId=24346908)
    FormBatch( cTitulo, aSays, aButtons,,200,530 )

    if nOpcao = 1
        //Para montar uma barra de progresso vou usar a função Processa()
        Processa({|| AEST003I(MV_PAR01,MV_PAR02)},"Aguarde....")	
    endif
    
    RestArea(cArea)
Return
  Na função abaixo irei importar o arquivo texto e a gravação na tabela SD3 usando a rotina automática. O arquivo texto é bem simples, no exemplo o usuário passou a seguinte estrutura: Primeira linha será o cabeçalho com as colunas: filial; tipo de movimentação;centro de custo Da segunda linha em diante, está definido: produto; armazem; quantidade; endereço; número de série
Static Function AEST003I(cArquivo,cRenomear)
    Local cLinha     := ""
    Local nI         := 0
    Local nHdl 
    Local nTamArq
    Local nTamLinha
    Local nLinhas
    Local aDadCab	 := {}
    Local aDadItens	 := {}		
    Local nCont
    Local cErro		 := ""
    Local lAchou	 := .F.
    Local aCabecalho := {}
    Local aItens	 := {}
    Local cProduto	 := ""
    Local cLocal	 := ""
    Local nQtde		 := 0
    Local cEndereco  := ""
    Local cSerie	 := ""
    Local y
    Default cRenomear:= "1"
    
    cRenomear  := IIF(ValType(cRenomear)=="N",Str(cRenomear),cRenomear)

    IncProc("Lendo arquivo texto para inclusao..." + Time() )

    if (Upper(Right(Alltrim(cArquivo),4)) != ".CSV" )
        MsgStop("Apenas arquivos com extensão CSV são aceitos!"+CRLF+"Verifique o arquivo informado!","Atenção")		
        Return(U_AEST003())
    EndIf     

    if !File(cArquivo)
        MsgStop("O arquivo "+Alltrim(cArquivo)+" não existe, favor informar um arquivo existente!","Atenção")		
        Return(U_AEST003())
    EndIf     
    
    nHdl := fOpen(cArquivo)

    If nHdl == -1 
        IF FERROR()== 516 
            ALERT("Feche a planilha que gerou o arquivo.")
        EndIF
    EndIf
    
    If nHdl == -1
        MsgAlert("O arquivo de nome "+Alltrim(cArquivo)+" nao pode ser aberto! Verifique os parametros.","Atencao!")
        Return(U_AEST003())
    Endif

    FSEEK(nHdl,0,0)

    nTamArq:=FSEEK(nHdl,0,2)
    
    FSEEK(nHdl,0,0)
    
    fClose(nHdl)
    FT_FUse(cArquivo)  //abre o arquivo 
    FT_FGOTOP()         //posiciona na primeira linha do arquivo      
    nTamLinha := Len(FT_FREADLN()) //Ve o tamanho da linha
    FT_FGOTOP()
    
    nLinhas := nTamArq/nTamLinha
    
    ProcRegua(nLinhas)		                                                            

    aDadCab:={}	      
    aDadItens :={}	      
    nCont  := 0

    While !FT_FEOF()
       
       	IncProc('Validando Linha: ' + Alltrim(Str(nCont)) )
      
        clinha := FT_FREADLN() 

        if !empty(cLinha)
            if nCont==0
                //O usuario enviou o arquivo texto com o cabeçalho na primeira linha
                AADD(aDadCab,Separa(cLinha,";",.T.))            
            Else
                //O usuário enviou o arquivo texto com os itens começando da segunda linha em diante
                AADD(aDadItens,Separa(cLinha,";",.T.))	
            Endif
        endif			

        FT_FSKIP()
        nCont++
    EndDo

    FT_FUse()
    fClose(nHdl)
    
    cErro := ""
    
    if Len(aDadCab) == 0 .OR. Len(aDadItens) == 0
    	MsgInfo("Não há dados para serem importados!","ATENÇÃO")
        Return
    endif

    aCabecalho	:={}

    aadd(aCabecalho, { "D3_FILIAL"	, xFilial("SD3")	, NIL}) //01-FILIAL
    aadd(aCabecalho, { "D3_TM"		, aDadCab[1,1]		, NIL}) //02-TM
    aadd(aCabecalho, { "D3_EMISSAO"	, dDatabase			, NIL}) //03-EMISSAO
    aadd(aCabecalho, { "D3_CC"		, aDadCab[1,2]		, NIL}) //04-CENTRO DE CUSTO
    
    For nI := 1 to len(aDadItens)
        nColunas := 0
        
        For y := 1 to len(aDadItens[nI])
            nColunas += 1
        Next

        //guardei os dados do array em variaveis para facilitar a leitura do codigo
        cProduto := aDadItens[nI,1]				
        cLocal	 := aDadItens[nI,2]
        nQtde	 := Valor(aDadItens[nI,3])
        cEndereco:= aDadItens[nI,4]
        cSerie	 := iif(nColunas >=5,aDadItens[nI,5],"") //este campo não é obrigatório e por isso verifico se existe a coluna 5

        IncProc("Lendo " + Alltrim(cProduto) + "..."+time())

        dbSelectArea("SB1")
        SB1->(dbSetOrder(1))
        SB1->(dbGoTop())
        
        if SB1->(!dbSeek(xFilial("SB1")+cProduto))
            cErro += Alltrim(cProduto)+CRLF
            IncProc("Produto "+Alltrim(cProduto)+" não existe..."+time())
        Else		                                           

            IncProc("Validando " + Alltrim(cProduto) + "..."+time())
            
            lMsErroAuto	:=	.f.
            aAdd(aItens,	{	{"D3_COD"		, cProduto			, NIL},;	//01-Produto
                                {"D3_LOCAL"		, cLocal			, NIL},;	//02-Local
                                {"D3_QUANT"		, nQtde				, NIL},;	//03-Quantidade
                                {"D3_NUMSERI"	, cSerie			, NIL},;	//04-Numero de Serie
                                {"D3_LOCALIZ"	, cEndereco			, NIL}})	//05-Endereo
                                
            Endif
        Endif 	   
    Next nI

    if Len(aCabecalho) == 0 .OR. Len(aItens) == 0
    	MsgStop("Não há dados para serem importados!","ATENÇÃO")
        Return
    endif

    IncProc("Atualizando..."+time())
    lMsErroAuto	:=	.f.

    MSExecAuto({|X,Y,Z| MATA241(X,Y,Z)}, aCabecalho, aItens, 3)
    
    If lMsErroAuto
        MostraErro()
        DisarmTransaction()
    Else
        ConfirmSx8()

        if !Empty(cErro)
            MsgStop("Alguns produtos não puderam ser importados por não existirem na tabela padrão de produtos"+cErro,"Erro")
        else
            If(cRenomear=="1")
                fRename(cArquivo,StrTran(Lower(cArquivo),".csv",".processado"))
            Endif
            MsgInfo("Sucesso!","Atenção")	
        Endif
    EndIf	
            
Return
 
Static Function AjustaSx1(cPerg)
    Local aParamBox	:= {}
    Local lRet 		:= .F.

    aadd(aParamBox,{6,"Arquivo"	,Space(254),"@!","",".T.",80,.T.,"Arquivo .CSV |*.CSV","C:\LOCALDATA\",GETF_LOCALHARD+GETF_NETWORKDRIVE}) // MV_PAR01
    aadd(aParamBox,{2,"Renomear",Space(1)  ,{"1=Sim","2=Não"},80,".T.",.T.,".T."})		// MV_PAR02

    If ParamBox(aParamBox,"Parametros",/*aRet*/,/*bOk*/,/*aButtons*/,.T.,,,,cPerg,.T.,.T.)
        lRet := .T.
    EndIf
Return(lRet)