Copiar string de forma peculiar

17/06/2008

2

Pessoal, tenho uma dúvida ao trabalhar com arquivo texto. Abaixo
preciso fazer o seguinte. Uma determinada string, não tem um valor
exato. Ela pode vir assim: WWWWWW 1 x 63,00 ou WWWWWW10 x 63,00
O que eu preciso é copiar todos os W´s, depois o 1 ou 10 e depois o
valor. Um copy length(sting) não dá, senão ele copia toda a linha.
Se a quantidade ou valor fossem fixos, tipo 001 ou 010, aí seria
fácil, mas não é. Essa é a minha dificuldade no momento. Como faço
uma rotina que me traga o que eu quero.
Os W´s são minha descrição, que terá até 26 caracteres, depois o
1 ou 10 é minha quantidade e depois o valor. Como faço então?
Espero ter sido claro.


Responder

Posts

um tanto estranho esse arquivo não ser padronizado...
de qualquer forma - pela sua explicação - sugiro a você fazer a varredura na linha, de trás pra frente.
procedure TForm1.BitBtn2Click(Sender: TObject);
var
  texto: tstringlist;
  i, j: integer;

  descricao, valor: string;
  vlrUnit, Qtd: double;
begin
  texto := tstringlist.create;
  texto.Add(´WWWWWW 1 x 63,00´);
  texto.Add(´WWWWWWDDRR DDDDDD10 x 63,03´);
  texto.Add(´WWWWWW XXXXXX ZZZZZZZZZ012x64,67´);

  // varre o arquivo-texto
  for i := 0 to texto.Count-1 do
  begin
    descricao := texto[i];
    valor := ´´;
    // varre a linha de trás pra frente
    for j := length(descricao) downto 1 do
      if UpperCase(descricao[j])[1] in [´X´, ´,´, ´ ´, ´0´..´9´] then
        valor := descricao[j] + valor
      else
        break;

    descricao := copy(descricao, 1, length(descricao)-length(valor));

    j := pos(´X´, UpperCase(valor));

    Qtd := StrToFloatDef(trim(copy(valor,1,j-1)),0);
    vlrUnit := StrToFloatDef(trim(copy(valor,j+1,length(valor))),0);

    ShowMessage(´Descricao:´+descricao+#13´Quantidade:´+
      FormatFloat(´0´,Qtd)+13´Valor unitário:´+FormatFloat(´,0.00´,vlrUnit));
  end;
end;



Responder

17/06/2008

Paulo

Emerson, eu não posso dizer que o que vem depois da string seja um 1. Pode ser 2, 3, 10, 18 etc... Por isso eu não posso fixar nada. Eu sei que deve ser um Downto, mas não estou sabendo fazer.


Responder

17/06/2008

Brunodsr

Eu implementei assim:

Funcao para separar a string em tres partes e retornar um StringList com elas
function TForm1.f_divideStrings(sWord: String): TStringList;
var
  i, nTam:integer;
  sAux, sAux2, sAux3 : String;
  bControl:Boolean;
begin
  //Inicializando as variaveis
  result := TStringlist.Create;
  sAux := ´´;
  sAux2 := ´´;
  bControl := true;
  sAux3 := Trim(sWord);

  //Varrendo a string original e retirando a primeira parte dela (WWWW)
  nTam := length(sAux3);
  for i:= 1 to nTam do
  begin
    if (UpCase(sAux3[i]) in [´A´,´B´,´C´,´W´,´Z´]) and bControl then
      sAux := sAux + sAux3[i]
    else
    begin
      sAux2 := sAux2 + sAux3[i];
      bControl := False;
    end;
  end;
  //Alimentando a primeira string
  Result.Add(sAux);
  //Limpando as variáveis
  bControl := True;
  sAux3 := Trim(sAux2);
  sAux  := ´´;
  sAux2 := ´´;

  //Varrendo o restante da string e retirando a segunda string dela (1, 2..10)
  nTam := length(sAux3);
  for i:= 1 to nTam do
  begin
    if (sAux3[i] in [´0´,´1´,´2´,´3´,´4´,´5´,´6´,´7´,´8´,´9´]) and bControl then
      sAux := sAux + sAux3[i]
    else
    begin
      sAux2 := sAux2 + sAux3[i];
      bControl := False;
    end;
  end;
  //Alimentando a segunda string
  Result.Add(sAux);

  //Limpando as variáveis
  sAux3 := Trim(sAux2);
  sAux  := ´´;
  sAux2 := ´´;

  //Varrendo o restante da string e retirando a ultima string dela (4.5, 4.00, ...)
  nTam := length(sAux3);
  for i:= 1 to nTam do
  begin
    if sAux3[i] in [´0´,´1´,´2´,´3´,´4´,´5´,´6´,´7´,´8´,´9´,´.´,´,´] then
      sAux := sAux + sAux3[i];
  end;
  //Alimentando a segunda string
  Result.Add(sAux);
