Pesquisa através parte de nome em um texto

24/04/2019

25

Olá pessoal, é possível criar uma linha de código onde eu consigo digitar em um campo de pesquisa parte de uma palavra que esteja no meio de um trecho de texto e essa busca ser realizada? Exemplo disso seria mais ou menos o mesmo comportamento da barra de pesquisa do Windows, onde vc digita parte de uma palavra e ele localiza essa palavra com pedaço desse trecho que está no meio de um texto. Isso em Delphi usando ClienteDataSet.
Responder

Post mais votado

25/04/2019

você pode usar o método locate() pra isso, mas ele não procura em qualquer parte do texto. o conteúdo procurado precisa ser prefixo do conteúdo pesquisado.

por exemplo:
- se o conteúdo do campo for 'RAZAO SOCIAL', e você digitar R na pesquisa, o registro SERÁ encontrado.
- se o conteúdo do campo for 'RAZAO SOCIAL', e você digitar S na pesquisa, o registro NÃO será encontrado.

a sintaxe para o locate() é:
Locate(Campo, ValorProcurado, OpcoesDeBusca);

segue um exemplo:
ClientDatasetCliente.Locate('Nome', 'R', [loPartialKey, loCaseInsensitive]);

você também pode procurar em mais de um campo simultaneamente.
para isso 'Campo' deverá ser uma lista de campos separados por ; (ponto e vírgula) e 'ValorProcurado' precisa ser um array. assim:
ClientDatasetCliente.Locate('Nome;UF', VarArrayOf(['R', 'SP']), [loPartialKey, loCaseInsensitive]);

Responder

Mais Posts

você pode usar o método locate() pra isso, mas ele não procura em qualquer parte do texto. o conteúdo procurado precisa ser prefixo do conteúdo pesquisado.

por exemplo:
- se o conteúdo do campo for 'RAZAO SOCIAL', e você digitar R na pesquisa, o registro SERÁ encontrado.
- se o conteúdo do campo for 'RAZAO SOCIAL', e você digitar S na pesquisa, o registro NÃO será encontrado.

a sintaxe para o locate() é:
Locate(Campo, ValorProcurado, OpcoesDeBusca);

segue um exemplo:
ClientDatasetCliente.Locate('Nome', 'R', [loPartialKey, loCaseInsensitive]);

você também pode procurar em mais de um campo simultaneamente.
para isso 'Campo' deverá ser uma lista de campos separados por ; (ponto e vírgula) e 'ValorProcurado' precisa ser um array. assim:
ClientDatasetCliente.Locate('Nome;UF', VarArrayOf(['R', 'SP']), [loPartialKey, loCaseInsensitive]);


Dessa forma eu teria que deixar na própria linha de comando o que eu iria precisar fazer a busca. O que eu preciso é algo similiar ao que o buscador do wuindows explore faz, ali na barra de pesquisa. Ele pesquisar por parte de trecho de um texto, por exemplo, tenho um nome de um serviço em um campo " Bloco de Orçamento / Pedido" ao digitar "pedido" terá que aparecer registro que contenha a palavra pedido, inclusive essa que acabei de citar, "Bloco de Orçamento / Pedido"
Responder
crie uma procedure pra fazer o que você precisa.

algo assim:
procedure BuscaRegistro(cds: TClientDataset; campo: string; conteudo: string);
var
  numRegistro: integer;
  bolEncontrou: boolean;
  strMensagem: string;
