quarta-feira, 7 de novembro de 2007

ExtractStrings: Você conhece?

Pessoal, resolvi começar a postar aqui, funções do delphi que normalmente quebram muitos galhos, e, por desconhece-las, acabamos "rebolando" pra criar algo "parecido". E não pensem que não estou falando de mim! :)

Uma função muito interessante e que tem uma enorme utilidade é a função ExtracStrings. Essa função preenche uma lista (StringList), com substrings de uma string.

Imagine que você precise ler um arquivo CSV (separado por ponto-e-vírgula). Dai você pergunta: "Como vou separar as colunas?"; a primeira idéia é criar uma função para localizar (Pos) o primeiro ponto-e-vírgula e extrair o fragmento da string (Copy), e assim sucessivamente, atire a primeira pedra que nunca fez assim!

Pois é! Perdemos nosso precioso tempo reinventando a roda.

Veja a sintaxe da função ExtractString:

function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings): Integer;

  • Separator - É um array onde você pode definir vários separadores
  • WhiteSpace - É um Array onde você define os caracteres que devem ser Ignorados quando ocorrerem no inicio da String.
  • Content - É a String de onde se deseja extrais as substrings
A Função retorna o número de Substrings extraídas.

Veja um pequeno exemplo de utilização:

procedure TForm1.Button1Click(Sender: TObject);
const

SDados = 'Cristiano Martins Alves; 28 Anos; Casado; São Paulo; SP';
var
Lista: TStringList;
iRetorno:Integer;

begin

Lista := TStringList.Create;

try

iRetorno :=
ExtractStrings([';'],[' '],PChar(sDados),Lista);
if
iRetorno > 0 then
ShowMessage(Lista.Text);

finally

FreeAndNil(Lista);

end
;

end
;

Veja o resultado:













Repare que na nossa constante existe um espaço entre o nome e a idade, mas ele foi ignorado conforme definido no segundo parâmetro.


É isso ai pessoal! Não deixem de comentar o blog!

6 comentários:

Anônimo disse...

Olá, beleza, muito bom este site, gostei deste commando, heheh, eu estou com um programa aqui e estava prestes a usar o Pos hehehe, esse comando caiu como uma luva para os meus propósitos.

Anônimo disse...

Olá, tdo bm?
Cara, gostei muito desse artigo, mas gostaria de saber +... hehehe
Como faço para ler de um arquivo com várias linhas e gerar um outro arquivo?
Como faço para atribuir a um edit só a primeira coluna?
ex: unidade;contrato;nome;valor.

Cristiano Martins Alves disse...

Olá, Tudo bem e você.

Cara existem muitas forma de se fazer isso. A que eu mais gosto é a seguinte (Obs: Valida se não for um arquivo muito grande como por exemplo umas 100.000).

var
Linhas, Colunas:TStringList;
i,j:integer;
begin
Linhas := TStringList.Create;
Colunas := TStringList.Create;
try
Linhas.LoadFromFile('C:\MeuArquivo.txt'); //Carregando arquivo
for i := 0 to Pred(Linhas.Count) do
begin
{Transformando os dados das colunas em Linhas}
Colunas.text := StringReplace(Linhas.Strings[i],';',#13,[rfReplaceAll]);
for j := 0 to Pred(Colunas.Count) do
begin
{ Aqui você faz alguma coisa como colocar num Edit
No Meu caso aqui para exemplificar vou apenas mostrar num ShowMessage}
ShowMessage('Valor "'+Colunas.Strings[j] + '" da Linha '+IntTostr(i+1) +
' Coluna '+IntToStr(j+1));
end;
end;
finally
Linhas.Free;
Colqunas.Free;
end;
end;


Note que ai eu pego o valor de cada campo em cada linha. No seu exemplo ficaria na coluna 1 o valor é "Unidade", na 2 é Contrato e assim por diante.

Se o seu arquivo for maior que 100.000 linhas, aconselho que leia diretamente do disco, utilizar uma variavel do Tipo TextFile.

Bom é isso, qualquer dúvida entre em contato.

Unknown disse...

Olá,Cristiano!
Parabéns pelo artigo; testei e funcionou bem.
Porém estou com uma necessidade, de separar um endereço em 3 campos :
Rua Conceição, 250
preciso mandar o "Rua" para um campo, "Conceição" para outro e "250" para outro campo, vc pode me dar uma orientação de como faço isso?

Cristiano Martins Alves disse...

Olá Ezequias,

Cara isso não fica legal com ExtractStrings porque só poderia extrair pelo espaço e se o nome da rua for composto já quebra a logica.

Você pode usar copy mesmo, você pode verificar se existe o tipo de logradouro no seu exemplo (Rua, Avenida, Travessa etc). Dai copiar essa parte e depois copiar até a virgula. Algo mais ou menos assim:

Coloque 4 Edit e 1 Button no form
Renomeie os edits para:

EdtEndereco
EdtLogradouro
EdtTipo
EdtNumero

e implemente o codigo abaixo no evento onClick do Button


const
arrTipoLogradouro: array[0..2] of String = ('Rua','Avenida', 'Travessa');
var
i:integer;
Numero:String;
begin
for i := low(arrTipoLogradouro) to high(arrTipoLogradouro) do
begin
if Pos(arrTipoLogradouro[i],'Rua', EdtEndereco.text);
EdtTipo.Text := arrTipoLogradouro[i];
EdtLogradouro := Copy(EdtEndereco.text,Length(EdtTipo.Text), Pos(',',EdtEndereco.text);
EdtNumero.Text := Copy(EdtEndereco.text,Pos(',',EdtEndereco.text), length(EdtEndereco.text));
end;

É isso ai, talvez precise de ajustes o código, eu não tive tempo de testar no delphi.

Abraço e boa sorte!

Unknown disse...

Muito bom...excelente dica, estava com um problema para extrair strings de arquivos csv..