O processo de importação de um arquivo texto no Protheus não é lá um processo muito simples, mas não impossível de se fazer, o mais fácil é quando temos um arquivo com delimitadores, seja usando ponto e vírgula (;), ou usando o pipe (|), barra (/), entre outros caracteres. Agora importar um arquivo texto sem delimitadores, já torna o processo um pouco mais chato, mas também nada impossível de se fazer. Alguns colegas que estão começando sempre me perguntam, tem alguma forma mais fácil de se fazer? Digo que depende muito da lógica a ser usada, mas os comandos serão sempre os mesmo. Neste artigo, irei demonstrar um exemplo de importação de arquivo texto sem delimitadores para que você possa utilizá-lo no seu dia a dia, mas para aqueles que fazem isso e tiver um exemplo mais fácil, compartilhe conosco, toda dica é bem vinda. Primeiramente irei mostrar o formato do arquivo texto, neste exemplo será um bem simples. (Arquivo exemplo) Tela inicial: colocarei todos os campos contidos no meu arquivo texto. Utilizarei os componentes: Say() = Exibe textos em uma tela de interface com o usuário MsGet() = Permite que o usuário digite informações na tela, conforme a necessidade da aplicação. TCBrowse() = Cria um objeto do tipo grade. Button() = Criar um botão na tela para que o usuário interaja com a aplicação. Desenhei a tela utilizando o programa GAIA 2010. Para selecionar o arquivo, usarei a função cGetFile (Apresenta uma janela com os diretórios disponíveis, na estação e no servidor, e retorna o nome do item.) , para saber mais sobre esta função consulte o TDN (http://tdn.totvs.com/display/tec/cGetFile). Após selecionar o arquivo e confirmá-lo, o arquivo é importado para a tela criada. Você poderia perfeitamente importar diretamente numa tabela. Visualizando assim, parece tudo simples não é mesmo?
#Include 'Protheus.ch' User Function exemplo3() /*Declaração das variáveis locais*/ Local oButton1 Local oButton2 Local oSim := LoadBitmap(GetResources(), "ENABLE") Local oNao := LoadBitmap(GetResources(), "DISABLE") Local oCEP Local oCidade Local oCNPJ Local oComplemento Local oContato Local oEmail Local oEmissao Local oEmpresa Local oEndereco Local oEntrega Local oMoeda Local oPagto Local oPedido Local oUF /*Declaração das variáveis privadas*/ Private oPedidos Private cPedido := Space(06) Private cCNPJ := Space(14) Private cCEP := Space(8) Private cEmpresa := Space(30) Private cEndereco := Space(100) Private cCidade := Space(30) Private cUF := Space(2) Private cContato := Space(30) Private cEmail := Space(200) Private dEmissao := CTOD("//") Private dEntrega := CTOD("//") Private cMoeda := Space(30) Private cPagto := Space(30) Private cComplemento:= Space(100) Private aPedidos := {} /*Declaração das variáveis estáticas*/ Static oDlg DEFINE MSDIALOG oDlg TITLE "Importando arquivo texto não delimitado" FROM 000, 000 TO 400, 500 PIXEL @ 003, 005 SAY oSay1 PROMPT "Pedido" SIZE 025, 007 OF oDlg PIXEL @ 011, 005 MSGET oPedido VAR cPedido SIZE 036, 010 OF oDlg PIXEL @ 003, 046 SAY oSay2 PROMPT "CNPJ" SIZE 025, 007 OF oDlg PIXEL @ 011, 046 MSGET oCNPJ VAR cCNPJ SIZE 061, 010 OF oDlg PIXEL @ 003, 112 SAY oSay3 PROMPT "Empresa" SIZE 025, 007 OF oDlg PIXEL @ 011, 112 MSGET oEmpresa VAR cEmpresa SIZE 131, 010 OF oDlg PIXEL @ 024, 005 SAY oSay4 PROMPT "Endereço" SIZE 025, 007 OF oDlg PIXEL @ 031, 005 MSGET oEndereco VAR cEndereco SIZE 101, 010 OF oDlg PIXEL @ 024, 112 SAY oSay5 PROMPT "Cidade" SIZE 025, 007 OF oDlg PIXEL @ 031, 112 MSGET oCidade VAR cCidade SIZE 110, 010 OF oDlg PIXEL @ 024, 227 SAY oSay6 PROMPT "UF" SIZE 014, 007 OF oDlg PIXEL @ 031, 227 MSGET oUF VAR cUF SIZE 016, 010 OF oDlg PIXEL @ 044, 005 SAY oSay7 PROMPT "CEP" SIZE 025, 007 OF oDlg PIXEL @ 051, 005 MSGET oCEP VAR cCEP SIZE 036, 010 OF oDlg PIXEL @ 044, 046 SAY oSay8 PROMPT "Contato" SIZE 025, 007 OF oDlg PIXEL @ 051, 046 MSGET oContato VAR cContato SIZE 061, 010 OF oDlg PIXEL @ 044, 112 SAY oSay9 PROMPT "E-mail" SIZE 025, 007 OF oDlg PIXEL @ 051, 112 MSGET oEmail VAR cEmail SIZE 131, 010 OF oDlg PIXEL //Usando o TCBrowse para gerenciar individualmente cada coluna oPedidos := TCBrowse():New(067, 005,238, 060,,,,oDlg,,,,,,,,,,,,.F.,,.T.,,.F.,,,) oPedidos:AddColumn(TCColumn():New(" " , {|| If(aPedidos[oPedidos:nAt,01],oSim,oNao) },,,,,,.T.,.F.,,,,.F., ) ) oPedidos:AddColumn(TCColumn():New("Codigo" , {|| aPedidos[oPedidos:nAt,02]},"@!",,,"CENTER", 025,.F.,.F.,,{|| .F. },,.F., ) ) oPedidos:AddColumn(TCColumn():New("Descrição" , {|| aPedidos[oPedidos:nAt,03]},"@!",,,"LEFT", 040,.F.,.F.,,{|| .F. },,.F., ) ) oPedidos:AddColumn(TCColumn():New("No.Serie" , {|| aPedidos[oPedidos:nAt,04]},"@!",,,"LEFT", 080,.F.,.F.,,{|| .F. },,.F., ) ) oPedidos:AddColumn(TCColumn():New("Qtde" , {|| aPedidos[oPedidos:nAt,05]},"@E 999,999,999.99",,,"RIGHT", 040,.F.,.F.,,{|| .F. },,.F., ) ) oPedidos:AddColumn(TCColumn():New("Valor" , {|| aPedidos[oPedidos:nAt,06]},"@E 999,999,999.99",,,"RIGHT", 040,.F.,.F.,,{|| .F. },,.F., ) ) oPedidos:AddColumn(TCColumn():New("Total" , {|| aPedidos[oPedidos:nAt,07]},"@E 999,999,999.99",,,"RIGHT", 040,.F.,.F.,,{|| .F. },,.F., ) ) oPedidos:AddColumn(TCColumn():New("Observação" , {|| aPedidos[oPedidos:nAt,08]},"@!",,,"LEFT", 120,.F.,.F.,,{|| .F. },,.F., ) ) oPedidos:SetArray(aPedidos) //Define um array para o browse oPedidos:bWhen := { || Len(aPedidos) > 0 } //Se o array estiver vazio, o browse fica desabilitado oPedidos:Refresh() @ 130, 005 SAY oSay10 PROMPT "Cond.Pagto" SIZE 035, 007 OF oDlg PIXEL @ 138, 005 MSGET oPagto VAR cPagto SIZE 113, 010 OF oDlg PIXEL @ 130, 122 SAY oSay11 PROMPT "Emissão" SIZE 025, 007 OF oDlg PIXEL @ 138, 122 MSGET oEmissao VAR dEmissao SIZE 041, 010 OF oDlg PIXEL @ 130, 169 SAY oSay12 PROMPT "Entrega" SIZE 025, 007 OF oDlg PIXEL @ 138, 169 MSGET oEntrega VAR dEntrega SIZE 041, 010 OF oDlg PIXEL @ 130, 214 SAY oSay13 PROMPT "Moeda" SIZE 020, 007 OF oDlg PIXEL @ 138, 214 MSGET oMoeda VAR cMoeda SIZE 030, 010 OF oDlg PIXEL @ 153, 005 SAY oSay14 PROMPT "Complemento:" SIZE 038, 007 OF oDlg PIXEL @ 160, 005 MSGET oComplemento VAR cComplemento SIZE 238, 010 OF oDlg PIXEL //Para o processamento, utilizarei a função Processa() //A função Processa() exibe um diálogo onde a execução //de um processo pode ser monitorada através da régua de progressão. @ 181, 155 BUTTON oButton1 PROMPT "Importar" SIZE 037, 012 OF oDlg ACTION Processa({|| Importar()},"Aguarde...") PIXEL @ 181, 207 BUTTON oButton2 PROMPT "Fechar" SIZE 037, 012 OF oDlg ACTION oDlg:End() PIXEL ACTIVATE MSDIALOG oDlg CENTERED Return //Função para importar o arquivo texto. Static Function Importar() Local cArquivo := cGetFile("Arquivo TXT (*.TXT) |*.TXT|","Selecione o Arquivo...",2,,.T.,GETF_LOCALHARD+GETF_NETWORKDRIVE) Local aItens := {} Local aFornece:= {} Local aRodape := {} Local nCont := 0 Local i := 0 Local nLinhas := 0 Local _aStr := {{"Texto","C",1000,0}} Local _cTmp := CriaTrab(NIL,.F.) Local nQtde := 0 Local nValor := 0 Local nTotal := 0 if !file(Alltrim(cArquivo)) Alert("Arquivo "+Alltrim(cArquivo)+" não existe!"+CRLF+"Abortando importação!") Return Endif //Criarei uma tabela temporária para armazenar cada linha do meu txt, poderia usar um array //mas irei motrar tambem como criar uma tabela temporária //dbCreate = Define uma nova tabela ou um novo arquivo do tipo tabela e sua estrutura (campos) dbCreate(_cTmp,_aStr) //Verifico se a área de trabalho está aberta, se estiver irei fechar, isso evita que o sistema //dê um erro informando que a área ja está aberta IF SELECT("TRB") # 0 TRB->(dbCloseArea()) ENDIF //DBUseArea = Abre uma tabela de dados na área de trabalho atual ou na primeira área de trabalho disponível. DBUseArea(.T.,,_cTmp,"TRB",.F.,.F.) //GetSrvProfString = Recupera o conteúdo de uma chave de configuração, do ambiente em uso, no arquivo de //configuração (.INI) do TOTVS Application Server. if AT(":\",cArquivo)>0 CpyT2S( cArquivo, GetSrvProfString("Startpath","") ) Else CpyT2S( cArquivo, GetSrvProfString("Startpath","") ) endif //Append From = Utilização do comando 'APPEND FROM ... SDF', para importação de dados de um arquivo texto Append From &cArquivo SDF //Vou para o inicio do arquivo TRB->(dbGoTop()) //conto quantas linhas eu tenho nLinhas:=TRB->(RecCount()) //Monto minha regua de processamento com a quantidade de linhas encontradas ProcRegua(nLinhas) //Limpo a variavel que irá receber os dados aPedidos:={} //Inicio a leitura da minha tabela, enquanto não for o final dela While TRB->(!Eof()) nCont++ If lEnd MsgInfo("Cancelado!","Fim") exit Endif IF nCont > nLinhas exit endif //IncProc = informa o texto que irá ser apresentado na tela de processamento IncProc("Lendo arquivo texto...Linha "+Alltrim(str(nCont))) //Recebo o conteudo do meu texto cLinha := ALLTRIM(UPPER(TRB->Texto)) if !empty(cLinha) /* Neste exemplo, o meu arquivo texto possui um campo inicial que identifica o que ele é: Linha que começa com 1 = Cabeçalho Linha que começa com 2 = Itens Linha que começa com 3 = Rodapé */ if Substr(cLinha,1,1)=="1" //aFornece[1][1] = PEDIDO //Tamanho: 6 //aFornece[1][2] = CNPJ //Tamanho: 11 //aFornece[1][3] = NOMEDAEMPRESA //Tamanho: 35 //aFornece[1][4] = ENDERECO //Tamanho: 30 //aFornece[1][5] = CIDADE //Tamanho: 18 //aFornece[1][6] = UF //Tamanho: 2 //aFornece[1][7] = CEP //Tamanho: 8 //aFornece[1][8] = CONTATO //Tamanho: 21 //aFornece[1][9] = EMAIL //Tamanho:100 aadd(aFornece,{Substr(cLinha, 2, 6),; Substr(cLinha, 8, 11),; Substr(cLinha, 22, 35),; Substr(cLinha, 58, 30),; Substr(cLinha, 89, 18),; Substr(cLinha,108, 2),; Substr(cLinha,110, 8),; Substr(cLinha,118, 21),; Substr(cLinha,140,100)}) Elseif Substr(cLinha,1,1)=="2" //aItens[1][1] = CODIGO //Tamanho: 6 //aItens[1][2] = DESCRICAO //Tamanho: 25 //aItens[1][3] = NUMEROSERIE //Tamanho: 22 //aItens[1][4] = QTDE //Tamanho: 10 //aItens[1][5] = VALOR //Tamanho: 10 //aItens[1][6] = OBSERVACAO //Tamanho:100 aadd(aItens,{ Substr(cLinha, 2, 6),; Substr(cLinha, 8, 25),; Substr(cLinha,34, 22),; Substr(cLinha,57, 10),; Substr(cLinha,67, 10),; Substr(cLinha,77,100)}) Elseif Substr(cLinha,1,1)=="3" //aItens[1][1] = PAGTO //Tamanho: 17 //aItens[1][2] = EMISSAO //Tamanho: 10 //aItens[1][3] = ENTREGA //Tamanho: 10 //aItens[1][4] = COMPLEMENTO //Tamanho: 75 //aItens[1][5] = MOEDA //Tamanho: 30 aadd(aRodape,{Substr(cLinha, 2,17),; Substr(cLinha, 20,10),; Substr(cLinha, 30,10),; Substr(cLinha, 40,75),; Substr(cLinha,116,30)}) Endif endif DbSkip() EndDo //Fecho a área aberta TRB->(dbCloseArea()) //Apago o arquivo temporario gerado para que não fique lixo no sistema Ferase(_cTmp+".DBF") //Começo a popular os campos e o browse if len(aFornece) > 0 M->cPedido := aFornece[1][1] M->cCNPJ := aFornece[1][2] M->cEmpresa := aFornece[1][3] M->cEndereco := aFornece[1][4] M->cCidade := aFornece[1][5] M->cUF := aFornece[1][6] M->cCEP := aFornece[1][7] M->cContato := aFornece[1][8] M->cEmail := aFornece[1][9] Endif if len(aRodape) > 0 M->cPagto := aRodape[1][1] M->cComplemento := aRodape[1][4] M->cMoeda := aRodape[1][5] //como o campo é do tipo data, irei transformar de //caracter para data usando o comando CTOD M->dEmissao := CTOD(aRodape[1][2]) M->dEntrega := CTOD(aRodape[1][3]) Endif //Inicio a leitura dos itens que irão popular o meu browse For i := 1 to len(aItens) IncProc("Inserindo item "+ Alltrim(aItens[i,1])+"...") //Convertendo texto para valores, utilizo a função VAL() nQuant := Val(Substr(aItens[i,4],1,8)+"."+ Substr(aItens[i,4],9,2)) nValor := Val(Substr(aItens[i,5],1,8)+"."+ Substr(aItens[i,5],9,2)) nTotal := nQuant * nValor aadd(aPedidos,{ .T.,; //01 - Legenda aItens[i][1],; //02 - Codigo aItens[i][2],; //03 - Descricao aItens[i][3],; //04 - No.Serie nQuant,; //05 - Quantidade nValor,; //06 - Valor nTotal,; //07 - Total aItens[i][6]; //08 - Observação }) Next //Populo o browse com os dados do array oPedidos:SetArray(aPedidos) //Elimino o arquivo texto que importei Ferase(GetSrvProfString("Startpath","")+cArquivo) Return