end;


Usando a funcao lendo de um edit
procedure TForm1.Button1Click(Sender: TObject);
var
  StringList: TStrings;
begin
  StringList := f_divideStrings(Edit1.Text);
  Showmessage(´1ª Parte: ´+StringList[0]+1310+
              ´2ª Parte: ´+StringList[1]+1310+
              ´3ª Parte: ´+StringList[2]+1310);
end;


Espero ter ajudado


Responder

17/06/2008

Carlosrm

Paulo,

se eu entendi, toda linha do arquivo texto começa com ´wwwwww´, seguida por um fator (1 .. 10), mais um ´ x ´ e também um número com duas casas decimais, cujo separador de decimais é uma vírgula (,).

Nesse caso, se você localizar a posição da vírgula, será possível copiar a substring da linha, que começara em 1 e vai até a posição da vírgula mais 2 (supondo que são sempre duas casas decimais). A substring não terá um tamanho único, mas você sempre saberá o tamanho exato a copiar.
No caso de poder aparecer uma outra vírgula, por exemplo, no meio dos ´ww..w´, você poderá considerar apenas a vírgula que vier depois do x...).
Vai precisar obter a posição do ´x´ em cada linha... (função pos()...)

Um outro caminho ( me parece mais trabalhoso), seria verificar a cada linha do txt lida, se o fator (1..10) tem uma ou dois (ou mais) dígitos. Se tiver menos que o necessário, poderia completar com espaços, zeros, o que for apropriado.

Espero que a idéia possa ser útil...


Responder
Emerson, eu não posso dizer que o que vem depois da string seja um 1. Pode ser 2, 3, 10, 18 etc... Por isso eu não posso fixar nada. Eu sei que deve ser um Downto, mas não estou sabendo fazer.

você testou o código que eu te passei? ele não fixa nada. você pode passar o que quiser.

porque você achou que o código está esperando ´1´ depois da string???

note no preenchimento da stringlist:
texto := tstringlist.create;
texto.Add(´WWWWWW 1 x 63,00´);
texto.Add(´WWWWWWDDRR DDDDDD10 x 63,03´);
texto.Add(´WWWWWW XXXXXX ZZZZZZZZZ012x64,67´);
veja que na terceira linha, depois da string, vem um zero.


Responder

17/06/2008

Lauro.balceiro

Segue uma idéia...

procedure TForm1.Button1Click(Sender: TObject);
var
  suaString : String;
  parte1 : String;
  parte2 : String;
  parte3 : String;
  aux : String;
begin

  suaString := ´WWWWWW 1 x 63,00 ´;

  aux := StrPos(PChar(suaString), ´x´);
  parte3 := trim(copy(aux,2,length(aux)));

  aux := trim(StringReplace(suaString,aux,´´,[rfReplaceAll]));
  parte1 := copy(aux,0,6);

  parte2 := trim(StringReplace(aux,parte1,´´,[rfReplaceAll]));

  ShowMessage(parte1 + ´ - ´ + parte2 + ´ - ´ + parte3);
end;



Responder

17/06/2008

Luciano.lirio

Tenta essa, só vai dar problema se na descrição tiver numeros...


procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  J: Integer;
  H: Integer;
  Linha: String;
  Descricao: String;
  Qtde: String;
  Valor: String;
begin
  Linha := ´WWWWWWDDRR DDDDDD10 x 63,03´;
  for I := 1 to Length(Linha) do if (Linha[I] in [´0´..´9´]) then Break;
  Descricao := Copy(Linha,1,I-1);
  for J := I to Length(Linha) do if not (Linha[J] in [´0´..´9´]) then Break;
  Qtde := Copy(Linha,I,J-I);
  for H := J to Length(Linha) do if (Linha[H] in [´0´..´9´]) then Break;
  Valor := Copy(Linha,H,Length(Linha)-H+1);
  ShowMessage(Descricao+´;´+Qtde+´;´+Valor);
end;



Responder