Ir para conteúdo
Fórum Script Brasil
  • 0

Essa, So Fera Consegue


MAIQUE

Pergunta

POR FAVOR alguém ME AJUDE !

Preciso fazer uma importacao de um arquivo IMPORTADO.TXT para uma tabela do Interbase, minha tabela possui o seguinte LAYOUT abaixo :

"","421303","33214","01/01/2005","2610,25","","PAGO CH 11580 ",""

aonde as aspas é o delimitador entre os campos da tabela. minha tabela possui os seguintes campos

COD,CONTAD, CONTAC,DATA,VALOR,REG1,HISTORICOS,REG2.

estou usando a seguinte logica :

procedure TForm1.Button1Click(Sender: TObject);

var

F1: textfile;

S1:String;

//if FileExists('h:\...\texto.txt')then

begin

AssignFile(F1,'C:\TESTE\IMPORTADO.TXT');

filemode := 2;

reset(f1);

while not eof(F1) do

begin

readln(f1,s1);

IBTable1.Open;

IBTable1.insert;//

IBTable1.fieldbyname('COD').asstring := copy(s1,01,02);

IBTable1.fieldbyname('CONTAD').asstring := copy(s1,05,06);

IBTable1.fieldbyname('CONTAC').asstring := copy(s1,13,06);

IBTable1.fieldbyname('DATA').asstring := copy(s1,22,10);

IBTable1.fieldbyname('VALOR').asstring := copy(s1,33,30);

IBTable1.fieldbyname('REG1').asstring := copy(s1,53,1);

IBTable1.fieldbyname('HISTORICO').asstring := copy(s1,56,70);

IBTable1.fieldbyname('REG2').asstring := copy(s1,88,1);

IBTable1.applyupdates;

closefile(f1);

end;

eu ate consigo gerar a importacao o grande problema é que tem linhas que saem certas outras não, porque os campos por exemplo:

CONTAD (é de tamanho 6, + as vezes recebem 5 caracteres e em outras vezes 6. quando a conta recebe 6 caracteres dá certo + quando recebe 5 dá erro porque a conta sae por exemplo assim 12345" na tabela enquanto eu precisava que saisse assim 12345 se fosse com seis caracteres sairia certo assim 123456 porque na linha de comando que eu usei ..... IBTable1.fieldbyname('CONTAD').asstring := copy(s1,05,06); aponta seis posições.

CONTAC acontece a mesma coisa que na CONTAD.

e assim tmb com o Historico.

precisava achar uma forma de fazer a importacao entender que eu so preciso da informacao entre as aspas, independente do tamanho dos caracteres.

EXemplo : a) - "","123456","123456","01/01/2005","20000610,25","","PAGO CH 11580 ",""

B) - "","12345","12345","01/01/2005","2610,25","","PAGO CNF CH 11000 A FULANO",""

rESULTADOS

ESPERADOS : a) - 0 123456 123456 01/01/2005 20000610,25 PAGO CH 11580 0

B) - 0 12345 12345 01/01/2005 2610,25 PAGO CNF CH 11000 A FULANO 0

OBS COLOQUEI Zero, nos campos aonde "" representam nada importado ou melhor campo zerado ou vazio.

Se alguém puder me ajuda? sei que essa é um poukinho complicado, + tenho certeza que algum abençoado por Deus vai me ajudar a sair dessa. de qualquer forma a quem puder me ajudar, desde já agradeço e um forte abracao Maique Castro

maiquecastro@hotmail.com

maiquecastro@oi.com.br

Link para o comentário
Compartilhar em outros sites

11 respostass a esta questão

Posts Recomendados

  • 0

Bom dia Maique,

Como é gerado esse arquivo .txt?

Caso seja você que gera ele crie algumas regras, como:

Se CONTAD < 6 então o programa completa com zeros na frente; Isso garantiria que os campos teriam sempre o mesmo comprimento.

Essa é uma solução possível, mas creio que existem outras.

Link para o comentário
Compartilhar em outros sites

  • 0

opa blzz

vou tentar te ajudar...

