Problema em referenciar Componentes
Tenho um problema. Por exemplo:
Em um botao eu crio um ClientDataSet e seto seu nome com um prefixo+valor
Var
NomePapel: String
ClientDataSet := TClientDataSet.Create(Form1);
ClientDataSet.Name := ´ClientDataSet´ + NomePapel; ClientDataSet.FieldDefs.Add(´Serie´,ftString,7,false);
E em um outro botao eu preciso adicionar dados a esse ClientDataSet, para eu preciso acessa-lo montando dinamicamente seu nome, como por exemplo:
(´ClientDataSet´ + ´Papel1´).Append;
(´ClientDataSet´ + ´Papel1´).Fieldbyname(´Serie´).AsString := ´K45´;
Sei que dessa forma nao funciona, mais é apenas uma forma de exemplicar. Tentei de varias formas mais nao consegui.
Eu vi exemplos onde eu posso ter uma variavel global e no momento da criacao associar o objeto criado a essa variavel global e depois utilizar essa variavel para referenciar o objeto. Mas eu nao posso ter variaveis globais estaticas pois eu nao sei quantos objetos serao criados.
Como posso resolver esse problema ?
Abracos.
Em um botao eu crio um ClientDataSet e seto seu nome com um prefixo+valor
Var
NomePapel: String
ClientDataSet := TClientDataSet.Create(Form1);
ClientDataSet.Name := ´ClientDataSet´ + NomePapel; ClientDataSet.FieldDefs.Add(´Serie´,ftString,7,false);
E em um outro botao eu preciso adicionar dados a esse ClientDataSet, para eu preciso acessa-lo montando dinamicamente seu nome, como por exemplo:
(´ClientDataSet´ + ´Papel1´).Append;
(´ClientDataSet´ + ´Papel1´).Fieldbyname(´Serie´).AsString := ´K45´;
Sei que dessa forma nao funciona, mais é apenas uma forma de exemplicar. Tentei de varias formas mais nao consegui.
Eu vi exemplos onde eu posso ter uma variavel global e no momento da criacao associar o objeto criado a essa variavel global e depois utilizar essa variavel para referenciar o objeto. Mas eu nao posso ter variaveis globais estaticas pois eu nao sei quantos objetos serao criados.
Como posso resolver esse problema ?
Abracos.
Kleysonr
Curtidas 0
Respostas
Joaoshi
24/10/2007
Colega, isto não vai resolver todo o problema, mas deve ajudar.
para teste coloque no form alguns componentes, e no evento do button1 coloque o codigo abaixo:
procedure TForm1.Button1Click(Sender: TObject);
var sArquivo:TClientDataSet;
nX:Integer;
begin
sArquivo:= TClientDataSet.Create(Self);
sArquivo.Name := ´Arquivo1´;
Try
For nX := 0 to Form1.ComponentCount -1 do
ListBox1.Items.add (Form1.Components[nX].Name);
Finally
sArquivo.Free;
End;
end;
Espero ter ajudado.
para teste coloque no form alguns componentes, e no evento do button1 coloque o codigo abaixo:
procedure TForm1.Button1Click(Sender: TObject);
var sArquivo:TClientDataSet;
nX:Integer;
begin
sArquivo:= TClientDataSet.Create(Self);
sArquivo.Name := ´Arquivo1´;
Try
For nX := 0 to Form1.ComponentCount -1 do
ListBox1.Items.add (Form1.Components[nX].Name);
Finally
sArquivo.Free;
End;
end;
Espero ter ajudado.
GOSTEI 0
Micheus
24/10/2007
[b:776b7f1e72]kleysonr[/b:776b7f1e72], minha sugestão é que no OnClick do seu botão que adiciona os dados:
é claro que vc deverá já ter algum meio de saber qual dataset irá acessar (o seu nome: Papel1, Papel2,...)
procedure Form1.BtnGravarClick(sender :TObject); var CDS :TClientDataSet; begin CDS := FindComponent(´ClientDataSet´ + ´Papel1´) as TClientDataSet; if Assigend(CDS) then // encontrou componente begin CDS.Append; CDS.Fieldbyname(´Serie´).AsString := ´K45´; ... CDS.Post; end; end;
é claro que vc deverá já ter algum meio de saber qual dataset irá acessar (o seu nome: Papel1, Papel2,...)
GOSTEI 0
Kleysonr
24/10/2007
Joaoshi isso nao me atende muito.
Olha so meu problema. Eu vou criar varios clientdataset (nao sei quantos) e esses dataset´s vao ser populados com dados. Entao eu vou estar recebendo constante de uma fonte externas dados para serem atualizados em um dbgrid, e desse dado que vem da parte externa tem um pedaco do nome que usei para setar a propriedade nome do ClientDataSet. E como o fluxo desses dados que chegam é muito grande e rapido eu nao posso ficar fazendo um loop nos componentes para achar o que eu quero, eu precisaria acessar diratamente o componente.
Nao existe uma forma de montar o nome e acessar diretamente ? Fazer um typecast ou alguma coisa assim ? Algo no estilo do exemplo abaixo ?
procedure AlterarDado(papel: string)
begin
TClientDataSet(´ClientDataSet´ + papel).Append;
...
end;
Olha so meu problema. Eu vou criar varios clientdataset (nao sei quantos) e esses dataset´s vao ser populados com dados. Entao eu vou estar recebendo constante de uma fonte externas dados para serem atualizados em um dbgrid, e desse dado que vem da parte externa tem um pedaco do nome que usei para setar a propriedade nome do ClientDataSet. E como o fluxo desses dados que chegam é muito grande e rapido eu nao posso ficar fazendo um loop nos componentes para achar o que eu quero, eu precisaria acessar diratamente o componente.
Nao existe uma forma de montar o nome e acessar diretamente ? Fazer um typecast ou alguma coisa assim ? Algo no estilo do exemplo abaixo ?
procedure AlterarDado(papel: string)
begin
TClientDataSet(´ClientDataSet´ + papel).Append;
...
end;
GOSTEI 0
Kleysonr
24/10/2007
Micheus,
Funcionou, eu havia testado dessa forma:
CDS := FindComponent(´ClientDataSet´ + ´Papel1´) as TClientDataSet;
So que nao tinha funcionado pois eu nao tinha colocado ´as TClientDataSet´. Agora com esse complemento foi.
Com o comando FindComponent eu acredito que ele faca um loop procurando o componente e testando o nome. Para uma aplicacao em tempo real com varias alteracoes ao mesmo tempo isso pode causar um overhead. Nao existe uma forma de acessar o componente direto ?
Mas mesmo assim, valeu !!
procedure Form1.BtnGravarClick(sender :TObject);
var
CDS :TClientDataSet;
begin
CDS := FindComponent(´ClientDataSet´ + ´Papel1´) as TClientDataSet;
if Assigend(CDS) then // encontrou componente
begin
CDS.Append;
CDS.Fieldbyname(´Serie´).AsString := ´K45´;
...
CDS.Post;
end;
end;
é claro que vc deverá já ter algum meio de saber qual dataset irá acessar (o seu nome: Papel1, Papel2,...)
_________________
´Há sempre, pelo menos, dois modos de fazer uma mesma coisa.
Mesmo que sejam: certo e errado.´ (Micheus)
Funcionou, eu havia testado dessa forma:
CDS := FindComponent(´ClientDataSet´ + ´Papel1´) as TClientDataSet;
So que nao tinha funcionado pois eu nao tinha colocado ´as TClientDataSet´. Agora com esse complemento foi.
Com o comando FindComponent eu acredito que ele faca um loop procurando o componente e testando o nome. Para uma aplicacao em tempo real com varias alteracoes ao mesmo tempo isso pode causar um overhead. Nao existe uma forma de acessar o componente direto ?
Mas mesmo assim, valeu !!
procedure Form1.BtnGravarClick(sender :TObject);
var
CDS :TClientDataSet;
begin
CDS := FindComponent(´ClientDataSet´ + ´Papel1´) as TClientDataSet;
if Assigend(CDS) then // encontrou componente
begin
CDS.Append;
CDS.Fieldbyname(´Serie´).AsString := ´K45´;
...
CDS.Post;
end;
end;
é claro que vc deverá já ter algum meio de saber qual dataset irá acessar (o seu nome: Papel1, Papel2,...)
_________________
´Há sempre, pelo menos, dois modos de fazer uma mesma coisa.
Mesmo que sejam: certo e errado.´ (Micheus)
GOSTEI 0
Micheus
24/10/2007
Com o comando FindComponent eu acredito que ele faca um loop procurando o componente e testando o nome.
exato. Será ´varrida´ toda a lista de componentes do seu Form.Para uma aplicacao em tempo real com varias alteracoes ao mesmo tempo isso pode causar um overhead. Nao existe uma forma de acessar o componente direto ?
Isto até seria relevante se seu form/datamodule contiver muitos componentes.Se for o caso, vc poderia utilizar um TStringList global a este seu form/datamodule e nele armazenar os TClientDataSet´s adicionados dinamicamente - é o único jeito de ter uma lista menor para procurar.
Deve ficar algo mais ou menos assim:
type Form1 = class(TForm) ... private CDSList :TStringList; end; ... procedure TForm1.Form1Create(sender :TObject); begin // aloca lista CDSList := TStringList.Create; ... end; procedure TForm1.FormDestroy(sender :TObject); var Idx :Integer; begin // libera componentes CDS da lista for Idx := 0 to CDSList.Count -1 do if Assigned(CDSList.Objects[Idx]) then (CDSList.Objects[Idx] as TClienteDataSet).Free; // libera lista alocada CDSList.Free; ... end; // onde vc faz a criação do CDS dinamicamente... procedure TForm1.IncluirDataSet... Var NomePapel: String CDS :TClientDataSet; begin ClientDataSet := TClientDataSet.Create(Form1); ClientDataSet.Name := ´ClientDataSet´ + NomePapel; ClientDataSet.FieldDefs.Add(´Serie´,ftString,7,false); ... // adiciona o CDS à lista CDSList.AddObject(ClientDataSet.Name, ClientDataSet); end; // onde vc grava os dados dinamicamente... procedure Form1.BtnGravarClick(sender :TObject); var Idx :Integer; CDS :TClientDataSet; begin if CDSList.Find(´ClientDataSet´ + ´Papel1´, Idx) then begin CDS := TClientDataSet(CDSList.Objects[Idx]); CDS.Append; CDS.Fieldbyname(´Serie´).AsString := ´K45´; ... CDS.Post; end; end; ... end.
GOSTEI 0