Página 1 de 2

Importar arquivo CSV para DBF

Enviado: 24 Jun 2015 16:32
por marcos.gurupi
Caro Jairo, preciso ler um arquivo CSV e gravar em um DBF mas o arquivo CSV tem mais campos do que o DBF. O exemplo q tem aqui o CSV eh identico ao DBF. Como faria para converter o CVS lendo apenas os campos q desejo ?

O CSV:

Código: Selecionar todos

PlanilhaID; Usuario; Cartorio; DataLivroDiario; Dia; Mes; Ano; Competencia; QTD; Conta; Referencia; De_Para_Referencia; Ato_Historico; Receita; Despesa; Despesas_Dedutiveis; Despesas_nao_Dedutiveis; Total_de_Receitas; Total_de_Despesas; Resultado 


O DBF:

Código: Selecionar todos

CODIGO = ID 
TIPO = CONSTANTE "ENTRADA" 
DATALAN = DataLivroDiario 
NCONTA = Uma combinacao de  Conta+Referencia 
CADHIST = Conta 
HISTORICO = De_Para_Referencia 
VALOR = Receita 
Observe que preciso somente de alguns campos do CSV e ai q estah me complicando.

Marcos Roberto
NetService Software

Importar arquivo CSV para DBF

Enviado: 24 Jun 2015 19:35
por Itamar M. Lins Jr.
Quem cria o CSV ?
Se for planilha do EXCEL pode salvar em DBF.
ou
Neste caso a solução é importar duas vezes. a) Para um DBF temporário e depois p/ b) DBF final.

Saudações,
Itamar M. Lins Jr.

Importar arquivo CSV para DBF

Enviado: 24 Jun 2015 21:21
por marcos.gurupi
Quem cria o CSV eh outro sistema. Entaum vou ter q fazer isso msm. Importar para um dbf temporario e depois para o dbf definitivo. Obr pela ideia amigo!

Importar arquivo CSV para DBF

Enviado: 24 Jun 2015 22:33
por Itamar M. Lins Jr.
Ola!
Pode ajudar no desempenho trabalhar com DBF temporário em memória.

Código: Selecionar todos