vamos supor que cada linha tenha o mesmo "layout" desta que você passou...

eu substitui o que sairia em branco por 0...

"0","421303","33214","01/01/2005","2610,25","0","PAGO CH 11580","0"

então você faz

//Cod

IBTable1.fieldbyname('COD').asstring := copy(s1, 2, 1);

Delete(s1, 1, pos(',"', s1) + 1);

//Contad

IBTable1.fieldbyname('CONTAD').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Contac

IBTable1.fieldbyname('CONTAC').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Data

IBTable1.fieldbyname('DATA').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Valor

IBTable1.fieldbyname('VALOR').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Reg1

IBTable1.fieldbyname('REG1').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Historio

IBTable1.fieldbyname('HISTORICO').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Reg2

IBTable1.fieldbyname('REG2').asstring := copy(s1, 1, length(s1) - 1);

repara que todos os campos tem a mesma base de cópia exceto o primeiro e o último...

independente do tamanho do texto, ele sempre vai puxar pelo layout e não por contagem....

seu código então vai ficar

procedure TForm1.Button1Click(Sender: TObject);

var

F1: textfile;

S1:String;

//if FileExists('h:\...\texto.txt')then

begin

AssignFile(F1,'C:\TESTE\IMPORTADO.TXT');

filemode := 2;

reset(f1);

while not eof(F1) do

begin

readln(f1,s1);

IBTable1.Open;

IBTable1.insert;//

//Cod

IBTable1.fieldbyname('COD').asstring := copy(s1, 2, 1);

Delete(s1, 1, pos(',"', s1) + 1);

//Contad

IBTable1.fieldbyname('CONTAD').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Contac

IBTable1.fieldbyname('CONTAC').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Data

IBTable1.fieldbyname('DATA').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Valor

IBTable1.fieldbyname('VALOR').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Reg1

IBTable1.fieldbyname('REG1').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Historio

IBTable1.fieldbyname('HISTORICO').asstring := copy(s1, 1, pos(',"', s1) - 2);

Delete(s1, 1, pos(',"', s1) + 1);

//Reg2

IBTable1.fieldbyname('REG2').asstring := copy(s1, 1, length(s1) - 1);

IBTable1.applyupdates;

closefile(f1);

end;

qlq coisa posta ai

abraços

Link para o comentário
Compartilhar em outros sites

  • 0

A função a seguir recebe como parametro sua string e o índice do campo que se deseja ler, e retorna o campo sem as aspas:

Function CopyQuote(st: string; index: integer) : String;
var i: cardinal;
 n, ps, fn : integer;
 aci, acf : boolean;

begin
  if (index = 0)then
  begin
    result:='';
    exit;
  end;
  aci:=false;
  acf:=false;
  n:=0;
  index:=index*2;
  for i:=1 to length(st) do
  begin
    if (st[i] = '"') then inc(n);
    if (n = (index-1)) and not(aci) then
    begin
      ps:=i;
      aci:=true;
    end;
    if (n = index) and not(acf) then
    begin
      fn:=i-ps;
      acf:=true;
    end;
  end;
  if (index>n) then
  begin
    result:='';
    exit;
  end else
  begin
    result:=copy(st,ps+1,fn-1);
  end;
end;

Link para o comentário
Compartilhar em outros sites

  • 0

Bom, vou entrar na onda também. ;)

Partindo do princípio que seu arquivo texto conterá os dados como você mensionou, não preocupei-me em fazer qualquer validação da linha lida.

Deste modo, a sugestão que tenho é utilizar uma função que irá receber a linha lida e a cada chamada a mesma, remove o campo lido retornando-o. Para isso, as atribuições a tabela deverão ser realizadas na seqüência que os campos aparecem na linha do arquivo texto. O resultado será apenas os valores - sem as aspas duplas delimitando os mesmos.

Se houver algum campo no arquivo texto que não seja utilizado, basta chamar a função sem atribuí-la a alguém.

Acho que funcina.

function GetField(var :FullStr :String) :string;
var
  Idx :Integer;
  FieldStr :string;