begin
  // verifica se o dataset está aberto e se o campo indicado existe
  if not cds.Active or (cds.FindField(campo) = nil) or cds.IsEmpty then
  begin
    if not cds.Active then
      strMensagem := 'A busca só pode ser realizada num dataset aberto'
    else
    if cds.IsEmpty then
      strMensagem := 'A pesquisa não pode ser realizada num dataset vazio'
    else
      strMensagem := 'O campo '''+campo+''' não existe no dataset';
    ShowMessage(strMensagem);
    exit;
  end;

  // guarda o registro posicionado antes de iniciar a pesquisa
  numRegistro := cds.RecNo;

  // inicializa a variável que indica se o texto foi encontrado
  bolEncontrou := False;

  // desabilita o refresh nos controles ligados ao dataset
  cds.DisableControls;

  // posiciona no primeiro registro
  cds.First;

  //varre o dataset à procura do conteudo desejado
  while not cds.Eof do
  begin
    // procura o valor digitado em qualquer parte do campo
    bolEncontrou := (Pos(AnsiUpperCase(conteudo), AnsiUpperCase(cds.FieldByName(campo).AsString)) > 0);

    // se encontrar o conteúdo, sai do loop
    if bolEncontrou then
      break;

    cds.Next;
  end;

  // se não encontrou um registro, reposiciona o ponteiro no registro inicial
  if not bolEncontrou then
    cds.RecNo := numRegistro;

  // habilita o refresh nos controles ligados ao dataset
  cds.EnableControls;
end;

você pode usar no OnChange de um Edit, por exemplo:
procedure TForm1.Edit1Change(Sender: TObject);
begin
  BuscaRegistro(ClientDataSet1, 'Nome', Edit1.Text);
end;


Você pode ainda implementar a procedure como um método numa classe derivada de TClientDataset:
type
  TXClientDataset = class(TClientDataset)
  public
    procedure BuscaRegistro(campo: string; conteudo: string);
  end;

procedure TXClientDataset.BuscaRegistro(campo,
  conteudo: string);
var
  numRegistro: integer;
  bolEncontrou: boolean;
  strMensagem: string;
begin
  // verifica se o dataset está aberto e se o campo indicado existe
  if not Self.Active or (Self.FindField(campo) = nil) or Self.IsEmpty then
  begin
    if not Self.Active then
      strMensagem := 'A busca só pode ser realizada num dataset aberto'
    else
    if Self.IsEmpty then
      strMensagem := 'A pesquisa não pode ser realizada num dataset vazio'
    else
      strMensagem := 'O campo '''+campo+''' não existe no dataset';
    ShowMessage(strMensagem);
    exit;
  end;

  // guarda o registro posicionado antes de iniciar a pesquisa
  numRegistro := Self.RecNo;

  // inicializa a variável que indica se o texto foi encontrado
  bolEncontrou := False;

  // desabilita o refresh nos controles ligados ao dataset
  Self.DisableControls;

  // posiciona no primeiro registro
  Self.First;

  //varre o dataset à procura do conteudo desejado
  while not Self.Eof do
  begin
    // procura o valor digitado em qualquer parte do campo
    bolEncontrou := (Pos(AnsiUpperCase(conteudo), AnsiUpperCase(Self.FieldByName(campo).AsString)) > 0);

    // se encontrar o conteúdo, sai do loop
    if bolEncontrou then
      break;

    Self.Next;
  end;

  // se não encontrou um registro, reposiciona o ponteiro no registro inicial
  if not bolEncontrou then
    Self.RecNo := numRegistro;

  // habilita o refresh nos controles ligados ao dataset
  Self.EnableControls;
end;

E usar assim:
procedure TForm1.Edit1Change(Sender: TObject);
begin
  TXClientDataset(ClientDataSet1).BuscaRegistro('Nome', Edit1.Text);
end;
Responder
Pelo que analisei, é possível que atenda o que preciso, vou fazer o teste hj a noite e dou retorno logo em seguida.
Responder

procedure BuscaRegistro(cds: TClientDataset; campo: string; conteudo: string); <----- Essa Procedure, é um componente que eu adiciono? Ela é adicionada na própria Unit do form que será feita a pesquisa? Caso seja uma procedure comum sem adição de componente ali onde está TClienteDataSet seria o Nome do meu ClienteDataSet neh, da forma que está o compilador não reconhece esse tipo.

Ali tbm vc postou duas forma, mas a de baixo seria apenas um complemento da parte de cima. Se puder me passar um pouco mais detalhado, fico muito agradecido.
Responder
Vamos lá:

A procedure:
procedure BuscaRegistro(cds: TClientDataset; campo: string; conteudo: string);
var
  numRegistro: integer;
  bolEncontrou: boolean;
  strMensagem: string;
begin
  // verifica se o dataset está aberto e se o campo indicado existe
  if not cds.Active or (cds.FindField(campo) = nil) or cds.IsEmpty then
  begin
    if not cds.Active then
      strMensagem := 'A busca só pode ser realizada num dataset aberto'
    else
    if cds.IsEmpty then
      strMensagem := 'A pesquisa não pode ser realizada num dataset vazio'
    else
      strMensagem := 'O campo '''+campo+''' não existe no dataset';
    ShowMessage(strMensagem);
    exit;
  end;
 
  // guarda o registro posicionado antes de iniciar a pesquisa
  numRegistro := cds.RecNo;
 
  // inicializa a variável que indica se o texto foi encontrado
  bolEncontrou := False;
 
  // desabilita o refresh nos controles ligados ao dataset
  cds.DisableControls;
 
  // posiciona no primeiro registro
  cds.First;
 
  //varre o dataset à procura do conteudo desejado
  while not cds.Eof do
  begin
    // procura o valor digitado em qualquer parte do campo
    bolEncontrou := (Pos(AnsiUpperCase(conteudo), AnsiUpperCase(cds.FieldByName(campo).AsString)) > 0);
 
    // se encontrar o conteúdo, sai do loop
    if bolEncontrou then
      break;
 
    cds.Next;
  end;
 
  // se não encontrou um registro, reposiciona o ponteiro no registro inicial
  if not bolEncontrou then
    cds.RecNo := numRegistro;
 
  // habilita o refresh nos controles ligados ao dataset
  cds.EnableControls;
end;

Deve ser colocada no seu código. Se você estiver usando um DataModule, implemente a procedure nele. Não é um componente nem nada. É uma procedure simples. Para que o compilador identifique a classe TClientDataset (está assim porque você disse que usa ClientDataset), será necessário adicionar a unit Datasnap.DBClient na cláusula uses.

E, para usar, basta fazer algo assim:
procedure TForm1.Edit1Change(Sender: TObject);
begin
  BuscaRegistro(cdsClientes, 'Nome', Edit1.Text); // aqui você manda teu ClientDataset, o campo que será pesquisado, e o valor a ser procurado
end;

Responder
Parece que ta dando resultado, apesar que ele da erro ali no ShowMessage, ai tenho que fazer usn ajuste pra corrigir, não sei pq ele da esse erro, (Undeclared) e o que não entendi bem foi aqui onde tenho que adicionar a unit Datasnap.DBClient na cláusula uses. Esse seria na propria Unit do Data Moduel mesmo neh? mas seria dessa forma mesmo com aquele ponto no meio? pq da erro, ele não reconhece esse comando.
Responder
Declare na uses do DataModule.
O uso de Datasnap.DBClient ou DBClient vai depender da versão do Delphi.
Responder
E, para que o ShowMessage funcione, adicione a unit Dialogs no uses.
Responder
Declare na uses do DataModule.
O uso de Datasnap.DBClient ou DBClient vai depender da versão do Delphi.

Uso o Delphi 10 e nele jah está declarado esse DBClient na uses do DM. eu adicionei um edit que no caso ficou como edit3 esse código:
procedure TForm1.Edit1Change(Sender: TObject);
begin
BuscaRegistro(ClientDataSet1, 'Nome', Edit1.Text);
end;
Mas ele da como Undeclared Indetifier: BuscaRegistro e no ClienteDataSet1
Responder
tudo vai depender de como você declarou a procedure no Datamodule:
- como um método (dentro da definição do datamodule)
type
  TDataModule1 = class(TDataModule)
    procedure DataModuleCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure BuscaRegistro(cds: TClientDataset; campo: string; conteudo: string); // declaração da procedure como método do datamodule
  end;

desta forma, você deve executar assim (indicando o datamodule) :
procedure TForm1.Edit1Change(Sender: TObject);
begin
  DataModule1.BuscaRegistro(TeuClientDataset, CampoASerUtilizado, ConteudoProdurado); // aqui você manda teu ClientDataset, o campo que será pesquisado, e o valor a ser procurado
end;


- como procedure (fora da definição do datamodule)
type
  TDataModule1 = class(TDataModule)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DataModule1: TDataModule1;

procedure BuscaRegistro(cds: TClientDataset; campo: string; conteudo: string); // declaração da procedure fora da definição do DataModule

implementation

desta forma, você deve executar assim (chama diretamente a procedure):
procedure TForm1.Edit1Change(Sender: TObject);
begin
  BuscaRegistro(TeuClientDataset, CampoASerUtilizado, ConteudoProdurado); // aqui você manda teu ClientDataset, o campo que será pesquisado, e o valor a ser procurado
end;


Para uma resposta mais precisa, publique o código fonte do teu datamodule.

Responder
Me passa o seu e-mail, lah te mando as imagem de como tah o meu Data Módule e o código fonte do Data Módule e do Form que to querendo colocar a pesquisa, te explico certinho.
lá no Dta Module ta esse:
type
  TDataModule1 = class(TDataModule)
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  DM: TDM; 
implementation

se não eu posto aqui mesmo os código fonte do DM e do Form.
Responder
Pode mandar para emerson.en@gmail.com
Responder
Tópico Resolvido. Obrigado a todos que participaram dando suas opiniões, conseguir resolver minha dúvida.
Responder