Function Importar_CSV
LOCAL aDBStrut := {{...
...
dbDrop("mem:"+cArqTmp,,"DBFCDX") //Apaga DBF na memória se existir
DbCreate("mem:"+cArqTmp,aDbStrut,'DBFCDX',.T.,"tmp") //Cria e abre DBF temporário
Append from cArqCSV DELIMITED WITH "," //Importar
DbSelectArea(cAlias) //Selecionar seu DBF
Do While ... //Importar p/ seu DBF
...
Nota, neste caso não precisa da rotina para ler o arquivo CSV, será transparente.

Saudações,
Itamar M. Lins Jr.

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 11:26
por marcos.gurupi
Obrigado por responder Itamar. Segue abaixo o resultado do codigo q me passou:

Codigo:

Código: Selecionar todos

Function ConverteCVStoDBF()
						  
LOCAL aDBStrut := {}
//Local cArqTmp :=alltrim(ptmp)+"TMP"+STRZERO(SECONDS(),5,0)
Local cArqTmp :="TMP"+STRZERO(SECONDS(),5,0)
Local cArqDes :=""
Local cArqCSV :=""

cArqCSV := SelectFile( "Arquivo CSV", "*.CSV")
cArqDes := SelectFile( "Arquivo DBF Destino", "MOVIM01.DBF")

MsgRun("Exportando dados de "+cArqCSV+" -> "+cArqDes)

AADD(aDBStrut,{ "PlanID", "C", 5, 0 })  
AADD(aDBStrut,{ "Usuario", "C", 1, 0 })  
AADD(aDBStrut,{ "Cartorio", "C", 1, 0 }) 
AADD(aDBStrut,{ "DtLivro", "C", 8, 0 }) 
AADD(aDBStrut,{ "Dia", "C", 2, 0 }) 
AADD(aDBStrut,{ "Mes", "C", 2, 0 }) 
AADD(aDBStrut,{ "Ano", "C", 4, 0 }) 
AADD(aDBStrut,{ "Competen", "C", 10, 0 }) 
AADD(aDBStrut,{ "Quant", "C", 05, 0 }) 
AADD(aDBStrut,{ "Conta", "C", 10, 0 }) 
AADD(aDBStrut,{ "Referenc", "C", 20, 0 }) 
AADD(aDBStrut,{ "De_Para", "C", 20, 0 }) 
AADD(aDBStrut,{ "Ato_Histor", "C", 20, 0 }) 
AADD(aDBStrut,{ "Receita", "C", 10, 0 })           
AADD(aDBStrut,{ "Despesa", "C", 10, 0 })           
AADD(aDBStrut,{ "Despesa_d", "C", 10, 0 })           
AADD(aDBStrut,{ "Despesa_d", "C", 10, 0 })           
AADD(aDBStrut,{ "Despesand", "C", 10, 0 })           
AADD(aDBStrut,{ "Tot_Receit", "C", 10, 0 })           
AADD(aDBStrut,{ "Tot_Despes", "C", 10, 0 })           
AADD(aDBStrut,{ "Resultado", "C", 10, 0 })           

Use (cArqDes) NEW Share Alias "ArqDes"

DbDrop("mem:"+cArqTmp,,"DBFCDX") //Apaga DBF na memória se existir
DbCreate("mem:"+cArqTmp,aDbStrut,'DBFCDX',.T.,"tmp") //Cria e abre DBF temporário
Append from (cArqCSV) DELIMITED WITH ";" //Importar

Dbgotop()
Do While !Eof()
	MsgInfo("dt.Lanc: "+SUBSTR(TMP->DtLivro,7,2)+"/"+SubStr(TMP->DtLivro,5,2)+"/"+SubStr(TMP->DtLivro,1,4)+chr(10)+chr(13)+;
           "nConta.: "+Tmp->Conta+chr(10)+chr(13)+;
           "Quant..: "+Tmp->Quant+chr(10)+chr(13)+;
           "Ato_His: "+Tmp->Ato_Histor+chr(10)+chr(13)+;
           "Conta..: "+Tmp->Conta+chr(10)+chr(13)+;
           "De_Para: "+Tmp->De_Para+chr(10)+chr(13)+;
           "Receita: "+Tmp->Receita)
	//Select("ArqDes")
	//DbAppend()
	//Replace Codigo     with LastRec()
	//Replace Tipo       with "ENTRADA"
	//Replace DataLan    with CTOD(SUBSTR(TMP->DtLivro,7,2)+"/"+SubStr(TMP->DtLivro,5,2)+"/"+SubStr(TMP->DtLivro,1,4))
	//Replace nConta     with Val(Tmp->Conta)
	//Replace Quant      with Val(Tmp->Quant)
	//Replace Descricao  with Tmp->Ato_Histor
	//Replace CodHist    with Val(Tmp->Conta)
	//Replace Historic   with Tmp->De_Para
	//Replace Valor      with Val(Tmp->Receita)
	//Select("TMP")
	DbSkip()
Enddo
Fim_Run()
Return .T.
Como nao estava incluindo nada eu peguei o DBF TEMPORARIO O resultado eh esse:

http://screencast.com/t/rm75c1QKUGq
Imagem

Entaum como percebe nao estah incluindo nada do arquivo CSV no DBF temporario.

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 12:54
por marcos.gurupi
Segue o arquivo.

Marcos Roberto.

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 15:07
por Euclides
Olá Marcos.
Esse negocio de DELIMITED é fogo...
A maneira mais fácil de resolver isso é:
1 - Abrir o arquivo CSV com um editor de texto
2 - trocar todas as vírgulas por um outro caracter: @
3 - trocar todos os ; por vírgula
4 - trocar todos os @ por um outro caracter: talvez ;
5 - corrigir a definição do DBF do programa

Código: Selecionar todos

AADD(aDBStrut,{ "PlanID", "C", 3, 0 })
AADD(aDBStrut,{ "Usuario", "C", 18, 0 })
AADD(aDBStrut,{ "Cartorio", "C", 90, 0 })
AADD(aDBStrut,{ "DtLivro", "C", 8, 0 })
AADD(aDBStrut,{ "Dia", "C", 2, 0 })
AADD(aDBStrut,{ "Mes", "C", 2, 0 })
AADD(aDBStrut,{ "Ano", "C", 4, 0 })
AADD(aDBStrut,{ "Competen", "C", 10, 0 })
AADD(aDBStrut,{ "Quant", "C", 05, 0 })
AADD(aDBStrut,{ "Conta", "C", 13, 0 })
AADD(aDBStrut,{ "Referenc", "C", 20, 0 })
AADD(aDBStrut,{ "De_Para", "C", 20, 0 })
AADD(aDBStrut,{ "Ato_Histor", "C", 120, 0 })
AADD(aDBStrut,{ "Receita", "C", 10, 0 })
AADD(aDBStrut,{ "Despesa", "C", 10, 0 })
AADD(aDBStrut,{ "Despesa_D", "C", 10, 0 })
AADD(aDBStrut,{ "Despesa_N", "C", 10, 0 })
AADD(aDBStrut,{ "Tot_Receit", "C", 10, 0 })
AADD(aDBStrut,{ "Tot_Despes", "C", 10, 0 })
AADD(aDBStrut,{ "Resultado", "C", 10, 0 })
no programa:

Código: Selecionar todos

   DbCreate(cArqTmp, aDbStrut)
   USE &cArqTmp
   Append from (cArqCSV) DELIMITED 
(a essa altura do campeonato, poco estou ligando para arquivos em memória ou temporários)
6 - Depois, é só fazer um APPEND para o DBF que precisar.
Acho que vai funcionar (comigo funcionou...).
T+, Euclides

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 17:46
por marcos.gurupi
Obrigado por responder.

Ocorre q o arquivo CSV eh exportado por outro aplicativo e o meu importaria para o DBF, entaum imagina toda importacao o usuario fazer essa troca.

Outra solucao eh importar o XLS, afinal o outro software tb exporta arquivo do tipo XLS. Estou lutando aqui com um exemplo daqui do forum para importar XLS para EXCEL.

Vlw

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 19:04
por Itamar M. Lins Jr.
Esse negocio de DELIMITED é fogo...
É, mas temos que resolver os problemas e não fugir deles, acredito que se fosse um erro o pessoal(gurus) teriam consertado.
Eu postei lá GIT abri um issue, e veio a resposta.
Eu vejo que é um erro do clipper, e o harbour tem o mesmo problema por causa da compatibilidade.

O pulo do gato!
Append from (cArqCSV) DELIMITED WITH ({,";"})

Código: Selecionar todos

DbDrop("mem:"+cArqTmp,,"DBFCDX") //Apaga DBF na memória se existir
DbCreate("mem:"+cArqTmp,aDbStrut,'DBFCDX',.T.,"tmp") //Cria e abre DBF temporário
Append from (cArqCSV) DELIMITED WITH ({,";"}) //Import
tmp->(DbGoTop())
browse()
Tem outra forma usando uma função chamada list2array, depois eu coloco aqui.

Saudações,
Itamar M. Lins Jr.

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 19:35
por marcos.gurupi
Isso msm amigo!

Se funcionou ai entaum pq n funcionaria aqui.

Obrigado.
:-Y
:{ :{

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 19:51
por Itamar M. Lins Jr.
Outra forma mais Smart!!!
Transforma o texto em ARRAY ai é so jogar no DBF, não precisa do temporário!

Código: Selecionar todos

REQUEST DBFCDX
Function Main
LOCAL aDBStrut := {}
Local cArqTmp :="TMP"+STRZERO(SECONDS(),5,0)
Local cArqCSV :="LivroDiario20150622.csv"
RDDSetDefault("DBFCDX")
cTexto := memoread("LivroDiario20150622.csv")
cTexto := StrTran(cTexto,hb_eol(),";") //precisa disso p/ trocar hb_eol() por ';' final da linha
aText := ListToArray(cTexto,";") //Transforma qualquer texto em array...
nTReg := mlcount(cTexto,500) //Total de linhas p/ importar!!
//alert(str(nTReg))
alert(hb_valtoexp(aText))

AADD(aDBStrut,{ "PlanID", "C", 5, 0 }) 
AADD(aDBStrut,{ "Usuario", "C", 1, 0 }) 
AADD(aDBStrut,{ "Cartorio", "C", 1, 0 }) 
AADD(aDBStrut,{ "DtLivro", "C", 8, 0 }) 
AADD(aDBStrut,{ "Dia", "C", 2, 0 }) 
AADD(aDBStrut,{ "Mes", "C", 2, 0 }) 
AADD(aDBStrut,{ "Ano", "C", 4, 0 }) 
AADD(aDBStrut,{ "Competen", "C", 10, 0 }) 
AADD(aDBStrut,{ "Quant", "C", 05, 0 }) 
AADD(aDBStrut,{ "Conta", "C", 10, 0 }) 
AADD(aDBStrut,{ "Referenc", "C", 20, 0 }) 
AADD(aDBStrut,{ "De_Para", "C", 20, 0 }) 
AADD(aDBStrut,{ "Ato_Histor", "C", 20, 0 }) 
AADD(aDBStrut,{ "Receita", "C", 10, 0 })     
AADD(aDBStrut,{ "Despesa", "C", 10, 0 })     
AADD(aDBStrut,{ "Despesa_d", "C", 10, 0 })     
AADD(aDBStrut,{ "Despesa_n", "C", 10, 0 })     
AADD(aDBStrut,{ "Tot_Receit", "C", 10, 0 })     
AADD(aDBStrut,{ "Tot_Despes", "C", 10, 0 })     
AADD(aDBStrut,{ "Resultado", "C", 10, 0 })     

DbDrop("mem:"+cArqTmp,,"DBFCDX") //Apaga DBF na memória se existir
DbCreate("mem:"+cArqTmp,aDbStrut,'DBFCDX',.T.,"tmp") //Cria e abre DBF temporário
//Append from (cArqCSV) DELIMITED WITH ({,";"}) //Import
//tmp->(DbGoTop())

nText := len(aText)
y:=0
For N:=1 to nTReg
   tmp->(DbAppend())
   tmp->PlanId     := aText[++y]
   tmp->Usuario    := aText[++y]
   tmp->Cartorio   := aText[++y]
   tmp->DtLivro    := aText[++y]
   tmp->Dia        := aText[++y]
   tmp->Mes        := aText[++y]
   tmp->Ano        := aText[++y]
   tmp->Competen   := aText[++y]
   tmp->Quant      := aText[++y]
   tmp->Conta      := aText[++y]
   tmp->Referenc   := aText[++y]
   tmp->De_Para    := aText[++y]
   tmp->Ato_Histor := aText[++y]
   tmp->Receita    := aText[++y]
   tmp->Despesa    := aText[++y]
   tmp->Despesa_d  := aText[++y]
   tmp->Despesa_n  := aText[++y]
   tmp->Tot_Receit := aText[++y]
   tmp->Tot_Despes := aText[++y]
   tmp->Resultado  := aText[++y]
Next

browse()
cls

/*----------------------------------------------------------------------------
 Function: ListToArray
------------------------------------------------------------------------------
 Purpose:  Convert a delimited string to an array
------------------------------------------------------------------------------
 Parms:    (1) The string to be parsed (may contain several delimiters)
           (2) The delimiter character (defaults to ",")
           (3) An option string, indicating how each element is trimmed etc
                 N - No trimming of elements (by default, blanks are trimmed)
                 D - If string is empty, returns {""} i.e. an array with one
                     dummy element.  Default is to return an empty array {}.
------------------------------------------------------------------------------
 Returns:  An array, with each element containing a segment of the string
------------------------------------------------------------------------------
 Notes:    Examples of usage:
             aRes := ListToArray("AB, BC,CD ")    // Result: {"AB","BC","CD"}
             aRes := ListToArray("A, B, C ",,"N") // Result: {"A"," B"," C "}
             aRes := ListToArray("A; B; C",";")   // Result: {"A","B","C"}
             aRes := ListToArray("   ")           // Result: {}
             aRes := ListToArray("   ","D")       // Result: {""}
----------------------------------------------------------------------------*/

FUNCTION ListToArray ( cList, cDelimiter, cOptions )

local  nPos
local  aList := {}        // Define an empty array
local  cToken             // Token in the list
local  lMore := .T.
local  lTrim := .T.
local  nDelimLen

hb_DEFAULT ( @cDelimiter, "," )
nDelimLen := Len(cDelimiter)

if .not.Empty(cOptions)            // Deal with the Options (if any supplied)
   cOptions := Upper(cOptions)
   lTrim := .not.("N" $ cOptions)
   if Empty(cList) .and. .not.("D"$ cOptions)   // Unless D, return an empty
      lMore := .F.                              // array if string is blank.
   endif
endif

do while lMore
   lEof := .F.   
   nPos := at(cDelimiter, cList)

   if nPos > 0                                   // If found a delimiter
      cToken := substr(cList,1,nPos-1)           // Extract token
   else
      cToken := cList                            // Else use remainder of str
      lMore := .F.
   endif

   if lTrim
      cToken := AllTrim(cToken)                  // Trim unless asked not to
   endif

   aAdd ( aList, cToken )                        // Add a new element
   cList := substr(cList, nPos+nDelimLen)

enddo

RETURN aList       // End of function ListToArray 
Saudações,
Itamar M. Lins Jr.

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 20:04
por marcos.gurupi
Vc eh o KRA

Vou testar essa dai tb

Mais uma vez obrigado.


Marcos Roberto.

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 22:44
por Itamar M. Lins Jr.
Ola!
Tem uma correção no fonte.
Subir a linha da função mlcount() para ficar logo em seguida da memoread()

Código: Selecionar todos

cTexto := memoread("LivroDiario20150622.csv")
nTReg := mlcount(cTexto,500)

cTexto := StrTran(cTexto,hb_eol(),";")
aText := ListToArray(cTexto,";")
Senão da chabu, na linha depois ele muda EOL por ';' e conta errado! 345 sem o cabeçalho, no exemplo contou 262... eu apaguei 2 linhas...

Saudações,
Itamar M. Lins Jr.

Importar arquivo CSV para DBF

Enviado: 25 Jun 2015 23:39
por Euclides
Olá Itamar!
Legal essa sua (d´eles) solução. ( DELIMITED WITH ({,";"}))
Funciona no Harbour e xHarbour. Não funciona no Clipper 5.3
Obrigado e boa noite!
Euclides

Importar arquivo CSV para DBF

Enviado: 26 Jun 2015 10:44
por Itamar M. Lins Jr.
Oi!
Ué, então no clipper use a listtoarray()!
Para quem está sem tempo, e ainda continua no clipper, parece mais que tem muito tempo, porque não conheço nada mais improdutivo que usar 16Bits em 32/64...Sem falar nas funções de TCP/IP e Win Printers, entre outras tantas coisas novas que não tem no clipper.

Saudações,
Itamar M. Lins Jr.