begin
 // retira qualquer espaço que possa haver nas extremidades
  FullStr := Trim(FullStr);
  Delete(FullStr, 1, 1);  // retira a primeira aspas dupla (") - primeiro delimitador
  Idx := Pos('"', FullStr);  // procura o último delimitador de texto do campo
  Result := Copy(FullStr, 1, Idx -1);  // retorna o field encontrado
  Delete(FullStr, 1, Idx);  // remove o field até o delimitador (")
  Delete(FullStr, 1, Pos(',', FullStr));  // remove a vírgula se houver
end;

...
while not eof(F1) do
begin
  readln(f1,s1);
  IBTable1.Open;
  IBTable1.insert;//
  IBTable1.fieldbyname('COD').asstring := GetField(s1);
  IBTable1.fieldbyname('CONTAD').asstring := GetField(s1);
  IBTable1.fieldbyname('CONTAC').asstring := GetField(s1);
  IBTable1.fieldbyname('DATA').asstring := GetField(s1);
  IBTable1.fieldbyname('VALOR').asstring := GetField(s1);
  IBTable1.fieldbyname('REG1').asstring := GetField(s1);
  IBTable1.fieldbyname('HISTORICO').asstring := GetField(s1);
  IBTable1.fieldbyname('REG2').asstring := GetField(s1);
  IBTable1.applyupdates;
  closefile(f1);
end;

Link para o comentário
Compartilhar em outros sites

  • 0

Bem, Micheus, acho que a minha função faz mais ou menos isso só que não modifica a string lida, sendo que é possível ler o mesmo campo várias vezes, apenas fornecendo o índice. A não ser que ele queira que sejam apagados os campos da string a medida em que são lidos.

Link para o comentário
Compartilhar em outros sites

  • 0

Ele vai ter que escrever um comando pra cada campo da tabela, então não vejo problema en passar o índice. E se fosse em loop for também não tinha problema, seria até melhor que aí ele usaria a var de controle para indexar o campo.

Link para o comentário
Compartilhar em outros sites

  • 0

Opa, será que assim dá certo? Juntando a minha função com loop for?

type Tfields = array [1..8] of string;
const
  fields : TFields = 
('COD', 'CONTAD',  'CONTAC',  'DATA', 'VALOR',  'REG1', 'HISTORICO',  'REG2');
begin
while not eof(F1) do
begin
  readln(f1,s1); 
  IBTable1.Open;
  IBTable1.insert;//
  for i:=1 to 8 do
  begin
    IBTable1.fieldbyname(fields[i]).asstring := GetQuote(s1,i);
  end;
  IBTable1.applyupdates;
  closefile(f1);
end;
end;

Link para o comentário
Compartilhar em outros sites

  • 0

Thales, com certeza dará certo e ainda achariamos outras tantas.

Bem, Micheus, acho que a minha função faz mais ou menos isso só que não modifica a string lida, sendo que é possível ler o mesmo campo várias vezes, apenas fornecendo o índice. A não ser que ele queira que sejam apagados os campos da string a medida em que são lidos.
Considerando o formato do texto que nosso colega postou: campos separados por vígula e texto delimitado por aspas duplas, acho (não estou com Delphi - não testei) daria para escrever a sua função deste modo:

Function CopyQuote(st: string; index: integer) : String;
var
  FieldValues :TStringList; 
begin
  FieldValues := TStringList.Create;
  try
    CommaText := st;
    if (Index >= 1) and (Index <= FieldValues.Count) then
      Result := FieldValues[Index -1]
    else
      Result := '';
  finally
    FieldValues.Free;
  end;
end;

Tudo é uma questão de situação/aplicação. A idéia foi propor apenas um ajuste ao que o colega já havia implementado, bem como dar mais uma opção a ele, já que haviam outros post's resolvendo o problema.

A cada alternativa apresentada ampliamos nosso conhecimento de modo a nos aperfeiçoar. Não é este nosso objetivo?! ;)

É como cito em minha nota de rodapé:

"Há sempre, pelo menos, dois modos de fazer uma mesma coisa. Mesmo que sejam certo e errado"

[]s

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...