Copiar string de forma peculiar
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.
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.
Paulo
Curtidas 0
Respostas
Emerson Nascimento
17/06/2008
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.
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;
GOSTEI 0
Paulo
17/06/2008
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.
GOSTEI 0
Brunodsr
17/06/2008
Eu implementei assim:
Funcao para separar a string em tres partes e retornar um StringList com elas
Usando a funcao lendo de um edit
Espero ter ajudado
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
GOSTEI 0
Carlosrm
17/06/2008
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...
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...
GOSTEI 0
Emerson Nascimento
17/06/2008
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.
GOSTEI 0
Lauro.balceiro
17/06/2008
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;
GOSTEI 0
Luciano.lirio
17/06/2008
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;
GOSTEI 0